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