Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752390AbbDBFTj (ORCPT ); Thu, 2 Apr 2015 01:19:39 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:18716 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750973AbbDBFTi (ORCPT ); Thu, 2 Apr 2015 01:19:38 -0400 Message-ID: <551CD15C.5070605@huawei.com> Date: Thu, 2 Apr 2015 13:19:24 +0800 From: Wang Nan User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Thunderbird/24.0.1 MIME-Version: 1.0 To: Ingo Molnar CC: , , , , , , Subject: Re: [PATCH] perf: unwind: fix segbase for libunwind. References: <1427897332-145581-1-git-send-email-wangnan0@huawei.com> <20150401144839.GA17340@gmail.com> <551CCE8B.5060704@huawei.com> In-Reply-To: <551CCE8B.5060704@huawei.com> Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.111.69.129] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 11158 Lines: 292 On 2015/4/2 13:07, Wang Nan wrote: > On 2015/4/1 22:48, Ingo Molnar wrote: >> >> * Wang Nan wrote: >> >>> Perf passes incorrect segbase and table_data to libunwind when >>> map->pgoff != 0, causes unwind failure. This patch fixes this >>> problem. >>> >>> segbase is an absolute offset from the head of object file, directly >>> read from ELF file. Original code computes corresponding virtual >>> address using map->start + segbase, doesn't consider map->pgoff. >>> Which causes libunwind read from incorrect offset. >> >> What's the effect of this bug in practice? >> >> Is there any before/after output you can show that demonstrates the >> fix? >> > > I found the problem when testing my '--map-adjustment' argument. I tried to > construct a test case for normal case, but it seems triggers futher bugs. > > Following is the reproducing steps. The first two > > Step 1: create a C file like this (libtest-load.c): > > --------test-load.c----------- > #define DATA_SZ 65535 > int data[DATA_SZ] = {1,1,2,3,5,8,13,}; > > int fib(int x) > { > if (x >= DATA_SZ) > return -1; > if ((x == 0) || (x == 1)) > return 1; > data[x] = fib(x - 1) + fib(x - 2); > return data[x]; > } > ---------------------- > > Step 2: create a shared object with folowing ld-script (test-load.lds) using: > > $ gcc -shared -fPIC ./test-load.c -Wl,-T./test-load.lds -O0 -o libtest-load.so > > --------------test-load.lds--------------- > SECTIONS > { > .note.gnu.build-id : { *(.node.*) } :text > .gnu.hash : { *(.gnu.hash) } :text > .dynsym : { *(.dynsym) } :text > .dynstr : { *(.dynstr) } :text > .gnu.version : { *(.gnu.version) } :text > .gnu.version_r : { *(.gnu.version_r) } :text > .rela.dyn : { *(.rela.dyn) } :text > .rela.plt : { *(.rela.plt) } :text > .init : { *(.init) } :text > .plt : { *(.plt) } :text > .text : { *(.text) } :text > .fini : { *(.fini) } :text > .eh_frame_hdr : { *(.eh_frame_hdr) } :text > .eh_frame : { *(.eh_frame) } :text > > .ctors : { *(.ctors) } :data > .dtors : { *(.dtors) } :data > .jcr : { *(.jcr) } :data > .got : { *(.got) } :data > .got.plt : { *(.got.plt) } :data > .data : { *(.data) } :data > .bss : { *(.bss) } :data > .dynamic : { *(.dynamic) } :dynamic > > } > > PHDRS > { > text PT_LOAD FLAGS(7); > data PT_LOAD FLAGS(7); > dynamic PT_DYNAMIC FLAGS(7); > note PT_NOTE FLAGS(4); > } > ----------------------------- > > In my environment, I get a shared object with: > > $ readelf -l ./libtest-load.so > > Elf file type is DYN (Shared object file) > Entry point 0x390 > There are 4 program headers, starting at offset 64 > > Program Headers: > Type Offset VirtAddr PhysAddr > FileSiz MemSiz Flags Align > LOAD 0x0000000000200000 0x0000000000000000 0x0000000000000000 > 0x00000000000005c4 0x00000000000005c4 RWE 200000 > LOAD 0x00000000002005c8 0x00000000000005c8 0x00000000000005c8 > 0x00000000000400a0 0x00000000000400b0 RWE 200000 > DYNAMIC 0x0000000000240678 0x0000000000040678 0x0000000000040678 > 0x0000000000000180 0x0000000000000180 RWE 8 > NOTE 0x0000000000000000 0x0000000000000000 0x0000000000000000 > 0x0000000000000000 0x0000000000000000 R 8 > > Section to Segment mapping: > Segment Sections... > 00 .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.plt .init .plt .text .fini .eh_frame_hdr .eh_frame .rela.dyn .note.gnu.build-id > 01 .ctors .dtors .jcr .got .got.plt .data .data.rel .bss > 02 .dynamic > 03 > > The goal of the first 2 steps is to create a shared object which will be mmap-ed with > pgoff != 0 (offset of a PT_LOAD segment != 0). I'm not sure which part of the ld scripts > leads to this, so I paste all of them. > > Step 3: Use that shared object: compile following C file using: > > $ gcc ./test.c -O0 -ltest-load -L. > > --------- test.c --------- > #include > extern int fib(int x); > int main() > { > printf("%d\n", fib(30)); > return 0; > } > ----------------- > > Step 4: perf record: > > $ perf record -g --call-graph=dwarf ./a.out > > Step 5: perf report: > > $ perf report --stdio --no-children > > # To display the perf.data header info, please use --header/--header-only options. > # > # Samples: 40 of event 'cycles' > # Event count (approx.): 28432005 > # > # Overhead Command Shared Object Symbol > # ........ ....... ................ ...................... > # > 18.40% a.out libtest-load.so [.] 0x00000000002004ee > | > ---0x7f17127964ee > > 16.85% a.out libtest-load.so [.] 0x00000000002004bf > | > ---0x7f17127964bf > > 15.20% a.out libtest-load.so [.] 0x00000000002004c2 > | > ---0x7f17127964c2 > > 9.33% a.out libtest-load.so [.] 0x000000000020049c > | > ---0x7f171279649c > > > Perf failed to extract symbol name and also failed to unwind. > > > With my patch, perf unwind works: > > # > # Overhead Command Shared Object Symbol > # ........ ....... ................ ...................... > # > 18.40% a.out libtest-load.so [.] 0x00000000002004ee > | > ---0x7f17127964ee > | > |--50.52%-- 0x7f17127964cc > | | > | |--64.45%-- 0x7f17127964cc > | | 0x7f17127964db > | | | > | | |--98.69%-- 0x7f17127964db > | | | | > | | | |--93.86%-- 0x7f17127964db > | | | | 0x7f17127964cc > | | | | 0x7f17127964cc > | | | | 0x7f17127964cc > | | | | 0x7f17127964db > | | | | 0x7f17127964cc > | | | | 0x7f17127964cc > | | | | 0x7f17127964cc > | | | | 0x7f17127964db > | | | | 0x7f17127964cc > | | | | 0x7f17127964db > | | | | 0x7f17127964cc > | | | | 0x7f17127964cc > | | | | 0x7f17127964db > | | | | 0x7f17127964db > | | | | 0x7f17127964cc > | | | | main > | | | | __libc_start_main > | | | | _start > | | | | > | | | --6.14%-- 0x7f17127964cc > > However, still unable to find symbol names. > >> Thanks, >> >> Ingo >> > Additional information: With following patch it seems to work: diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 476268c..1177f02 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1049,8 +1049,10 @@ new_symbol: if (demangled != NULL) elf_name = demangled; } - f = symbol__new(sym.st_value, sym.st_size, + f = symbol__new(sym.st_value + map->pgoff, sym.st_size, GELF_ST_BIND(sym.st_info), elf_name); free(demangled); if (!f) goto out_elf_end; result: Overhead Command Shared Object Symbol # ........ ....... ................ ...................... # 86.37% a.out libtest-load.so [.] fib | ---fib fib fib fib fib fib fib fib fib fib fib fib fib fib | |--94.35%-- fib | fib | | | |--93.42%-- fib | | | | | |--93.12%-- fib | | | fib | | | | | | | |--84.90%-- fib | | | | | | | | | |--74.34%-- fib | | | | | | | | | | | |--90.56%-- fib | | | | | | | | | | | | | |--57.37%-- fib | | | | | | | | | | | | | | | |--83.51%-- main | | | | | | | | __libc_start_main | | | | | | | | _start | | | | | | | | | | | | | | | --16.49%-- fib | | | | | | | main | | | | | | | __libc_start_main | | | | | | | _start ... However, I think this is only a temporary solutsion. What we need is to obay both Offset and VirtAddr in PHDR. Thank you. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/