Skip to content
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

Implement writing of .debug_info, .debug_abbrev and .debug_str #340

Merged
merged 4 commits into from
Nov 19, 2018

Conversation

philipc
Copy link
Collaborator

@philipc philipc commented Nov 9, 2018

Also implements reading debug sections and converting into the write data structures.

@coveralls
Copy link

coveralls commented Nov 9, 2018

Coverage Status

Coverage increased (+0.9%) to 86.541% when pulling 1362c16 on philipc:write into 2138f48 on gimli-rs:master.

@philipc philipc changed the title [WIP] Implement writing of .debug_info, .debug_abbrev and .debug_str Implement writing of .debug_info, .debug_abbrev and .debug_str Nov 15, 2018
@philipc philipc requested a review from fitzgen November 15, 2018 06:26
@philipc
Copy link
Collaborator Author

philipc commented Nov 15, 2018

This now has good test coverage and minimal docs.

Some notes about the implementation:

  • This is more of a higher level builder API, rather than low-level writes. This is required though in order to correctly handle references.
  • References are stored as Id values (eg UnitEntryId), rather than offsets. When writing, these are initially written as zeroes, then we go back and write the offsets once we know what they are. Same for unit lengths.
  • A lot of AttributeValue variants still use offsets, but these will change to ids once we support writing more sections.
  • Relocations can be supported if the user implements Writer::write_address/write_offset (similar to what was done for reading relocations).

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

A few comments inline below, but nothing that should prevent this from landing, just follow ups and things to think about.

👍

@@ -241,5 +243,8 @@ pub mod read;
// For backwards compat.
pub use read::*;

#[cfg(feature = "std")]
pub mod write;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is worth having two traits: read and write that enable their corresponding modules. This way, compilers that are emitting DWARF don't need to pay compile time for DWARF reading, and a stack unwinder doesn't need to pay compile time for DWARF writing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do this in a follow up PR.

pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
w.write_uleb128(self.tag.0)?;
w.write_u8(if self.has_children {
constants::DW_CHILDREN_yes.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems our dw! macro for constants could also generate a thin little write method. Although, I suppose most of the time we want to write LEB128s, so maybe it wouldn't be super useful and this location would still be the exception.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about the usefulness:

  • they would be simple one line functions
  • many of them could be written in multiple forms that the caller would need to decide, since attribute values could potentially use either LEB128 or a fixed size, and this needs to match the form, so it's better to have this code closer to the form decision.

src/write/endian_vec.rs Show resolved Hide resolved
src/write/str.rs Outdated
// - able to get an existing value given an id
//
// Limitations of current implementation (using IndexSet):
// - inserting a duplicate requires an allocation or a double lookup
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of my longest standing annoyances with hash tables in Rust in general (mostly std, but apparently indexmap as well). I suspect a duplicated lookup is probably cheaper than an allocation (I haven't read further to see what you ended up implementing).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually allocation for duplicate, and double lookup for non-duplicate, so will depend on how often there are duplicates. I did the simplest (allocation), and we can change based on benchmarks.

src/write/str.rs Outdated Show resolved Hide resolved
parent: Option<UnitEntryId>,
tag: constants::DwTag,
/// Whether to emit `DW_AT_sibling`.
// TODO: should this be automatic?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What heuristics would we use to decide whether to emit this? Whether the children forest is of a certain size? It seems like maybe certain DIEs always end up having their children walked, while others are skipped past, so maybe there would be a whitelist of tags that should get the sibling links.

Anyways, agree that for now this should be manual.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking maybe we could do it based on a tag whitelist. The whitelist members would be chosen based on typical access patterns of debuggers/unwinders.

src/write/unit.rs Show resolved Hide resolved
@philipc
Copy link
Collaborator Author

philipc commented Nov 19, 2018

Thanks for the review @fitzgen! I've added a commit with doc fixes.

@philipc philipc merged commit 65748f8 into gimli-rs:master Nov 19, 2018
@philipc philipc deleted the write branch November 19, 2018 05:23
@bjorn3
Copy link
Contributor

bjorn3 commented Nov 19, 2018

Hooray

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants