summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pmcstat
diff options
context:
space:
mode:
authorjkoshy <jkoshy@FreeBSD.org>2005-10-18 05:13:27 +0000
committerjkoshy <jkoshy@FreeBSD.org>2005-10-18 05:13:27 +0000
commit1c6388f59d84d44e26ad31d5dc72b9d2d3533c08 (patch)
treedc596a6dfb2fc2bb13956ecdeaf8d19feefdaea4 /usr.sbin/pmcstat
parent94200415ae821f8a9a0a303f2f1cb3725e913744 (diff)
downloadFreeBSD-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.c99
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);
OpenPOWER on IntegriCloud