From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18882 invoked by alias); 25 Nov 2014 22:10:04 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 18866 invoked by uid 89); 25 Nov 2014 22:10:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_LOW,SPF_PASS,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mail-vc0-f170.google.com Received: from mail-vc0-f170.google.com (HELO mail-vc0-f170.google.com) (209.85.220.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 25 Nov 2014 22:10:01 +0000 Received: by mail-vc0-f170.google.com with SMTP id hy4so735523vcb.29 for ; Tue, 25 Nov 2014 14:09:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc:content-type; bh=wR/ZEqgdmGrl9JmQ+StsGEa9nxC3faIvmXPmxgcr1gU=; b=VMj6lq/wjcuNNBArNe45/3q8NXCG2CgC4qPNYCSEkg8mMlqBJdp75zcvMm44SyZzlc 9FrTyJQZlSU5idB1hYra+9lHwVEWcxEFLG/P+x9aCTqOsPuE/g03ulLS5oEBdKlSC6qz ESUu0ANxSqvbgKiCTYnh/DyPd/4oW43ImB2o/tNlE5xKXEXOwOeoJXmVgzcPzSvlfw3A Jht1DNeE6zJ4OA3fl+hE6Jso5a6ghxPr4mPjZiiP6Ua0N3GTCDUHdClR0HSK2U7rBwHt izN5KpkPE05/MLdGW8j7+K+w/uAKM7TorEPo3woD3/GTXr5NYoj88U0AQbV5zo++VGca UhUg== X-Gm-Message-State: ALoCoQk3m/jNeDxdBpWLrU6588Qsz/lBzwHKp0lt/pOnerZ2RdLyPVB3vhAcs2nWTKl15SSyMJ1U MIME-Version: 1.0 X-Received: by 10.52.29.172 with SMTP id l12mr5290811vdh.33.1416953399246; Tue, 25 Nov 2014 14:09:59 -0800 (PST) Received: by 10.52.114.101 with HTTP; Tue, 25 Nov 2014 14:09:59 -0800 (PST) In-Reply-To: References: Date: Tue, 25 Nov 2014 22:10:00 -0000 Message-ID: Subject: Re: [RFC] While processing a struct die, store the method's address in its fn_field From: Doug Evans To: Siva Chandra Cc: gdb-patches Content-Type: text/plain; charset=UTF-8 X-IsSubscribed: yes X-SW-Source: 2014-11/txt/msg00633.txt.bz2 On Tue, Nov 25, 2014 at 7:00 AM, Siva Chandra wrote: > On Mon, Nov 24, 2014 at 12:22 PM, Doug Evans wrote: >> Adding new fields to types or symbols is a big deal. >> I'd like to understand why things are failing better. >> For normal functions gdb gets the start address >> from BLOCK_START (SYMBOL_BLOCK_VALUE (sym)). > > I will try, but tl;dr. > > Consider a simple class definition like this which has a method which > is not inlined: > > class A > { > public: > int method (int a); > }; > > int > A::method (int a) > { > return a * a; > } > > The DWARF for the class comes out like this: > > < 1><0x0000002d> DW_TAG_class_type > DW_AT_name "A" > DW_AT_byte_size 0x00000001 > DW_AT_decl_file 0x00000001 /tmp > DW_AT_decl_line 0x00000001 > DW_AT_sibling <0x00000057> > < 2><0x00000037> DW_TAG_subprogram > DW_AT_external yes(1) > DW_AT_name "method" > DW_AT_decl_file 0x00000001 /tmp > DW_AT_decl_line 0x00000004 > DW_AT_linkage_name "_ZN1A6methodEi" > DW_AT_type <0x00000057> > DW_AT_accessibility DW_ACCESS_public > DW_AT_declaration yes(1) > DW_AT_object_pointer <0x0000004b> > < 3><0x0000004b> DW_TAG_formal_parameter > DW_AT_type <0x0000005e> > DW_AT_artificial yes(1) > < 3><0x00000050> DW_TAG_formal_parameter > DW_AT_type <0x00000057> > > Notice that there is a linkage name for the method named "method". So, > one can demangle the linkage name and get to the symbol. If this > fails, one can use the linkage name to get to the minsym. The issue > with lambdas is that their operator() methods do not have a linkage > name. Not exactly true: they have a linkage name but the DWARF doesn't > specify it. Consider this example: > > $> cat lambda.cc > > int > main () > { > auto lambda = [] (int j) { return j + 113; }; > return lambda (-113); > } > > $> g++ -g -std=c++11 lambda.cc -o lambda > > The DWARF for the lambda struct come out like this: > > < 3><0x00000070> DW_TAG_structure_type > DW_AT_name "" > DW_AT_byte_size 0x00000001 > DW_AT_decl_file 0x00000001 /tmp > DW_AT_decl_line 0x00000004 > < 4><0x00000078> DW_TAG_subprogram > DW_AT_name "" > DW_AT_artificial yes(1) > DW_AT_declaration yes(1) > DW_AT_object_pointer <0x00000085> > DW_AT_sibling <0x0000009c> > < 5><0x00000085> DW_TAG_formal_parameter > DW_AT_type <0x0000008a> > DW_AT_artificial yes(1) > < 5><0x0000008a> DW_TAG_pointer_type > DW_AT_byte_size 0x00000008 > DW_AT_type <0x00000070> > < 5><0x00000090> DW_TAG_formal_parameter > DW_AT_type <0x00000095> > < 5><0x00000095> DW_TAG_rvalue_reference_type > DW_AT_byte_size 0x00000008 > DW_AT_type <0x00000070> > < 4><0x0000009c> DW_TAG_subprogram > DW_AT_name "" > DW_AT_artificial yes(1) > DW_AT_declaration yes(1) > DW_AT_object_pointer <0x000000a9> > DW_AT_sibling <0x000000bf> > < 5><0x000000a9> DW_TAG_formal_parameter > DW_AT_type <0x0000008a> > DW_AT_artificial yes(1) > < 5><0x000000ae> DW_TAG_formal_parameter > DW_AT_type <0x000000b3> > < 5><0x000000b3> DW_TAG_reference_type > DW_AT_byte_size 0x00000008 > DW_AT_type <0x000000b9> > < 5><0x000000b9> DW_TAG_const_type > DW_AT_type <0x00000070> > < 4><0x000000bf> DW_TAG_subprogram > DW_AT_name "" > DW_AT_artificial yes(1) > DW_AT_declaration yes(1) > yes(1) > DW_AT_object_pointer <0x000000cc> > DW_AT_sibling <0x000000d2> > < 5><0x000000cc> DW_TAG_formal_parameter > DW_AT_type <0x0000008a> > DW_AT_artificial yes(1) > < 4><0x000000d2> DW_TAG_subprogram > DW_AT_name "~" > DW_AT_artificial yes(1) > DW_AT_declaration yes(1) > DW_AT_object_pointer <0x000000df> > DW_AT_sibling <0x000000ea> > < 5><0x000000df> DW_TAG_formal_parameter > DW_AT_type <0x0000008a> > DW_AT_artificial yes(1) > < 5><0x000000e4> DW_TAG_formal_parameter > DW_AT_type <0x0000002d> > DW_AT_artificial yes(1) > < 4><0x000000ea> DW_TAG_subprogram > DW_AT_name "operator()" > DW_AT_type <0x0000002d> > DW_AT_artificial yes(1) > DW_AT_low_pc 0x00400566 > DW_AT_high_pc 19 > DW_AT_frame_base len 0x0001: > 9c: DW_OP_call_frame_cfa > DW_AT_object_pointer <0x0000010f> > DW_AT_GNU_all_call_sites yes(1) > < 5><0x00000109> DW_TAG_pointer_type > DW_AT_byte_size 0x00000008 > DW_AT_type <0x000000b9> > < 5><0x0000010f> DW_TAG_formal_parameter > DW_AT_name "__closure" > DW_AT_type <0x0000011b> > DW_AT_artificial yes(1) > DW_AT_location len 0x0002: > 9168: DW_OP_fbreg -24 > < 5><0x0000011b> DW_TAG_const_type > DW_AT_type <0x00000109> > < 5><0x00000120> DW_TAG_formal_parameter > DW_AT_name "j" > DW_AT_decl_file 0x00000001 /tmp > DW_AT_decl_line 0x00000004 > DW_AT_type <0x0000002d> > DW_AT_location len 0x0002: > 9164: DW_OP_fbreg -28 > > Notice that the operator() method has no linkage name specified in the > DWARF. But, it has a DW_AT_low_pc. Lets grep the binary for this low > pc value: > > $> readelf -a lambda | grep 400566 > 41: 0000000000400566 19 FUNC LOCAL DEFAULT 12 _ZZ4mainENKUliE_clEi > > So then, there is an ELF symbol for the operator() method! Lets > demangle the name: > > (gdb) maintenance demangle _ZZ4mainENKUliE_clEi > main::{lambda(int)#1}::operator()(int) const > > This name is not the same as the name of the lambda structure given by > DWARF! If I use clang to compile, the demangled ELF symbol for the > operator() turns out to be "main::$_0::operator()(int) const", which > seems to indicate that gcc and clang have their own way of > differentiating the different lambdas that can occur in a CU. Hence, > GDB should probably not even attempt to generate a name, mangle it and > lookup for a symbol with that name. However, low_pc is immediately > available in the DWARF generated by GCC, so why not use it? For functions/methods gdb already uses lowpc as the start address. [IOW it doesn't use the linkage name, though even recently I'd forgotten this and thought otherwise. Also, GDB doesn't take a demangled name, mangle it, and then try to look that up in the ELF symbol table.] If I do "mt print symbols foo.sym", then I see this: Symtab for file lambda.cc Compilation directory is /home/dje/src/play Read from object file /home/dje/ruffies-copy/src/play/lambda.x64 (0x288bf00) Language: c++ Line table: line 6 at 0x4006a6 line 6 at 0x4006b1 line 5 at 0x4006b9 line 7 at 0x4006c1 line 8 at 0x4006d3 line 0 at 0x4006d5 Blockvector: block #000, object at 0x277ee90, 1 syms/buckets in 0x4006a6..0x4006d5 int main(); block object 0x277edc0, 0x4006b9..0x4006d5 section .text block #001, object at 0x277ee20 under 0x277ee90, 1 syms/buckets in 0x4006a6..0x4006d5 typedef int int; block #002, object at 0x277ec80 under 0x277ed50, 3 syms/buckets in 0x4006a6..0x4006b9, function ::operator()(int) const int ::operator()(int) const; block object 0x277ec80, 0x4006a6..0x4006b9 const struct { } * const __closure; computed at runtime int j; computed at runtime block #003, object at 0x277edc0 under 0x277ee20, 0 syms/buckets in 0x4006b9..0x4006d5, function main() block #004, object at 0x277ed50 under 0x277edc0, 1 syms/buckets in 0x4006c1..0x4006d3 struct { } lambda; computed at runtime struct { }; Note that there is a block for "function <::operator()(int) const>" with a start address of 0x4006a6. (gdb) ! nm lambda.x64 | grep ZZ4 00000000004006a6 t _ZZ4mainENKUliE_clEi So I think(!) the existing mechanism of using BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) should work here, we just need to make sure the various pieces are glued together. But we don't AFAICT need a new field to record low_pc, it is already recorded. > [Clang > actually does not put out the low pc value for the subprogram die > under a structure die, but it puts out a separate (not under a > structure die) subprogram die for the operator() method with the low > pc value.] DWARF can be hard to read at times. Note that GCC can do this too. E.g., It will output a declaration in the proper context (e.g., inside a class definition for a method) without DW_AT_low_pc and then it will output another DIE at the top level with DW_AT_low_pc and with a DW_AT_specification referring back to previous DIE in its context.