-
Notifications
You must be signed in to change notification settings - Fork 158
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
Get proper name for over-8-character sections #100
Changes from 1 commit
39b1829
3ece54d
3478f94
a15b6f6
9ca571b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,10 @@ use scroll::{self, Pread}; | |
use error; | ||
|
||
#[repr(C)] | ||
#[derive(Debug, PartialEq, Copy, Clone, Default)] | ||
#[derive(Debug, PartialEq, Clone, Default)] | ||
pub struct SectionTable { | ||
pub name: [u8; 8], | ||
pub real_name: Option<String>, | ||
pub virtual_size: u32, | ||
pub virtual_address: u32, | ||
pub size_of_raw_data: u32, | ||
|
@@ -19,12 +20,13 @@ pub struct SectionTable { | |
pub const SIZEOF_SECTION_TABLE: usize = 8 * 5; | ||
|
||
impl SectionTable { | ||
pub fn parse(bytes: &[u8], offset: &mut usize) -> error::Result<Self> { | ||
pub fn parse(bytes: &[u8], offset: &mut usize, string_table_offset: usize) -> error::Result<Self> { | ||
let mut table = SectionTable::default(); | ||
let mut name = [0u8; 8]; | ||
for i in 0..8 { | ||
name[i] = bytes.gread_with(offset, scroll::LE)?; | ||
} | ||
|
||
table.name = name; | ||
table.virtual_size = bytes.gread_with(offset, scroll::LE)?; | ||
table.virtual_address = bytes.gread_with(offset, scroll::LE)?; | ||
|
@@ -35,10 +37,25 @@ impl SectionTable { | |
table.number_of_relocations = bytes.gread_with(offset, scroll::LE)?; | ||
table.number_of_linenumbers = bytes.gread_with(offset, scroll::LE)?; | ||
table.characteristics = bytes.gread_with(offset, scroll::LE)?; | ||
|
||
// Based on https://github.com/llvm-mirror/llvm/blob/af7b1832a03ab6486c42a40d21695b2c03b2d8a3/lib/Object/COFFObjectFile.cpp#L1054 | ||
if name[0] == b'/' { | ||
let idx: usize = if name[1] == b'/' { | ||
// TODO: Base-64 encoding | ||
panic!("At the disco") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume this panic (at the disco) will disappear in the final PR? |
||
} else { | ||
name[1..].pread::<&str>(0)?.parse().unwrap() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}; | ||
table.real_name = Some(bytes.pread::<&str>(string_table_offset + idx)?.to_string()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since you're writing directly into a field whose type is statically known, i believe you can remove the It might also be a good time to make this struct zero copy w.r.t. strings, but maybe who cares? since this probably isn't super common and copying some section names isn't a big deal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The type annotation is necessary, rust can't infer the type otherwise. WRT zero-copy, I could do this pretty easy, just have to tuck a lifetime on the struct. Would you prefer this approach? For what it's worth, this pattern is pretty common on MinGW binaries. Most of their sections are setup this way. |
||
} | ||
Ok(table) | ||
} | ||
|
||
pub fn name(&self) -> error::Result<&str> { | ||
Ok(self.name.pread(0)?) | ||
match self.real_name.as_ref() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you need this as_ref() here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I run into borrow errors otherwise. The second as_ref in the Some case isn't necessary though. |
||
Some(s) => Ok(s.as_ref()), | ||
None => Ok(self.name.pread(0)?) | ||
} | ||
} | ||
} | ||
|
||
|
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.
where does this magic 18 come from? I believe it should be a
const
with a (good) name, or at least a comment explaining itThere 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 is the size_of a single symbol in the table. Do we have a struct representing a Symbol in goblin ? I hardcoded 18, which is the common case scenario. But if we're handling a BigObj COFF (https://github.com/llvm-mirror/llvm/blob/af7b1832a03ab6486c42a40d21695b2c03b2d8a3/lib/Object/COFFObjectFile.cpp#L704), then that'll be wrong.
I believe goblin doesn't support bigobj coffs, though. I guess I'll put a comment about this, and put it in a const.