Skip to content

Commit

Permalink
read/pe: style changes for resource parsing (#427)
Browse files Browse the repository at this point in the history
  • Loading branch information
philipc authored Feb 17, 2022
1 parent 34076c0 commit 3ff2b10
Show file tree
Hide file tree
Showing 5 changed files with 291 additions and 276 deletions.
103 changes: 76 additions & 27 deletions crates/examples/src/readobj/pe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,48 +315,74 @@ fn print_resource_dir(
sections: &SectionTable,
data_directories: &DataDirectories,
) -> Option<()> {
let rsc_table = data_directories
.resource_directory_table(data, sections)
let directory = data_directories
.resource_directory(data, sections)
.print_err(p)??;
p.group("ResourceDirectory", |p| print_resource_table(p, &rsc_table));
let root = directory.root().print_err(p)?;
print_resource_table(p, directory, root, 0);
Some(())
}

fn print_resource_table(p: &mut Printer<'_>, table: &ResourceDirectoryTable<'_>) {
p.group("Directory", |p| {
fn print_resource_table(
p: &mut Printer<'_>,
directory: ResourceDirectory<'_>,
table: ResourceDirectoryTable<'_>,
level: usize,
) {
p.group("ImageResourceDirectory", |p| {
p.field("Characteristics", table.header.characteristics.get(LE));
p.field("TimeDateStamp", table.header.time_date_stamp.get(LE));
p.field("MajorVersion", table.header.major_version.get(LE));
p.field("MinorVersion", table.header.minor_version.get(LE));
p.field(
"Number of named entries",
table.table.number_of_named_entries.get(LE),
"NumberOfNamedEntries",
table.header.number_of_named_entries.get(LE),
);
p.field(
"Number of ID entries",
table.table.number_of_id_entries.get(LE),
"NumberOfIdEntries",
table.header.number_of_id_entries.get(LE),
);
p.group("Entries", |p| {
for e in table.iter() {
match e.name() {
ResourceNameOrId::Name(name) => match name.to_string_lossy() {
Ok(name) => p.field("Name", name),
Err(_) => p.field("Name", "Invalid"),
},
for entry in table.entries {
p.group("ImageResourceDirectoryEntry", |p| {
match entry.name_or_id() {
ResourceNameOrId::Name(name) => {
let offset = entry.name_or_id.get(LE);
if let Some(name) = name.to_string_lossy(directory).print_err(p) {
p.field_name("NameOrId");
writeln!(p.w, "\"{}\" (0x{:X})", name, offset).unwrap();
} else {
p.field_hex("NameOrId", offset);
}
}
ResourceNameOrId::Id(id) => {
p.field("Name ID", id);
if level == 0 {
p.field_enum("NameOrId", id, FLAGS_RT);
} else {
p.field("NameOrId", id);
}
}
}
p.field_hex(
"OffsetToDataOrDirectory",
entry.offset_to_data_or_directory.get(LE),
);

match e.data() {
Ok(ResourceDirectoryEntryData::Directory(table)) => {
print_resource_table(p, &table)
match entry.data(directory).print_err(p) {
Some(ResourceDirectoryEntryData::Table(table)) => {
print_resource_table(p, directory, table, level + 1)
}
Ok(ResourceDirectoryEntryData::Entry(rsc)) => {
p.field_hex("VirtualAddress", rsc.offset_to_data.get(LE));
p.field("Size", rsc.size.get(LE));
p.field("Code page", rsc.code_page.get(LE));
Some(ResourceDirectoryEntryData::Data(data_entry)) => {
p.group("ImageResourceDataEntry", |p| {
p.field_hex("VirtualAddress", data_entry.offset_to_data.get(LE));
p.field("Size", data_entry.size.get(LE));
p.field("CodePage", data_entry.code_page.get(LE));
p.field_hex("Reserved", data_entry.reserved.get(LE));
});
}
_ => p.field("Data", "Invalid"),
None => {}
}
}
});
});
}
})
}

Expand Down Expand Up @@ -1074,3 +1100,26 @@ static FLAGS_IMAGE_REL_RISCV_BASED: &[Flag<u16>] = &flags!(
IMAGE_REL_BASED_RISCV_LOW12I,
IMAGE_REL_BASED_RISCV_LOW12S,
);
static FLAGS_RT: &[Flag<u16>] = &flags!(
RT_CURSOR,
RT_BITMAP,
RT_ICON,
RT_MENU,
RT_DIALOG,
RT_STRING,
RT_FONTDIR,
RT_FONT,
RT_ACCELERATOR,
RT_RCDATA,
RT_MESSAGETABLE,
RT_GROUP_CURSOR,
RT_GROUP_ICON,
RT_VERSION,
RT_DLGINCLUDE,
RT_PLUGPLAY,
RT_VXD,
RT_ANICURSOR,
RT_ANIICON,
RT_HTML,
RT_MANIFEST,
);
50 changes: 33 additions & 17 deletions crates/examples/testfiles/pe/base-gnu.exe.readobj
Original file line number Diff line number Diff line change
Expand Up @@ -15687,25 +15687,41 @@ ImageBaseRelocation {
Type: IMAGE_REL_BASED_DIR64 (0xA)
Addend: 0x140001690
}
ResourceDirectory {
Directory {
Number of named entries: 0
Number of ID entries: 1
Entries {
Name ID: 24
Directory {
Number of named entries: 0
Number of ID entries: 1
Entries {
Name ID: 1
Directory {
Number of named entries: 0
Number of ID entries: 1
Entries {
Name ID: 0
ImageResourceDirectory {
Characteristics: 0
TimeDateStamp: 0
MajorVersion: 0
MinorVersion: 0
NumberOfNamedEntries: 0
NumberOfIdEntries: 1
ImageResourceDirectoryEntry {
NameOrId: RT_MANIFEST (0x18)
OffsetToDataOrDirectory: 0x80000018
ImageResourceDirectory {
Characteristics: 0
TimeDateStamp: 0
MajorVersion: 0
MinorVersion: 0
NumberOfNamedEntries: 0
NumberOfIdEntries: 1
ImageResourceDirectoryEntry {
NameOrId: 1
OffsetToDataOrDirectory: 0x80000030
ImageResourceDirectory {
Characteristics: 0
TimeDateStamp: 0
MajorVersion: 0
MinorVersion: 0
NumberOfNamedEntries: 0
NumberOfIdEntries: 1
ImageResourceDirectoryEntry {
NameOrId: 0
OffsetToDataOrDirectory: 0x48
ImageResourceDataEntry {
VirtualAddress: 0x10058
Size: 1167
Code page: 0
CodePage: 0
Reserved: 0x0
}
}
}
Expand Down
46 changes: 46 additions & 0 deletions src/pe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2062,12 +2062,58 @@ pub struct ImageResourceDirStringU {
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct ImageResourceDataEntry {
/// RVA of the data.
pub offset_to_data: U32<LE>,
pub size: U32<LE>,
pub code_page: U32<LE>,
pub reserved: U32<LE>,
}

// Resource type: https://docs.microsoft.com/en-us/windows/win32/menurc/resource-types

/// ID for: Hardware-dependent cursor resource.
pub const RT_CURSOR: u16 = 1;
/// ID for: Bitmap resource.
pub const RT_BITMAP: u16 = 2;
/// ID for: Hardware-dependent icon resource.
pub const RT_ICON: u16 = 3;
/// ID for: Menu resource.
pub const RT_MENU: u16 = 4;
/// ID for: Dialog box.
pub const RT_DIALOG: u16 = 5;
/// ID for: String-table entry.
pub const RT_STRING: u16 = 6;
/// ID for: Font directory resource.
pub const RT_FONTDIR: u16 = 7;
/// ID for: Font resource.
pub const RT_FONT: u16 = 8;
/// ID for: Accelerator table.
pub const RT_ACCELERATOR: u16 = 9;
/// ID for: Application-defined resource (raw data).
pub const RT_RCDATA: u16 = 10;
/// ID for: Message-table entry.
pub const RT_MESSAGETABLE: u16 = 11;
/// ID for: Hardware-independent cursor resource.
pub const RT_GROUP_CURSOR: u16 = 12;
/// ID for: Hardware-independent icon resource.
pub const RT_GROUP_ICON: u16 = 14;
/// ID for: Version resource.
pub const RT_VERSION: u16 = 16;
/// ID for: Allows a resource editing tool to associate a string with an .rc file.
pub const RT_DLGINCLUDE: u16 = 17;
/// ID for: Plug and Play resource.
pub const RT_PLUGPLAY: u16 = 19;
/// ID for: VXD.
pub const RT_VXD: u16 = 20;
/// ID for: Animated cursor.
pub const RT_ANICURSOR: u16 = 21;
/// ID for: Animated icon.
pub const RT_ANIICON: u16 = 22;
/// ID for: HTML resource.
pub const RT_HTML: u16 = 23;
/// ID for: Side-by-Side Assembly Manifest.
pub const RT_MANIFEST: u16 = 24;

//
// Code Integrity in loadconfig (CI)
//
Expand Down
14 changes: 6 additions & 8 deletions src/read/pe/data_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ use core::slice;
use crate::read::{Error, ReadError, ReadRef, Result};
use crate::{pe, LittleEndian as LE};

use super::{
ExportTable, ImportTable, RelocationBlockIterator, ResourceDirectoryTable, SectionTable,
};
use super::{ExportTable, ImportTable, RelocationBlockIterator, ResourceDirectory, SectionTable};

/// The table of data directories in a PE file.
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -123,20 +121,20 @@ impl<'data> DataDirectories<'data> {
Ok(Some(RelocationBlockIterator::new(reloc_data)))
}

/// Returns the root resource directory table.
/// Returns the resource directory.
///
/// `data` must be the entire file data.
pub fn resource_directory_table<R: ReadRef<'data>>(
pub fn resource_directory<R: ReadRef<'data>>(
&self,
data: R,
sections: &SectionTable<'data>,
) -> Result<Option<ResourceDirectoryTable<'data>>> {
) -> Result<Option<ResourceDirectory<'data>>> {
let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_RESOURCE) {
Some(data_dir) => data_dir,
None => return Ok(None),
};
let rsc_data = data_dir.data(data, sections)?;
ResourceDirectoryTable::parse(rsc_data).map(Some)
let rsrc_data = data_dir.data(data, sections)?;
Ok(Some(ResourceDirectory::new(rsrc_data)))
}
}

Expand Down
Loading

0 comments on commit 3ff2b10

Please sign in to comment.