Changes in V2: - Updated mailing list distribution
Fedora 37 distributed shared binary and executable mapped files show a zero text section offset. Starting with the Fedora 38 distribution, the shared binary and executable mapped files show a non-zero text section offset for some binaries. The text offset parameter is never passed into the arm-cs-trace-disasm.py script to allow the script to adjust the start/end address range passed to objdump. This adjustment is required to correctly offset into the dso text section. Not doing so results in an incorrect user instruction trace display for Fedora 38 (and later) user trace output.
Steve Clevenger (5): Add dso__is_pie call to identify ELF PIE Add dso__is_pie prototype Force MAPPING_TYPE__IDENTIY for PIE Add map pgoff to python dictionary based on MAPPING_TYPE Adjust objdump start/end range per map pgoff parameter
.../scripts/python/arm-cs-trace-disasm.py | 17 +++++- tools/perf/util/map.c | 5 +- .../scripting-engines/trace-event-python.c | 13 +++- tools/perf/util/symbol-elf.c | 60 +++++++++++++++++++ tools/perf/util/symbol.h | 1 + 5 files changed, 90 insertions(+), 6 deletions(-)
Changes in V2: - Updated mailing list distribution
Extract map_pgoff parameter from the dictionary, and adjust start/end range passed to objdump based on the value.
The start_addr/stop_addr address checks are changed to print a warning only if verbose == True. This script repeatedly sees a zero value passed in for start_addr = cpu_data[str(cpu) + 'addr']
These zero values are not a new problem. The start_addr/stop_addr warning clutters the instruction trace output, hence this change.
Signed-off-by: Steve Clevenger scclevenger@os.amperecomputing.com --- .../perf/scripts/python/arm-cs-trace-disasm.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/tools/perf/scripts/python/arm-cs-trace-disasm.py b/tools/perf/scripts/python/arm-cs-trace-disasm.py index d973c2baed1c..6bf806078f9a 100755 --- a/tools/perf/scripts/python/arm-cs-trace-disasm.py +++ b/tools/perf/scripts/python/arm-cs-trace-disasm.py @@ -187,6 +187,7 @@ def process_event(param_dict): dso_start = get_optional(param_dict, "dso_map_start") dso_end = get_optional(param_dict, "dso_map_end") symbol = get_optional(param_dict, "symbol") + map_pgoff = get_optional(param_dict, "map_pgoff")
cpu = sample["cpu"] ip = sample["ip"] @@ -250,13 +251,25 @@ def process_event(param_dict): return
if (start_addr < int(dso_start) or start_addr > int(dso_end)): - print("Start address 0x%x is out of range [ 0x%x .. 0x%x ] for dso %s" % (start_addr, int(dso_start), int(dso_end), dso)) + if (options.verbose == True): + print("Start address 0x%x is out of range [ 0x%x .. 0x%x ] for dso %s" % (start_addr, int(dso_start), int(dso_end), dso)) return
if (stop_addr < int(dso_start) or stop_addr > int(dso_end)): - print("Stop address 0x%x is out of range [ 0x%x .. 0x%x ] for dso %s" % (stop_addr, int(dso_start), int(dso_end), dso)) + if (options.verbose == True): + print("Stop address 0x%x is out of range [ 0x%x .. 0x%x ] for dso %s" % (stop_addr, int(dso_start), int(dso_end), dso)) return
+ if map_pgoff != None and map_pgoff != '[unknown]': + if (dso == "[kernel.kallsyms]"): + dso_vm_start = 0 + map_pgoff = '[unknown]' + else: + dso_vm_start = int(dso_start) + start_addr += map_pgoff + stop_addr += map_pgoff + map_pgoff = '[unknown]' + if (options.objdump_name != None): # It doesn't need to decrease virtual memory offset for disassembly # for kernel dso and executable file dso, so in this case we set
Changes in V2: - Updated mailing list distribution
Add map_pgoff parameter to python dictionary so it can be seen by the python script, arm-cs-trace-disasm.py. map_pgoff is forced to zero in the dictionary if file type is MAPPING_TYPE__IDENTITY. Otherwise, the map_pgoff value is directly added to the dictionary.
Signed-off-by: Steve Clevenger scclevenger@os.amperecomputing.com --- .../util/scripting-engines/trace-event-python.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index fb00f3ad6815..8a056c3574ec 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -798,7 +798,8 @@ static int set_regs_in_dict(PyObject *dict, static void set_sym_in_dict(PyObject *dict, struct addr_location *al, const char *dso_field, const char *dso_bid_field, const char *dso_map_start, const char *dso_map_end, - const char *sym_field, const char *symoff_field) + const char *sym_field, const char *symoff_field, + const char *map_pgoff) { char sbuild_id[SBUILD_ID_SIZE];
@@ -814,6 +815,12 @@ static void set_sym_in_dict(PyObject *dict, struct addr_location *al, PyLong_FromUnsignedLong(map__start(al->map))); pydict_set_item_string_decref(dict, dso_map_end, PyLong_FromUnsignedLong(map__end(al->map))); + if (al->map->mapping_type == MAPPING_TYPE__DSO) + pydict_set_item_string_decref(dict, map_pgoff, + PyLong_FromUnsignedLongLong(al->map->pgoff)); + else + pydict_set_item_string_decref(dict, map_pgoff, + PyLong_FromUnsignedLongLong(0)); } if (al->sym) { pydict_set_item_string_decref(dict, sym_field, @@ -898,7 +905,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, pydict_set_item_string_decref(dict, "comm", _PyUnicode_FromString(thread__comm_str(al->thread))); set_sym_in_dict(dict, al, "dso", "dso_bid", "dso_map_start", "dso_map_end", - "symbol", "symoff"); + "symbol", "symoff", "map_pgoff")
pydict_set_item_string_decref(dict, "callchain", callchain);
@@ -923,7 +930,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, PyBool_FromLong(1)); set_sym_in_dict(dict_sample, addr_al, "addr_dso", "addr_dso_bid", "addr_dso_map_start", "addr_dso_map_end", - "addr_symbol", "addr_symoff"); + "addr_symbol", "addr_symoff", "map_pgoff"); }
if (sample->flags)
Changes in V2: - Updated mailing list distribution
Use dso__is_pie() to check whether the DSO file is a Position Independent Executable (PIE). If PIE, change the MAPPING_TYPE to MAPPING_TYPE__IDENTITY so a zero map pgoff (text offset) is passed into the script.
Signed-off-by: Steve Clevenger scclevenger@os.amperecomputing.com --- tools/perf/util/map.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index e1d14936a60d..df7c06fc373e 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -171,8 +171,11 @@ struct map *map__new(struct machine *machine, u64 start, u64 len, assert(!dso__kernel(dso)); map__init(result, start, start + len, pgoff, dso);
+ if (map->pgoff && !no_dso) + no_dso = dso__is_pie(dso); // PIE check + if (anon || no_dso) { - map->mapping_type = MAPPING_TYPE__IDENTITY; + map__set_mapping_type(map, MAPPING_TYPE__IDENTITY);
/* * Set memory without DSO as loaded. All map__find_*
Changes in V2: - Updated mailing list distribution
Add prototype to dso__is_pie() global.
Signed-off-by: Steve Clevenger scclevenger@os.amperecomputing.com --- tools/perf/util/symbol.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 3fb5d146d9b1..33ea2596ce31 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -127,6 +127,7 @@ void dso__insert_symbol(struct dso *dso, struct symbol *sym); void dso__delete_symbol(struct dso *dso, struct symbol *sym); +bool dso__is_pie(struct dso *dso);
struct symbol *dso__find_symbol(struct dso *dso, u64 addr); struct symbol *dso__find_symbol_nocache(struct dso *dso, u64 addr);