-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Dwarf 5 .debug_rnglists and .debug_loclists #272
Conversation
Note that these sections have an indirection scheme involving .debug_addr but I haven't encountered that being used yet so I haven't added support for it (nor do I fully understand it). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This is looking good.
There's a few minor things to fix that I've left comments for, some of these will apply to both locations and ranges.
The main thing we still need to work out is how we get a location list given an attribute with class loclist
(and similar for range lists). It'd be great if you could modify the dwarfdump example to do this, and test it on the binaries that gcc creates. But we can also leave that for followup work if you want, as long as we have an idea of how it is meant to work.
src/loc.rs
Outdated
/// Return true if this section is empty | ||
pub fn is_empty(&self) -> bool { | ||
self.debug_loc_section.is_empty() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this into the DebugLoc<R>
impl? Same for the other sections.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure
/// `FallibleIterator`](./index.html#using-with-fallibleiterator). | ||
pub fn locations( | ||
&self, | ||
offset: DebugLocOffset<R::Offset>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably should be a DebugLocListsOffset
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's easier to use if we share the same offset type for DebugLoc::locations
and DebugLocLists::locations
. Basically gcc is creating DW_AT_location
s with DW_FORM_sec_offset
; for Dwarf4 those are offsets into .debug_loc
, and in Dwarf5 those are offsets into .debug_loclists
. In my code that uses gimli, we try loading both sections and call locations
on whichever one is non-empty, passing the same offset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The difference in usability is small though, so I can make this change if you really want it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though I can imagine cases where people would want to store the location offset somewhere in way that's independent of Dwarf version; in that case having different offset types would force them to create their own enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, using DebugLocOffset
is fine then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible for a binary to have a mix of Dwarf4 and Dwarf5 units, so that neither section is empty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, but in that case I think DW_AT_location
with DW_FORM_sec_offset
would be ambiguous; I don't see any way to tell which section to look it up in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume we would base it on the compilation unit version. I'll investigate a bit later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is possible to have mixed Dwarf4 and Dwarf5, and I think you're probably right about using the compilation unit version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll fix this.
/// `FallibleIterator`](./index.html#using-with-fallibleiterator). | ||
pub fn ranges( | ||
&self, | ||
offset: DebugRangesOffset<R::Offset>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a DebugRngListsOffset
.
src/loclists.rs
Outdated
} | ||
|
||
fn parse_header<R: Reader>(input: &mut R) -> Result<LocListsHeader> { | ||
let (_, format) = parser::parse_initial_length(input)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to split the input at the length that is parsed, and return that. Have a look at what ArangeParser::parse_header
does for an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably isn't necessary, since we don't continue parsing that input currently.
src/loclists.rs
Outdated
return Err(Error::UnknownVersion(version as u64)); | ||
} | ||
let address_size = input.read_u8()?; | ||
let _segment_selector_size = input.read_u8()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're not going to implement segment selector support then we need to return an error if this is non-zero. Also, I tried to see what would be involved in supporting this, and I can't see where the segment selector is defined in the location list entries. Do you know anything about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I'll add the zero check. But I think we should panic for unsupported segment sizes.
src/loclists.rs
Outdated
}, | ||
_ => { | ||
// We don't support AddressIndex-based entries yet | ||
panic!("Unsupported loclists entry: {:?}", raw_loc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to return an error instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
src/loclists.rs
Outdated
|
||
impl<R: Reader> RawLocListEntry<R> { | ||
/// Parse a range entry from `.debug_rnglists` | ||
#[doc(hidden)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't need this attribute on a private function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
/// `FallibleIterator`](./index.html#using-with-fallibleiterator). | ||
pub fn raw_locations( | ||
&self, | ||
offset: DebugLocOffset<R::Offset>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably should be a DebugLocListsOffset
. However, I can't see in the standard where there are any attributes that contain an offset to a location list header, which is what this function currently wants. The loclist
and loclistsptr
classes are either a section offset for an offset table, an index into that offset table, or an offset to a location list.
So I'm not sure that this method is useful. But I'm also not sure how the location list headers are meant to be used in practice. Is the DWARF consumer meant to iterate over all location list headers and record their offset ranges, and then when there is a loclist
or loclistsptr
attribute, it needs to search to see which header to use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The offset here is an offset within the section to the start of a location list. There is no such thing as a "location list header" as far as I know. This corresponds to class loclistptr
or the DW_FORM_sec_offset
form of class loclist
in the Dwarf5 spec 7.5.5.
The section's offset table is used with DW_FORM_loclistx
and I haven't found gcc using that yet (and the .debug_loclists
sections I've seen so far don't have an offset table) so I'm not sure how it's supposed to work. I think we'd support that by adding alternative iterator construction methods, although possibly we could just detect that the offset is within the offset table.
raw_locations
is actually parsing the same section header every time we create a location list iterator. This is slightly inefficient, but the alternative is to parse the section header when we construct DebugLocLists
, in which case the construction needs to return a Result
, which means we can't use From
, which means we can't implement the Section
trait, which seems bad.
As for how these are used, see above. We take a DW_AT_location
DW_FORM_sec_offset
and pass it directly in here.
An attribute with There's a different approach using |
I can modify dwarfdump to handle |
Do you mean methods such as |
Ah, I was misreading what |
I think it's more accurate to say that the section has a header and the individual location lists do not. |
See sections 7.28 and 7.29 in the spec. |
Updating |
I guess I can avoid the replication by iterating over the raw and cooked entries together... |
Ah yeah that code is a bit messy. Dumping only the cooked entries would be fine too. It doesn't need to match what's there already. |
Dumping the raw entries could actually be useful though. |
I'm encountering a good example of where deny(missing_docs) gets annoying, e.g.
Never mind I guess... |
I removed the |
gcc 7.2.1 uses Sdata for a FileIndex so this needs to work.
Just wanted to pop in and say thanks for the PR @rocallahan ! |
Thanks @rocallahan ! |
You're welcome! |
gcc 7.2.1, for example, uses these when you specify
-gdwarf-5
.