4 use crate::endian
::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32}
;
6 use crate::write
::string
::*;
7 use crate::write
::util
::*;
10 #[derive(Default, Clone, Copy)]
11 struct SectionOffsets
{
13 str_id
: Option
<StringId
>,
16 associative_section
: u16,
19 #[derive(Default, Clone, Copy)]
20 struct SymbolOffsets
{
22 str_id
: Option
<StringId
>,
26 /// Internal format to use for the `.drectve` section containing linker
27 /// directives for symbol exports.
28 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
29 pub enum CoffExportStyle
{
30 /// MSVC format supported by link.exe and LLD.
32 /// Gnu format supported by GNU LD and LLD.
37 pub(crate) fn coff_section_info(
39 section
: StandardSection
,
40 ) -> (&'
static [u8], &'
static [u8], SectionKind
, SectionFlags
) {
42 StandardSection
::Text
=> (&[], &b
".text"[..], SectionKind
::Text
, SectionFlags
::None
),
43 StandardSection
::Data
=> (&[], &b
".data"[..], SectionKind
::Data
, SectionFlags
::None
),
44 StandardSection
::ReadOnlyData
45 | StandardSection
::ReadOnlyDataWithRel
46 | StandardSection
::ReadOnlyString
=> (
49 SectionKind
::ReadOnlyData
,
52 StandardSection
::UninitializedData
=> (
55 SectionKind
::UninitializedData
,
58 // TLS sections are data sections with a special name.
59 StandardSection
::Tls
=> (&[], &b
".tls$"[..], SectionKind
::Data
, SectionFlags
::None
),
60 StandardSection
::UninitializedTls
=> {
61 // Unsupported section.
62 (&[], &[], SectionKind
::UninitializedTls
, SectionFlags
::None
)
64 StandardSection
::TlsVariables
=> {
65 // Unsupported section.
66 (&[], &[], SectionKind
::TlsVariables
, SectionFlags
::None
)
68 StandardSection
::Common
=> {
69 // Unsupported section.
70 (&[], &[], SectionKind
::Common
, SectionFlags
::None
)
72 StandardSection
::GnuProperty
=> {
73 // Unsupported section.
74 (&[], &[], SectionKind
::Note
, SectionFlags
::None
)
79 pub(crate) fn coff_subsection_name(&self, section
: &[u8], value
: &[u8]) -> Vec
<u8> {
80 let mut name
= section
.to_vec();
82 name
.extend_from_slice(value
);
86 pub(crate) fn coff_fixup_relocation(&mut self, mut relocation
: &mut Relocation
) -> i64 {
87 if relocation
.kind
== RelocationKind
::GotRelative
{
88 // Use a stub symbol for the relocation instead.
89 // This isn't really a GOT, but it's a similar purpose.
90 // TODO: need to handle DLL imports differently?
91 relocation
.kind
= RelocationKind
::Relative
;
92 relocation
.symbol
= self.coff_add_stub_symbol(relocation
.symbol
);
93 } else if relocation
.kind
== RelocationKind
::PltRelative
{
94 // Windows doesn't need a separate relocation type for
95 // references to functions in import libraries.
96 // For convenience, treat this the same as Relative.
97 relocation
.kind
= RelocationKind
::Relative
;
100 let constant
= match self.architecture
{
101 Architecture
::I386
| Architecture
::Arm
| Architecture
::Aarch64
=> match relocation
.kind
103 RelocationKind
::Relative
=> {
104 // IMAGE_REL_I386_REL32, IMAGE_REL_ARM_REL32, IMAGE_REL_ARM64_REL32
105 relocation
.addend
+ 4
107 _
=> relocation
.addend
,
109 Architecture
::X86_64
=> match relocation
.kind
{
110 RelocationKind
::Relative
=> {
111 // IMAGE_REL_AMD64_REL32 through to IMAGE_REL_AMD64_REL32_5
112 if relocation
.addend
<= -4 && relocation
.addend
>= -9 {
115 relocation
.addend
+ 4
118 _
=> relocation
.addend
,
120 _
=> unimplemented
!(),
122 relocation
.addend
-= constant
;
126 fn coff_add_stub_symbol(&mut self, symbol_id
: SymbolId
) -> SymbolId
{
127 if let Some(stub_id
) = self.stub_symbols
.get(&symbol_id
) {
130 let stub_size
= self.architecture
.address_size().unwrap().bytes();
132 let name
= b
".rdata$.refptr".to_vec();
133 let section_id
= self.add_section(Vec
::new(), name
, SectionKind
::ReadOnlyData
);
134 let section
= self.section_mut(section_id
);
135 section
.set_data(vec
![0; stub_size
as usize], u64::from(stub_size
));
136 section
.relocations
= vec
![Relocation
{
139 kind
: RelocationKind
::Absolute
,
140 encoding
: RelocationEncoding
::Generic
,
145 let mut name
= b
".refptr.".to_vec();
146 name
.extend_from_slice(&self.symbol(symbol_id
).name
);
147 let stub_id
= self.add_raw_symbol(Symbol
{
150 size
: u64::from(stub_size
),
151 kind
: SymbolKind
::Data
,
152 scope
: SymbolScope
::Compilation
,
154 section
: SymbolSection
::Section(section_id
),
155 flags
: SymbolFlags
::None
,
157 self.stub_symbols
.insert(symbol_id
, stub_id
);
162 /// Appends linker directives to the `.drectve` section to tell the linker
163 /// to export all symbols with `SymbolScope::Dynamic`.
165 /// This must be called after all symbols have been defined.
166 pub fn add_coff_exports(&mut self, style
: CoffExportStyle
) {
167 assert_eq
!(self.format
, BinaryFormat
::Coff
);
169 let mut directives
= vec
![];
170 for symbol
in &self.symbols
{
171 if symbol
.scope
== SymbolScope
::Dynamic
{
173 CoffExportStyle
::Msvc
=> directives
.extend(b
" /EXPORT:\""),
174 CoffExportStyle
::Gnu
=> directives
.extend(b
" -export:\""),
176 directives
.extend(&symbol
.name
);
177 directives
.extend(b
"\"");
178 if symbol
.kind
!= SymbolKind
::Text
{
180 CoffExportStyle
::Msvc
=> directives
.extend(b
",DATA"),
181 CoffExportStyle
::Gnu
=> directives
.extend(b
",data"),
186 let drectve
= self.add_section(vec
![], b
".drectve".to_vec(), SectionKind
::Linker
);
187 self.append_section_data(drectve
, &directives
, 1);
190 pub(crate) fn coff_write(&self, buffer
: &mut dyn WritableBuffer
) -> Result
<()> {
191 // Calculate offsets of everything, and build strtab.
193 let mut strtab
= StringTable
::default();
196 offset
+= mem
::size_of
::<coff
::ImageFileHeader
>();
199 offset
+= self.sections
.len() * mem
::size_of
::<coff
::ImageSectionHeader
>();
201 // Calculate size of section data and add section strings to strtab.
202 let mut section_offsets
= vec
![SectionOffsets
::default(); self.sections
.len()];
203 for (index
, section
) in self.sections
.iter().enumerate() {
204 if section
.name
.len() > 8 {
205 section_offsets
[index
].str_id
= Some(strtab
.add(§ion
.name
));
208 let len
= section
.data
.len();
210 // TODO: not sure what alignment is required here, but this seems to match LLVM
211 offset
= align(offset
, 4);
212 section_offsets
[index
].offset
= offset
;
215 section_offsets
[index
].offset
= 0;
218 // Calculate size of relocations.
219 let mut count
= section
.relocations
.len();
221 section_offsets
[index
].reloc_offset
= offset
;
225 offset
+= count
* mem
::size_of
::<coff
::ImageRelocation
>();
230 for comdat
in &self.comdats
{
231 let symbol
= &self.symbols
[comdat
.symbol
.0];
232 let comdat_section
= match symbol
.section
{
233 SymbolSection
::Section(id
) => id
.0,
235 return Err(Error(format
!(
236 "unsupported COMDAT symbol `{}` section {:?}",
237 symbol
.name().unwrap_or(""),
242 section_offsets
[comdat_section
].selection
= match comdat
.kind
{
243 ComdatKind
::NoDuplicates
=> coff
::IMAGE_COMDAT_SELECT_NODUPLICATES
,
244 ComdatKind
::Any
=> coff
::IMAGE_COMDAT_SELECT_ANY
,
245 ComdatKind
::SameSize
=> coff
::IMAGE_COMDAT_SELECT_SAME_SIZE
,
246 ComdatKind
::ExactMatch
=> coff
::IMAGE_COMDAT_SELECT_EXACT_MATCH
,
247 ComdatKind
::Largest
=> coff
::IMAGE_COMDAT_SELECT_LARGEST
,
248 ComdatKind
::Newest
=> coff
::IMAGE_COMDAT_SELECT_NEWEST
,
249 ComdatKind
::Unknown
=> {
250 return Err(Error(format
!(
251 "unsupported COMDAT symbol `{}` kind {:?}",
252 symbol
.name().unwrap_or(""),
257 for id
in &comdat
.sections
{
258 let section
= &self.sections
[id
.0];
259 if section
.symbol
.is_none() {
260 return Err(Error(format
!(
261 "missing symbol for COMDAT section `{}`",
262 section
.name().unwrap_or(""),
265 if id
.0 != comdat_section
{
266 section_offsets
[id
.0].selection
= coff
::IMAGE_COMDAT_SELECT_ASSOCIATIVE
;
267 section_offsets
[id
.0].associative_section
= comdat_section
as u16 + 1;
272 // Calculate size of symbols and add symbol strings to strtab.
273 let mut symbol_offsets
= vec
![SymbolOffsets
::default(); self.symbols
.len()];
274 let mut symtab_count
= 0;
275 for (index
, symbol
) in self.symbols
.iter().enumerate() {
276 symbol_offsets
[index
].index
= symtab_count
;
279 SymbolKind
::File
=> {
280 // Name goes in auxiliary symbol records.
281 let aux_count
= (symbol
.name
.len() + coff
::IMAGE_SIZEOF_SYMBOL
- 1)
282 / coff
::IMAGE_SIZEOF_SYMBOL
;
283 symbol_offsets
[index
].aux_count
= aux_count
as u8;
284 symtab_count
+= aux_count
;
285 // Don't add name to strtab.
288 SymbolKind
::Section
=> {
289 symbol_offsets
[index
].aux_count
= 1;
294 if symbol
.name
.len() > 8 {
295 symbol_offsets
[index
].str_id
= Some(strtab
.add(&symbol
.name
));
299 // Calculate size of symtab.
300 let symtab_offset
= offset
;
301 let symtab_len
= symtab_count
* coff
::IMAGE_SIZEOF_SYMBOL
;
302 offset
+= symtab_len
;
304 // Calculate size of strtab.
305 let strtab_offset
= offset
;
306 let mut strtab_data
= Vec
::new();
307 // First 4 bytes of strtab are the length.
308 strtab
.write(4, &mut strtab_data
);
309 let strtab_len
= strtab_data
.len() + 4;
310 offset
+= strtab_len
;
315 .map_err(|_
| Error(String
::from("Cannot allocate buffer")))?
;
317 // Write file header.
318 let header
= coff
::ImageFileHeader
{
321 match self.architecture
{
322 Architecture
::Arm
=> coff
::IMAGE_FILE_MACHINE_ARMNT
,
323 Architecture
::Aarch64
=> coff
::IMAGE_FILE_MACHINE_ARM64
,
324 Architecture
::I386
=> coff
::IMAGE_FILE_MACHINE_I386
,
325 Architecture
::X86_64
=> coff
::IMAGE_FILE_MACHINE_AMD64
,
327 return Err(Error(format
!(
328 "unimplemented architecture {:?}",
334 number_of_sections
: U16
::new(LE
, self.sections
.len() as u16),
335 time_date_stamp
: U32
::default(),
336 pointer_to_symbol_table
: U32
::new(LE
, symtab_offset
as u32),
337 number_of_symbols
: U32
::new(LE
, symtab_count
as u32),
338 size_of_optional_header
: U16
::default(),
339 characteristics
: match self.flags
{
340 FileFlags
::Coff { characteristics }
=> U16
::new(LE
, characteristics
),
344 buffer
.write(&header
);
346 // Write section headers.
347 for (index
, section
) in self.sections
.iter().enumerate() {
348 let mut characteristics
= if let SectionFlags
::Coff
{
355 SectionKind
::Text
=> {
356 coff
::IMAGE_SCN_CNT_CODE
357 | coff
::IMAGE_SCN_MEM_EXECUTE
358 | coff
::IMAGE_SCN_MEM_READ
360 SectionKind
::Data
=> {
361 coff
::IMAGE_SCN_CNT_INITIALIZED_DATA
362 | coff
::IMAGE_SCN_MEM_READ
363 | coff
::IMAGE_SCN_MEM_WRITE
365 SectionKind
::UninitializedData
=> {
366 coff
::IMAGE_SCN_CNT_UNINITIALIZED_DATA
367 | coff
::IMAGE_SCN_MEM_READ
368 | coff
::IMAGE_SCN_MEM_WRITE
370 SectionKind
::ReadOnlyData
371 | SectionKind
::ReadOnlyDataWithRel
372 | SectionKind
::ReadOnlyString
=> {
373 coff
::IMAGE_SCN_CNT_INITIALIZED_DATA
| coff
::IMAGE_SCN_MEM_READ
375 SectionKind
::Debug
| SectionKind
::Other
| SectionKind
::OtherString
=> {
376 coff
::IMAGE_SCN_CNT_INITIALIZED_DATA
377 | coff
::IMAGE_SCN_MEM_READ
378 | coff
::IMAGE_SCN_MEM_DISCARDABLE
380 SectionKind
::Linker
=> coff
::IMAGE_SCN_LNK_INFO
| coff
::IMAGE_SCN_LNK_REMOVE
,
383 | SectionKind
::UninitializedTls
384 | SectionKind
::TlsVariables
386 | SectionKind
::Unknown
387 | SectionKind
::Metadata
388 | SectionKind
::Elf(_
) => {
389 return Err(Error(format
!(
390 "unimplemented section `{}` kind {:?}",
391 section
.name().unwrap_or(""),
397 if section_offsets
[index
].selection
!= 0 {
398 characteristics
|= coff
::IMAGE_SCN_LNK_COMDAT
;
400 if section
.relocations
.len() > 0xffff {
401 characteristics
|= coff
::IMAGE_SCN_LNK_NRELOC_OVFL
;
403 characteristics
|= match section
.align
{
404 1 => coff
::IMAGE_SCN_ALIGN_1BYTES
,
405 2 => coff
::IMAGE_SCN_ALIGN_2BYTES
,
406 4 => coff
::IMAGE_SCN_ALIGN_4BYTES
,
407 8 => coff
::IMAGE_SCN_ALIGN_8BYTES
,
408 16 => coff
::IMAGE_SCN_ALIGN_16BYTES
,
409 32 => coff
::IMAGE_SCN_ALIGN_32BYTES
,
410 64 => coff
::IMAGE_SCN_ALIGN_64BYTES
,
411 128 => coff
::IMAGE_SCN_ALIGN_128BYTES
,
412 256 => coff
::IMAGE_SCN_ALIGN_256BYTES
,
413 512 => coff
::IMAGE_SCN_ALIGN_512BYTES
,
414 1024 => coff
::IMAGE_SCN_ALIGN_1024BYTES
,
415 2048 => coff
::IMAGE_SCN_ALIGN_2048BYTES
,
416 4096 => coff
::IMAGE_SCN_ALIGN_4096BYTES
,
417 8192 => coff
::IMAGE_SCN_ALIGN_8192BYTES
,
419 return Err(Error(format
!(
420 "unimplemented section `{}` align {}",
421 section
.name().unwrap_or(""),
426 let mut coff_section
= coff
::ImageSectionHeader
{
428 virtual_size
: U32
::default(),
429 virtual_address
: U32
::default(),
430 size_of_raw_data
: U32
::new(LE
, section
.size
as u32),
431 pointer_to_raw_data
: U32
::new(LE
, section_offsets
[index
].offset
as u32),
432 pointer_to_relocations
: U32
::new(LE
, section_offsets
[index
].reloc_offset
as u32),
433 pointer_to_linenumbers
: U32
::default(),
434 number_of_relocations
: if section
.relocations
.len() > 0xffff {
437 U16
::new(LE
, section
.relocations
.len() as u16)
439 number_of_linenumbers
: U16
::default(),
440 characteristics
: U32
::new(LE
, characteristics
),
442 if section
.name
.len() <= 8 {
443 coff_section
.name
[..section
.name
.len()].copy_from_slice(§ion
.name
);
445 let mut str_offset
= strtab
.get_offset(section_offsets
[index
].str_id
.unwrap());
446 if str_offset
<= 9_999_999 {
447 let mut name
= [0; 7];
453 while str_offset
!= 0 {
454 let rem
= (str_offset
% 10) as u8;
456 name
[6 - len
] = b'
0'
+ rem
;
460 coff_section
.name
= [0; 8];
461 coff_section
.name
[0] = b'
/'
;
462 coff_section
.name
[1..][..len
].copy_from_slice(&name
[7 - len
..]);
463 } else if str_offset
as u64 <= 0xf_ffff_ffff {
464 coff_section
.name
[0] = b'
/'
;
465 coff_section
.name
[1] = b'
/'
;
467 let rem
= (str_offset
% 64) as u8;
470 0..=25 => b'A'
+ rem
,
471 26..=51 => b'a'
+ rem
- 26,
472 52..=61 => b'
0'
+ rem
- 52,
477 coff_section
.name
[7 - i
] = c
;
480 return Err(Error(format
!("invalid section name offset {}", str_offset
)));
483 buffer
.write(&coff_section
);
486 // Write section data and relocations.
487 for (index
, section
) in self.sections
.iter().enumerate() {
488 let len
= section
.data
.len();
490 write_align(buffer
, 4);
491 debug_assert_eq
!(section_offsets
[index
].offset
, buffer
.len());
492 buffer
.write_bytes(§ion
.data
);
495 if !section
.relocations
.is_empty() {
496 debug_assert_eq
!(section_offsets
[index
].reloc_offset
, buffer
.len());
497 if section
.relocations
.len() > 0xffff {
498 let coff_relocation
= coff
::ImageRelocation
{
499 virtual_address
: U32Bytes
::new(LE
, section
.relocations
.len() as u32 + 1),
500 symbol_table_index
: U32Bytes
::new(LE
, 0),
501 typ
: U16Bytes
::new(LE
, 0),
503 buffer
.write(&coff_relocation
);
505 for reloc
in §ion
.relocations
{
506 //assert!(reloc.implicit_addend);
507 let typ
= match self.architecture
{
508 Architecture
::I386
=> match (reloc
.kind
, reloc
.size
, reloc
.addend
) {
509 (RelocationKind
::Absolute
, 16, 0) => coff
::IMAGE_REL_I386_DIR16
,
510 (RelocationKind
::Relative
, 16, 0) => coff
::IMAGE_REL_I386_REL16
,
511 (RelocationKind
::Absolute
, 32, 0) => coff
::IMAGE_REL_I386_DIR32
,
512 (RelocationKind
::ImageOffset
, 32, 0) => coff
::IMAGE_REL_I386_DIR32NB
,
513 (RelocationKind
::SectionIndex
, 16, 0) => coff
::IMAGE_REL_I386_SECTION
,
514 (RelocationKind
::SectionOffset
, 32, 0) => coff
::IMAGE_REL_I386_SECREL
,
515 (RelocationKind
::SectionOffset
, 7, 0) => coff
::IMAGE_REL_I386_SECREL7
,
516 (RelocationKind
::Relative
, 32, -4) => coff
::IMAGE_REL_I386_REL32
,
517 (RelocationKind
::Coff(x
), _
, _
) => x
,
519 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
522 Architecture
::X86_64
=> match (reloc
.kind
, reloc
.size
, reloc
.addend
) {
523 (RelocationKind
::Absolute
, 64, 0) => coff
::IMAGE_REL_AMD64_ADDR64
,
524 (RelocationKind
::Absolute
, 32, 0) => coff
::IMAGE_REL_AMD64_ADDR32
,
525 (RelocationKind
::ImageOffset
, 32, 0) => coff
::IMAGE_REL_AMD64_ADDR32NB
,
526 (RelocationKind
::Relative
, 32, -4) => coff
::IMAGE_REL_AMD64_REL32
,
527 (RelocationKind
::Relative
, 32, -5) => coff
::IMAGE_REL_AMD64_REL32_1
,
528 (RelocationKind
::Relative
, 32, -6) => coff
::IMAGE_REL_AMD64_REL32_2
,
529 (RelocationKind
::Relative
, 32, -7) => coff
::IMAGE_REL_AMD64_REL32_3
,
530 (RelocationKind
::Relative
, 32, -8) => coff
::IMAGE_REL_AMD64_REL32_4
,
531 (RelocationKind
::Relative
, 32, -9) => coff
::IMAGE_REL_AMD64_REL32_5
,
532 (RelocationKind
::SectionIndex
, 16, 0) => coff
::IMAGE_REL_AMD64_SECTION
,
533 (RelocationKind
::SectionOffset
, 32, 0) => coff
::IMAGE_REL_AMD64_SECREL
,
534 (RelocationKind
::SectionOffset
, 7, 0) => coff
::IMAGE_REL_AMD64_SECREL7
,
535 (RelocationKind
::Coff(x
), _
, _
) => x
,
537 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
540 Architecture
::Arm
=> match (reloc
.kind
, reloc
.size
, reloc
.addend
) {
541 (RelocationKind
::Absolute
, 32, 0) => coff
::IMAGE_REL_ARM_ADDR32
,
542 (RelocationKind
::ImageOffset
, 32, 0) => coff
::IMAGE_REL_ARM_ADDR32NB
,
543 (RelocationKind
::Relative
, 32, -4) => coff
::IMAGE_REL_ARM_REL32
,
544 (RelocationKind
::SectionIndex
, 16, 0) => coff
::IMAGE_REL_ARM_SECTION
,
545 (RelocationKind
::SectionOffset
, 32, 0) => coff
::IMAGE_REL_ARM_SECREL
,
546 (RelocationKind
::Coff(x
), _
, _
) => x
,
548 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
551 Architecture
::Aarch64
=> match (reloc
.kind
, reloc
.size
, reloc
.addend
) {
552 (RelocationKind
::Absolute
, 32, 0) => coff
::IMAGE_REL_ARM64_ADDR32
,
553 (RelocationKind
::ImageOffset
, 32, 0) => coff
::IMAGE_REL_ARM64_ADDR32NB
,
554 (RelocationKind
::SectionIndex
, 16, 0) => coff
::IMAGE_REL_ARM64_SECTION
,
555 (RelocationKind
::SectionOffset
, 32, 0) => coff
::IMAGE_REL_ARM64_SECREL
,
556 (RelocationKind
::Absolute
, 64, 0) => coff
::IMAGE_REL_ARM64_ADDR64
,
557 (RelocationKind
::Relative
, 32, -4) => coff
::IMAGE_REL_ARM64_REL32
,
558 (RelocationKind
::Coff(x
), _
, _
) => x
,
560 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
564 return Err(Error(format
!(
565 "unimplemented architecture {:?}",
570 let coff_relocation
= coff
::ImageRelocation
{
571 virtual_address
: U32Bytes
::new(LE
, reloc
.offset
as u32),
572 symbol_table_index
: U32Bytes
::new(
574 symbol_offsets
[reloc
.symbol
.0].index
as u32,
576 typ
: U16Bytes
::new(LE
, typ
),
578 buffer
.write(&coff_relocation
);
584 debug_assert_eq
!(symtab_offset
, buffer
.len());
585 for (index
, symbol
) in self.symbols
.iter().enumerate() {
586 let mut name
= &symbol
.name
[..];
587 let section_number
= match symbol
.section
{
588 SymbolSection
::None
=> {
589 debug_assert_eq
!(symbol
.kind
, SymbolKind
::File
);
590 coff
::IMAGE_SYM_DEBUG
as u16
592 SymbolSection
::Undefined
=> coff
::IMAGE_SYM_UNDEFINED
as u16,
593 SymbolSection
::Absolute
=> coff
::IMAGE_SYM_ABSOLUTE
as u16,
594 SymbolSection
::Common
=> coff
::IMAGE_SYM_UNDEFINED
as u16,
595 SymbolSection
::Section(id
) => id
.0 as u16 + 1,
597 let typ
= if symbol
.kind
== SymbolKind
::Text
{
598 coff
::IMAGE_SYM_DTYPE_FUNCTION
<< coff
::IMAGE_SYM_DTYPE_SHIFT
600 coff
::IMAGE_SYM_TYPE_NULL
602 let storage_class
= match symbol
.kind
{
603 SymbolKind
::File
=> {
604 // Name goes in auxiliary symbol records.
606 coff
::IMAGE_SYM_CLASS_FILE
608 SymbolKind
::Section
=> coff
::IMAGE_SYM_CLASS_STATIC
,
609 SymbolKind
::Label
=> coff
::IMAGE_SYM_CLASS_LABEL
,
610 SymbolKind
::Text
| SymbolKind
::Data
| SymbolKind
::Tls
=> {
611 match symbol
.section
{
612 SymbolSection
::None
=> {
613 return Err(Error(format
!(
614 "missing section for symbol `{}`",
615 symbol
.name().unwrap_or("")
618 SymbolSection
::Undefined
| SymbolSection
::Common
=> {
619 coff
::IMAGE_SYM_CLASS_EXTERNAL
621 SymbolSection
::Absolute
| SymbolSection
::Section(_
) => {
623 // TODO: does this need aux symbol records too?
624 _
if symbol
.weak
=> coff
::IMAGE_SYM_CLASS_WEAK_EXTERNAL
,
625 SymbolScope
::Unknown
=> {
626 return Err(Error(format
!(
627 "unimplemented symbol `{}` scope {:?}",
628 symbol
.name().unwrap_or(""),
632 SymbolScope
::Compilation
=> coff
::IMAGE_SYM_CLASS_STATIC
,
633 SymbolScope
::Linkage
| SymbolScope
::Dynamic
=> {
634 coff
::IMAGE_SYM_CLASS_EXTERNAL
640 SymbolKind
::Unknown
| SymbolKind
::Null
=> {
641 return Err(Error(format
!(
642 "unimplemented symbol `{}` kind {:?}",
643 symbol
.name().unwrap_or(""),
648 let number_of_aux_symbols
= symbol_offsets
[index
].aux_count
;
649 let value
= if symbol
.section
== SymbolSection
::Common
{
654 let mut coff_symbol
= coff
::ImageSymbol
{
656 value
: U32Bytes
::new(LE
, value
),
657 section_number
: U16Bytes
::new(LE
, section_number
),
658 typ
: U16Bytes
::new(LE
, typ
),
660 number_of_aux_symbols
,
663 coff_symbol
.name
[..name
.len()].copy_from_slice(name
);
665 let str_offset
= strtab
.get_offset(symbol_offsets
[index
].str_id
.unwrap());
666 coff_symbol
.name
[4..8].copy_from_slice(&u32::to_le_bytes(str_offset
as u32));
668 buffer
.write(&coff_symbol
);
670 // Write auxiliary symbols.
672 SymbolKind
::File
=> {
673 let aux_len
= number_of_aux_symbols
as usize * coff
::IMAGE_SIZEOF_SYMBOL
;
674 debug_assert
!(aux_len
>= symbol
.name
.len());
675 let old_len
= buffer
.len();
676 buffer
.write_bytes(&symbol
.name
);
677 buffer
.resize(old_len
+ aux_len
);
679 SymbolKind
::Section
=> {
680 debug_assert_eq
!(number_of_aux_symbols
, 1);
681 let section_index
= symbol
.section
.id().unwrap().0;
682 let section
= &self.sections
[section_index
];
683 let aux
= coff
::ImageAuxSymbolSection
{
684 length
: U32Bytes
::new(LE
, section
.size
as u32),
685 number_of_relocations
: if section
.relocations
.len() > 0xffff {
686 U16Bytes
::new(LE
, 0xffff)
688 U16Bytes
::new(LE
, section
.relocations
.len() as u16)
690 number_of_linenumbers
: U16Bytes
::default(),
691 check_sum
: U32Bytes
::new(LE
, checksum(section
.data())),
692 number
: U16Bytes
::new(
694 section_offsets
[section_index
].associative_section
,
696 selection
: section_offsets
[section_index
].selection
,
699 high_number
: U16Bytes
::default(),
704 debug_assert_eq
!(number_of_aux_symbols
, 0);
709 // Write strtab section.
710 debug_assert_eq
!(strtab_offset
, buffer
.len());
711 buffer
.write_bytes(&u32::to_le_bytes(strtab_len
as u32));
712 buffer
.write_bytes(&strtab_data
);
714 debug_assert_eq
!(offset
, buffer
.len());
721 fn checksum(data
: &[u8]) -> u32 {
722 let mut hasher
= crc32fast
::Hasher
::new_with_initial(0xffff_ffff);