diff options
author | jkoshy <jkoshy@FreeBSD.org> | 2005-10-18 05:13:27 +0000 |
---|---|---|
committer | jkoshy <jkoshy@FreeBSD.org> | 2005-10-18 05:13:27 +0000 |
commit | 1c6388f59d84d44e26ad31d5dc72b9d2d3533c08 (patch) | |
tree | dc596a6dfb2fc2bb13956ecdeaf8d19feefdaea4 /usr.sbin/pmcstat | |
parent | 94200415ae821f8a9a0a303f2f1cb3725e913744 (diff) | |
download | FreeBSD-src-1c6388f59d84d44e26ad31d5dc72b9d2d3533c08.zip FreeBSD-src-1c6388f59d84d44e26ad31d5dc72b9d2d3533c08.tar.gz |
Handle 32 bit executables better on AMD64 platforms.
Diffstat (limited to 'usr.sbin/pmcstat')
-rw-r--r-- | usr.sbin/pmcstat/pmcstat_log.c | 99 |
1 files changed, 69 insertions, 30 deletions
diff --git a/usr.sbin/pmcstat/pmcstat_log.c b/usr.sbin/pmcstat/pmcstat_log.c index d4def0e..a7bb4ef 100644 --- a/usr.sbin/pmcstat/pmcstat_log.c +++ b/usr.sbin/pmcstat/pmcstat_log.c @@ -328,6 +328,11 @@ pmcstat_image_get_elf_params(struct pmcstat_image *image) const Elf_Ehdr *h; const Elf_Phdr *ph; const Elf_Shdr *sh; +#if defined(__amd64__) + const Elf32_Ehdr *h32; + const Elf32_Phdr *ph32; + const Elf32_Shdr *sh32; +#endif const char *path; assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN); @@ -352,47 +357,81 @@ pmcstat_image_get_elf_params(struct pmcstat_image *image) if (!IS_ELF(*h)) err(EX_SOFTWARE, "ERROR: \"%s\" not an ELF file", path); - sh = (const Elf_Shdr *)((uintptr_t) mapbase + h->e_shoff); - - if (h->e_type == ET_EXEC || h->e_type == ET_DYN) { - /* - * Some kind of executable object: find the min,max va - * for its executable sections. - */ - for (i = 0; i < h->e_shnum; i++) - if (sh[i].sh_flags & SHF_EXECINSTR) { /* code */ - minva = min(minva, sh[i].sh_addr); - maxva = max(maxva, sh[i].sh_addr + - sh[i].sh_size); - } - } else + /* we only handle executable objects */ + if (h->e_type != ET_EXEC && h->e_type != ET_DYN) err(EX_DATAERR, "ERROR: Unknown file type for \"%s\"", image->pi_internedpath); +#define GET_VA(H, SH, MINVA, MAXVA) do { \ + for (i = 0; i < (H)->e_shnum; i++) \ + if ((SH)[i].sh_flags & SHF_EXECINSTR) { \ + (MINVA) = min((MINVA),(SH)[i].sh_addr); \ + (MAXVA) = max((MAXVA),(SH)[i].sh_addr + \ + (SH)[i].sh_size); \ + } \ + } while (0) + + +#define GET_PHDR_INFO(H, PH, IMAGE) do { \ + for (i = 0; i < (H)->e_phnum; i++) { \ + switch ((PH)[i].p_type) { \ + case PT_DYNAMIC: \ + image->pi_isdynamic = 1; \ + break; \ + case PT_INTERP: \ + image->pi_dynlinkerpath = \ + pmcstat_string_intern( \ + (char *) mapbase + \ + (PH)[i].p_offset); \ + break; \ + } \ + } \ + } while (0) + image->pi_type = PMCSTAT_IMAGE_ELF; - image->pi_start = minva; - image->pi_entry = h->e_entry; - image->pi_end = maxva; image->pi_isdynamic = 0; image->pi_dynlinkerpath = NULL; + switch (h->e_machine) { + case EM_386: + case EM_486: +#if defined(__amd64__) + /* a 32 bit executable */ + h32 = (const Elf32_Ehdr *) h; + sh32 = (const Elf32_Shdr *)((uintptr_t) mapbase + h32->e_shoff); - if (h->e_type == ET_EXEC) { - ph = (const Elf_Phdr *)((uintptr_t) mapbase + h->e_phoff); - for (i = 0; i < h->e_phnum; i++) { - switch (ph[i].p_type) { - case PT_DYNAMIC: - image->pi_isdynamic = 1; - break; - case PT_INTERP: - image->pi_dynlinkerpath = - pmcstat_string_intern((char *) mapbase + - ph[i].p_offset); - break; - } + GET_VA(h32, sh32, minva, maxva); + + image->pi_entry = h32->e_entry; + + if (h32->e_type == ET_EXEC) { + ph32 = (const Elf32_Phdr *)((uintptr_t) mapbase + + h32->e_phoff); + GET_PHDR_INFO(h32, ph32, image); } + break; +#endif + default: + sh = (const Elf_Shdr *)((uintptr_t) mapbase + h->e_shoff); + + GET_VA(h, sh, minva, maxva); + + image->pi_entry = h->e_entry; + + if (h->e_type == ET_EXEC) { + ph = (const Elf_Phdr *)((uintptr_t) mapbase + + h->e_phoff); + GET_PHDR_INFO(h, ph, image); + } + break; } +#undef GET_PHDR_INFO +#undef GET_VA + + image->pi_start = minva; + image->pi_end = maxva; + if (munmap(mapbase, st.st_size) < 0) err(EX_OSERR, "ERROR: Cannot unmap \"%s\"", path); |