-
-
Notifications
You must be signed in to change notification settings - Fork 78
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
Add ElfObject::debug_link #450
Conversation
7eea04d
to
3c3a8b9
Compare
Apologies, I had missed a bare link. |
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.
Generally looks good I think, though I'm not very comfortable with all the .expect()
calls and would prefer if this would return an error code instead, even though these should never happen (programming errors always happen at some point).
symbolic-debuginfo/src/elf.rs
Outdated
|
||
// let's be liberal and assume that the padding is correct and all 0s, | ||
// and just check that we have enough remaining length for the CRC. | ||
if data.len() <= filename_len_with_nul + 4 { |
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.
IIUC the expected length is supposed to be filename_len_with_null + (filename_len_with_nul % 4) + 4
. Does it not make sense to check that size exactly here?
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.
You understand correctly.
Doing the check depends on where you stand wrt strictness of parsers. For example, in PE we often see binaries that don't completely respect the specification, but are still run successfully by Windows. A strict parser will not be able to retrieve information from these PE files though. OTOH, a liberal parser might occasionally retrieve wrong information (here, we could get a truncated CRC with a byte of padding if the CRC is not actually of 4 bytes and we have a byte of padding).
I have no idea of the prevalence of this problem in the gnu_debuglink section though.
If you are more comfortable with a strict parser, I can update the code to do a stricter length check, and let the user do their own parsing if they want to recover for malformed sections (this is why the error type exposes the original data section contents).
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.
Yeah, you have a good point about being lenient when parsing. I'm not sure what usually the symbolic behaviour is, maybe @jan-auer can chime in?
symbolic-debuginfo/src/elf.rs
Outdated
|
||
let crc = match endianity { | ||
Endian::Little => { | ||
u32::from_le_bytes(data[data.len() - 4..].try_into().expect("wrong size")) |
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.
Out of an abundance of caution I"d be tempted to use data.get(...)
instead of direct slicing here. Though the checks before do make sure this can't happen but hey.
I'm also a bit uncomfortable about using .expect()
for the same reason, another error variant can do this without panicking code.
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 understand that seeing expect()
is not a reassuring sight, especially in code by a new contributor 😅.
I'll try to refactor the code because I believe we can remove the expects here.
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 pushed a new version of the diff that removes all expect()
calls.
Thank you for the swift review! I will take another try to remove the |
I pushed a new version of the diff that removes all expect() calls. I had to refactor a bit the code, and the vector is no longer reused when the Cow was originally owned (I couldn't remove that particular instance of expect otherwise, as I couldn't recover the original data after truncating the vector). DebugLinkError has been split into its kind (without lifetime, for my sanity), and its original data. I see no difference in behavior with the previous version when running my (manual) tests again |
If the new version is good for you, I can squash my commits |
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 think this looks good, thanks for making the changes!
If you're squashing the changes anyway, mind adding an entry to the changelog with Unreleased
as version name in the section?
oh, i forgot to write about tests, it would still be very nice to add some. What I'd propose is that you make a tiny hello world binary compiled with the debug link, hopefully the resulting debug info is not too large to put into Do you think that's reasonable? |
Thanks again for the review!
Sure! Will do!
Yes, your proposition looks good. I'm just unsure how the fixtures work exactly. Do you have any pointer on how I should add new fixtures? Otherwise I can attach the binaries (and/or its source, if you prefer to build it yourself) when I have it, so that you can "fixturize" it? First, I will write the tests and produce the binaries and get back to you. |
You save the files and open them directly in the test code, e.g. looking at an existing file in the fixtures directory yields
It would be nice to have the source of the fixture in the repo as well i guess with a tiny script or comment on how to produce the |
OK, I was thinking they were generated in some way due to the UUID in the filename 😅 I will do that and then update! |
Heh, in that case the filename is important because the filename is a DebugID and it is part of the test that the filename is parsed correctly. But otherwise the filename has no significance, whatever works for your test and makes sense. |
I pushed a new version:
Tell me what you think :-) |
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.
Very thorough testing, thanks!
cd $OUTPUT | ||
|
||
# 1. compile our C example. To keep size low, let's compile the simplest program we can write. | ||
cc -x c -Os -o elf_without_debuglink - << EOF |
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.
isn't the debuglink a GCC-specific thing? should this be directly gcc? Or is this a POSIX thing?
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.
Since the debuginfo is added to the ELF afterwards using objcopy
and is fake anyway (for testing purposes), I'm not sure if this can pose a problem.
It is no harm to change it though, since apparently I failed to run clippy on the tests and need to update 👀.
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.
Changed (FTR, I probably missed the clippy error due to running cargo clippy
instead of cargo clippy --all-features --workspace --tests --examples -- -D clippy::all
like the CI)
Thanks you very much for the PR and following up on everything! ❤️ |
Well thank you for the review, it has been my pleasure! 👍 |
Hello 👋,
I needed
ElfObject
to expose the debug link of the ELF. The debug link is one of the means (together with the build ID) for GDB to specify the location of a separate debug info file (see here for more information). This allows eg debuggers to find the debug files even when the build id is not specified.This PR adds support for exposing the debug link as a
CStr
with its CRC.Tests
Tested manually on binaries of two systems (manjaro current and Debian stretch): made sure that the executable below would return the same debug_link filename as
readelf --string-dump=.gnu_debuglink <binary>
. I'm not sure how to automate the tests though.Thank you for your time and consideration!