From d13e467edc667b45e012e274c538ee49ff75f22b Mon Sep 17 00:00:00 2001 From: Seyed-Vahid Azhari Date: Mon, 10 Apr 2023 10:15:53 -0400 Subject: [PATCH 1/9] dynamic: Load dynamic info only once This is in preparation of runtime dynamic patching. This commit guarantees that dynamic info is read only once for the target binary and for each module. Co-authored-by: Gabriel-Andrew Pollo-Guilbert Signed-off-by: Seyed-Vahid Azhari --- libmcount/dynamic.c | 113 +++++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/libmcount/dynamic.c b/libmcount/dynamic.c index 507162060..99c27c3fc 100644 --- a/libmcount/dynamic.c +++ b/libmcount/dynamic.c @@ -31,6 +31,8 @@ #include "utils/symbol.h" #include "utils/utils.h" +static bool main_loaded; +static bool modules_loaded; static struct mcount_dynamic_info *mdinfo; static struct mcount_dynamic_stats { int total; @@ -293,7 +295,14 @@ static struct mcount_dynamic_info *create_mdi(struct dl_phdr_info *info) return mdi; } -/* callback for dl_iterate_phdr() */ +/** + * 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 + */ static int find_dynamic_module(struct dl_phdr_info *info, size_t sz, void *data) { struct mcount_dynamic_info *mdi; @@ -302,6 +311,15 @@ static int find_dynamic_module(struct dl_phdr_info *info, size_t sz, void *data) struct uftrace_mmap *map; bool is_executable = mcount_is_main_executable(info->dlpi_name, sym_info->filename); + if (is_executable) { + if (main_loaded) + return !fmd->needs_modules; + } + else if (!fmd->needs_modules) + return main_loaded; + else if (modules_loaded) + return 0; + mdi = create_mdi(info); map = find_map(sym_info, mdi->base_addr); @@ -311,6 +329,9 @@ static int find_dynamic_module(struct dl_phdr_info *info, size_t sz, void *data) mdi->next = mdinfo; mdinfo = mdi; + if (is_executable) + main_loaded = true; + pr_dbg3("load dynamic info for '%s'\n", mdi->map->libname); } else { free(mdi); @@ -319,6 +340,12 @@ static int find_dynamic_module(struct dl_phdr_info *info, size_t sz, void *data) return !fmd->needs_modules && is_executable; } +/** + * prepare_dynamic_update - create dynamic data structures and load dynamic + * modules info + * @sinfo - dynamic symbol info + * @needs_modules - whether to prepare dynamic modules or only the main binary + */ static void prepare_dynamic_update(struct uftrace_sym_info *sinfo, bool needs_modules) { struct find_module_data fmd = { @@ -327,12 +354,21 @@ static void prepare_dynamic_update(struct uftrace_sym_info *sinfo, bool needs_mo }; int hash_size = sinfo->exec_map->mod->symtab.nr_sym * 3 / 4; - if (needs_modules) - hash_size *= 2; + if (code_hmap) { + /* main executable already loaded */ + if (!needs_modules || modules_loaded) + return; + } + else { /* nothing loaded */ + if (needs_modules) + hash_size *= 2; + code_hmap = hashmap_create(hash_size, hashmap_ptr_hash, hashmap_ptr_equals); + } - code_hmap = hashmap_create(hash_size, hashmap_ptr_hash, hashmap_ptr_equals); + int rc = dl_iterate_phdr(find_dynamic_module, &fmd); - dl_iterate_phdr(find_dynamic_module, &fmd); + if (needs_modules && rc == 0) + modules_loaded = true; } struct mcount_dynamic_info *setup_trampoline(struct uftrace_mmap *map) @@ -384,17 +420,10 @@ static bool match_pattern_module(char *pathname) return ret; } -/** - * match_pattern_list - match a symbol name against a pattern list - * @map - memory map of the symbol - * @soname - name of the module - * @sym_name - name of the symbol - * @return - -1 if match negative, 1 if match positive, 0 if no match - */ -static int match_pattern_list(struct uftrace_mmap *map, char *soname, char *sym_name) +static bool match_pattern_list(struct uftrace_mmap *map, char *soname, char *sym_name) { struct patt_list *pl; - int ret = 0; + bool ret = false; char *libname = basename(map->libname); list_for_each_entry(pl, &patterns, list) { @@ -405,7 +434,7 @@ static int match_pattern_list(struct uftrace_mmap *map, char *soname, char *sym_ continue; if (match_filter_pattern(&pl->patt, sym_name)) - ret = pl->positive ? 1 : -1; + ret = pl->positive; } return ret; @@ -417,6 +446,7 @@ static void parse_pattern_list(char *patch_funcs, char *def_mod, enum uftrace_pa char *name; int j; struct patt_list *pl; + bool all_negative = true; strv_split(&funcs, patch_funcs, ";"); @@ -427,8 +457,10 @@ static void parse_pattern_list(char *patch_funcs, char *def_mod, enum uftrace_pa if (name[0] == '!') name++; - else + else { pl->positive = true; + all_negative = false; + } delim = strchr(name, '@'); if (delim == NULL) { @@ -443,6 +475,20 @@ static void parse_pattern_list(char *patch_funcs, char *def_mod, enum uftrace_pa list_add_tail(&pl->list, &patterns); } + /* prepend match-all pattern, if all patterns are negative */ + if (all_negative) { + pl = xzalloc(sizeof(*pl)); + pl->positive = true; + pl->module = xstrdup(def_mod); + + if (ptype == PATT_REGEX) + init_filter_pattern(ptype, &pl->patt, "."); + else + init_filter_pattern(PATT_GLOB, &pl->patt, "*"); + + list_add(&pl->list, &patterns); + } + strv_free(&funcs); } @@ -477,6 +523,12 @@ static bool skip_sym(struct uftrace_symbol *sym, struct mcount_dynamic_info *mdi if (sym->type != ST_LOCAL_FUNC && sym->type != ST_GLOBAL_FUNC && sym->type != ST_WEAK_FUNC) return true; + if (!match_pattern_list(map, soname, sym->name)) { + if (mcount_unpatch_func(mdi, sym, &disasm) == 0) + stats.unpatch++; + return true; + } + return false; } @@ -555,7 +607,6 @@ static void patch_normal_func_matched(struct mcount_dynamic_info *mdi, struct uf unsigned i; struct uftrace_symbol *sym; bool found = false; - int match; char *soname = get_soname(map->libname); symtab = &map->mod->symtab; @@ -565,15 +616,9 @@ static void patch_normal_func_matched(struct mcount_dynamic_info *mdi, struct uf if (skip_sym(sym, mdi, map, soname)) continue; - found = true; - match = match_pattern_list(map, soname, sym->name); - if (!match) - continue; - else if (match == 1) - mcount_patch_func_with_stats(mdi, sym); - else - mcount_unpatch_func(mdi, sym, NULL); + found = true; + mcount_patch_func_with_stats(mdi, sym); } if (!found) @@ -849,27 +894,27 @@ TEST_CASE(dynamic_pattern_list) pr_dbg("check simple match with default module\n"); parse_pattern_list("abc;!def", "main", PATT_SIMPLE); - TEST_EQ(match_pattern_list(main_map, NULL, "abc"), 1); - TEST_EQ(match_pattern_list(main_map, NULL, "def"), -1); - TEST_EQ(match_pattern_list(other_map, NULL, "xyz"), 0); + TEST_EQ(match_pattern_list(main_map, NULL, "abc"), true); + TEST_EQ(match_pattern_list(main_map, NULL, "def"), false); + TEST_EQ(match_pattern_list(other_map, NULL, "xyz"), false); release_pattern_list(); pr_dbg("check negative regex match with default module\n"); parse_pattern_list("!^a", "main", PATT_REGEX); - TEST_EQ(match_pattern_list(main_map, NULL, "abc"), -1); - TEST_EQ(match_pattern_list(main_map, NULL, "def"), 0); - TEST_EQ(match_pattern_list(other_map, NULL, "xyz"), 0); + TEST_EQ(match_pattern_list(main_map, NULL, "abc"), false); + TEST_EQ(match_pattern_list(main_map, NULL, "def"), true); + TEST_EQ(match_pattern_list(other_map, NULL, "xyz"), false); release_pattern_list(); pr_dbg("check wildcard match with other module\n"); parse_pattern_list("*@other", "main", PATT_GLOB); - TEST_EQ(match_pattern_list(main_map, NULL, "abc"), 0); - TEST_EQ(match_pattern_list(main_map, NULL, "def"), 0); - TEST_EQ(match_pattern_list(other_map, NULL, "xyz"), 1); + TEST_EQ(match_pattern_list(main_map, NULL, "abc"), false); + TEST_EQ(match_pattern_list(main_map, NULL, "def"), false); + TEST_EQ(match_pattern_list(other_map, NULL, "xyz"), true); release_pattern_list(); From 873fbf2d6c3bccd419b6dc02c80916545e37f3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Guidi?= Date: Mon, 10 Apr 2023 10:18:31 -0400 Subject: [PATCH 2/9] dynamic: Initialize size filter only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If 'mcount_dynamic_update' is called multiple times (e.g. at runtime), it initializes the size filter only once. Signed-off-by: Clément Guidi --- libmcount/dynamic.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libmcount/dynamic.c b/libmcount/dynamic.c index 99c27c3fc..dcc275327 100644 --- a/libmcount/dynamic.c +++ b/libmcount/dynamic.c @@ -371,6 +371,21 @@ static void prepare_dynamic_update(struct uftrace_sym_info *sinfo, bool needs_mo modules_loaded = true; } +/** + * setup_size_filter - initialize size filter if not set + */ +void setup_size_filter(void) +{ + char *size_filter; + + if (min_size) + return; + + size_filter = getenv("UFTRACE_MIN_SIZE"); + if (size_filter) + min_size = strtoul(size_filter, NULL, 0); +} + struct mcount_dynamic_info *setup_trampoline(struct uftrace_mmap *map) { struct mcount_dynamic_info *mdi; @@ -704,16 +719,13 @@ int mcount_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs, enum uftrace_pattern_type ptype) { int ret = 0; - char *size_filter; bool needs_modules = !!strchr(patch_funcs, '@'); mcount_disasm_init(&disasm); prepare_dynamic_update(sinfo, needs_modules); - size_filter = getenv("UFTRACE_MIN_SIZE"); - if (size_filter != NULL) - min_size = strtoul(size_filter, NULL, 0); + setup_size_filter(); ret = do_dynamic_update(sinfo, patch_funcs, ptype); From 6ef85df17a9ff0ef580a8a15df4fa3d73a1d2438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Guidi?= Date: Mon, 10 Apr 2023 10:20:35 -0400 Subject: [PATCH 3/9] dynamic: arch: Initialize disassembly engine once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skip the initialization of the disassembly engine with it has already been performed. Signed-off-by: Clément Guidi --- arch/aarch64/mcount-insn.c | 11 ++++++++++- arch/x86_64/mcount-insn.c | 19 ++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/arch/aarch64/mcount-insn.c b/arch/aarch64/mcount-insn.c index 13488487b..7e0a2dc8a 100644 --- a/arch/aarch64/mcount-insn.c +++ b/arch/aarch64/mcount-insn.c @@ -8,10 +8,19 @@ #include #include +/** + * mcount_disasm_init - initialize the capstone engine once + * @disasm - mcount disassembly engine + */ void mcount_disasm_init(struct mcount_disasm_engine *disasm) { + if (disasm->engine) + return; + + pr_dbg2("initialize disassembly engine\n"); + if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &disasm->engine) != CS_ERR_OK) { - pr_dbg("failed to init Capstone disasm engine\n"); + pr_dbg("failed to init capstone disasm engine\n"); return; } diff --git a/arch/x86_64/mcount-insn.c b/arch/x86_64/mcount-insn.c index c8ab6105a..d438034d8 100644 --- a/arch/x86_64/mcount-insn.c +++ b/arch/x86_64/mcount-insn.c @@ -19,8 +19,17 @@ struct disasm_check_data { uint32_t size; }; +/** + * mcount_disasm_init - initialize the capstone engine once + * @disasm - mcount disassembly engine + */ void mcount_disasm_init(struct mcount_disasm_engine *disasm) { + if (disasm->engine) + return; + + pr_dbg2("initialize disassembly engine\n"); + if (cs_open(CS_ARCH_X86, CS_MODE_64, &disasm->engine) != CS_ERR_OK) { pr_dbg("failed to init capstone disasm engine\n"); return; @@ -674,7 +683,7 @@ TEST_CASE(dynamic_x86_handle_lea) .addr = 0x3000, .size = 32, }; - struct mcount_disasm_engine disasm; + struct mcount_disasm_engine disasm = { 0 }; struct mcount_disasm_info info = { .sym = &sym, .addr = ORIGINAL_BASE + sym.addr, @@ -745,7 +754,7 @@ TEST_CASE(dynamic_x86_handle_call) .addr = 0x4000, .size = 32, }; - struct mcount_disasm_engine disasm; + struct mcount_disasm_engine disasm = { 0 }; struct mcount_disasm_info info = { .sym = &sym1, .addr = ORIGINAL_BASE + sym1.addr, @@ -823,7 +832,7 @@ TEST_CASE(dynamic_x86_handle_jmp) .addr = 0x3000, .size = 32, }; - struct mcount_disasm_engine disasm; + struct mcount_disasm_engine disasm = { 0 }; struct mcount_disasm_info info = { .sym = &sym, .addr = ORIGINAL_BASE + sym.addr, @@ -927,7 +936,7 @@ TEST_CASE(dynamic_x86_handle_jcc) .addr = 0x3000, .size = 32, }; - struct mcount_disasm_engine disasm; + struct mcount_disasm_engine disasm = { 0 }; struct mcount_disasm_info info = { .sym = &sym, .addr = ORIGINAL_BASE + sym.addr, @@ -1036,7 +1045,7 @@ TEST_CASE(dynamic_x86_handle_mov_load) .addr = 0x3000, .size = 32, }; - struct mcount_disasm_engine disasm; + struct mcount_disasm_engine disasm = { 0 }; struct mcount_disasm_info info = { .sym = &sym, .addr = ORIGINAL_BASE + sym.addr, From 971f89a0503abef011b78e8aa74ee48b707cd704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Guidi?= Date: Mon, 10 Apr 2023 10:22:27 -0400 Subject: [PATCH 4/9] dynamic: Discard the pattern list after update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dynamic pattern list is not reused from a dynamic update to another, keeping libmcount stateless in that regard. Co-authored-by: Gabriel-Andrew Pollo-Guilbert Signed-off-by: Clément Guidi --- libmcount/dynamic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libmcount/dynamic.c b/libmcount/dynamic.c index dcc275327..9a42587ea 100644 --- a/libmcount/dynamic.c +++ b/libmcount/dynamic.c @@ -680,6 +680,8 @@ static int do_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs, patch_func_matched(mdi, map); } + release_pattern_list(); + if (stats.failed + stats.skipped + stats.nomatch == 0) { pr_dbg("patched all (%d) functions in '%s'\n", stats.total, basename(sinfo->filename)); From f5a598d053dc3bd5b24a3fa1810dc4677d7cdd94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Guidi?= Date: Mon, 10 Apr 2023 10:24:22 -0400 Subject: [PATCH 5/9] dynamic: Refactor 'mcount_dynamic_update' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'mcount_dynamic_update' is now safe to call multiple times, including at runtime. On each call, it will perform patching and unpatching of the target (not implemented yet). Signed-off-by: Clément Guidi --- libmcount/dynamic.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libmcount/dynamic.c b/libmcount/dynamic.c index 9a42587ea..21143ad51 100644 --- a/libmcount/dynamic.c +++ b/libmcount/dynamic.c @@ -717,6 +717,14 @@ static int calc_percent(int n, int total, int *rem) return quot; } +/** + * mcount_dynamic_update - prepare and perform dynamic patching or unpatching, + * then display statistics + * @sinfo - dynamic symbol info + * @patch_funcs - spec of symbols to patch or unpatch + * @ptype - matching pattern type + * @return - 0 (unused) + */ int mcount_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs, enum uftrace_pattern_type ptype) { @@ -724,9 +732,7 @@ int mcount_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs, bool needs_modules = !!strchr(patch_funcs, '@'); mcount_disasm_init(&disasm); - prepare_dynamic_update(sinfo, needs_modules); - setup_size_filter(); ret = do_dynamic_update(sinfo, patch_funcs, ptype); From d884b23e718757818c241fe37deca7944a0f8288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Guidi?= Date: Tue, 7 Mar 2023 11:32:24 -0500 Subject: [PATCH 6/9] dynamic: Streamline trampoline life cycle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Clément Guidi --- libmcount/dynamic.c | 82 +++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/libmcount/dynamic.c b/libmcount/dynamic.c index 21143ad51..8f38bdd30 100644 --- a/libmcount/dynamic.c +++ b/libmcount/dynamic.c @@ -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; @@ -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) @@ -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, @@ -365,7 +369,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; @@ -657,10 +661,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) @@ -669,15 +681,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(); @@ -690,24 +698,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) { @@ -752,7 +742,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; } @@ -798,9 +788,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); } From c98e5fa044e2661d6334ddc705a0ceaf9dbdee45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Guidi?= Date: Tue, 4 Apr 2023 09:34:13 -0400 Subject: [PATCH 7/9] dynamic: Init arch-specific structures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trigger architecture specific dynamic initialization when initializing the dynamic instrumentation mechanics. Co-authored-by: Gabriel-Andrew Pollo-Guilbert Signed-off-by: Clément Guidi --- libmcount/dynamic.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libmcount/dynamic.c b/libmcount/dynamic.c index 8f38bdd30..6b8bf4f7e 100644 --- a/libmcount/dynamic.c +++ b/libmcount/dynamic.c @@ -62,6 +62,8 @@ static unsigned min_size; /* disassembly engine for dynamic code patch (for capstone) */ static struct mcount_disasm_engine disasm; +static bool mcount_dynamic_is_initialized; + static struct mcount_orig_insn *create_code(struct Hashmap *map, unsigned long addr) { struct mcount_orig_insn *entry; @@ -249,6 +251,11 @@ __weak void mcount_disasm_finish(struct mcount_disasm_engine *disasm) { } +__weak int mcount_arch_dynamic_init(void) +{ + return -1; +} + __weak int mcount_arch_branch_table_size(struct mcount_disasm_info *info) { return 0; @@ -683,6 +690,13 @@ static int do_dynamic_update(struct uftrace_sym_info *sinfo, char *patch_funcs, /* TODO: filter out unsupported libs */ for (mdi = mdinfo; mdi != NULL; mdi = mdi->next) { + if (mdi->type == DYNAMIC_NONE && !mcount_dynamic_is_initialized) { + if (mcount_arch_dynamic_init() >= 0) + mcount_dynamic_is_initialized = true; + else + continue; + } + map = mdi->map; if (mdi->trampoline) patch_func_matched(mdi, map); From 0646d28bdb005308dcb9c9b497ffb113a134b466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Guidi?= Date: Mon, 19 Jun 2023 12:50:40 -0400 Subject: [PATCH 8/9] dynamic: Save original instructions only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't save instructions if they are already present in the code hmap. Signed-off-by: Clément Guidi --- libmcount/dynamic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libmcount/dynamic.c b/libmcount/dynamic.c index 6b8bf4f7e..462f1b3c9 100644 --- a/libmcount/dynamic.c +++ b/libmcount/dynamic.c @@ -105,6 +105,9 @@ void mcount_save_code(struct mcount_disasm_info *info, unsigned call_size, void struct mcount_orig_insn *orig; int patch_size; + if (hashmap_get(code_hmap, (void *)info->addr + call_size)) + return; + if (unlikely(info->modified)) { /* it needs to save original instructions as well */ int orig_size = ALIGN(info->orig_size, 16); From e4ad5a38be84305ab79f8b33a3eb24745ea330ad Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl <43588962+bernhardkaindl@users.noreply.github.com> Date: Fri, 24 Nov 2023 10:00:00 +0100 Subject: [PATCH 9/9] =?UTF-8?q?Rebased=20Cl=C3=A9ment=20Guidi's=20PR#1702?= =?UTF-8?q?=20to=20master=20(without=20changes)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commands used: gh pr checkout 1702 git switch -c new-branch git rebase master # (no warnings, no conflicts) git push Signed-off-by: Bernhard Kaindl <43588962+bernhardkaindl@users.noreply.github.com>