Fangrui Song dc2cf4ca86 perf unwind: Fix segbase for ld.lld linked objects
segbase is the address of .eh_frame_hdr and table_data is segbase plus
the header size. find_proc_info computes segbase as `map->start +
segbase - map->pgoff` which is wrong when

* .eh_frame_hdr and .text are in different PT_LOAD program headers
* and their p_vaddr difference does not equal their p_offset difference

Since 10.0, ld.lld's default --rosegment -z noseparate-code layout has
such R and RX PT_LOAD program headers.

    ld.lld (default) => perf report fails to unwind `perf record
    --call-graph dwarf` recorded data
    ld.lld --no-rosegment => ok (trivial, no R PT_LOAD)
    ld.lld -z separate-code => ok but by luck: there are two PT_LOAD but
    their p_vaddr difference equals p_offset difference

    ld.bfd -z noseparate-code => ok (trivial, no R PT_LOAD)
    ld.bfd -z separate-code (default for Linux/x86) => ok but by luck:
    there are two PT_LOAD but their p_vaddr difference equals p_offset
    difference

To fix the issue, compute segbase as dso's base address plus
PT_GNU_EH_FRAME's p_vaddr. The base address is computed by iterating
over all dso-associated maps and then subtract the first PT_LOAD p_vaddr
(the minimum guaranteed by generic ABI) from the minimum address.

In libunwind, find_proc_info transitively called by unw_step is cached,
so the iteration overhead is acceptable.

Reported-by: Sebastian Ullrich <sebasti@nullri.ch>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Fangrui Song <maskray@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: llvm@lists.linux.dev
Link: https://github.com/ClangBuiltLinux/linux/issues/1646
Link: https://lore.kernel.org/r/20220527182039.673248-1-maskray@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2022-06-03 21:20:25 +02:00
..
2022-01-12 17:01:38 -08:00
2019-02-19 16:11:56 -03:00
2022-02-14 16:47:13 -03:00
2022-01-12 14:28:23 -03:00
2021-09-03 08:15:10 -03:00
2021-04-29 10:30:58 -03:00
2022-05-23 10:11:39 -03:00
2022-05-23 10:11:39 -03:00
2021-08-11 09:35:44 -03:00
2021-08-11 09:35:44 -03:00
2022-01-12 14:28:23 -03:00
2022-01-12 14:28:23 -03:00
2022-05-23 10:18:38 -03:00
2022-04-11 16:37:26 -03:00
2021-11-07 12:27:38 -03:00
2021-02-03 13:10:44 -03:00
2021-07-15 17:30:22 -03:00
2022-05-23 10:18:38 -03:00
2022-05-23 10:18:38 -03:00
2022-02-14 16:56:32 -03:00
2022-02-11 14:05:49 -03:00
2021-11-07 12:27:38 -03:00
2022-05-23 10:18:38 -03:00
2020-10-14 13:34:26 -03:00
2021-02-17 15:15:06 -03:00
2021-02-17 15:15:06 -03:00
2020-04-18 09:05:01 -03:00
2020-04-18 09:05:01 -03:00
2022-02-15 17:15:29 -03:00