[Dwarf-Discuss] compilers generating ABI non-compliant function calls?
Part of a typical Application Binary Interface is to specify the function calling convention. Several uses are: - ensuring function calls across interface boundaries work (function in one object calls function in second object) - the debugger supplementing the debug information describing the location of parameters - the debugger implementing inferior function calls Typically calls both between and within object files (DWARF compilation unit) follow the ABI (with exceptions for things like __mul, but good ABIs even defined those). Technically, however, only functions visible via an interface need comply with the ABI. This means that: - for simple objects, local functions; and - with link-time-optimization, everything except library interface functions are fair game for ABI non-compliant call optimizations. Is anyone aware of a compiler doing this (I figure with LTO there's a strong incentive)? And if so, how is this described to the debugger. The ABI / calling-convention is no longer on hand for filling in the blanks. (Keep in mind that this is different to adding an attribute to a function indicating it should follow a different calling convention - while different, it is still defined ahead of time). ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
Hi, Andrew - On Tue, Mar 09, 2021 at 10:05:04AM -0500, Andrew Cagney via Dwarf-Discuss wrote: > [...] > This means that: > - for simple objects, local functions; and > - with link-time-optimization, everything except library interface functions > are fair game for ABI non-compliant call optimizations. > > Is anyone aware of a compiler doing this (I figure with LTO there's a > strong incentive)? And if so, how is this described to the debugger. > The ABI / calling-convention is no longer on hand for filling in the > blanks. FWIW, gcc does not leave ABI-dependent gaps in the DWARF generated for function parameters. First class location lists are given, whether or not they are in the ABI-governed locations, or whether they've been moved somewhere else, or whether they've been optimized out so that a consumer must recompute it somehow, or whether they exist at all. As I understand it, the location of *function return values* is however a gap in DWARF, and a consumer tool must resort to ABI specs. (Thus the elfutils dwfl_module_return_value_location() function.) I'm sure there's a Reason for this, but having worked on a consumer, it'd be handy if DWARF did explicitly identify the return value location too. - FChE ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 09, 2021 at 10:05:04AM -0500, Andrew Cagney via Dwarf-Discuss wrote: > Is anyone aware of a compiler doing this (I figure with LTO there's a > strong incentive)? And if so, how is this described to the debugger. > The ABI / calling-convention is no longer on hand for filling in the > blanks. Sure, GCC does that. On many architectures, IPA-RA might keep data live across a function call even in registers that are per the ABI officially call clobbered (if it can prove the particular callee does not clobber it). This isn't expressed in DWARF I believe. On x86, GCC can use different register calling conventions for local functions (basically automatic regparm and/or sseregparm calling conventions when possible). I think this is reflected in the debug info, the DW_TAG_formal_parameter locations should match those. Jakub ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
(re-sending because outlook omitted the group address) > -Original Message- > From: Dwarf-Discuss On Behalf > Of Jakub Jelinek via Dwarf-Discuss > Sent: Tuesday, March 9, 2021 10:16 AM > To: Andrew Cagney > Cc: DWARF Discussion > Subject: Re: [Dwarf-Discuss] compilers generating ABI non-compliant > function calls? > > On Tue, Mar 09, 2021 at 10:05:04AM -0500, Andrew Cagney via Dwarf-Discuss > wrote: > > Is anyone aware of a compiler doing this (I figure with LTO there's a > > strong incentive)? And if so, how is this described to the debugger. > > The ABI / calling-convention is no longer on hand for filling in the > > blanks. > > Sure, GCC does that. On many architectures, IPA-RA might keep data > live across a function call even in registers that are per the ABI > officially call clobbered (if it can prove the particular callee does not > clobber it). This isn't expressed in DWARF I believe. DWARF doesn't describe clobbering or non-clobbering; it describes where values live. If something gets clobbered by a call, the location list should reflect that the location changes (or doesn't exist) as of the instruction after the call; if it doesn't get clobbered, the location range should correctly span the call instruction. The debugger does not need to know the ABI in order to trust that location lists are correct. The producer is responsible for emitting correct location lists that don't depend on ABI knowledge by the consumer. AFAIK the main reason to annotate a subprogram with a calling convention is so that a debugger can manufacture a call correctly, in response to a user command. It might also be necessary to identify the location of the return value, as someone else mentioned. --paulr > > On x86, GCC can use different register calling conventions for local > functions (basically automatic regparm and/or sseregparm calling > conventions > when possible). I think this is reflected in the debug info, the > DW_TAG_formal_parameter locations should match those. > > Jakub > > ___ > Dwarf-Discuss mailing list > Dwarf-Discuss@lists.dwarfstd.org > https://urldefense.com/v3/__http://lists.dwarfstd.org/listinfo.cgi/dwarf- > discuss- > dwarfstd.org__;!!JmoZiZGBv3RvKRSx!saJXjJCyJzGPm7PNYMIYGGdh4Ox2WiUfnoR9uFea > -PrVPbcUNCuNYk9zgwlQJrcZ9Q$ ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
Hi Andrew On Tue Mar 9, 2021 at 3:05 PM GMT, Andrew Cagney via Dwarf-Discuss wrote: > Part of a typical Application Binary Interface is to specify the > function calling convention. Several uses are: > > - ensuring function calls across interface boundaries work (function > in one object calls function in second object) > - the debugger supplementing the debug information describing the > location of parameters > - the debugger implementing inferior function calls > > Typically calls both between and within object files (DWARF > compilation unit) follow the ABI (with exceptions for things like > __mul, but good ABIs even defined those). > > Technically, however, only functions visible via an interface need > comply with the ABI. This means that: > > - for simple objects, local functions; and > - with link-time-optimization, everything except library interface > functions > > are fair game for ABI non-compliant call optimizations. > > Is anyone aware of a compiler doing this (I figure with LTO there's a > strong incentive)? And if so, how is this described to the debugger. > The ABI / calling-convention is no longer on hand for filling in the > blanks. > Both GCC and LLVM do this in some capacity. Probably many others too. An easy way to trigger this behaviour is with a combination of `static` and `noinline`. Here is an example with gcc10/amd64: $ cc -g -O2 -xc - < #include static __attribute__((noinline)) int three_args(int i, int j, int k) { return i + k; } int add2(int i, int k) { return three_args(i, 0, k); } int main(int argc, char **argv) { int i = strtol(argv[1], NULL, 0); int k = strtol(argv[2], NULL, 0); printf("i + k == %d\n", add2(i, k)); } EOF $ gdb --args ./a.out 3 4 Reading symbols from ./a.out... (gdb) b three_args Breakpoint 1 at 0x11a0: file , line 6. (gdb) r Starting program: /tmp/a.out 3 4 Breakpoint 1, three_args (i=3, k=4, j=0) at :6 6 : No such file or directory. (gdb) disassemble Dump of assembler code for function three_args: => 0x51a0 <+0>: lea(%rdi,%rsi,1),%eax 0x51a3 <+3>: ret End of assembler dump. (gdb) Notice that `$rsi` is used in place of `%rdi` because the second formal argument is unused and the compiler can use `%rsi` instead. The dwarfdump for this program shows where the formal arguments were put by the compiler: < 1><0x01eb>DW_TAG_subprogram DW_AT_abstract_origin <0x01bb> DW_AT_low_pc0x11a0 DW_AT_high_pc 4 DW_AT_frame_baselen 0x0001: 0x9c: DW_OP_call_frame_cfa DW_AT_GNU_all_call_sitesyes(1) DW_AT_sibling <0x021b> < 2><0x0206> DW_TAG_formal_parameter DW_AT_abstract_origin <0x01cc> DW_AT_location len 0x0001: 0x55: DW_OP_reg5 < 2><0x020d> DW_TAG_formal_parameter DW_AT_abstract_origin <0x01e0> DW_AT_location len 0x0001: 0x54: DW_OP_reg4 < 2><0x0214> DW_TAG_formal_parameter DW_AT_abstract_origin <0x01d6> DW_AT_const_value 0 Therefore the debugger doesn't have to special case anything because arbitrary calling conventions can be communicated this way. All the best Luke -- Codeplay Software Ltd. Company registered in England and Wales, number: 04567874 Registered office: Regent House, 316 Beulah Hill, London, SE19 3HF ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, 9 Mar 2021 at 10:13, Frank Ch. Eigler wrote: > > Hi, Andrew - > > On Tue, Mar 09, 2021 at 10:05:04AM -0500, Andrew Cagney via Dwarf-Discuss > wrote: > > [...] > > This means that: > > - for simple objects, local functions; and > > - with link-time-optimization, everything except library interface functions > > are fair game for ABI non-compliant call optimizations. > > > > Is anyone aware of a compiler doing this (I figure with LTO there's a > > strong incentive)? And if so, how is this described to the debugger. > > The ABI / calling-convention is no longer on hand for filling in the > > blanks. > > FWIW, gcc does not leave ABI-dependent gaps in the DWARF generated for > function parameters. First class location lists are given, whether or > not they are in the ABI-governed locations, or whether they've been > moved somewhere else, or whether they've been optimized out so that a > consumer must recompute it somehow, or whether they exist at all. So for instance, given a 64-bit big-endian ABI that left-packs large structs vis: struct { uint64_t register_three; uint8_t left_side_of_register_four; }; but decides to pass left_side_of_register_four on the RHS would generate a DW_OP_bit_piece DW_OP_piece (implied LHS). > As I understand it, the location of *function return values* is > however a gap in DWARF, and a consumer tool must resort to ABI specs. > (Thus the elfutils dwfl_module_return_value_location() function.) I'm > sure there's a Reason for this, but having worked on a consumer, it'd > be handy if DWARF did explicitly identify the return value location > too. > > - FChE > ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 09 2021, Frank Ch. Eigler via Dwarf-Discuss wrote: [...] > FWIW, gcc does not leave ABI-dependent gaps in the DWARF generated for > function parameters. First class location lists are given, whether or > not they are in the ABI-governed locations, or whether they've been > moved somewhere else, or whether they've been optimized out so that a > consumer must recompute it somehow, or whether they exist at all. Except for varying parameters, in which case DW_TAG_unspecified_parameters gets emitted instead, right? -- Andreas ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On 3/9/21 7:13 AM, Frank Ch. Eigler via Dwarf-Discuss wrote: As I understand it, the location of*function return values* is however a gap in DWARF, and a consumer tool must resort to ABI specs. (Thus the elfutils dwfl_module_return_value_location() function.) I'm sure there's a Reason for this, but having worked on a consumer, it'd be handy if DWARF did explicitly identify the return value location too. DWARF does not duplicate information which is documented in the ABI or in other information which is shared by compilers and debuggers. For example, DWARF does not describe the calling convention for a function. Producers and consumers are expected to know this info. The rationale is that duplicating shared ABI knowledge would greatly increase the size of a debug file, while not improving the ability to debug a program. For example, DWARF describes the arguments to a function. It doesn't describe the calling convention, which registers are preserved, which are clobbered, or anything else which is specified by the ABI. In most ABIs, the location of a function return value is similarly constrained. If there are multiple calling conventions, this is identified to allow a debugger to generate a valid call to a function. DWARF only contains information which describes what a compiler generates which cannot be unambiguous determined by knowledge of the ABI. A limited exception is the CFI, which in many cases mirrors the ABI. If there are occasions when a compiler might place a function return value in a variety of different locations, not constrained by the ABI, a DWARF attribute might be useful. -- Michael Eager ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] Retrieving variables, function address using dwarf
It's difficult to offer advice with such a spare description. You might read the executable and relocate the .debug_info and other debug sections using the process map. If you have the process image, this probably would not be necessary. On 3/8/21 1:49 AM, Archana Deshmukh via Dwarf-Discuss wrote: Hello, I have a pinatrace.out and process map of a file. With this input, I need to build a symbol table. Best Regards, Archana Deshmukh On Sun, Mar 7, 2021 at 10:29 AM Archana Deshmukh mailto:desharchan...@gmail.com>> wrote: -- Forwarded message - From: *Michael Eager* mailto:ea...@eagercon.com>> Date: Sat, Mar 6, 2021 at 10:53 PM Subject: Re: [Dwarf-Discuss] Retrieving variables, function address using dwarf To: Archana Deshmukh mailto:desharchan...@gmail.com>>, mailto:dwarf-discuss@lists.dwarfstd.org>> On 3/5/21 8:28 PM, Archana Deshmukh via Dwarf-Discuss wrote: > I need to read the address of local variable, global variable, function > name and function arguments from the process. > > For global variables , I read the address "55b51afea000" from > /proc//maps file. I use DW_OP_addr parameter to retrieve the address. > 55b51afea000 + DW_OP_addr gives me the address of global variable. > > I need to read the stack segment, heap. Is there any way to read > segments? DW_AT_segment parameter seems to be for 16 bit. > > I need to read the following process map using dwarf. > > Any suggestion, pointers are welcome. > > 55b51afea000-55b51afeb000 r-xp fd:00 5902563 Can you explain what you are trying to do? Usually a DWARF consumer (a debugger) does not need to read the process memory map. All of the information you mention is in the DWARF data. You may need to relocate addresses in the DWARF debug data. DWARF does not contain information about the process memory layout, such as the location of the heap or the start of the stack. -- Michael Eager ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org -- Michael Eager ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
Frank: FWIW, gcc does not leave ABI-dependent gaps in the DWARF generated for function parameters. First class location lists are given, whether or not they are in the ABI-governed locations, or whether they've been moved somewhere else, or whether they've been optimized out so that a consumer must recompute it somehow, or whether they exist at all. I don't think it's valid for a DWARF consumer to use the DW_AT_location of a parameter to determine the calling convention, though. DW_AT_locations for parameters only need to be valid after the prologue, so they don't necessarily describe how the parameter was passed to the function (for instance - LLVM and GCC and -O0 describe parameters as being on the stack, not in registers, even though the calling convention dictates that the parameters be passed in registers). eg: clang and gcc both compile this: void f1(int i) { } to include a DW_AT_location with fbreg, nothing about how the ABI represents 'i' - so that would be an ABI gap. In the cases where the compiler does modify any ABI-relevant properties, how would the DWARF consumer know that /that/ location represents the ABI calling convention, but the above fbreg location does not? At least for Clang - the two cases of DAE described below (either modifying a parameter to be unused but present (because the signature must be maintained for external callers) and truly removing the parameter (thus shifting other parameters down)) would be indistinguishable in any DWARF I can imagine - in both cases the parameter would have no DW_AT_location. Any idea how GCC handles that, if it does that kind of optimization? On Tue, Mar 9, 2021 at 8:36 AM Michael Eager via Dwarf-Discuss < dwarf-discuss@lists.dwarfstd.org> wrote: > On 3/9/21 7:13 AM, Frank Ch. Eigler via Dwarf-Discuss wrote: > > As I understand it, the location of*function return values* is > > however a gap in DWARF, and a consumer tool must resort to ABI specs. > > (Thus the elfutils dwfl_module_return_value_location() function.) I'm > > sure there's a Reason for this, but having worked on a consumer, it'd > > be handy if DWARF did explicitly identify the return value location > > too. > > DWARF does not duplicate information which is documented in the ABI > or in other information which is shared by compilers and debuggers. > For example, DWARF does not describe the calling convention for a > function. Producers and consumers are expected to know this info. > > The rationale is that duplicating shared ABI knowledge would greatly > increase the size of a debug file, while not improving the ability > to debug a program. > > For example, DWARF describes the arguments to a function. It doesn't > describe the calling convention, which registers are preserved, which > are clobbered, or anything else which is specified by the ABI. In > most ABIs, the location of a function return value is similarly > constrained. If there are multiple calling conventions, this is > identified to allow a debugger to generate a valid call to a function. > > DWARF only contains information which describes what a compiler > generates which cannot be unambiguous determined by knowledge of the > ABI. A limited exception is the CFI, which in many cases mirrors the > ABI. > > If there are occasions when a compiler might place a function return > value in a variety of different locations, not constrained by the > ABI, a DWARF attribute might be useful. > Essentially, with LTO, everything can be (& is) changed by the compiler - because it can see all callers to a function. Basically the ABI doesn't hold for anything except functions that need to be called from outside the binary (in some cases, that means only "main" conforms to the ABI). A simple one I know of for LLVM is in the optimizations Argument Promotion and Dead Argument Elimination. Argument Promotion can change a pointer parameter to a value parameter, for instance - how should a compiler describe this situation in the DWARF? The source code says the function parameter is a pointer, but if the debugger tries to call that function with a pointer it will be quite broken - the pointer must be dereferenced before the function is called. (but what happens if the compiler optimized away a null test for that parameter? Because the compiler determined all callers were passing non-null parameters - so the user might try to run a function call with the parameter being null, but that could crash, for instance) With Dead Argument Elimination the compiler can determine that certain parameters are unused - this can happen in two flavors: 1) the easy case, if the function ABI must be preserved: Some callers might be modified to not pass a certain parameter because it's known to be unused inside the function. This generally means that the variable can have no valid location inside the function (except using call_site_parameters) - so I think that case has a pretty clear answer today 2) if the ABI doesn't have to be maintained, L
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 09, 2021 at 11:16:01AM -0800, David Blaikie via Dwarf-Discuss wrote: > void f1(int i) { } > > to include a DW_AT_location with fbreg, nothing about how the ABI > represents 'i' - so that would be an ABI gap. > > In the cases where the compiler does modify any ABI-relevant properties, > how would the DWARF consumer know that /that/ location represents the ABI > calling convention, but the above fbreg location does not? > > At least for Clang - the two cases of DAE described below (either modifying > a parameter to be unused but present (because the signature must be > maintained for external callers) and truly removing the parameter (thus > shifting other parameters down)) would be indistinguishable in any DWARF I > can imagine - in both cases the parameter would have no DW_AT_location. Any > idea how GCC handles that, if it does that kind of optimization? If GCC optimizes away some parameter (of course that is possible only for functions not exported from TUs or on non-exported copies of the exported functions), e.g. with static __attribute__((noinline)) int foo (int x, int y) { return x; } int bar (void) { return foo (3, 17) + foo (3, 18) + foo (3, 19); } it will emit: .uleb128 0xa# (DIE (0xb9) DW_TAG_formal_parameter) .long 0x85# DW_AT_abstract_origin .byte 0x3 # DW_AT_const_value for the x case (where the parameter has been optimized away and is known to be 3 in all cases) and for y uses a GNU extension (that has been added too late in the DWARF5 cycle so it was too late to propose it for DWARF5) .uleb128 0x9# (DIE (0xad) DW_TAG_formal_parameter) .long 0x8d# DW_AT_abstract_origin .uleb128 0x6# DW_AT_location .byte 0xfa# DW_OP_GNU_parameter_ref .long 0x8d .byte 0x9f# DW_OP_stack_value which has a reference to the formal parameter and value can be (with luck) found in DW_TAG_call_site_parameter in the callers. Jakub ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 9, 2021 at 11:29 AM Jakub Jelinek wrote: > On Tue, Mar 09, 2021 at 11:16:01AM -0800, David Blaikie via Dwarf-Discuss > wrote: > > void f1(int i) { } > > > > to include a DW_AT_location with fbreg, nothing about how the ABI > > represents 'i' - so that would be an ABI gap. > > > > In the cases where the compiler does modify any ABI-relevant properties, > > how would the DWARF consumer know that /that/ location represents the ABI > > calling convention, but the above fbreg location does not? > > > > At least for Clang - the two cases of DAE described below (either > modifying > > a parameter to be unused but present (because the signature must be > > maintained for external callers) and truly removing the parameter (thus > > shifting other parameters down)) would be indistinguishable in any DWARF > I > > can imagine - in both cases the parameter would have no DW_AT_location. > Any > > idea how GCC handles that, if it does that kind of optimization? > > If GCC optimizes away some parameter (of course that is possible only for > functions not exported from TUs or on non-exported copies of the exported > functions), e.g. with > static __attribute__((noinline)) int foo (int x, int y) { return x; } > int bar (void) { return foo (3, 17) + foo (3, 18) + foo (3, 19); } > it will emit: > .uleb128 0xa# (DIE (0xb9) DW_TAG_formal_parameter) > .long 0x85# DW_AT_abstract_origin > .byte 0x3 # DW_AT_const_value > for the x case (where the parameter has been optimized away and is known to > be 3 in all cases) and for y uses a GNU extension (that has been added too > late in the DWARF5 cycle so it was too late to propose it for DWARF5) > .uleb128 0x9# (DIE (0xad) DW_TAG_formal_parameter) > .long 0x8d# DW_AT_abstract_origin > .uleb128 0x6# DW_AT_location > .byte 0xfa# DW_OP_GNU_parameter_ref > .long 0x8d > .byte 0x9f# DW_OP_stack_value > which has a reference to the formal parameter and value can be (with luck) > found in DW_TAG_call_site_parameter in the callers. > Thanks for the details! So in this case GCC changes the ABI of foo(int x, int y) to be equivalent to foo(int y) and the parameter description of 'y' using DW_OP_GNU_parameter_ref says something like "look at where the first ABI parameter would be stored"? So a DWARF consumer should read the locations of the parameters - see the constant value of the first parameter and conclude that the first parameter is omitted from the ABI? Then reading the second parameter and see that its stored in the ABI first parameter - and then conclude that since no other parameters are mentioned, only that first parameter slot is used (to pass the second source parameter)/should be passed? Does GCC do anything like the LLVM optimization when the function is externally visible, but some callers are visible to the optimizer - and the compiler concludes that since the parameter is unused inside the function implementation those callers can be modified to pass effectively garbage in that parameter? And what sort of DWARF does GCC use to describe that? ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 09, 2021 at 11:43:54AM -0800, David Blaikie wrote: > Thanks for the details! So in this case GCC changes the ABI of foo(int x, > int y) to be equivalent to foo(int y) and the parameter description of 'y' No, it is actually equivalent to foo(void) but DW_TAG_call_site_parameter in those cases holds the value the optimized away parameter would have if it would be passed. So, when the consumer evaluates DW_OP_GNU_parameter_ref, it handles it similarly to DW_OP_entry_value, unwinds to caller if it can identify it, and just looks up if some value is specified for it in that particular caller. > Does GCC do anything like the LLVM optimization when the function is > externally visible, but some callers are visible to the optimizer - and the > compiler concludes that since the parameter is unused inside the function > implementation those callers can be modified to pass effectively garbage in > that parameter? And what sort of DWARF does GCC use to describe that? I think GCC doesn't do that, instead it would if considered beneficial copy the function to a non-exported one and optimize away the parameters in there (etc.). Also note that the callee is exported, there is the question if it can be semantically interposed (for GCC yes by default with -fpic/-fPIC unless playing e.g. with visibility attributes) and in that case you don't know if the parameter will be unused there. Jakub ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 9, 2021 at 11:52 AM Jakub Jelinek wrote: > On Tue, Mar 09, 2021 at 11:43:54AM -0800, David Blaikie wrote: > > Thanks for the details! So in this case GCC changes the ABI of foo(int x, > > int y) to be equivalent to foo(int y) and the parameter description of > 'y' > > No, it is actually equivalent to foo(void) Ah, I see - the used parameter is constant, so it doesn't need to be passed (it was constant propagated from all callers to the callee) and the varied parameter was unused so it didn't need to be passed either. > but DW_TAG_call_site_parameter > in those cases holds the value the optimized away parameter would have if > it > would be passed. So, when the consumer evaluates DW_OP_GNU_parameter_ref, it handles it > similarly to DW_OP_entry_value, unwinds to caller if it can identify it, > and just looks up if some value is specified for it in that particular > caller. > Could you help me understand more how DW_OP_GNU_parameter_ref works/differently from DW_OP_entry_value? > Does GCC do anything like the LLVM optimization when the function is > > externally visible, but some callers are visible to the optimizer - and > the > > compiler concludes that since the parameter is unused inside the function > > implementation those callers can be modified to pass effectively garbage > in > > that parameter? And what sort of DWARF does GCC use to describe that? > > I think GCC doesn't do that, instead it would if considered beneficial > copy the function to a non-exported one and optimize away the parameters in > there (etc.). Ah, OK - in which case there would be no DWARF for the copy? And the original function would look as though it were "optimized away" (ie: not have any DW_AT_low/high_pc, etc)? > Also note that the callee is exported, there is the question > if it can be semantically interposed (for GCC yes by default with > -fpic/-fPIC unless playing e.g. with visibility attributes) and in that > case > you don't know if the parameter will be unused there. > Ah, yeah, this only applies in the non-interposable case. - Dave ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 9, 2021 at 1:28 PM Paul Robinson via Dwarf-Discuss < dwarf-discuss@lists.dwarfstd.org> wrote: > (re-sending because outlook omitted the group address) > > > -Original Message- > > From: Dwarf-Discuss On Behalf > > Of Jakub Jelinek via Dwarf-Discuss > > Sent: Tuesday, March 9, 2021 10:16 AM > > To: Andrew Cagney > > Cc: DWARF Discussion > > Subject: Re: [Dwarf-Discuss] compilers generating ABI non-compliant > > function calls? > > > > On Tue, Mar 09, 2021 at 10:05:04AM -0500, Andrew Cagney via Dwarf-Discuss > > wrote: > > > Is anyone aware of a compiler doing this (I figure with LTO there's a > > > strong incentive)? And if so, how is this described to the debugger. > > > The ABI / calling-convention is no longer on hand for filling in the > > > blanks. > > > > Sure, GCC does that. On many architectures, IPA-RA might keep data > > live across a function call even in registers that are per the ABI > > officially call clobbered (if it can prove the particular callee does not > > clobber it). This isn't expressed in DWARF I believe. > > > DWARF doesn't describe clobbering or non-clobbering; it describes where > values live. Right - but that lack of knowledge may be problematic in some situations I'm trying to describe. (ie: a "gap" where current DWARF encoding + ABI knowledge is insufficient for a consumer to behave correctly) > If something gets clobbered by a call, the location list > should reflect that the location changes (or doesn't exist) as of the > instruction after the call; if it doesn't get clobbered, the location > range should correctly span the call instruction. The debugger does not > need to know the ABI in order to trust that location lists are correct. > Agreed that the debugger doesn't need to know the clobber/callee save/caller save ABI to use a location list correctly. > The producer is responsible for emitting correct location lists that > don't depend on ABI knowledge by the consumer. > > AFAIK the main reason to annotate a subprogram with a calling convention > is so that a debugger can manufacture a call correctly, in response to a > user command. > Right - and generally the debugger would expect to call this function using the ABI - except that with internalized functions (either static CU-local functions, or with any function that LTO optimizations can internalize - everything other than the specified entry points (in the worst case, only "main")) the ABI may be violated (because the compiler can see the implementation of the function and all its callers - well, it thinks it can see all the callers, but it doesn't know about the debugger making calls). So, for instance, the internalized function may use callee save registers without restoring them - if a debugger then tried to call this function expecting it to conform to the ABI and restore those registers before returning, the debugger may malfunction/break as the register values would not be restored. I think? - Dave > It might also be necessary to identify the location of the return value, > as someone else mentioned. > --paulr > > > > > On x86, GCC can use different register calling conventions for local > > functions (basically automatic regparm and/or sseregparm calling > > conventions > > when possible). I think this is reflected in the debug info, the > > DW_TAG_formal_parameter locations should match those. > > > > Jakub > > > > ___ > > Dwarf-Discuss mailing list > > Dwarf-Discuss@lists.dwarfstd.org > > > https://urldefense.com/v3/__http://lists.dwarfstd.org/listinfo.cgi/dwarf- > > discuss- > > > dwarfstd.org__;!!JmoZiZGBv3RvKRSx!saJXjJCyJzGPm7PNYMIYGGdh4Ox2WiUfnoR9uFea > > -PrVPbcUNCuNYk9zgwlQJrcZ9Q$ > ___ > Dwarf-Discuss mailing list > Dwarf-Discuss@lists.dwarfstd.org > http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org > ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 09, 2021 at 03:22:35PM -0800, David Blaikie wrote: > So, when the consumer evaluates DW_OP_GNU_parameter_ref, it handles it > > similarly to DW_OP_entry_value, unwinds to caller if it can identify it, > > and just looks up if some value is specified for it in that particular > > caller. > > > > Could you help me understand more how DW_OP_GNU_parameter_ref > works/differently from DW_OP_entry_value? DW_OP_entry_value refers to a register or memory in which a parameter is passed. When a parameter is not passed at all, there is no register or memory to which it can refer to. So, DW_OP_GNU_parameter_ref instead refers to the DW_TAG_formal_parameter DIE and the consumer needs to find a DW_TAG_call_site_parameter that refers to the same DIE. > > I think GCC doesn't do that, instead it would if considered beneficial > > copy the function to a non-exported one and optimize away the parameters in > > there (etc.). > > > Ah, OK - in which case there would be no DWARF for the copy? And the > original function would look as though it were "optimized away" (ie: not > have any DW_AT_low/high_pc, etc)? No, there is DWARF for the copy. The original user function is the abstract origin and then it has two (or more) DW_TAG_subprogram DIEs that refer to that (and refer to DW_TAG_formal_parameter and DW_TAG_variable etc.) in it. Jakub ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] compilers generating ABI non-compliant function calls?
On Tue, Mar 9, 2021 at 3:40 PM Jakub Jelinek wrote: > On Tue, Mar 09, 2021 at 03:22:35PM -0800, David Blaikie wrote: > > So, when the consumer evaluates DW_OP_GNU_parameter_ref, it handles it > > > similarly to DW_OP_entry_value, unwinds to caller if it can identify > it, > > > and just looks up if some value is specified for it in that particular > > > caller. > > > > > > > Could you help me understand more how DW_OP_GNU_parameter_ref > > works/differently from DW_OP_entry_value? > > DW_OP_entry_value refers to a register or memory in which a parameter > is passed. When a parameter is not passed at all, there is no register or > memory to which it can refer to. So, DW_OP_GNU_parameter_ref instead > refers to the DW_TAG_formal_parameter DIE and the consumer needs to find > a DW_TAG_call_site_parameter that refers to the same DIE. > Ah, OK. Hmm - do you have different call_site_parameters for registers versus parameters? Or I guess a call_site_parameter without a DW_AT_location and only a DW_AT_call_value? > > I think GCC doesn't do that, instead it would if considered beneficial > > > copy the function to a non-exported one and optimize away the > parameters in > > > there (etc.). > > > > > > Ah, OK - in which case there would be no DWARF for the copy? And the > > original function would look as though it were "optimized away" (ie: not > > have any DW_AT_low/high_pc, etc)? > > No, there is DWARF for the copy. The original user function is the > abstract > origin and then it has two (or more) DW_TAG_subprogram DIEs that refer to > that (and refer to DW_TAG_formal_parameter and DW_TAG_variable etc.) in it. > Hmm - is that "conforming" (I'm all for "DWARF provides some tools and here's a way we can use them to describe this situation") DWARF? I would've thought that there could only be one concrete instance of an abstract definition. And given that, could the user call this function from their debugger, and how would the debugger get the ABI correct? (let's say there were no other callers in other files - and we used gc-sections to optimize away that original external copy, perhaps - if that makes a difference) I guess since GCC didn't use the original symbol name, maybe the debugger wouldn't consider the modified copy to be a valid target to call the original function even though the DWARF says this is an instance of the original function? To come back to the original question - are there gaps between DWARF and the ABI, I think the answer is yes (for internalized functions), certainly for LLVM but I think for GCC too. At least in terms of what's guaranteed/explicitly communicated - we might have to formalize some things to make clear what conclusions can be reached when certain parameter locations are used. As it is today, DWARF doesn't guarantee that the DW_AT_location of a variable has no bearing on the way the function is called - even a DW_AT_location that doesn't use a location list only has to be valid after the prologue - so you can't guarantee that the location can be used for the calling the function (the simplest example of this is at -O0, you get nothing about how to call the function - but this DWARF would be ambiguous with an optimized build that took the parameter from some non-ABI register in the prologue and moved it into fbreg) - is that correct? Have I misunderstood something? - Dave ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org