diff --git a/lib/libkldelf/ef_obj.c b/lib/libkldelf/ef_obj.c --- a/lib/libkldelf/ef_obj.c +++ b/lib/libkldelf/ef_obj.c @@ -276,6 +276,7 @@ size_t i, nshdr; int error, pb, ra, rl; int j, nsym, symstrindex, symtabindex; + bool incorelayout; hdr = &efile->ef_hdr; if (hdr->e_type != ET_REL || hdr->e_shnum == 0 || hdr->e_shoff == 0 || @@ -285,6 +286,7 @@ ef = calloc(1, sizeof(*ef)); if (ef == NULL) return (errno); + incorelayout = (efile->ef_flags & KELF_F_OINCORELAYOUT) != 0; efile->ef_ef = ef; efile->ef_ops = &ef_obj_file_ops; @@ -304,9 +306,16 @@ symtabindex = -1; symstrindex = -1; for (i = 0; i < nshdr; i++) { + if (incorelayout && shdr[i].sh_size == 0) + continue; switch (shdr[i].sh_type) { case SHT_PROGBITS: case SHT_NOBITS: + case SHT_X86_64_UNWIND: + case SHT_INIT_ARRAY: + case SHT_FINI_ARRAY: + if (incorelayout && (shdr[i].sh_flags & SHF_ALLOC) == 0) + break; ef->nprogtab++; break; case SHT_SYMTAB: @@ -385,9 +394,16 @@ ra = 0; mapbase = 0; for (i = 0; i < nshdr; i++) { + if (incorelayout && shdr[i].sh_size == 0) + continue; switch (shdr[i].sh_type) { case SHT_PROGBITS: case SHT_NOBITS: + case SHT_X86_64_UNWIND: + case SHT_INIT_ARRAY: + case SHT_FINI_ARRAY: + if (incorelayout && (shdr[i].sh_flags & SHF_ALLOC) == 0) + break; mapbase = roundup2(mapbase, shdr[i].sh_addralign); ef->progtab[pb].addr = mapbase; if (shdr[i].sh_type == SHT_PROGBITS) { diff --git a/lib/libkldelf/elf.c b/lib/libkldelf/elf.c --- a/lib/libkldelf/elf.c +++ b/lib/libkldelf/elf.c @@ -63,12 +63,14 @@ } int -elf_open_file(struct elf_file *efile, const char *filename, int verbose) +elf_open_file(struct elf_file *efile, const char *filename, unsigned int flags, + int verbose) { int error; memset(efile, 0, sizeof(*efile)); efile->ef_filename = filename; + efile->ef_flags = flags; efile->ef_fd = open(filename, O_RDONLY); if (efile->ef_fd == -1) { if (verbose) diff --git a/lib/libkldelf/kldelf.h b/lib/libkldelf/kldelf.h --- a/lib/libkldelf/kldelf.h +++ b/lib/libkldelf/kldelf.h @@ -101,6 +101,7 @@ elf_reloc_t *ef_reloc; GElf_Ehdr ef_hdr; size_t ef_pointer_size; + unsigned int ef_flags; int ef_fd; }; @@ -153,12 +154,15 @@ * use libelf. */ +/* For an object file, load the image as how it is loaded by kernel linker */ +#define KELF_F_OINCORELAYOUT (1 << 1u) + /* * Open an ELF file with libelf. Populates fields other than ef_ef * and ef_ops in '*efile'. */ int elf_open_file(struct elf_file *efile, const char *filename, - int verbose); + unsigned int flags, int verbose); /* Close an ELF file. */ void elf_close_file(struct elf_file *efile); diff --git a/usr.sbin/kldxref/kldxref.c b/usr.sbin/kldxref/kldxref.c --- a/usr.sbin/kldxref/kldxref.c +++ b/usr.sbin/kldxref/kldxref.c @@ -640,7 +640,7 @@ if (verbose || dflag) printf("%s\n", filename); - error = elf_open_file(&ef, filename, verbose); + error = elf_open_file(&ef, filename, 0, verbose); if (error != 0) return (error);