Skip to content

Commit eae18b2

Browse files
committed
read/pe: style changes for resource parsing
1 parent 34076c0 commit eae18b2

File tree

5 files changed

+291
-276
lines changed

5 files changed

+291
-276
lines changed

crates/examples/src/readobj/pe.rs

+76-27
Original file line numberDiff line numberDiff line change
@@ -315,48 +315,74 @@ fn print_resource_dir(
315315
sections: &SectionTable,
316316
data_directories: &DataDirectories,
317317
) -> Option<()> {
318-
let rsc_table = data_directories
319-
.resource_directory_table(data, sections)
318+
let directory = data_directories
319+
.resource_directory(data, sections)
320320
.print_err(p)??;
321-
p.group("ResourceDirectory", |p| print_resource_table(p, &rsc_table));
321+
let root = directory.root().print_err(p)?;
322+
print_resource_table(p, directory, root, 0);
322323
Some(())
323324
}
324325

325-
fn print_resource_table(p: &mut Printer<'_>, table: &ResourceDirectoryTable<'_>) {
326-
p.group("Directory", |p| {
326+
fn print_resource_table(
327+
p: &mut Printer<'_>,
328+
directory: ResourceDirectory<'_>,
329+
table: ResourceDirectoryTable<'_>,
330+
level: usize,
331+
) {
332+
p.group("ImageResourceDirectory", |p| {
333+
p.field("Characteristics", table.header.characteristics.get(LE));
334+
p.field("TimeDateStamp", table.header.time_date_stamp.get(LE));
335+
p.field("MajorVersion", table.header.major_version.get(LE));
336+
p.field("MinorVersion", table.header.minor_version.get(LE));
327337
p.field(
328-
"Number of named entries",
329-
table.table.number_of_named_entries.get(LE),
338+
"NumberOfNamedEntries",
339+
table.header.number_of_named_entries.get(LE),
330340
);
331341
p.field(
332-
"Number of ID entries",
333-
table.table.number_of_id_entries.get(LE),
342+
"NumberOfIdEntries",
343+
table.header.number_of_id_entries.get(LE),
334344
);
335-
p.group("Entries", |p| {
336-
for e in table.iter() {
337-
match e.name() {
338-
ResourceNameOrId::Name(name) => match name.to_string_lossy() {
339-
Ok(name) => p.field("Name", name),
340-
Err(_) => p.field("Name", "Invalid"),
341-
},
345+
for entry in table.entries {
346+
p.group("ImageResourceDirectoryEntry", |p| {
347+
match entry.name_or_id() {
348+
ResourceNameOrId::Name(name) => {
349+
let offset = entry.name_or_id.get(LE);
350+
if let Some(name) = name.to_string_lossy(directory).print_err(p) {
351+
p.field_name("NameOrId");
352+
writeln!(p.w, "\"{}\" (0x{:X})", name, offset).unwrap();
353+
} else {
354+
p.field_hex("NameOrId", offset);
355+
}
356+
}
342357
ResourceNameOrId::Id(id) => {
343-
p.field("Name ID", id);
358+
if level == 0 {
359+
p.field_enum("NameOrId", id, FLAGS_RT);
360+
} else {
361+
p.field("NameOrId", id);
362+
}
344363
}
345364
}
365+
p.field_hex(
366+
"OffsetToDataOrDirectory",
367+
entry.offset_to_data_or_directory.get(LE),
368+
);
346369

347-
match e.data() {
348-
Ok(ResourceDirectoryEntryData::Directory(table)) => {
349-
print_resource_table(p, &table)
370+
match entry.data(directory).print_err(p) {
371+
Some(ResourceDirectoryEntryData::Table(table)) => {
372+
print_resource_table(p, directory, table, level + 1)
350373
}
351-
Ok(ResourceDirectoryEntryData::Entry(rsc)) => {
352-
p.field_hex("VirtualAddress", rsc.offset_to_data.get(LE));
353-
p.field("Size", rsc.size.get(LE));
354-
p.field("Code page", rsc.code_page.get(LE));
374+
Some(ResourceDirectoryEntryData::Data(data_entry)) => {
375+
p.group("ImageResourceDataEntry", |p| {
376+
p.field_hex("VirtualAddress", data_entry.offset_to_data.get(LE));
377+
p.field("Size", data_entry.size.get(LE));
378+
p.field("CodePage", data_entry.code_page.get(LE));
379+
p.field_hex("Reserved", data_entry.reserved.get(LE));
380+
});
355381
}
356-
_ => p.field("Data", "Invalid"),
382+
None => {}
357383
}
358-
}
359-
});
384+
});
385+
}
360386
})
361387
}
362388

@@ -1074,3 +1100,26 @@ static FLAGS_IMAGE_REL_RISCV_BASED: &[Flag<u16>] = &flags!(
10741100
IMAGE_REL_BASED_RISCV_LOW12I,
10751101
IMAGE_REL_BASED_RISCV_LOW12S,
10761102
);
1103+
static FLAGS_RT: &[Flag<u16>] = &flags!(
1104+
RT_CURSOR,
1105+
RT_BITMAP,
1106+
RT_ICON,
1107+
RT_MENU,
1108+
RT_DIALOG,
1109+
RT_STRING,
1110+
RT_FONTDIR,
1111+
RT_FONT,
1112+
RT_ACCELERATOR,
1113+
RT_RCDATA,
1114+
RT_MESSAGETABLE,
1115+
RT_GROUP_CURSOR,
1116+
RT_GROUP_ICON,
1117+
RT_VERSION,
1118+
RT_DLGINCLUDE,
1119+
RT_PLUGPLAY,
1120+
RT_VXD,
1121+
RT_ANICURSOR,
1122+
RT_ANIICON,
1123+
RT_HTML,
1124+
RT_MANIFEST,
1125+
);

crates/examples/testfiles/pe/base-gnu.exe.readobj

+33-17
Original file line numberDiff line numberDiff line change
@@ -15687,25 +15687,41 @@ ImageBaseRelocation {
1568715687
Type: IMAGE_REL_BASED_DIR64 (0xA)
1568815688
Addend: 0x140001690
1568915689
}
15690-
ResourceDirectory {
15691-
Directory {
15692-
Number of named entries: 0
15693-
Number of ID entries: 1
15694-
Entries {
15695-
Name ID: 24
15696-
Directory {
15697-
Number of named entries: 0
15698-
Number of ID entries: 1
15699-
Entries {
15700-
Name ID: 1
15701-
Directory {
15702-
Number of named entries: 0
15703-
Number of ID entries: 1
15704-
Entries {
15705-
Name ID: 0
15690+
ImageResourceDirectory {
15691+
Characteristics: 0
15692+
TimeDateStamp: 0
15693+
MajorVersion: 0
15694+
MinorVersion: 0
15695+
NumberOfNamedEntries: 0
15696+
NumberOfIdEntries: 1
15697+
ImageResourceDirectoryEntry {
15698+
NameOrId: RT_MANIFEST (0x18)
15699+
OffsetToDataOrDirectory: 0x80000018
15700+
ImageResourceDirectory {
15701+
Characteristics: 0
15702+
TimeDateStamp: 0
15703+
MajorVersion: 0
15704+
MinorVersion: 0
15705+
NumberOfNamedEntries: 0
15706+
NumberOfIdEntries: 1
15707+
ImageResourceDirectoryEntry {
15708+
NameOrId: 1
15709+
OffsetToDataOrDirectory: 0x80000030
15710+
ImageResourceDirectory {
15711+
Characteristics: 0
15712+
TimeDateStamp: 0
15713+
MajorVersion: 0
15714+
MinorVersion: 0
15715+
NumberOfNamedEntries: 0
15716+
NumberOfIdEntries: 1
15717+
ImageResourceDirectoryEntry {
15718+
NameOrId: 0
15719+
OffsetToDataOrDirectory: 0x48
15720+
ImageResourceDataEntry {
1570615721
VirtualAddress: 0x10058
1570715722
Size: 1167
15708-
Code page: 0
15723+
CodePage: 0
15724+
Reserved: 0x0
1570915725
}
1571015726
}
1571115727
}

src/pe.rs

+46
Original file line numberDiff line numberDiff line change
@@ -2062,12 +2062,58 @@ pub struct ImageResourceDirStringU {
20622062
#[derive(Debug, Clone, Copy)]
20632063
#[repr(C)]
20642064
pub struct ImageResourceDataEntry {
2065+
/// RVA of the data.
20652066
pub offset_to_data: U32<LE>,
20662067
pub size: U32<LE>,
20672068
pub code_page: U32<LE>,
20682069
pub reserved: U32<LE>,
20692070
}
20702071

2072+
// Resource type: https://docs.microsoft.com/en-us/windows/win32/menurc/resource-types
2073+
2074+
/// ID for: Hardware-dependent cursor resource.
2075+
pub const RT_CURSOR: u16 = 1;
2076+
/// ID for: Bitmap resource.
2077+
pub const RT_BITMAP: u16 = 2;
2078+
/// ID for: Hardware-dependent icon resource.
2079+
pub const RT_ICON: u16 = 3;
2080+
/// ID for: Menu resource.
2081+
pub const RT_MENU: u16 = 4;
2082+
/// ID for: Dialog box.
2083+
pub const RT_DIALOG: u16 = 5;
2084+
/// ID for: String-table entry.
2085+
pub const RT_STRING: u16 = 6;
2086+
/// ID for: Font directory resource.
2087+
pub const RT_FONTDIR: u16 = 7;
2088+
/// ID for: Font resource.
2089+
pub const RT_FONT: u16 = 8;
2090+
/// ID for: Accelerator table.
2091+
pub const RT_ACCELERATOR: u16 = 9;
2092+
/// ID for: Application-defined resource (raw data).
2093+
pub const RT_RCDATA: u16 = 10;
2094+
/// ID for: Message-table entry.
2095+
pub const RT_MESSAGETABLE: u16 = 11;
2096+
/// ID for: Hardware-independent cursor resource.
2097+
pub const RT_GROUP_CURSOR: u16 = 12;
2098+
/// ID for: Hardware-independent icon resource.
2099+
pub const RT_GROUP_ICON: u16 = 14;
2100+
/// ID for: Version resource.
2101+
pub const RT_VERSION: u16 = 16;
2102+
/// ID for: Allows a resource editing tool to associate a string with an .rc file.
2103+
pub const RT_DLGINCLUDE: u16 = 17;
2104+
/// ID for: Plug and Play resource.
2105+
pub const RT_PLUGPLAY: u16 = 19;
2106+
/// ID for: VXD.
2107+
pub const RT_VXD: u16 = 20;
2108+
/// ID for: Animated cursor.
2109+
pub const RT_ANICURSOR: u16 = 21;
2110+
/// ID for: Animated icon.
2111+
pub const RT_ANIICON: u16 = 22;
2112+
/// ID for: HTML resource.
2113+
pub const RT_HTML: u16 = 23;
2114+
/// ID for: Side-by-Side Assembly Manifest.
2115+
pub const RT_MANIFEST: u16 = 24;
2116+
20712117
//
20722118
// Code Integrity in loadconfig (CI)
20732119
//

src/read/pe/data_directory.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ use core::slice;
33
use crate::read::{Error, ReadError, ReadRef, Result};
44
use crate::{pe, LittleEndian as LE};
55

6-
use super::{
7-
ExportTable, ImportTable, RelocationBlockIterator, ResourceDirectoryTable, SectionTable,
8-
};
6+
use super::{ExportTable, ImportTable, RelocationBlockIterator, ResourceDirectory, SectionTable};
97

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

126-
/// Returns the root resource directory table.
124+
/// Returns the resource directory.
127125
///
128126
/// `data` must be the entire file data.
129-
pub fn resource_directory_table<R: ReadRef<'data>>(
127+
pub fn resource_directory<R: ReadRef<'data>>(
130128
&self,
131129
data: R,
132130
sections: &SectionTable<'data>,
133-
) -> Result<Option<ResourceDirectoryTable<'data>>> {
131+
) -> Result<Option<ResourceDirectory<'data>>> {
134132
let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_RESOURCE) {
135133
Some(data_dir) => data_dir,
136134
None => return Ok(None),
137135
};
138-
let rsc_data = data_dir.data(data, sections)?;
139-
ResourceDirectoryTable::parse(rsc_data).map(Some)
136+
let rsrc_data = data_dir.data(data, sections)?;
137+
Ok(Some(ResourceDirectory::new(rsrc_data)))
140138
}
141139
}
142140

0 commit comments

Comments
 (0)