[llvm-dev] DWARF .debug_aranges data objects and address spaces

Robinson, Paul via llvm-dev llvm-dev at lists.llvm.org
Mon Mar 16 09:31:49 PDT 2020

With AVR being affected, upstreaming a patch to put segment selectors into .debug_aranges becomes completely reasonable.  There would likely want to be a target hook somewhere to return a value saying what size to use, with the default implementation returning zero.

> If the producer has put ranges on the CU it's not a lot of work - it's parsing one DIE & looking for a couple of attributes.

It’s walking through all the CUs, picking up the associated abbrevs, trolling down the list of attributes… “not a lot” indeed, but not as trivial as running through a single section linearly, which is what .debug_aranges gets you.  I’ve been lectured by @clayborg on what consumers really want for performance gains.

> It's enough at least at Google for us to not use them & use CU ranges for the same purpose.

Google is much more seriously concerned about debug-info size than about debugger performance, IIRC.  This is not universally the preferred tradeoff.  Just sayin’.

From: Dylan McKay <me at dylanmckay.io>
Sent: Monday, March 16, 2020 1:32 AM
To: David Blaikie <dblaikie at gmail.com>
Cc: Robinson, Paul <paul.robinson at sony.com>; llvm-dev at lists.llvm.org
Subject: Re: [llvm-dev] DWARF .debug_aranges data objects and address spaces

I'm not across most of this debug info stuff but I'll stomp in here to confirm that AVR is a Harvard architecture, with separate addressing for the data and program buses via specialized instructions which will load from either one, or the other, but never both.

It makes sense that this particular problem would also affect AVR - the backend does have some issues with debug info generation.

On Fri, Mar 13, 2020 at 12:22 PM David Blaikie via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>> wrote:

On Thu, Mar 12, 2020 at 1:51 PM Robinson, Paul <paul.robinson at sony.com<mailto:paul.robinson at sony.com>> wrote:
I’ve encountered this kind of architecture before, a long time ago (academically).    In a flat-address-space machine such as X64, there is still an instruction/data distinction, but usually only down at the level of I-cache versus D-cache (instruction fetch versus data fetch).  A Harvard architecture machine exposes that to the programmer, which effectively doubles the available address space.  Code and data live in different address spaces, although the address space identifier per se is not explicit.  A Move instruction would implicitly use the data address space, while an indirect Branch would implicitly target the code address space.  An OS running on a Harvard architecture would require the loader to be privileged, so it can map data from an object file into the code address space and implement any necessary fixups.  Self-modifying code is at least wicked hard if not impossible to achieve.

In DWARF this would indeed be described by a segment selector.  It’s up to the target ABI to specify what the segment selector numbers actually are.  For a Harvard architecture machine this is pretty trivial, you say something like 0 for code and 1 for data.  Boom done.

LLVM basically doesn’t have targets like this, or at least it has never come up before that I’m aware of.  So, when we emit DWARF, we assume a flat address space (unconditionally setting the segment selector size to zero), and llvm-dwarfdump will choke (hopefully cleanly, but still) on an object file that uses DWARF segment selectors.

FWIW Luke mentioned in the original email the AVR in-tree backend seems to have this problem with an ambiguous debug_aranges entries.

 The point of .debug_aranges is to accelerate the search for the appropriate CU.  Yes you can spend time trolling through .debug_info and .debug_abbrev, decoding the CU DIEs looking for low_pc/high_pc pairs (or perhaps pointers to .debug_ranges) and effectively rebuild a .debug_aranges section yourself, if the compiler/linker isn’t kind enough to pre-build the table for you.  I don’t understand why .debug_aranges should be discouraged; I shouldn’t think they would be huge, and consumers can avoid loading lots of data just to figure out what’s not worth looking at.  Forcing all consumers to do things the slow way seems unnecessarily inefficient.

If the producer has put ranges on the CU it's not a lot of work - it's parsing one DIE & looking for a couple of attributes. With Split DWARF the cost of becomes a bit more prominent - Sema.o from clang, with split dwarf (v4 or v5 about the same) is about 3.5% larger with debug aranges (not sure about the overall data). It's enough at least at Google for us to not use them & use CU ranges for the same purpose.

I thought I might be able to find some email history about why we turned it off by default, but seems we never turned it /on/ by default to begin with & it wasn't implemented until relatively late in the game (well, what I think as relatively late - after I started on the project at least).

 Thinking about Harvard architecture specifically, you *need* the segment selector only when an address could be ambiguous about whether it’s a code or data address.  This basically comes up *only* in .debug_aranges, he said thinking about it for about 30 seconds.  Within .debug_info you don’t need it because when you pick up the address of an entity, you know whether it’s for a code or data entity.  Location lists and range lists always point to code.  For .debug_aranges you would need the segment selector, but I think that’s the only place.

For an architecture with multiple code or data segments, then you’d need the segment selector more widely, but I should think this case wouldn’t be all that difficult to make work.  Even factoring in the llvm-dwarfdump part, it has to understand the selector only for the .debug_aranges section; everything else can remain as it is, pretending there’s a flat address space.

Now, if your target is downstream, that would make upstreaming the LLVM support a bit dicier, because we’d not want to have that feature in the upstream repo if there are no targets using it.  You’d be left maintaining that patch on your own.  But as I described above, I don’t think it would be a huge deal.


From: David Blaikie <dblaikie at gmail.com<mailto:dblaikie at gmail.com>>
Sent: Thursday, March 12, 2020 2:20 PM
To: Luke Drummond <luke.drummond at codeplay.com<mailto:luke.drummond at codeplay.com>>; Adrian Prantl <aprantl at apple.com<mailto:aprantl at apple.com>>; Jonas Devlieghere <jdevlieghere at apple.com<mailto:jdevlieghere at apple.com>>; Robinson, Paul <paul.robinson at sony.com<mailto:paul.robinson at sony.com>>
Cc: llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>
Subject: Re: [llvm-dev] DWARF .debug_aranges data objects and address spaces

On Thu, Mar 12, 2020 at 11:00 AM Luke Drummond <luke.drummond at codeplay.com<mailto:luke.drummond at codeplay.com>> wrote:
On Thu Mar 12, 2020 at 5:37 PM, David Blaikie wrote:
> On Wed, Mar 11, 2020 at 8:09 AM Luke Drummond
> <luke.drummond at codeplay.com<mailto:luke.drummond at codeplay.com>>
> wrote:
> > On Tue Mar 10, 2020 at 7:45 PM, David Blaikie wrote:
> > > If you only want code addresses, why not use the CU's
> > > low_pc/high_pc/ranges
> > > - those are guaranteed to be only code addresses, I think?
> > >
> > In the common case, for most targets LLVM supports I think you're right,
> > but for my case, regrettably, not. Because my target is a Harvard
> > Architecture, any code address can have the same ordinal value as any
> > data address: the code and data reside on different buses so the whole
> > 4GiB space is available to both code, and data. `DW_AT_low_pc` and
> > `DW_AT_high_pc` can be used to find the range of the code segment, but
> > given an arbitrary address, cannot be used to conclusively determine
> > whether that address belongs to code or data when both segments contain
> > addresses in that numeric range.
> Sorry I'm not following, partly probably due to my not having worked
> with
> such machines before.
> But how are the code addresses and data addresses differentiated then
> (eg:
> if you had segment selectors in debug_aranges, how would they be used?
> The
> addresses taken from the system at runtime have some kind of segment
> selector associated with them, that you can then use to match with the
> addr+segment selector in aranges?).
Yes. This. The system mostly provides us the ability to disambiguate
addresses because the device's simulator / debugger make this
unambiguous, but the current .debug_aranges does not allow us to do this
because it's missing such info.
> Actually, coming at it from a different angle: It sounds like in the
> original email you're suggesting if debug_aranges did not contain data
> addresses, this would be good/sufficient for you? So somehow you'd be
> ensuring you only query debug_aranges using things you know are code
> addresses, not data addresses? So why would the same solution/approach
> not
> hold to querying low/high/ranges on a CU that's already guaranteed not
> to
> contain data addresses?
That's the root of the issue: the .debug_aranges section emitted by llvm
*does* contain data addresses by default and therefore can be ambiguous.
I've worked around this locally by hacking llvm to only emit aranges for
text objects,

Sorry, but I'm still not understanding why "aranges for only text objects" is more usable for your use case than "high/low/ranges on the CU"? Could you help me understand how those are different in your situation?

but I was wandering if it's something that's valuable to
fix upstream. My guess is that it's probably too niche to worry about
for the moment, but if there's interest I can propose a design (probably
a target hook to ask if segment selectors are required and how to get
their number from an object).

Added a few debug info folks in case they've got opinions. I don't really mind if we removed data objects from debug_aranges, though as you say, it's arguably correct/maybe useful as-is. Supporting it properly - probably using address segment selectors would be fine too, I guess AVR uses address spaces for its pointers to differentiate data and code addresses? In which case we could encode the LLVM address space as the segment selector (& probably would need to query the target to decide if it has non-zero address spaces and use that to decide whether to use segment selectors in debug_aranges)

But in general, I'm mostly just discouraging people from using aranges - the data is duplicated in the CU's ranges anyway (there's some small caveats there - a producer doesn't /have/ to produce ranges on the CU, but I'd just say lower performance on such DWARF would be acceptable) & makes object files/executables larger for minimal value/mostly duplicate data.

- Dave

Thanks for your help


Codeplay Software Ltd.
Company registered in England and Wales, number: 04567874
Registered office: Regent House, 316 Beulah Hill, London, SE19 3HF
LLVM Developers mailing list
llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200316/4f8d9666/attachment-0001.html>

More information about the llvm-dev mailing list