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