Skip to content

Commit

Permalink
dynamic: Streamline trampoline life cycle
Browse files Browse the repository at this point in the history
Install a trampoline for each loaded module map, on initialization. Keep
the trampolines in memory to allow for dynamic patching at runtime.
Clear the trampolines on libmcount exit.

Co-authored-by: Gabriel-Andrew Pollo-Guilbert <[email protected]>
Signed-off-by: Clément Guidi <[email protected]>
  • Loading branch information
2 people authored and azharivs committed Aug 29, 2023
1 parent 1a9e896 commit 6942135
Showing 1 changed file with 46 additions and 36 deletions.
82 changes: 46 additions & 36 deletions libmcount/dynamic.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,14 @@ static struct mcount_dynamic_info *create_mdi(struct dl_phdr_info *info)
}

/**
* find_dynamic_module - callback for dl_iterate_phdr(), iterated over all
* loaded shared objects
* @info - info about shared object
* @sz - _unused_
* @data - mcount module data
* @return - 0 to continue iteration, non-zero to stop
* prepare_dynamic_module - store dynamic module info and install trampoline;
* callback for dl_iterate_phdr()
* @info - module info
* @sz - data size (unused)
* @data - callback data: symbol info and module parsing flag
* @return - stop iteration on non-zero value
*/
static int find_dynamic_module(struct dl_phdr_info *info, size_t sz, void *data)
static int prepare_dynamic_module(struct dl_phdr_info *info, size_t sz, void *data)
{
struct mcount_dynamic_info *mdi;
struct find_module_data *fmd = data;
Expand All @@ -327,6 +327,9 @@ static int find_dynamic_module(struct dl_phdr_info *info, size_t sz, void *data)
mdi->map = map;
mcount_arch_find_module(mdi, &map->mod->symtab);

if (mcount_setup_trampoline(mdi) < 0)
mdi->trampoline = 0;

mdi->next = mdinfo;
mdinfo = mdi;
if (is_executable)
Expand All @@ -348,6 +351,7 @@ static int find_dynamic_module(struct dl_phdr_info *info, size_t sz, void *data)
*/
static void prepare_dynamic_update(struct uftrace_sym_info *sinfo, bool needs_modules)
{
int rc = 0;
struct find_module_data fmd = {
.sinfo = sinfo,
.needs_modules = needs_modules,
Expand All @@ -366,7 +370,7 @@ static void prepare_dynamic_update(struct uftrace_sym_info *sinfo, bool needs_mo
code_hmap = hashmap_create(hash_size, hashmap_ptr_hash, hashmap_ptr_equals);
}

int rc = dl_iterate_phdr(find_dynamic_module, &fmd);
rc = dl_iterate_phdr(prepare_dynamic_module, &fmd);

if (needs_modules && rc == 0)
modules_loaded = true;
Expand Down Expand Up @@ -646,10 +650,18 @@ static void patch_func_matched(struct mcount_dynamic_info *mdi, struct uftrace_m
patch_normal_func_matched(mdi, map);
}

/**
* do_dynamic_update - apply (un)patching across loaded modules' maps
* @sinfo - dynamic symbol info
* @patch_funcs - spec of symbols to (un)patch
* @ptype - matching pattern type
* @return - 0 (unused)
*/
static int do_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs,
enum uftrace_pattern_type ptype)
{
struct uftrace_mmap *map;
struct mcount_dynamic_info *mdi;
char *def_mod;

if (patch_funcs == NULL)
Expand All @@ -658,15 +670,11 @@ static int do_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs,
def_mod = basename(sinfo->exec_map->libname);
parse_pattern_list(patch_funcs, def_mod, ptype);

for_each_map(sinfo, map) {
struct mcount_dynamic_info *mdi;

/* TODO: filter out unsuppported libs */
mdi = setup_trampoline(map);
if (mdi == NULL)
continue;

patch_func_matched(mdi, map);
/* TODO: filter out unsupported libs */
for (mdi = mdinfo; mdi != NULL; mdi = mdi->next) {
map = mdi->map;
if (mdi->trampoline)
patch_func_matched(mdi, map);
}

release_pattern_list();
Expand All @@ -679,24 +687,6 @@ static int do_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs,
return 0;
}

static void freeze_dynamic_update(void)
{
struct mcount_dynamic_info *mdi, *tmp;

mdi = mdinfo;
while (mdi) {
tmp = mdi->next;

mcount_arch_dynamic_recover(mdi, &disasm);
mcount_cleanup_trampoline(mdi);
free(mdi);

mdi = tmp;
}

mcount_freeze_code();
}

/* do not use floating-point in libmcount */
static int calc_percent(int n, int total, int *rem)
{
Expand Down Expand Up @@ -741,7 +731,7 @@ int mcount_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs,
pr_dbg("no match: %8d\n", stats.nomatch);
}

freeze_dynamic_update();
mcount_freeze_code();
return ret;
}

Expand Down Expand Up @@ -787,9 +777,29 @@ void mcount_dynamic_dlopen(struct uftrace_sym_info *sinfo, struct dl_phdr_info *
mcount_freeze_code();
}

/**
* mcount_free_mdinfo - free all dynamic info structures
*/
static void mcount_free_mdinfo(void)
{
struct mcount_dynamic_info *mdi, *tmp;

mdi = mdinfo;
while (mdi) {
tmp = mdi->next;

mcount_arch_dynamic_recover(mdi, &disasm);
mcount_cleanup_trampoline(mdi);
free(mdi);

mdi = tmp;
}
}

void mcount_dynamic_finish(void)
{
release_pattern_list();
mcount_free_mdinfo();
mcount_disasm_finish(&disasm);
}

Expand Down

0 comments on commit 6942135

Please sign in to comment.