Skip to content

Commit a38d471

Browse files
committed
Avoid requiring aligned access to COFF fields.
And fix lints.
1 parent 08dcc1c commit a38d471

File tree

3 files changed

+131
-69
lines changed

3 files changed

+131
-69
lines changed

src/dll_import_lib/ar.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ use super::string_table::StringTable;
7979
use super::DataWriter;
8080

8181
#[derive(Copy, Clone)]
82-
pub(crate) struct MemberName(pub [u8; 16]);
82+
pub(crate) struct MemberName(pub(crate) [u8; 16]);
8383

8484
impl MemberName {
8585
pub(crate) const SYMBOL_TABLE: Self = MemberName(*b"/ ");
@@ -153,6 +153,7 @@ pub(crate) struct Member<'data> {
153153
pub(crate) header_offset: usize,
154154
}
155155

156+
#[allow(dead_code)] // TODO: remove if this isn't pulled out into a crate?
156157
impl<'data> Member<'data> {
157158
const HEADER_SIZE: usize = std::mem::size_of::<object::archive::Header>();
158159

src/dll_import_lib/coff.rs

Lines changed: 125 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -43,48 +43,68 @@
4343
// 4: sequence of null-terminated strings
4444

4545
use object::pe::*;
46-
use object::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32};
46+
use object::{LittleEndian as LE, U16Bytes, U32Bytes};
4747
use std::ops::{Deref, DerefMut};
4848

4949
use super::data::DataWriter;
5050
use super::string_table::StringTable;
5151

5252
pub(crate) const NULL_IMPORT_DESCRIPTOR_SYMBOL: &str = "__NULL_IMPORT_DESCRIPTOR";
5353

54-
fn u16_aligned(value: u16) -> U16<LE> {
55-
U16::new(LE, value)
54+
fn u16(value: u16) -> U16Bytes<LE> {
55+
U16Bytes::new(LE, value)
5656
}
5757

58-
fn u32_aligned(value: u32) -> U32<LE> {
59-
U32::new(LE, value)
58+
fn u32(value: u32) -> U32Bytes<LE> {
59+
U32Bytes::new(LE, value)
6060
}
6161

62-
fn u16_unaligned(value: u16) -> U16Bytes<LE> {
63-
U16Bytes::new(LE, value)
62+
#[derive(Debug, Clone, Copy)]
63+
#[repr(C)]
64+
pub(crate) struct ImportObjectHeaderUnaligned {
65+
/// Must be IMAGE_FILE_MACHINE_UNKNOWN
66+
pub(crate) sig1: U16Bytes<LE>,
67+
/// Must be IMPORT_OBJECT_HDR_SIG2.
68+
pub(crate) sig2: U16Bytes<LE>,
69+
pub(crate) version: U16Bytes<LE>,
70+
pub(crate) machine: U16Bytes<LE>,
71+
/// Time/date stamp
72+
pub(crate) time_date_stamp: U32Bytes<LE>,
73+
/// particularly useful for incremental links
74+
pub(crate) size_of_data: U32Bytes<LE>,
75+
76+
/// if grf & IMPORT_OBJECT_ORDINAL
77+
pub(crate) ordinal_or_hint: U16Bytes<LE>,
78+
79+
// WORD Type : 2;
80+
// WORD NameType : 3;
81+
// WORD Reserved : 11;
82+
pub(crate) name_type: U16Bytes<LE>,
6483
}
6584

66-
fn u32_unaligned(value: u32) -> U32Bytes<LE> {
67-
U32Bytes::new(LE, value)
68-
}
85+
/// # Safety
86+
/// A type that is `Pod` must:
87+
/// - be `#[repr(C)]` or `#[repr(transparent)]`
88+
/// - have no invalid byte values
89+
/// - have no padding
90+
unsafe impl object::pod::Pod for ImportObjectHeaderUnaligned {}
6991

7092
pub(crate) fn write_short_import(
7193
data: &mut DataWriter,
7294
dll_name: &str,
7395
name: &&str,
74-
ordinal_or_hint: Option<u16>,
96+
ordinal_or_hint: Option<std::primitive::u16>,
7597
) {
76-
data.write_pod(&ImportObjectHeader {
77-
sig1: u16_aligned(IMAGE_FILE_MACHINE_UNKNOWN),
78-
sig2: u16_aligned(IMPORT_OBJECT_HDR_SIG2),
79-
version: u16_aligned(0),
80-
machine: u16_aligned(IMAGE_FILE_MACHINE_AMD64),
81-
time_date_stamp: u32_aligned(0),
82-
size_of_data: u32_aligned((name.len() + 1 + dll_name.len() + 1) as u32),
83-
ordinal_or_hint: u16_aligned(ordinal_or_hint.unwrap_or_default()),
84-
name_type: u16_aligned(
85-
IMPORT_OBJECT_CODE << IMPORT_OBJECT_TYPE_SHIFT
86-
| IMPORT_OBJECT_NAME << IMPORT_OBJECT_NAME_SHIFT,
87-
),
98+
data.write_pod(&ImportObjectHeaderUnaligned {
99+
sig1: u16(IMAGE_FILE_MACHINE_UNKNOWN),
100+
sig2: u16(IMPORT_OBJECT_HDR_SIG2),
101+
version: u16(0),
102+
machine: u16(IMAGE_FILE_MACHINE_AMD64),
103+
time_date_stamp: u32(0),
104+
size_of_data: u32((name.len() + 1 + dll_name.len() + 1) as u32),
105+
ordinal_or_hint: u16(ordinal_or_hint.unwrap_or_default()),
106+
name_type: u16(IMPORT_OBJECT_CODE << IMPORT_OBJECT_TYPE_SHIFT
107+
| IMPORT_OBJECT_NAME << IMPORT_OBJECT_NAME_SHIFT),
88108
});
89109
data.write_c_str(name);
90110
data.write_c_str(dll_name);
@@ -143,29 +163,29 @@ pub(crate) fn write_import_descriptor(
143163
let import_descriptor_pointer_to_relocations = file.data.len() - file.offset;
144164

145165
let header = import_directory_header.get_mut(file.data);
146-
header.number_of_relocations = u16_aligned(3);
166+
header.number_of_relocations = u16(3);
147167

148-
header.pointer_to_relocations = u32_aligned(import_descriptor_pointer_to_relocations as u32);
168+
header.pointer_to_relocations = u32(import_descriptor_pointer_to_relocations as u32);
149169

150170
// todo: CoffRelocWriter
151171

152172
// relocation 0: [3] import lookup table rva => points to UNDEF symbol .idata$4
153173
file.data.write_pod(&ImageRelocation {
154-
virtual_address: u32_unaligned(0),
155-
symbol_table_index: u32_unaligned(3),
156-
typ: u16_unaligned(IMAGE_REL_AMD64_ADDR32NB),
174+
virtual_address: u32(0),
175+
symbol_table_index: u32(3),
176+
typ: u16(IMAGE_REL_AMD64_ADDR32NB),
157177
});
158178
// relocation 1: [2] name rva => points to DLL name section .idata$6
159179
file.data.write_pod(&ImageRelocation {
160-
virtual_address: u32_unaligned(12),
161-
symbol_table_index: u32_unaligned(2),
162-
typ: u16_unaligned(IMAGE_REL_AMD64_ADDR32NB),
180+
virtual_address: u32(12),
181+
symbol_table_index: u32(2),
182+
typ: u16(IMAGE_REL_AMD64_ADDR32NB),
163183
});
164184
// relocation 2: [4] import address table rva => points to UNDEF symbol .idata$5
165185
file.data.write_pod(&ImageRelocation {
166-
virtual_address: u32_unaligned(16),
167-
symbol_table_index: u32_unaligned(4),
168-
typ: u16_unaligned(IMAGE_REL_AMD64_ADDR32NB),
186+
virtual_address: u32(16),
187+
symbol_table_index: u32(4),
188+
typ: u16(IMAGE_REL_AMD64_ADDR32NB),
169189
});
170190

171191
// [1] section .idata$6 data
@@ -269,6 +289,47 @@ pub(crate) fn write_null_import_descriptor(data: &mut DataWriter) {
269289
);
270290
}
271291

292+
#[derive(Debug, Clone, Copy)]
293+
#[repr(C)]
294+
pub(crate) struct ImageFileHeaderUnaligned {
295+
pub(crate) machine: U16Bytes<LE>,
296+
pub(crate) number_of_sections: U16Bytes<LE>,
297+
pub(crate) time_date_stamp: U32Bytes<LE>,
298+
pub(crate) pointer_to_symbol_table: U32Bytes<LE>,
299+
pub(crate) number_of_symbols: U32Bytes<LE>,
300+
pub(crate) size_of_optional_header: U16Bytes<LE>,
301+
pub(crate) characteristics: U16Bytes<LE>,
302+
}
303+
304+
/// # Safety
305+
/// A type that is `Pod` must:
306+
/// - be `#[repr(C)]` or `#[repr(transparent)]`
307+
/// - have no invalid byte values
308+
/// - have no padding
309+
unsafe impl object::pod::Pod for ImageFileHeaderUnaligned {}
310+
311+
#[derive(Debug, Default, Clone, Copy)]
312+
#[repr(C)]
313+
pub(crate) struct ImageSectionHeaderUnaligned {
314+
pub(crate) name: [u8; IMAGE_SIZEOF_SHORT_NAME],
315+
pub(crate) virtual_size: U32Bytes<LE>,
316+
pub(crate) virtual_address: U32Bytes<LE>,
317+
pub(crate) size_of_raw_data: U32Bytes<LE>,
318+
pub(crate) pointer_to_raw_data: U32Bytes<LE>,
319+
pub(crate) pointer_to_relocations: U32Bytes<LE>,
320+
pub(crate) pointer_to_linenumbers: U32Bytes<LE>,
321+
pub(crate) number_of_relocations: U16Bytes<LE>,
322+
pub(crate) number_of_linenumbers: U16Bytes<LE>,
323+
pub(crate) characteristics: U32Bytes<LE>,
324+
}
325+
326+
/// # Safety
327+
/// A type that is `Pod` must:
328+
/// - be `#[repr(C)]` or `#[repr(transparent)]`
329+
/// - have no invalid byte values
330+
/// - have no padding
331+
unsafe impl object::pod::Pod for ImageSectionHeaderUnaligned {}
332+
272333
struct CoffFileWriter<'data> {
273334
data: &'data mut DataWriter,
274335
offset: usize,
@@ -279,43 +340,43 @@ struct CoffFileWriter<'data> {
279340
impl<'data> CoffFileWriter<'data> {
280341
fn new(data: &'data mut DataWriter, machine: u16) -> Self {
281342
let file_offset = data.len();
282-
data.write_pod(&ImageFileHeader {
283-
machine: u16_aligned(machine),
284-
number_of_sections: u16_aligned(0),
285-
time_date_stamp: u32_aligned(0),
286-
pointer_to_symbol_table: u32_aligned(0),
287-
number_of_symbols: u32_aligned(0),
288-
size_of_optional_header: u16_aligned(0),
289-
characteristics: u16_aligned(0),
343+
data.write_pod(&ImageFileHeaderUnaligned {
344+
machine: u16(machine),
345+
number_of_sections: u16(0),
346+
time_date_stamp: u32(0),
347+
pointer_to_symbol_table: u32(0),
348+
number_of_symbols: u32(0),
349+
size_of_optional_header: u16(0),
350+
characteristics: u16(0),
290351
});
291352
let string_table = CoffStringTable::new();
292353
Self { data, offset: file_offset, number_of_sections: 0, string_table }
293354
}
294355

295-
fn file_header_mut(&mut self) -> &mut ImageFileHeader {
356+
fn file_header_mut(&mut self) -> &mut ImageFileHeaderUnaligned {
296357
self.data.get_pod_mut(self.offset)
297358
}
298359

299360
fn write_section_header(&mut self, name: &str, characteristics: u32) -> CoffSectionHeader {
300361
self.number_of_sections += 1;
301-
let offset = self.data.write_pod(&ImageSectionHeader {
362+
let offset = self.data.write_pod(&ImageSectionHeaderUnaligned {
302363
name: self.string_table.get_raw_name(name),
303-
virtual_size: u32_aligned(0),
304-
virtual_address: u32_aligned(0),
305-
size_of_raw_data: u32_aligned(0), // filled out later
306-
pointer_to_raw_data: u32_aligned(0), // ditto.
307-
pointer_to_relocations: u32_aligned(0), // (possibly) ditto.
308-
pointer_to_linenumbers: u32_aligned(0),
309-
number_of_relocations: u16_aligned(0),
310-
number_of_linenumbers: u16_aligned(0),
311-
characteristics: u32_aligned(characteristics),
364+
virtual_size: u32(0),
365+
virtual_address: u32(0),
366+
size_of_raw_data: u32(0), // filled out later
367+
pointer_to_raw_data: u32(0), // ditto.
368+
pointer_to_relocations: u32(0), // (possibly) ditto.
369+
pointer_to_linenumbers: u32(0),
370+
number_of_relocations: u16(0),
371+
number_of_linenumbers: u16(0),
372+
characteristics: u32(characteristics),
312373
});
313374
CoffSectionHeader { offset }
314375
}
315376

316377
fn start_symbol_table(&mut self) -> CoffSymbolTableWriter<'_, 'data> {
317378
let offset = self.len();
318-
self.file_header_mut().pointer_to_symbol_table = u32_aligned((offset - self.offset) as u32);
379+
self.file_header_mut().pointer_to_symbol_table = u32((offset - self.offset) as u32);
319380
CoffSymbolTableWriter { file: self, offset, number_of_symbols: 0 }
320381
}
321382
}
@@ -338,7 +399,7 @@ impl Drop for CoffFileWriter<'_> {
338399
fn drop(&mut self) {
339400
let number_of_sections = self.number_of_sections;
340401
let header = self.file_header_mut();
341-
header.number_of_sections = u16_aligned(number_of_sections);
402+
header.number_of_sections = u16(number_of_sections);
342403
self.string_table.write(self.data);
343404
}
344405
}
@@ -356,7 +417,7 @@ impl CoffStringTable {
356417
writer.write(data);
357418
}
358419

359-
pub fn get_raw_name(&mut self, value: &str) -> [u8; 8] {
420+
pub(crate) fn get_raw_name(&mut self, value: &str) -> [u8; 8] {
360421
let mut result = [0u8; 8];
361422
if value.len() > 8 {
362423
// add 4 for the string table length
@@ -375,7 +436,7 @@ struct CoffSectionHeader {
375436
}
376437

377438
impl CoffSectionHeader {
378-
fn get_mut(self, data: &mut DataWriter) -> &mut ImageSectionHeader {
439+
fn get_mut(self, data: &mut DataWriter) -> &mut ImageSectionHeaderUnaligned {
379440
data.get_pod_mut(self.offset)
380441
}
381442
}
@@ -416,8 +477,8 @@ impl Drop for CoffSectionRawData<'_, '_> {
416477
let header = self.header.get_mut(self.file.data);
417478
let size_of_raw_data = end_offset - self.offset;
418479
let pointer_to_raw_data = self.offset - self.file.offset;
419-
header.size_of_raw_data = u32_aligned(size_of_raw_data as u32);
420-
header.pointer_to_raw_data = u32_aligned(pointer_to_raw_data as u32);
480+
header.size_of_raw_data = u32(size_of_raw_data as u32);
481+
header.pointer_to_raw_data = u32(pointer_to_raw_data as u32);
421482
}
422483
}
423484

@@ -444,9 +505,9 @@ impl CoffSymbolTableWriter<'_, '_> {
444505
let name = self.file.string_table.get_raw_name(name);
445506
self.file.write_pod(&ImageSymbol {
446507
name,
447-
value: u32_unaligned(options.value),
448-
section_number: u16_unaligned(options.section_number as u16),
449-
typ: u16_unaligned(options.base_type | options.complex_type << 8),
508+
value: u32(options.value),
509+
section_number: u16(options.section_number as u16),
510+
typ: u16(options.base_type | options.complex_type << 8),
450511
storage_class: options.storage_class,
451512
number_of_aux_symbols: options.number_of_aux_symbols,
452513
});
@@ -458,7 +519,7 @@ impl Drop for CoffSymbolTableWriter<'_, '_> {
458519
fn drop(&mut self) {
459520
let pointer_to_symbol_table = self.offset - self.file.offset;
460521
let header = self.file.file_header_mut();
461-
header.pointer_to_symbol_table = u32_aligned(pointer_to_symbol_table as u32);
462-
header.number_of_symbols = u32_aligned(self.number_of_symbols);
522+
header.pointer_to_symbol_table = u32(pointer_to_symbol_table as u32);
523+
header.number_of_symbols = u32(self.number_of_symbols);
463524
}
464525
}

src/dll_import_lib/string_table.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
pub struct StringTable(Vec<u8>);
1+
pub(crate) struct StringTable(Vec<u8>);
22

33
impl StringTable {
4-
pub fn new() -> Self {
4+
pub(crate) fn new() -> Self {
55
Self(vec![])
66
}
77

8-
pub fn data(&self) -> &[u8] {
8+
pub(crate) fn data(&self) -> &[u8] {
99
self.0.as_slice()
1010
}
1111

12-
pub fn find_or_insert(&mut self, value: &str) -> usize {
12+
pub(crate) fn find_or_insert(&mut self, value: &str) -> usize {
1313
// Find the name *including the null terminator* in the existing buffer.
1414
// Note, this could find "bar\0" in "foobar\0", but that should be fine?
1515
// It still counts as a null terminated "bar" string.

0 commit comments

Comments
 (0)