Changeset View
Changeset View
Standalone View
Standalone View
lib/libpmcstat/libpmcstat_process.c
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
#include "libpmcstat.h" | #include "libpmcstat.h" | ||||
/* | /* | ||||
* Associate an AOUT image with a process. | * Associate an AOUT image with a process. | ||||
*/ | */ | ||||
void | void | ||||
pmcstat_process_aout_exec(struct pmcstat_process *pp, | pmcstat_process_aout_exec(struct pmcstat_process *pp, | ||||
struct pmcstat_image *image, uintfptr_t entryaddr) | struct pmcstat_image *image, uintptr_t baseaddr) | ||||
{ | { | ||||
(void) pp; | (void) pp; | ||||
(void) image; | (void) image; | ||||
(void) entryaddr; | (void) baseaddr; | ||||
/* TODO Implement a.out handling */ | /* TODO Implement a.out handling */ | ||||
emaste: I think we could just delete this function | |||||
} | } | ||||
/* | /* | ||||
* Associate an ELF image with a process. | * Associate an ELF image with a process. | ||||
*/ | */ | ||||
void | void | ||||
pmcstat_process_elf_exec(struct pmcstat_process *pp, | pmcstat_process_elf_exec(struct pmcstat_process *pp, | ||||
struct pmcstat_image *image, uintfptr_t entryaddr, | struct pmcstat_image *image, uintptr_t baseaddr, uintptr_t dynaddr, | ||||
struct pmcstat_args *args, struct pmc_plugins *plugins, | struct pmcstat_args *args, struct pmc_plugins *plugins, | ||||
struct pmcstat_stats *pmcstat_stats) | struct pmcstat_stats *pmcstat_stats) | ||||
{ | { | ||||
uintmax_t libstart; | |||||
struct pmcstat_image *rtldimage; | struct pmcstat_image *rtldimage; | ||||
assert(image->pi_type == PMCSTAT_IMAGE_ELF32 || | assert(image->pi_type == PMCSTAT_IMAGE_ELF32 || | ||||
image->pi_type == PMCSTAT_IMAGE_ELF64); | image->pi_type == PMCSTAT_IMAGE_ELF64); | ||||
/* Create a map entry for the base executable. */ | /* | ||||
pmcstat_image_link(pp, image, image->pi_vaddr); | * The exact address where the executable gets mapped in will vary for | ||||
* PIEs. The dynamic address recorded at process exec time corresponds | |||||
* to the address where the executable's file object had been mapped to. | |||||
*/ | |||||
pmcstat_image_link(pp, image, image->pi_vaddr + dynaddr); | |||||
Not Done Inline ActionsPresumably pi_vaddr is always 0 for PIEs? jhb: Presumably pi_vaddr is always 0 for PIEs? | |||||
Done Inline ActionsYes. If you have a non-zero base address for ET_DYN then the kernel will honour it. jrtc27: Yes. If you have a non-zero base address for ET_DYN then the kernel will honour it. | |||||
/* | /* | ||||
* For dynamically linked executables we need to determine | * For dynamically linked executables we need to determine | ||||
* where the dynamic linker was mapped to for this process, | * where the dynamic linker was mapped to for this process, | ||||
* Subsequent executable objects that are mapped in by the | * Subsequent executable objects that are mapped in by the | ||||
* dynamic linker will be tracked by log events of type | * dynamic linker will be tracked by log events of type | ||||
* PMCLOG_TYPE_MAP_IN. | * PMCLOG_TYPE_MAP_IN. | ||||
*/ | */ | ||||
if (image->pi_isdynamic) { | if (image->pi_isdynamic) { | ||||
/* | /* | ||||
* The runtime loader gets loaded just after the maximum | * The runtime loader gets loaded just after the maximum | ||||
* possible heap address. Like so: | * possible heap address. Like so: | ||||
* | * | ||||
* [ TEXT DATA BSS HEAP -->*RTLD SHLIBS <--STACK] | * [ TEXT DATA BSS HEAP -->*RTLD SHLIBS <--STACK] | ||||
* ^ ^ | * ^ ^ | ||||
* 0 VM_MAXUSER_ADDRESS | * 0 VM_MAXUSER_ADDRESS | ||||
* | * | ||||
* The exact address where the loader gets mapped in | * The exact address where the loader gets mapped in | ||||
* will vary according to the size of the executable | * will vary according to the size of the executable | ||||
* and the limits on the size of the process'es data | * and the limits on the size of the process'es data | ||||
* segment at the time of exec(). The entry address | * segment at the time of exec(). The base address | ||||
* recorded at process exec time corresponds to the | * recorded at process exec time corresponds to the | ||||
* 'start' address inside the dynamic linker. From | * address where the runtime loader's file object had | ||||
* this we can figure out the address where the | * been mapped to. | ||||
* runtime loader's file object had been mapped to. | |||||
*/ | */ | ||||
rtldimage = pmcstat_image_from_path(image->pi_dynlinkerpath, | rtldimage = pmcstat_image_from_path(image->pi_dynlinkerpath, | ||||
0, args, plugins); | 0, args, plugins); | ||||
if (rtldimage == NULL) { | if (rtldimage == NULL) { | ||||
warnx("WARNING: Cannot find image for \"%s\".", | warnx("WARNING: Cannot find image for \"%s\".", | ||||
pmcstat_string_unintern(image->pi_dynlinkerpath)); | pmcstat_string_unintern(image->pi_dynlinkerpath)); | ||||
pmcstat_stats->ps_exec_errors++; | pmcstat_stats->ps_exec_errors++; | ||||
return; | return; | ||||
} | } | ||||
if (rtldimage->pi_type == PMCSTAT_IMAGE_UNKNOWN) | if (rtldimage->pi_type == PMCSTAT_IMAGE_UNKNOWN) | ||||
pmcstat_image_get_elf_params(rtldimage, args); | pmcstat_image_get_elf_params(rtldimage, args); | ||||
if (rtldimage->pi_type != PMCSTAT_IMAGE_ELF32 && | if (rtldimage->pi_type != PMCSTAT_IMAGE_ELF32 && | ||||
rtldimage->pi_type != PMCSTAT_IMAGE_ELF64) { | rtldimage->pi_type != PMCSTAT_IMAGE_ELF64) { | ||||
warnx("WARNING: rtld not an ELF object \"%s\".", | warnx("WARNING: rtld not an ELF object \"%s\".", | ||||
pmcstat_string_unintern(image->pi_dynlinkerpath)); | pmcstat_string_unintern(image->pi_dynlinkerpath)); | ||||
return; | return; | ||||
} | } | ||||
libstart = entryaddr - rtldimage->pi_entry; | pmcstat_image_link(pp, rtldimage, baseaddr); | ||||
Not Done Inline ActionsPresumably rtld is always PIE which is why rtldimage->pi_vaddr can be ignored here? jhb: Presumably rtld is always PIE which is why rtldimage->pi_vaddr can be ignored here? | |||||
Done Inline ActionsIn effect (otherwise the existing code wouldn't have worked; it relied on pi_entry being the offset of the entry point in order to turn entryaddr back into baseaddr). Really it's a shared library that has an entry point (I guess a static PIE in effect, even?). jrtc27: In effect (otherwise the existing code wouldn't have worked; it relied on pi_entry being the… | |||||
pmcstat_image_link(pp, rtldimage, libstart); | |||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Associate an image and a process. | * Associate an image and a process. | ||||
*/ | */ | ||||
void | void | ||||
pmcstat_process_exec(struct pmcstat_process *pp, | pmcstat_process_exec(struct pmcstat_process *pp, | ||||
pmcstat_interned_string path, uintfptr_t entryaddr, | pmcstat_interned_string path, uintptr_t baseaddr, uintptr_t dynaddr, | ||||
struct pmcstat_args *args, struct pmc_plugins *plugins, | struct pmcstat_args *args, struct pmc_plugins *plugins, | ||||
struct pmcstat_stats *pmcstat_stats) | struct pmcstat_stats *pmcstat_stats) | ||||
{ | { | ||||
struct pmcstat_image *image; | struct pmcstat_image *image; | ||||
if ((image = pmcstat_image_from_path(path, 0, | if ((image = pmcstat_image_from_path(path, 0, | ||||
args, plugins)) == NULL) { | args, plugins)) == NULL) { | ||||
pmcstat_stats->ps_exec_errors++; | pmcstat_stats->ps_exec_errors++; | ||||
return; | return; | ||||
} | } | ||||
if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN) | if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN) | ||||
pmcstat_image_determine_type(image, args); | pmcstat_image_determine_type(image, args); | ||||
assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN); | assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN); | ||||
switch (image->pi_type) { | switch (image->pi_type) { | ||||
case PMCSTAT_IMAGE_ELF32: | case PMCSTAT_IMAGE_ELF32: | ||||
case PMCSTAT_IMAGE_ELF64: | case PMCSTAT_IMAGE_ELF64: | ||||
pmcstat_stats->ps_exec_elf++; | pmcstat_stats->ps_exec_elf++; | ||||
pmcstat_process_elf_exec(pp, image, entryaddr, | pmcstat_process_elf_exec(pp, image, baseaddr, dynaddr, | ||||
args, plugins, pmcstat_stats); | args, plugins, pmcstat_stats); | ||||
break; | break; | ||||
case PMCSTAT_IMAGE_AOUT: | case PMCSTAT_IMAGE_AOUT: | ||||
pmcstat_stats->ps_exec_aout++; | pmcstat_stats->ps_exec_aout++; | ||||
pmcstat_process_aout_exec(pp, image, entryaddr); | pmcstat_process_aout_exec(pp, image, baseaddr); | ||||
break; | break; | ||||
case PMCSTAT_IMAGE_INDETERMINABLE: | case PMCSTAT_IMAGE_INDETERMINABLE: | ||||
pmcstat_stats->ps_exec_indeterminable++; | pmcstat_stats->ps_exec_indeterminable++; | ||||
break; | break; | ||||
default: | default: | ||||
err(EX_SOFTWARE, | err(EX_SOFTWARE, | ||||
▲ Show 20 Lines • Show All 179 Lines • Show Last 20 Lines |
I think we could just delete this function