diff options
author | marcel <marcel@FreeBSD.org> | 2014-10-20 17:04:03 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2014-10-20 17:04:03 +0000 |
commit | d2387926bad74ed69fd6276e007f3fe3177524e2 (patch) | |
tree | 3a50bd48ab8a770ba6e79126bc1edb6227bd78f8 /sys/boot | |
parent | fbbd6ea1dce36d355ca0bd5788f5489b292fe9d3 (diff) | |
download | FreeBSD-src-d2387926bad74ed69fd6276e007f3fe3177524e2.zip FreeBSD-src-d2387926bad74ed69fd6276e007f3fe3177524e2.tar.gz |
Fully support constructors for the purpose of code coverage analysis.
This involves:
1. Have the loader pass the start and size of the .ctors section to the
kernel in 2 new metadata elements.
2. Have the linker backends look for and record the start and size of
the .ctors section in dynamically loaded modules.
3. Have the linker backends call the constructors as part of the final
work of initializing preloaded or dynamically loaded modules.
Note that LLVM appends the priority of the constructors to the name of
the .ctors section. Not so when compiling with GCC. The code currently
works for GCC and not for LLVM.
Submitted by: Dmitry Mikulin <dmitrym@juniper.net>
Obtained from: Juniper Networks, Inc.
Diffstat (limited to 'sys/boot')
-rw-r--r-- | sys/boot/common/load_elf.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index 8990d90..04a7dbe 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -240,6 +240,7 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) Elf_Ehdr *ehdr; Elf_Phdr *phdr, *php; Elf_Shdr *shdr; + char *shstr; int ret; vm_offset_t firstaddr; vm_offset_t lastaddr; @@ -248,6 +249,7 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) Elf_Addr ssym, esym; Elf_Dyn *dp; Elf_Addr adp; + Elf_Addr ctors; int ndp; int symstrindex; int symtabindex; @@ -383,10 +385,11 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) lastaddr = roundup(lastaddr, sizeof(long)); /* - * Now grab the symbol tables. This isn't easy if we're reading a - * .gz file. I think the rule is going to have to be that you must - * strip a file to remove symbols before gzipping it so that we do not - * try to lseek() on it. + * Get the section headers. We need this for finding the .ctors + * section as well as for loading any symbols. Both may be hard + * to do if reading from a .gz file as it involves seeking. I + * think the rule is going to have to be that you must strip a + * file to remove symbols before gzipping it. */ chunk = ehdr->e_shnum * ehdr->e_shentsize; if (chunk == 0 || ehdr->e_shoff == 0) @@ -399,6 +402,33 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) } file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr); + /* + * Read the section string table and look for the .ctors section. + * We need to tell the kernel where it is so that it can call the + * ctors. + */ + chunk = shdr[ehdr->e_shstrndx].sh_size; + if (chunk) { + shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset, chunk); + if (shstr) { + for (i = 0; i < ehdr->e_shnum; i++) { + if (strcmp(shstr + shdr[i].sh_name, ".ctors") != 0) + continue; + ctors = shdr[i].sh_addr; + file_addmetadata(fp, MODINFOMD_CTORS_ADDR, sizeof(ctors), + &ctors); + size = shdr[i].sh_size; + file_addmetadata(fp, MODINFOMD_CTORS_SIZE, sizeof(size), + &size); + break; + } + free(shstr); + } + } + + /* + * Now load any symbols. + */ symtabindex = -1; symstrindex = -1; for (i = 0; i < ehdr->e_shnum; i++) { |