aboutsummaryrefslogtreecommitdiff
path: root/lib/libpmcstat
diff options
context:
space:
mode:
authorLeandro Lupori <luporl@FreeBSD.org>2020-11-05 16:47:23 +0000
committerLeandro Lupori <luporl@FreeBSD.org>2020-11-05 16:47:23 +0000
commit926da0492a672c3175d81f24bfa1b4ad461b884b (patch)
treedea8ad759cec22b62f09aa4aa53ed05718a9777b /lib/libpmcstat
parent5cebdfc072f2c26a266e90534f1a4044f321a5ba (diff)
downloadsrc-926da0492a672c3175d81f24bfa1b4ad461b884b.tar.gz
src-926da0492a672c3175d81f24bfa1b4ad461b884b.zip
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
Notes
Notes: svn path=/head/; revision=367392
Diffstat (limited to 'lib/libpmcstat')
-rw-r--r--lib/libpmcstat/libpmcstat_image.c25
1 files changed, 25 insertions, 0 deletions
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 <sys/param.h>
#include <sys/endian.h>
#include <sys/pmc.h>
+#include <sys/sysctl.h>
#include <sys/imgact_aout.h>
#include <sys/imgact_elf.h>
@@ -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);
@@ -184,6 +189,26 @@ pmcstat_image_link(struct pmcstat_process *pp, struct pmcstat_image *image,
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.
*/