From 926da0492a672c3175d81f24bfa1b4ad461b884b Mon Sep 17 00:00:00 2001 From: Leandro Lupori Date: Thu, 5 Nov 2020 16:47:23 +0000 Subject: [PATCH] pmcstat: fix PPC kernel symbol resolution PowerPC kernel is of DYN type and it has a base address where it is initially loaded, before being relocated. As the start address passed to pmcstat_image_link() is where the kernel was relocated to, but the symbols always use the original base address, we need to subtract it to get the correct offset. Reviewed by: jhibbits Sponsored by: Eldorado Research Institute (eldorado.org.br) Differential Revision: https://reviews.freebsd.org/D26114 --- lib/libpmcstat/libpmcstat_image.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/libpmcstat/libpmcstat_image.c b/lib/libpmcstat/libpmcstat_image.c index 94d103228d28..9ee7097e95ec 100644 --- a/lib/libpmcstat/libpmcstat_image.c +++ b/lib/libpmcstat/libpmcstat_image.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -176,6 +177,10 @@ pmcstat_image_link(struct pmcstat_process *pp, struct pmcstat_image *image, { struct pmcstat_pcmap *pcm, *pcmnew; uintfptr_t offset; +#ifdef __powerpc__ + unsigned long kernbase; + size_t kernbase_len; +#endif assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN && image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE); @@ -183,6 +188,26 @@ pmcstat_image_link(struct pmcstat_process *pp, struct pmcstat_image *image, if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL) err(EX_OSERR, "ERROR: Cannot create a map entry"); + /* + * PowerPC kernel is of DYN type and it has a base address + * where it is initially loaded, before being relocated. + * As the address in 'start' is where the kernel was relocated to, + * but the symbols always use the original base address, we need to + * subtract it to get the correct offset. + */ +#ifdef __powerpc__ + if (pp->pp_pid == -1) { + kernbase = 0; + kernbase_len = sizeof(kernbase); + if (sysctlbyname("kern.base_address", &kernbase, &kernbase_len, + NULL, 0) == -1) + warnx( + "WARNING: Could not retrieve kernel base address"); + else + start -= kernbase; + } +#endif + /* * Adjust the map entry to only cover the text portion * of the object.