1 use crc32fast;
2 use std::mem;
3 use std::vec::Vec;
4
5 use crate::endian::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32};
6 use crate::pe as coff;
7 use crate::pod::{bytes_of, WritableBuffer};
8 use crate::write::string::*;
9 use crate::write::util::*;
10 use crate::write::*;
11
12 #[derive(Default, Clone, Copy)]
13 struct SectionOffsets {
14 offset: usize,
15 str_id: Option<StringId>,
16 reloc_offset: usize,
17 selection: u8,
18 associative_section: u16,
19 }
20
21 #[derive(Default, Clone, Copy)]
22 struct SymbolOffsets {
23 index: usize,
24 str_id: Option<StringId>,
25 aux_count: u8,
26 }
27
28 impl Object {
coff_section_info( &self, section: StandardSection, ) -> (&'static [u8], &'static [u8], SectionKind)29 pub(crate) fn coff_section_info(
30 &self,
31 section: StandardSection,
32 ) -> (&'static [u8], &'static [u8], SectionKind) {
33 match section {
34 StandardSection::Text => (&[], &b".text"[..], SectionKind::Text),
35 StandardSection::Data => (&[], &b".data"[..], SectionKind::Data),
36 StandardSection::ReadOnlyData
37 | StandardSection::ReadOnlyDataWithRel
38 | StandardSection::ReadOnlyString => (&[], &b".rdata"[..], SectionKind::ReadOnlyData),
39 StandardSection::UninitializedData => {
40 (&[], &b".bss"[..], SectionKind::UninitializedData)
41 }
42 // TLS sections are data sections with a special name.
43 StandardSection::Tls => (&[], &b".tls$"[..], SectionKind::Data),
44 StandardSection::UninitializedTls => {
45 // Unsupported section.
46 (&[], &[], SectionKind::UninitializedTls)
47 }
48 StandardSection::TlsVariables => {
49 // Unsupported section.
50 (&[], &[], SectionKind::TlsVariables)
51 }
52 StandardSection::Common => {
53 // Unsupported section.
54 (&[], &[], SectionKind::Common)
55 }
56 }
57 }
58
coff_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8>59 pub(crate) fn coff_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
60 let mut name = section.to_vec();
61 name.push(b'$');
62 name.extend(value);
63 name
64 }
65
coff_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> i6466 pub(crate) fn coff_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> i64 {
67 if relocation.kind == RelocationKind::GotRelative {
68 // Use a stub symbol for the relocation instead.
69 // This isn't really a GOT, but it's a similar purpose.
70 // TODO: need to handle DLL imports differently?
71 relocation.kind = RelocationKind::Relative;
72 relocation.symbol = self.coff_add_stub_symbol(relocation.symbol);
73 } else if relocation.kind == RelocationKind::PltRelative {
74 // Windows doesn't need a separate relocation type for
75 // references to functions in import libraries.
76 // For convenience, treat this the same as Relative.
77 relocation.kind = RelocationKind::Relative;
78 }
79
80 let constant = match self.architecture {
81 Architecture::I386 => match relocation.kind {
82 RelocationKind::Relative => {
83 // IMAGE_REL_I386_REL32
84 relocation.addend + 4
85 }
86 _ => relocation.addend,
87 },
88 Architecture::X86_64 => match relocation.kind {
89 RelocationKind::Relative => {
90 // IMAGE_REL_AMD64_REL32 through to IMAGE_REL_AMD64_REL32_5
91 if relocation.addend <= -4 && relocation.addend >= -9 {
92 0
93 } else {
94 relocation.addend + 4
95 }
96 }
97 _ => relocation.addend,
98 },
99 _ => unimplemented!(),
100 };
101 relocation.addend -= constant;
102 constant
103 }
104
coff_add_stub_symbol(&mut self, symbol_id: SymbolId) -> SymbolId105 fn coff_add_stub_symbol(&mut self, symbol_id: SymbolId) -> SymbolId {
106 if let Some(stub_id) = self.stub_symbols.get(&symbol_id) {
107 return *stub_id;
108 }
109 let stub_size = self.architecture.address_size().unwrap().bytes();
110
111 let mut name = b".rdata$.refptr.".to_vec();
112 name.extend(&self.symbols[symbol_id.0].name);
113 let section_id = self.add_section(Vec::new(), name, SectionKind::ReadOnlyData);
114 let section = self.section_mut(section_id);
115 section.set_data(vec![0; stub_size as usize], u64::from(stub_size));
116 section.relocations = vec![Relocation {
117 offset: 0,
118 size: stub_size * 8,
119 kind: RelocationKind::Absolute,
120 encoding: RelocationEncoding::Generic,
121 symbol: symbol_id,
122 addend: 0,
123 }];
124
125 let mut name = b".refptr.".to_vec();
126 name.extend(&self.symbol(symbol_id).name);
127 let stub_id = self.add_raw_symbol(Symbol {
128 name,
129 value: 0,
130 size: u64::from(stub_size),
131 kind: SymbolKind::Data,
132 scope: SymbolScope::Compilation,
133 weak: false,
134 section: SymbolSection::Section(section_id),
135 flags: SymbolFlags::None,
136 });
137 self.stub_symbols.insert(symbol_id, stub_id);
138
139 stub_id
140 }
141
coff_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()>142 pub(crate) fn coff_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
143 // Calculate offsets of everything, and build strtab.
144 let mut offset = 0;
145 let mut strtab = StringTable::default();
146
147 // COFF header.
148 offset += mem::size_of::<coff::ImageFileHeader>();
149
150 // Section headers.
151 offset += self.sections.len() * mem::size_of::<coff::ImageSectionHeader>();
152
153 // Calculate size of section data and add section strings to strtab.
154 let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()];
155 for (index, section) in self.sections.iter().enumerate() {
156 if section.name.len() > 8 {
157 section_offsets[index].str_id = Some(strtab.add(§ion.name));
158 }
159
160 let len = section.data.len();
161 if len != 0 {
162 // TODO: not sure what alignment is required here, but this seems to match LLVM
163 offset = align(offset, 4);
164 section_offsets[index].offset = offset;
165 offset += len;
166 } else {
167 section_offsets[index].offset = 0;
168 }
169
170 // Calculate size of relocations.
171 let count = section.relocations.len();
172 if count != 0 {
173 section_offsets[index].reloc_offset = offset;
174 offset += count * mem::size_of::<coff::ImageRelocation>();
175 }
176 }
177
178 // Set COMDAT flags.
179 for comdat in &self.comdats {
180 let symbol = &self.symbols[comdat.symbol.0];
181 let comdat_section = match symbol.section {
182 SymbolSection::Section(id) => id.0,
183 _ => {
184 return Err(Error(format!(
185 "unsupported COMDAT symbol `{}` section {:?}",
186 symbol.name().unwrap_or(""),
187 symbol.section
188 )));
189 }
190 };
191 section_offsets[comdat_section].selection = match comdat.kind {
192 ComdatKind::NoDuplicates => coff::IMAGE_COMDAT_SELECT_NODUPLICATES,
193 ComdatKind::Any => coff::IMAGE_COMDAT_SELECT_ANY,
194 ComdatKind::SameSize => coff::IMAGE_COMDAT_SELECT_SAME_SIZE,
195 ComdatKind::ExactMatch => coff::IMAGE_COMDAT_SELECT_EXACT_MATCH,
196 ComdatKind::Largest => coff::IMAGE_COMDAT_SELECT_LARGEST,
197 ComdatKind::Newest => coff::IMAGE_COMDAT_SELECT_NEWEST,
198 ComdatKind::Unknown => {
199 return Err(Error(format!(
200 "unsupported COMDAT symbol `{}` kind {:?}",
201 symbol.name().unwrap_or(""),
202 comdat.kind
203 )));
204 }
205 };
206 for id in &comdat.sections {
207 let section = &self.sections[id.0];
208 if section.symbol.is_none() {
209 return Err(Error(format!(
210 "missing symbol for COMDAT section `{}`",
211 section.name().unwrap_or(""),
212 )));
213 }
214 if id.0 != comdat_section {
215 section_offsets[id.0].selection = coff::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
216 section_offsets[id.0].associative_section = comdat_section as u16 + 1;
217 }
218 }
219 }
220
221 // Calculate size of symbols and add symbol strings to strtab.
222 let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()];
223 let mut symtab_count = 0;
224 for (index, symbol) in self.symbols.iter().enumerate() {
225 symbol_offsets[index].index = symtab_count;
226 symtab_count += 1;
227 match symbol.kind {
228 SymbolKind::File => {
229 // Name goes in auxilary symbol records.
230 let aux_count = (symbol.name.len() + coff::IMAGE_SIZEOF_SYMBOL - 1)
231 / coff::IMAGE_SIZEOF_SYMBOL;
232 symbol_offsets[index].aux_count = aux_count as u8;
233 symtab_count += aux_count;
234 // Don't add name to strtab.
235 continue;
236 }
237 SymbolKind::Section => {
238 symbol_offsets[index].aux_count = 1;
239 symtab_count += 1;
240 }
241 _ => {}
242 }
243 if symbol.name.len() > 8 {
244 symbol_offsets[index].str_id = Some(strtab.add(&symbol.name));
245 }
246 }
247
248 // Calculate size of symtab.
249 let symtab_offset = offset;
250 let symtab_len = symtab_count * coff::IMAGE_SIZEOF_SYMBOL;
251 offset += symtab_len;
252
253 // Calculate size of strtab.
254 let strtab_offset = offset;
255 let mut strtab_data = Vec::new();
256 // First 4 bytes of strtab are the length.
257 strtab.write(4, &mut strtab_data);
258 let strtab_len = strtab_data.len() + 4;
259 offset += strtab_len;
260
261 // Start writing.
262 buffer
263 .reserve(offset)
264 .map_err(|_| Error(String::from("Cannot allocate buffer")))?;
265
266 // Write file header.
267 let header = coff::ImageFileHeader {
268 machine: U16::new(
269 LE,
270 match self.architecture {
271 Architecture::I386 => coff::IMAGE_FILE_MACHINE_I386,
272 Architecture::X86_64 => coff::IMAGE_FILE_MACHINE_AMD64,
273 _ => {
274 return Err(Error(format!(
275 "unimplemented architecture {:?}",
276 self.architecture
277 )));
278 }
279 },
280 ),
281 number_of_sections: U16::new(LE, self.sections.len() as u16),
282 time_date_stamp: U32::default(),
283 pointer_to_symbol_table: U32::new(LE, symtab_offset as u32),
284 number_of_symbols: U32::new(LE, symtab_count as u32),
285 size_of_optional_header: U16::default(),
286 characteristics: match self.flags {
287 FileFlags::Coff { characteristics } => U16::new(LE, characteristics),
288 _ => U16::default(),
289 },
290 };
291 buffer.extend(bytes_of(&header));
292
293 // Write section headers.
294 for (index, section) in self.sections.iter().enumerate() {
295 let mut characteristics = match section.flags {
296 SectionFlags::Coff {
297 characteristics, ..
298 } => characteristics,
299 _ => 0,
300 };
301 if section_offsets[index].selection != 0 {
302 characteristics |= coff::IMAGE_SCN_LNK_COMDAT;
303 };
304 characteristics |= match section.kind {
305 SectionKind::Text => {
306 coff::IMAGE_SCN_CNT_CODE
307 | coff::IMAGE_SCN_MEM_EXECUTE
308 | coff::IMAGE_SCN_MEM_READ
309 }
310 SectionKind::Data => {
311 coff::IMAGE_SCN_CNT_INITIALIZED_DATA
312 | coff::IMAGE_SCN_MEM_READ
313 | coff::IMAGE_SCN_MEM_WRITE
314 }
315 SectionKind::UninitializedData => {
316 coff::IMAGE_SCN_CNT_UNINITIALIZED_DATA
317 | coff::IMAGE_SCN_MEM_READ
318 | coff::IMAGE_SCN_MEM_WRITE
319 }
320 SectionKind::ReadOnlyData | SectionKind::ReadOnlyString => {
321 coff::IMAGE_SCN_CNT_INITIALIZED_DATA | coff::IMAGE_SCN_MEM_READ
322 }
323 SectionKind::Debug | SectionKind::Other | SectionKind::OtherString => {
324 coff::IMAGE_SCN_CNT_INITIALIZED_DATA
325 | coff::IMAGE_SCN_MEM_READ
326 | coff::IMAGE_SCN_MEM_DISCARDABLE
327 }
328 SectionKind::Linker => coff::IMAGE_SCN_LNK_INFO | coff::IMAGE_SCN_LNK_REMOVE,
329 SectionKind::Common
330 | SectionKind::Tls
331 | SectionKind::UninitializedTls
332 | SectionKind::TlsVariables
333 | SectionKind::Note
334 | SectionKind::Unknown
335 | SectionKind::Metadata => {
336 return Err(Error(format!(
337 "unimplemented section `{}` kind {:?}",
338 section.name().unwrap_or(""),
339 section.kind
340 )));
341 }
342 } | match section.align {
343 1 => coff::IMAGE_SCN_ALIGN_1BYTES,
344 2 => coff::IMAGE_SCN_ALIGN_2BYTES,
345 4 => coff::IMAGE_SCN_ALIGN_4BYTES,
346 8 => coff::IMAGE_SCN_ALIGN_8BYTES,
347 16 => coff::IMAGE_SCN_ALIGN_16BYTES,
348 32 => coff::IMAGE_SCN_ALIGN_32BYTES,
349 64 => coff::IMAGE_SCN_ALIGN_64BYTES,
350 128 => coff::IMAGE_SCN_ALIGN_128BYTES,
351 256 => coff::IMAGE_SCN_ALIGN_256BYTES,
352 512 => coff::IMAGE_SCN_ALIGN_512BYTES,
353 1024 => coff::IMAGE_SCN_ALIGN_1024BYTES,
354 2048 => coff::IMAGE_SCN_ALIGN_2048BYTES,
355 4096 => coff::IMAGE_SCN_ALIGN_4096BYTES,
356 8192 => coff::IMAGE_SCN_ALIGN_8192BYTES,
357 _ => {
358 return Err(Error(format!(
359 "unimplemented section `{}` align {}",
360 section.name().unwrap_or(""),
361 section.align
362 )));
363 }
364 };
365 let mut coff_section = coff::ImageSectionHeader {
366 name: [0; 8],
367 virtual_size: U32::default(),
368 virtual_address: U32::default(),
369 size_of_raw_data: U32::new(LE, section.size as u32),
370 pointer_to_raw_data: U32::new(LE, section_offsets[index].offset as u32),
371 pointer_to_relocations: U32::new(LE, section_offsets[index].reloc_offset as u32),
372 pointer_to_linenumbers: U32::default(),
373 number_of_relocations: U16::new(LE, section.relocations.len() as u16),
374 number_of_linenumbers: U16::default(),
375 characteristics: U32::new(LE, characteristics),
376 };
377 if section.name.len() <= 8 {
378 coff_section.name[..section.name.len()].copy_from_slice(§ion.name);
379 } else {
380 let mut str_offset = strtab.get_offset(section_offsets[index].str_id.unwrap());
381 if str_offset <= 9_999_999 {
382 let mut name = [0; 7];
383 let mut len = 0;
384 if str_offset == 0 {
385 name[6] = b'0';
386 len = 1;
387 } else {
388 while str_offset != 0 {
389 let rem = (str_offset % 10) as u8;
390 str_offset /= 10;
391 name[6 - len] = b'0' + rem;
392 len += 1;
393 }
394 }
395 coff_section.name = [0; 8];
396 coff_section.name[0] = b'/';
397 coff_section.name[1..][..len].copy_from_slice(&name[7 - len..]);
398 } else if str_offset as u64 <= 0xfff_fff_fff {
399 coff_section.name[0] = b'/';
400 coff_section.name[1] = b'/';
401 for i in 0..6 {
402 let rem = (str_offset % 64) as u8;
403 str_offset /= 64;
404 let c = match rem {
405 0..=25 => b'A' + rem,
406 26..=51 => b'a' + rem - 26,
407 52..=61 => b'0' + rem - 52,
408 62 => b'+',
409 63 => b'/',
410 _ => unreachable!(),
411 };
412 coff_section.name[7 - i] = c;
413 }
414 } else {
415 return Err(Error(format!("invalid section name offset {}", str_offset)));
416 }
417 }
418 buffer.extend(bytes_of(&coff_section));
419 }
420
421 // Write section data and relocations.
422 for (index, section) in self.sections.iter().enumerate() {
423 let len = section.data.len();
424 if len != 0 {
425 write_align(buffer, 4);
426 debug_assert_eq!(section_offsets[index].offset, buffer.len());
427 buffer.extend(section.data.as_slice());
428 }
429
430 if !section.relocations.is_empty() {
431 debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len());
432 for reloc in §ion.relocations {
433 //assert!(reloc.implicit_addend);
434 let typ = match self.architecture {
435 Architecture::I386 => match (reloc.kind, reloc.size, reloc.addend) {
436 (RelocationKind::Absolute, 16, 0) => coff::IMAGE_REL_I386_DIR16,
437 (RelocationKind::Relative, 16, 0) => coff::IMAGE_REL_I386_REL16,
438 (RelocationKind::Absolute, 32, 0) => coff::IMAGE_REL_I386_DIR32,
439 (RelocationKind::ImageOffset, 32, 0) => coff::IMAGE_REL_I386_DIR32NB,
440 (RelocationKind::SectionIndex, 16, 0) => coff::IMAGE_REL_I386_SECTION,
441 (RelocationKind::SectionOffset, 32, 0) => coff::IMAGE_REL_I386_SECREL,
442 (RelocationKind::SectionOffset, 7, 0) => coff::IMAGE_REL_I386_SECREL7,
443 (RelocationKind::Relative, 32, -4) => coff::IMAGE_REL_I386_REL32,
444 (RelocationKind::Coff(x), _, _) => x,
445 _ => {
446 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
447 }
448 },
449 Architecture::X86_64 => match (reloc.kind, reloc.size, reloc.addend) {
450 (RelocationKind::Absolute, 64, 0) => coff::IMAGE_REL_AMD64_ADDR64,
451 (RelocationKind::Absolute, 32, 0) => coff::IMAGE_REL_AMD64_ADDR32,
452 (RelocationKind::ImageOffset, 32, 0) => coff::IMAGE_REL_AMD64_ADDR32NB,
453 (RelocationKind::Relative, 32, -4) => coff::IMAGE_REL_AMD64_REL32,
454 (RelocationKind::Relative, 32, -5) => coff::IMAGE_REL_AMD64_REL32_1,
455 (RelocationKind::Relative, 32, -6) => coff::IMAGE_REL_AMD64_REL32_2,
456 (RelocationKind::Relative, 32, -7) => coff::IMAGE_REL_AMD64_REL32_3,
457 (RelocationKind::Relative, 32, -8) => coff::IMAGE_REL_AMD64_REL32_4,
458 (RelocationKind::Relative, 32, -9) => coff::IMAGE_REL_AMD64_REL32_5,
459 (RelocationKind::SectionIndex, 16, 0) => coff::IMAGE_REL_AMD64_SECTION,
460 (RelocationKind::SectionOffset, 32, 0) => coff::IMAGE_REL_AMD64_SECREL,
461 (RelocationKind::SectionOffset, 7, 0) => coff::IMAGE_REL_AMD64_SECREL7,
462 (RelocationKind::Coff(x), _, _) => x,
463 _ => {
464 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
465 }
466 },
467 _ => {
468 return Err(Error(format!(
469 "unimplemented architecture {:?}",
470 self.architecture
471 )));
472 }
473 };
474 let coff_relocation = coff::ImageRelocation {
475 virtual_address: U32Bytes::new(LE, reloc.offset as u32),
476 symbol_table_index: U32Bytes::new(
477 LE,
478 symbol_offsets[reloc.symbol.0].index as u32,
479 ),
480 typ: U16Bytes::new(LE, typ),
481 };
482 buffer.extend(bytes_of(&coff_relocation));
483 }
484 }
485 }
486
487 // Write symbols.
488 debug_assert_eq!(symtab_offset, buffer.len());
489 for (index, symbol) in self.symbols.iter().enumerate() {
490 let mut name = &symbol.name[..];
491 let section_number = match symbol.section {
492 SymbolSection::None => {
493 debug_assert_eq!(symbol.kind, SymbolKind::File);
494 coff::IMAGE_SYM_DEBUG
495 }
496 SymbolSection::Undefined => coff::IMAGE_SYM_UNDEFINED,
497 SymbolSection::Absolute => coff::IMAGE_SYM_ABSOLUTE,
498 SymbolSection::Common => coff::IMAGE_SYM_UNDEFINED,
499 SymbolSection::Section(id) => id.0 as u16 + 1,
500 };
501 let typ = if symbol.kind == SymbolKind::Text {
502 coff::IMAGE_SYM_DTYPE_FUNCTION << coff::IMAGE_SYM_DTYPE_SHIFT
503 } else {
504 coff::IMAGE_SYM_TYPE_NULL
505 };
506 let storage_class = match symbol.kind {
507 SymbolKind::File => {
508 // Name goes in auxilary symbol records.
509 name = b".file";
510 coff::IMAGE_SYM_CLASS_FILE
511 }
512 SymbolKind::Section => coff::IMAGE_SYM_CLASS_STATIC,
513 SymbolKind::Label => coff::IMAGE_SYM_CLASS_LABEL,
514 SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls => {
515 match symbol.section {
516 SymbolSection::None => {
517 return Err(Error(format!(
518 "missing section for symbol `{}`",
519 symbol.name().unwrap_or("")
520 )));
521 }
522 SymbolSection::Undefined | SymbolSection::Common => {
523 coff::IMAGE_SYM_CLASS_EXTERNAL
524 }
525 SymbolSection::Absolute | SymbolSection::Section(_) => {
526 match symbol.scope {
527 // TODO: does this need aux symbol records too?
528 _ if symbol.weak => coff::IMAGE_SYM_CLASS_WEAK_EXTERNAL,
529 SymbolScope::Unknown => {
530 return Err(Error(format!(
531 "unimplemented symbol `{}` scope {:?}",
532 symbol.name().unwrap_or(""),
533 symbol.scope
534 )));
535 }
536 SymbolScope::Compilation => coff::IMAGE_SYM_CLASS_STATIC,
537 SymbolScope::Linkage | SymbolScope::Dynamic => {
538 coff::IMAGE_SYM_CLASS_EXTERNAL
539 }
540 }
541 }
542 }
543 }
544 SymbolKind::Unknown | SymbolKind::Null => {
545 return Err(Error(format!(
546 "unimplemented symbol `{}` kind {:?}",
547 symbol.name().unwrap_or(""),
548 symbol.kind
549 )));
550 }
551 };
552 let number_of_aux_symbols = symbol_offsets[index].aux_count;
553 let value = if symbol.section == SymbolSection::Common {
554 symbol.size as u32
555 } else {
556 symbol.value as u32
557 };
558 let mut coff_symbol = coff::ImageSymbol {
559 name: [0; 8],
560 value: U32Bytes::new(LE, value),
561 section_number: U16Bytes::new(LE, section_number as u16),
562 typ: U16Bytes::new(LE, typ),
563 storage_class,
564 number_of_aux_symbols,
565 };
566 if name.len() <= 8 {
567 coff_symbol.name[..name.len()].copy_from_slice(name);
568 } else {
569 let str_offset = strtab.get_offset(symbol_offsets[index].str_id.unwrap());
570 coff_symbol.name[4..8].copy_from_slice(&u32::to_le_bytes(str_offset as u32));
571 }
572 buffer.extend(bytes_of(&coff_symbol));
573
574 // Write auxiliary symbols.
575 match symbol.kind {
576 SymbolKind::File => {
577 let aux_len = number_of_aux_symbols as usize * coff::IMAGE_SIZEOF_SYMBOL;
578 debug_assert!(aux_len >= symbol.name.len());
579 let old_len = buffer.len();
580 buffer.extend(&symbol.name);
581 buffer.resize(old_len + aux_len, 0);
582 }
583 SymbolKind::Section => {
584 debug_assert_eq!(number_of_aux_symbols, 1);
585 let section_index = symbol.section.id().unwrap().0;
586 let section = &self.sections[section_index];
587 let aux = coff::ImageAuxSymbolSection {
588 length: U32Bytes::new(LE, section.size as u32),
589 number_of_relocations: U16Bytes::new(LE, section.relocations.len() as u16),
590 number_of_linenumbers: U16Bytes::default(),
591 check_sum: U32Bytes::new(LE, checksum(section.data.as_slice())),
592 number: U16Bytes::new(
593 LE,
594 section_offsets[section_index].associative_section,
595 ),
596 selection: section_offsets[section_index].selection,
597 reserved: 0,
598 // TODO: bigobj
599 high_number: U16Bytes::default(),
600 };
601 buffer.extend(bytes_of(&aux));
602 }
603 _ => {
604 debug_assert_eq!(number_of_aux_symbols, 0);
605 }
606 }
607 }
608
609 // Write strtab section.
610 debug_assert_eq!(strtab_offset, buffer.len());
611 buffer.extend(&u32::to_le_bytes(strtab_len as u32));
612 buffer.extend(&strtab_data);
613
614 debug_assert_eq!(offset, buffer.len());
615
616 Ok(())
617 }
618 }
619
620 // JamCRC
checksum(data: &[u8]) -> u32621 fn checksum(data: &[u8]) -> u32 {
622 let mut hasher = crc32fast::Hasher::new_with_initial(0xffff_ffff);
623 hasher.update(data);
624 !hasher.finalize()
625 }
626