[Dwarf-Discuss] compilers generating ABI non-compliant function calls?

David Blaikie dblaikie@gmail.com
Tue Mar 9 19:16:01 GMT 2021


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 at 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, LLVM will remove arguments
that are unused - so trying to call the function from a debugger using the
source-level signature will break, arguments will be offset (ie: the user's
3rd argument would be treated as the 2nd argument, etc). Using the
parameter locations is insufficient - there's no guarantee they describe
the location of a variable at the very start of the function (in general
they do not - usually they only describe the location that's valid after
the prologue).

So, essentially, in an LTO world, there is no ABI and DWARF may need to be
able to describe arbitrary "ABI"s on a per-function/parameter basis. Though
having a fallback for the common case rather than describing every
function's ABI would be valuable. (maybe some way to share the
descriptions, but still be self-descriptive)

- Dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dwarfstd.org/pipermail/dwarf-discuss-dwarfstd.org/attachments/20210309/a722abd6/attachment-0001.html>



More information about the Dwarf-discuss mailing list