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

PE: Add base relocation parser #444

Merged
merged 11 commits into from
Apr 10, 2025
Merged

PE: Add base relocation parser #444

merged 11 commits into from
Apr 10, 2025

Conversation

kkent030315
Copy link
Contributor

@kkent030315 kkent030315 commented Jan 17, 2025

It was a little bit surprise for me that goblin does not have a parser for base relocations in PE besides COFF relocations.

  • Added parser for IMAGE_DIRECTORY_ENTRY_BASERELOC directory.
  • Added COFF relocation type constants for ARM, ARM64 and IA64.
  • Added PE generic relocations type constants. (COFF and PE relocations are different things)

@kkent030315
Copy link
Contributor Author

@m4b Hi there, I'd like to get review and see if this worth merging. Thank you very much for your attention (as always)!

kkent030315 added a commit to kkent030315/goblin-experimental that referenced this pull request Mar 26, 2025
Copy link
Owner

@m4b m4b left a comment

Choose a reason for hiding this comment

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

the only issue is have is the temproary empty &[] i mentioned in a comment. not sure if there is a better way.

only other thing is very minor nit about missing pub docs on the simpler items, but it's fine, the other documentation is excellent, thank you!

otherwise, this is great!

i'll sit on this a bit to think if there's a better design (or if you think of one) w.r.t. &[] otherwise i'll merge.

one option is to hide the TryFromCtx impl in some way, though I don't see that being feasible without annoying things.

Comment on lines 350 to 359
if offset + dd.size as usize > bytes.len() {
return Err(error::Error::Malformed(format!(
"base reloc offset {:#x} and size {:#x} exceeds the bounds of the bytes size {:#x}",
offset,
dd.size,
bytes.len()
)));
}

let bytes = &bytes[offset..offset + dd.size as usize];
Copy link
Owner

Choose a reason for hiding this comment

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

it doesn't matter now but i wonder if a better pattern here to use is something like:

let size = dd.size as usize;
let bytes = bytes[offset..].pread::<&[u8]>(size).map_err(|_| TheErrorWeWantToDisplay)?;

it's just easy to copy-pasta the bounds error, and slice the wrong bounds that were different than what we checked, etc. anyway, not too important.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wow, didn't know that there's such a great expression. Thanks!

let mut offset = 0;
let rva = bytes.gread_with::<u32>(&mut offset, ctx)?;
let size = bytes.gread_with::<u32>(&mut offset, ctx)?;
let bytes = &[];
Copy link
Owner

Choose a reason for hiding this comment

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

why?

// "Block"s and "Word"s are entirely contiguous
self.offset += word_size;
Ok(RelocationBlock {
bytes: word_bytes,
Copy link
Owner

Choose a reason for hiding this comment

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

i see, this gets rewritten later. hmmm, one thing i don't like is that temporarily, if someone were to use that raw TryFromCtx impl the bytes is empty, which feels "half-constructed" to me, which is generally a pattern i like to avoid.

however, not sure there is a better solution here, other than making it optional, which also feels a little laborious and still doesn't capture semantic meaning that well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's been quite a while since I wrote the code and I have no idea why did I chose to do this ugly.. anyway, I fixed that. It was trivial to just merge that construction into the TryFromCtx for RelocationBlock.

Copy link
Owner

@m4b m4b left a comment

Choose a reason for hiding this comment

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

This is super awesome PR thank you for revising and fixing the half constructed thing.

I’d merge except I think we don’t need repr(C) on the struct, and it’ll be a new pub item so good to get it right.

again this is awesome sorry took so long to get it merged but almost there :)

@m4b m4b merged commit bc33409 into m4b:master Apr 10, 2025
6 checks passed
@m4b
Copy link
Owner

m4b commented Apr 10, 2025

NB: backwards compatible

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.

2 participants