[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 pmderodat at gcc dot gnu.org changed: What|Removed |Added Status|NEW |RESOLVED CC||pmderodat at gcc dot gnu.org Resolution|--- |FIXED Assignee|unassigned at gcc dot gnu.org |pmderodat at gcc dot gnu.org Target Milestone|--- |6.0 --- Comment #25 from pmderodat at gcc dot gnu.org --- DW_AT_static_link is properly generated after revision 230968.
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #24 from pmderodat at gcc dot gnu.org --- Author: pmderodat Date: Thu Nov 26 14:56:24 2015 New Revision: 230968 URL: https://gcc.gnu.org/viewcvs?rev=230968=gcc=rev Log: DWARF: fix loc. descr. generation for DW_AT_static_link gcc/ChangeLog: PR debug/53927 * tree-nested.c (finalize_nesting_tree_1): Append a field to hold the frame base address. * dwarf2out.c (gen_subprogram_die): Generate for DW_AT_static_link a location description that computes the value of this field. Modified: trunk/gcc/ChangeLog trunk/gcc/dwarf2out.c trunk/gcc/tree-nested.c
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #23 from Eric Botcazou ebotcazou at gcc dot gnu.org --- The offset between the CFA and e FRAME object is now 0x90 bytes. So because of alignment constraints, I think we cannot assume we can have a constant offset (even function-dependent). This offset is dynamic and the only way to compute it is to use the frame's context: here, nestee's saved registers, which we don't have access to in DWARF when computing the static link attribute. OK, thanks for the investigation, the counter-example is quite telling and puts an end to this approach. To rescue some of this work, you could add a line to the comment in the finalize_nesting_tree_1 hunk, explaining that we need to go through the BUILT_IN_DWARF_CFA indirection because the offset of the FRAME object in the stack frame can be dynamic if the FRAME object needs to be more aligned than the stack.
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #21 from Pierre-Marie de Rodat derodat at adacore dot com --- (In reply to Eric Botcazou from comment #18) I think this is worth investigating though because it's conceptually much simpler than adding yet another indirection. And we should concentrate on -O0 (and -Og), we don't really care about what happens with aggressive optimization. Understood and agreed. Nevertheless... I guess the question is: can we arrange to have a constant offset between the frame base and the FRAME object, constant meaning valid for every function but possibly target-dependent? I started to hack into cfgexpand.c and dwarf2out.c, but I realized this is not possible in the general case. Consider the following example: #include stdlib.h int nestee (void) { int a __attribute__((aligned(64))) = 1234; void nested (int b) { a = b; } nested (2345); return a; } int call_nestee (int n) { int *v = alloca (sizeof (int) * n); v[0] = nestee (); return v[0]; } int main (void) { call_nestee (1); call_nestee (8); return 0; } With a GCC 5.0 built from fairly recent sources, I get the following CFA information: 0090 002c 0064 FDE cie=0030 pc=004004ac..004004eb DW_CFA_advance_loc: 5 to 004004b1 DW_CFA_def_cfa: r10 (r10) ofs 0 DW_CFA_advance_loc: 9 to 004004ba DW_CFA_expression: r6 (rbp) (DW_OP_breg6 (rbp): 0) DW_CFA_advance_loc: 5 to 004004bf DW_CFA_def_cfa_expression (DW_OP_breg6 (rbp): -8; DW_OP_deref) DW_CFA_advance_loc: 38 to 004004e5 And now here is what I get under GDB: $ gdb -n -q -ex 'b nestee' ./dyn_frame Reading symbols from ./dyn_frame...done. Breakpoint 1 at 0x4004c3: file dyn_frame.c, line 6. (gdb) r [...] Breakpoint 1, nestee () at dyn_frame.c:6 6 int a __attribute__((aligned(64))) = 1234; (gdb) p $pc $1 = (void (*)()) 0x4004c3 nestee+23 (gdb) x/1xg $rbp - 8 0x7fffdf28: 0x7fffdf60 (gdb) p/x (char *) 0x7fffdf60 - (char *) a $2 = 0xa0 ... so for this frame, the CFA and the FRAME object are 0xa0 bytes from each other. Now let's resume to see the next nestee frame: (gdb) c Continuing. Breakpoint 1, nestee () at dyn_frame.c:6 6 int a __attribute__((aligned(64))) = 1234; (gdb) p $pc $3 = (void (*)()) 0x4004c3 nestee+23 (gdb) x/1xg $rbp - 8 0x7fffdf28: 0x7fffdf50 (gdb) p/x (char *) 0x7fffdf50 - (char *) a $4 = 0x90 The offset between the CFA and e FRAME object is now 0x90 bytes. So because of alignment constraints, I think we cannot assume we can have a constant offset (even function-dependent). This offset is dynamic and the only way to compute it is to use the frame's context: here, nestee's saved registers, which we don't have access to in DWARF when computing the static link attribute.
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #22 from Pierre-Marie de Rodat derodat at adacore dot com --- (In reply to Tom Tromey from comment #20) Yeah. There wasn't much point submitting it when it wouldn't work anyhow :} Also see the README.archer file. It explains some changes that are needed. Also I remember thinking that the dwarf locexpr baton changes needed some update, but I no longer recall what. I see now that I recorded my thoughts in the commit messages. Yay me! Great, thank you for this!
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #20 from Tom Tromey tromey at gcc dot gnu.org --- Yeah. There wasn't much point submitting it when it wouldn't work anyhow :} Also see the README.archer file. It explains some changes that are needed. Also I remember thinking that the dwarf locexpr baton changes needed some update, but I no longer recall what. I see now that I recorded my thoughts in the commit messages. Yay me!
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #19 from Tom Tromey tromey at gcc dot gnu.org --- (In reply to Pierre-Marie de Rodat from comment #17) (In reply to Tom Tromey from comment #16) I'm curious if you tried it on the test case in this PR. I did not, but it looks like it now works as expected. Great! Thanks very much for trying it. Interesting! Having a look at this: thank you! I guess you waited for the GCC issue to be solved before submitting them to GDB? Yeah. There wasn't much point submitting it when it wouldn't work anyhow :} Also see the README.archer file. It explains some changes that are needed. Also I remember thinking that the dwarf locexpr baton changes needed some update, but I no longer recall what. Feel free to reuse any parts of that branch (or any other gdb branch of mine on gitorious) that you like. All that code was written while I was at Red Hat and so there are no legal barriers to putting it in. Also, btw, this is https://sourceware.org/bugzilla/show_bug.cgi?id=8300
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #18 from Eric Botcazou ebotcazou at gcc dot gnu.org --- Jason suggested to change DW_AT_frame_base in order to make it equal to the address of the FRAME object. I was not sure: 1) how to do it: location descriptions for all local variables would need to be updated; 2) whether it's safe to do this: what if optimizers move/duplicate this FRAME object in the stack frame or do similar disturbing things? I'm not familiar enough with optimization passes to estimate if it's likely: feedback welcome. :-) I thought: why not make DW_AT_static_link compute the parent frame base address from the current static link argument? Well, when generating DW_AT_static_link for a nested subprogram, we do not know yet the offset between the FRAME object and the frame base address. This is because nested subprograms reach the back-end before their parent. Besides, see point 2: are we only sure that such a constant offset exists? I think this is worth investigating though because it's conceptually much simpler than adding yet another indirection. And we should concentrate on -O0 (and -Og), we don't really care about what happens with aggressive optimization. I guess the question is: can we arrange to have a constant offset between the frame base and the FRAME object, constant meaning valid for every function but possibly target-dependent?
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #17 from Pierre-Marie de Rodat derodat at adacore dot com --- (In reply to Tom Tromey from comment #16) I'm curious if you tried it on the test case in this PR. I did not, but it looks like it now works as expected. Here are the frame base info for nestee and the static link info for nested: [nestee] 69 DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) [nested] aa DW_AT_static_link : 6 byte block: 91 60 6 23 20 6(DW_OP_fbreg: -32; DW_OP_deref; DW_OP_plus_uconst: 32; DW_OP_deref) ... and the CFA for the two locations we will be interrested in later: LOC CFA 00400496 rsp+8 00400497 rsp+16 0040049a rbp+16 # A 004004af rsp+8 LOC CFA 0040053b rsp+8 0040053c rsp+16 0040053f rbp+16 # B 00400564 rsp+8 Now in GDB: $ gdb -n -q -ex 'b pr53927.c:7' -ex r --args ./pr53927 [...] Breakpoint 1, nested (nested_arg=10) at pr53927.c:7 7 return nested_arg + 23 + self_call; /* Break here */ (gdb) bt #0 nested (nested_arg=10) at pr53927.c:7 #1 0x0040052b in nestee (computer=0x7fffdf24, arg=10) at pr53927.c:13 #2 0x0040051d in nestee (computer=0x40052d misc, arg=5) at pr53927.c:11 #3 0x0040055e in main (argc=1, argv=0x7fffe058) at pr53927.c:23 (gdb) p $pc $1 = (void (*)()) 0x4004a4 nested+14 # This PC corresponds to the B line above: CFA = $rbp + 16 (gdb) x/1gx $rbp + 16 - 32 0x7fffdea0: 0x7fffdf20 (gdb) x/1gx 0x7fffdf20 + 32 0x7fffdf40: 0x7fffdf60 ... so the static link expression gives us the following frame base address: 0x7fffdf60 (gdb) f 2 #2 0x0040051d in nestee (computer=0x40052d misc, arg=5) at pr53927.c:11 11 arg = nestee (nested, arg + 5, 0); # This PC corresponds to the A line above: CFA = $rbp + 16 (gdb) p/x $rbp + 16 $2 = 0x7fffdf60 So the static link expression correctly yields the frame 2's CFA. Yeah, growing these is to be avoided. My patch for this added a method to symbol_computed_ops instead. Unfortunately gitorious is acting weird so you can't see the patch online :-(. But you can fetch from https://gitorious.org/binutils-gdb/gdb.git and look at the branch static-link-fix if you like. Interesting! Having a look at this: thank you! I guess you waited for the GCC issue to be solved before submitting them to GDB?
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #16 from Tom Tromey tromey at gcc dot gnu.org --- (In reply to Pierre-Marie de Rodat from comment #15) (In reply to Pierre-Marie de Rodat from comment #13) [1] This patch teaches GDB how to use DW_AT_static_link in order to find the frame corresponding to the lexically enclosing scope. I think I will try to submit it to GDB soon. For the record, here it is: https://www.sourceware.org/ml/gdb-patches/2015-03/msg00040.html. I'm curious if you tried it on the test case in this PR. In the patch you wrote: Since I'm not sure of how this issue should be solved, I'm nevertheless posting this patch here so this matter can be discussed. In the context of this feature, I think we need a backlink from all symbols to the corresponding embedding block but on the other hand only a few blocks have static link: maybe we could turn this static_link field into a objfile-based hashtable lookup. Thoughts? Yeah, growing these is to be avoided. My patch for this added a method to symbol_computed_ops instead. Unfortunately gitorious is acting weird so you can't see the patch online :-(. But you can fetch from https://gitorious.org/binutils-gdb/gdb.git and look at the branch static-link-fix if you like.
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #15 from Pierre-Marie de Rodat derodat at adacore dot com --- (In reply to Pierre-Marie de Rodat from comment #13) [1] This patch teaches GDB how to use DW_AT_static_link in order to find the frame corresponding to the lexically enclosing scope. I think I will try to submit it to GDB soon. For the record, here it is: https://www.sourceware.org/ml/gdb-patches/2015-03/msg00040.html.
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #14 from Pierre-Marie de Rodat derodat at adacore dot com --- Created attachment 34868 -- https://gcc.gnu.org/bugzilla/attachment.cgi?id=34868action=edit patch to generate DWARF-compliant DW_AT_static_link attributes gcc/ * tree-nested.c (finalize_nesting_tree_1): Append a field to hold the frame base address. * dwarf2out.c (gen_subprogram_die): Generate for DW_AT_static_link a location description that computes the value of this field.
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 Pierre-Marie de Rodat derodat at adacore dot com changed: What|Removed |Added CC||derodat at adacore dot com --- Comment #13 from Pierre-Marie de Rodat derodat at adacore dot com --- (In reply to Tom Tromey from comment #8) Yes, but you can do something useful even with this value of DW_AT_static_link, albeit not exactly what DWARF means. Regardless, I think GCC should emit correct DWARF. I gave it a try: see the attached patch. Jason suggested to change DW_AT_frame_base in order to make it equal to the address of the FRAME object. I was not sure: 1) how to do it: location descriptions for all local variables would need to be updated; 2) whether it's safe to do this: what if optimizers move/duplicate this FRAME object in the stack frame or do similar disturbing things? I'm not familiar enough with optimization passes to estimate if it's likely: feedback welcome. :-) I thought: why not make DW_AT_static_link compute the parent frame base address from the current static link argument? Well, when generating DW_AT_static_link for a nested subprogram, we do not know yet the offset between the FRAME object and the frame base address. This is because nested subprograms reach the back-end before their parent. Besides, see point 2: are we only sure that such a constant offset exists? So instead, I patched tree-nested.c in order to append a field at the end of the FRAME object to hold the frame base address (computed with the DWARF_CFA builtin). Then, dwarf2out.c just has to emit a location description for nested subprograms' DW_AT_static_link that fetches this using the static link argument. It's consuming a little stack space, I'm not sure if it's a problem. Once again: feedback welcome! Besides, this does not work yet with Fortran since for this front-end, the DWARF_CFA builtin is not registered. None of builtins.def are registered by the way: how could I register only this one without duplicating code? Is it a good idea anyway? For the record, I bootstrapped and reg-tested this patch on x86_64-linux and preliminary manual testing with a patched GDB[1] and Ada reproducers shows that this approach is working. Thoughts? [1] This patch teaches GDB how to use DW_AT_static_link in order to find the frame corresponding to the lexically enclosing scope. I think I will try to submit it to GDB soon.
[Bug debug/53927] wrong value for DW_AT_static_link
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #12 from Eric Botcazou ebotcazou at gcc dot gnu.org --- Author: ebotcazou Date: Fri Jun 6 08:13:24 2014 New Revision: 211308 URL: http://gcc.gnu.org/viewcvs?rev=211308root=gccview=rev Log: PR debug/53927 * function.c (instantiate_decls): Process the saved static chain. (expand_function_start): If not optimizing, save the static chain onto the stack. * tree-nested.c (convert_all_function_calls): Always create the static chain for nested functions if not optimizing. Modified: trunk/gcc/ChangeLog trunk/gcc/function.c trunk/gcc/tree-nested.c
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #11 from Eric Botcazou ebotcazou at gcc dot gnu.org --- OK, I'm attaching the patchlet. I can submit it when stage #1 opens. I obviously missed one stage #1, but this is now done: http://gcc.gnu.org/ml/gcc-patches/2014-05/msg00573.html
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #8 from Tom Tromey tromey at gcc dot gnu.org 2013-02-01 18:22:21 UTC --- Yes, but you can do something useful even with this value of DW_AT_static_link, albeit not exactly what DWARF means. Regardless, I think GCC should emit correct DWARF. Indeed, that's why in AdaCore's version of the compiler, we always generate DW_AT_static_link at -O0, and we even force the static chain onto the stack in this case (as there are no location lists at -O0). I think this would be a nice addition.
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #9 from Eric Botcazou ebotcazou at gcc dot gnu.org 2013-02-01 22:16:47 UTC --- I think this would be a nice addition. OK, I'm attaching the patchlet. I can submit it when stage #1 opens.
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #10 from Eric Botcazou ebotcazou at gcc dot gnu.org 2013-02-01 22:20:38 UTC --- Created attachment 29333 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=29333 patch to tweak the static chain at -O0 * function.c (instantiate_decls): Process the saved static chain. (expand_function_start): If not optimizing, save the static chain onto the stack. * tree-nested.c (convert_all_function_calls): Always create the static chain for nested functions if not optimizing.
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 Eric Botcazou ebotcazou at gcc dot gnu.org changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2013-01-31 CC||ebotcazou at gcc dot ||gnu.org Ever Confirmed|0 |1 --- Comment #2 from Eric Botcazou ebotcazou at gcc dot gnu.org 2013-01-31 15:00:50 UTC --- GCC doesn't set DW_AT_static_link to the frame base of the statically enclosing frame but to the address of the FRAME object of that frame.
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 Jason Merrill jason at gcc dot gnu.org changed: What|Removed |Added Status|NEW |WAITING CC||jason at gcc dot gnu.org --- Comment #3 from Jason Merrill jason at gcc dot gnu.org 2013-01-31 19:23:02 UTC --- I don't see the problem. On both i686 and x86_64 'p self_call' prints 1, which matches the value returned by the function, so debugging seems to be working fine. On i686 the DW_AT_static_link points to $eax because that's where the static chain lives during (part of) the function. As Eric says, the value of the static chain pointer is not the same as the CFA; it points to a struct in the stack frame of the caller. What's the bug?
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #4 from Tom Tromey tromey at gcc dot gnu.org 2013-01-31 19:40:16 UTC --- (In reply to comment #3) I don't see the problem. On both i686 and x86_64 'p self_call' prints 1, which matches the value returned by the function, so debugging seems to be working fine. You can't go by what gdb says here. gdb currently doesn't look at DW_AT_static_link at all. Instead it just does some guessing. This bug came up because I tried to make it work properly. If you try print arg you will see gdb get it wrong: (gdb) print arg $1 = 0 I think the correct answer is 5. On i686 the DW_AT_static_link points to $eax because that's where the static chain lives during (part of) the function. As Eric says, the value of the static chain pointer is not the same as the CFA; it points to a struct in the stack frame of the caller. What's the bug? DWARF defines DW_AT_static_link to be the frame base of the appropriate outer invocation: If a subroutine or entry point is nested, it may have a DW_AT_static_link attribute, whose value is a location description that computes the frame base of the relevant instance of the subroutine that immediately encloses the subroutine or entry point. The idea is you can determine which instance by computing the static link, then unwind the stack and look for the corresponding CFA. The test case here is supposed to confound simplistic approaches to this by having multiple instances of 'nestee' on the stack. Note also that if the nested function doesn't refer to any variables from the outer scope, then GCC seems not to emit DW_AT_static_link at all. I guess this is an optimization; but it is a little unfortunate since it makes debugging less obvious.
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 Jason Merrill jason at gcc dot gnu.org changed: What|Removed |Added Status|WAITING |NEW --- Comment #5 from Jason Merrill jason at gcc dot gnu.org 2013-01-31 20:12:14 UTC --- Oh, I see what you mean; GCC is using its internal concept of static chain, but DWARF wants something else.
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #6 from Eric Botcazou ebotcazou at gcc dot gnu.org 2013-01-31 22:34:02 UTC --- The idea is you can determine which instance by computing the static link, then unwind the stack and look for the corresponding CFA. The test case here is supposed to confound simplistic approaches to this by having multiple instances of 'nestee' on the stack. Yes, but you can do something useful even with this value of DW_AT_static_link, albeit not exactly what DWARF means. In the GDB released by AdaCore, we do use this value of DW_AT_static_link to deal with up-level references; you can ask Joel for the details. Note also that if the nested function doesn't refer to any variables from the outer scope, then GCC seems not to emit DW_AT_static_link at all. I guess this is an optimization; but it is a little unfortunate since it makes debugging less obvious. Indeed, that's why in AdaCore's version of the compiler, we always generate DW_AT_static_link at -O0, and we even force the static chain onto the stack in this case (as there are no location lists at -O0).
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #7 from Jason Merrill jason at gcc dot gnu.org 2013-01-31 23:23:01 UTC --- I think these two meanings of DW_AT_static_link could be compatible if we changed nestee's DW_AT_frame_base to point to the FRAME object, i.e. CFA-24.
[Bug debug/53927] wrong value for DW_AT_static_link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927 --- Comment #1 from Tom Tromey tromey at gcc dot gnu.org 2013-01-24 20:24:18 UTC --- It seems that I read the wrong frame info in my original report. However, the bug still exists. Here is a new and hopefully more correct example showing the bug. I used a relatively recent git master gcc for this. I just followed the directions in the original report. The static link info for 'nested': aa DW_AT_static_link : 1 byte block: 50 (DW_OP_reg0 (rax)) In the 'nested' frame this is: (gdb) p/x $rax $1 = 0x7fffe370 In the outer 'nestee' frame: (gdb) p $pc $2 = (void (*)()) 0x4004e9 nestee+99 The frame info as shown by readelf --debug-dump=frames-interp: 0060 0024 0064 FDE cie= pc=00400486..004004fe LOC CFA rbx rbp ra 00400486 rsp+8u u c-8 00400487 rsp+16 u c-16 c-8 0040048a rbp+16 u c-16 c-8 0040048f rbp+16 c-24 c-16 c-8 --- this row 004004fd rsp+8c-24 c-16 c-8 So the CFA we want is $rbp + 16 in the outermost 'nestee' frame: (gdb) p/x $rbp + 16 $3 = 0x7fffe3b0 ... but this is different from $1.