]> git.proxmox.com Git - rustc.git/blob - vendor/object/src/write/mod.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / vendor / object / src / write / mod.rs
1 //! Interface for writing object files.
2
3 use alloc::borrow::Cow;
4 use alloc::string::String;
5 use alloc::vec::Vec;
6 use core::{fmt, result, str};
7 #[cfg(not(feature = "std"))]
8 use hashbrown::HashMap;
9 #[cfg(feature = "std")]
10 use std::{boxed::Box, collections::HashMap, error, io};
11
12 use crate::endian::{Endianness, U32, U64};
13 use crate::{
14 Architecture, BinaryFormat, ComdatKind, FileFlags, RelocationEncoding, RelocationKind,
15 SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope,
16 };
17
18 #[cfg(feature = "coff")]
19 mod coff;
20 #[cfg(feature = "coff")]
21 pub use coff::CoffExportStyle;
22
23 #[cfg(feature = "elf")]
24 pub mod elf;
25
26 #[cfg(feature = "macho")]
27 mod macho;
28 #[cfg(feature = "macho")]
29 pub use macho::MachOBuildVersion;
30
31 #[cfg(feature = "pe")]
32 pub mod pe;
33
34 #[cfg(feature = "xcoff")]
35 mod xcoff;
36
37 mod string;
38 pub use string::StringId;
39
40 mod util;
41 pub use util::*;
42
43 /// The error type used within the write module.
44 #[derive(Debug, Clone, PartialEq, Eq)]
45 pub struct Error(String);
46
47 impl fmt::Display for Error {
48 #[inline]
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 f.write_str(&self.0)
51 }
52 }
53
54 #[cfg(feature = "std")]
55 impl error::Error for Error {}
56
57 /// The result type used within the write module.
58 pub type Result<T> = result::Result<T, Error>;
59
60 /// A writable relocatable object file.
61 #[derive(Debug)]
62 pub struct Object<'a> {
63 format: BinaryFormat,
64 architecture: Architecture,
65 endian: Endianness,
66 sections: Vec<Section<'a>>,
67 standard_sections: HashMap<StandardSection, SectionId>,
68 symbols: Vec<Symbol>,
69 symbol_map: HashMap<Vec<u8>, SymbolId>,
70 stub_symbols: HashMap<SymbolId, SymbolId>,
71 comdats: Vec<Comdat>,
72 /// File flags that are specific to each file format.
73 pub flags: FileFlags,
74 /// The symbol name mangling scheme.
75 pub mangling: Mangling,
76 /// Mach-O "_tlv_bootstrap" symbol.
77 tlv_bootstrap: Option<SymbolId>,
78 /// Mach-O CPU subtype.
79 #[cfg(feature = "macho")]
80 macho_cpu_subtype: Option<u32>,
81 #[cfg(feature = "macho")]
82 macho_build_version: Option<MachOBuildVersion>,
83 }
84
85 impl<'a> Object<'a> {
86 /// Create an empty object file.
87 pub fn new(format: BinaryFormat, architecture: Architecture, endian: Endianness) -> Object<'a> {
88 Object {
89 format,
90 architecture,
91 endian,
92 sections: Vec::new(),
93 standard_sections: HashMap::new(),
94 symbols: Vec::new(),
95 symbol_map: HashMap::new(),
96 stub_symbols: HashMap::new(),
97 comdats: Vec::new(),
98 flags: FileFlags::None,
99 mangling: Mangling::default(format, architecture),
100 tlv_bootstrap: None,
101 #[cfg(feature = "macho")]
102 macho_cpu_subtype: None,
103 #[cfg(feature = "macho")]
104 macho_build_version: None,
105 }
106 }
107
108 /// Return the file format.
109 #[inline]
110 pub fn format(&self) -> BinaryFormat {
111 self.format
112 }
113
114 /// Return the architecture.
115 #[inline]
116 pub fn architecture(&self) -> Architecture {
117 self.architecture
118 }
119
120 /// Return the current mangling setting.
121 #[inline]
122 pub fn mangling(&self) -> Mangling {
123 self.mangling
124 }
125
126 /// Specify the mangling setting.
127 #[inline]
128 pub fn set_mangling(&mut self, mangling: Mangling) {
129 self.mangling = mangling;
130 }
131
132 /// Return the name for a standard segment.
133 ///
134 /// This will vary based on the file format.
135 #[allow(unused_variables)]
136 pub fn segment_name(&self, segment: StandardSegment) -> &'static [u8] {
137 match self.format {
138 #[cfg(feature = "coff")]
139 BinaryFormat::Coff => &[],
140 #[cfg(feature = "elf")]
141 BinaryFormat::Elf => &[],
142 #[cfg(feature = "macho")]
143 BinaryFormat::MachO => self.macho_segment_name(segment),
144 _ => unimplemented!(),
145 }
146 }
147
148 /// Get the section with the given `SectionId`.
149 #[inline]
150 pub fn section(&self, section: SectionId) -> &Section<'a> {
151 &self.sections[section.0]
152 }
153
154 /// Mutably get the section with the given `SectionId`.
155 #[inline]
156 pub fn section_mut(&mut self, section: SectionId) -> &mut Section<'a> {
157 &mut self.sections[section.0]
158 }
159
160 /// Set the data for an existing section.
161 ///
162 /// Must not be called for sections that already have data, or that contain uninitialized data.
163 pub fn set_section_data<T>(&mut self, section: SectionId, data: T, align: u64)
164 where
165 T: Into<Cow<'a, [u8]>>,
166 {
167 self.sections[section.0].set_data(data, align)
168 }
169
170 /// Append data to an existing section. Returns the section offset of the data.
171 pub fn append_section_data(&mut self, section: SectionId, data: &[u8], align: u64) -> u64 {
172 self.sections[section.0].append_data(data, align)
173 }
174
175 /// Append zero-initialized data to an existing section. Returns the section offset of the data.
176 pub fn append_section_bss(&mut self, section: SectionId, size: u64, align: u64) -> u64 {
177 self.sections[section.0].append_bss(size, align)
178 }
179
180 /// Return the `SectionId` of a standard section.
181 ///
182 /// If the section doesn't already exist then it is created.
183 pub fn section_id(&mut self, section: StandardSection) -> SectionId {
184 self.standard_sections
185 .get(&section)
186 .cloned()
187 .unwrap_or_else(|| {
188 let (segment, name, kind, flags) = self.section_info(section);
189 let id = self.add_section(segment.to_vec(), name.to_vec(), kind);
190 self.section_mut(id).flags = flags;
191 id
192 })
193 }
194
195 /// Add a new section and return its `SectionId`.
196 ///
197 /// This also creates a section symbol.
198 pub fn add_section(&mut self, segment: Vec<u8>, name: Vec<u8>, kind: SectionKind) -> SectionId {
199 let id = SectionId(self.sections.len());
200 self.sections.push(Section {
201 segment,
202 name,
203 kind,
204 size: 0,
205 align: 1,
206 data: Cow::Borrowed(&[]),
207 relocations: Vec::new(),
208 symbol: None,
209 flags: SectionFlags::None,
210 });
211
212 // Add to self.standard_sections if required. This may match multiple standard sections.
213 let section = &self.sections[id.0];
214 for standard_section in StandardSection::all() {
215 if !self.standard_sections.contains_key(standard_section) {
216 let (segment, name, kind, _flags) = self.section_info(*standard_section);
217 if segment == &*section.segment && name == &*section.name && kind == section.kind {
218 self.standard_sections.insert(*standard_section, id);
219 }
220 }
221 }
222
223 id
224 }
225
226 fn section_info(
227 &self,
228 section: StandardSection,
229 ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) {
230 match self.format {
231 #[cfg(feature = "coff")]
232 BinaryFormat::Coff => self.coff_section_info(section),
233 #[cfg(feature = "elf")]
234 BinaryFormat::Elf => self.elf_section_info(section),
235 #[cfg(feature = "macho")]
236 BinaryFormat::MachO => self.macho_section_info(section),
237 #[cfg(feature = "xcoff")]
238 BinaryFormat::Xcoff => self.xcoff_section_info(section),
239 _ => unimplemented!(),
240 }
241 }
242
243 /// Add a subsection. Returns the `SectionId` and section offset of the data.
244 pub fn add_subsection(
245 &mut self,
246 section: StandardSection,
247 name: &[u8],
248 data: &[u8],
249 align: u64,
250 ) -> (SectionId, u64) {
251 let section_id = if self.has_subsections_via_symbols() {
252 self.set_subsections_via_symbols();
253 self.section_id(section)
254 } else {
255 let (segment, name, kind, flags) = self.subsection_info(section, name);
256 let id = self.add_section(segment.to_vec(), name, kind);
257 self.section_mut(id).flags = flags;
258 id
259 };
260 let offset = self.append_section_data(section_id, data, align);
261 (section_id, offset)
262 }
263
264 fn has_subsections_via_symbols(&self) -> bool {
265 match self.format {
266 BinaryFormat::Coff | BinaryFormat::Elf | BinaryFormat::Xcoff => false,
267 BinaryFormat::MachO => true,
268 _ => unimplemented!(),
269 }
270 }
271
272 fn set_subsections_via_symbols(&mut self) {
273 match self.format {
274 #[cfg(feature = "macho")]
275 BinaryFormat::MachO => self.macho_set_subsections_via_symbols(),
276 _ => unimplemented!(),
277 }
278 }
279
280 fn subsection_info(
281 &self,
282 section: StandardSection,
283 value: &[u8],
284 ) -> (&'static [u8], Vec<u8>, SectionKind, SectionFlags) {
285 let (segment, section, kind, flags) = self.section_info(section);
286 let name = self.subsection_name(section, value);
287 (segment, name, kind, flags)
288 }
289
290 #[allow(unused_variables)]
291 fn subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
292 debug_assert!(!self.has_subsections_via_symbols());
293 match self.format {
294 #[cfg(feature = "coff")]
295 BinaryFormat::Coff => self.coff_subsection_name(section, value),
296 #[cfg(feature = "elf")]
297 BinaryFormat::Elf => self.elf_subsection_name(section, value),
298 _ => unimplemented!(),
299 }
300 }
301
302 /// Get the COMDAT section group with the given `ComdatId`.
303 #[inline]
304 pub fn comdat(&self, comdat: ComdatId) -> &Comdat {
305 &self.comdats[comdat.0]
306 }
307
308 /// Mutably get the COMDAT section group with the given `ComdatId`.
309 #[inline]
310 pub fn comdat_mut(&mut self, comdat: ComdatId) -> &mut Comdat {
311 &mut self.comdats[comdat.0]
312 }
313
314 /// Add a new COMDAT section group and return its `ComdatId`.
315 pub fn add_comdat(&mut self, comdat: Comdat) -> ComdatId {
316 let comdat_id = ComdatId(self.comdats.len());
317 self.comdats.push(comdat);
318 comdat_id
319 }
320
321 /// Get the `SymbolId` of the symbol with the given name.
322 pub fn symbol_id(&self, name: &[u8]) -> Option<SymbolId> {
323 self.symbol_map.get(name).cloned()
324 }
325
326 /// Get the symbol with the given `SymbolId`.
327 #[inline]
328 pub fn symbol(&self, symbol: SymbolId) -> &Symbol {
329 &self.symbols[symbol.0]
330 }
331
332 /// Mutably get the symbol with the given `SymbolId`.
333 #[inline]
334 pub fn symbol_mut(&mut self, symbol: SymbolId) -> &mut Symbol {
335 &mut self.symbols[symbol.0]
336 }
337
338 /// Add a new symbol and return its `SymbolId`.
339 pub fn add_symbol(&mut self, mut symbol: Symbol) -> SymbolId {
340 // Defined symbols must have a scope.
341 debug_assert!(symbol.is_undefined() || symbol.scope != SymbolScope::Unknown);
342 if symbol.kind == SymbolKind::Section {
343 // There can only be one section symbol, but update its flags, since
344 // the automatically generated section symbol will have none.
345 let symbol_id = self.section_symbol(symbol.section.id().unwrap());
346 if symbol.flags != SymbolFlags::None {
347 self.symbol_mut(symbol_id).flags = symbol.flags;
348 }
349 return symbol_id;
350 }
351 if !symbol.name.is_empty()
352 && (symbol.kind == SymbolKind::Text
353 || symbol.kind == SymbolKind::Data
354 || symbol.kind == SymbolKind::Tls)
355 {
356 let unmangled_name = symbol.name.clone();
357 if let Some(prefix) = self.mangling.global_prefix() {
358 symbol.name.insert(0, prefix);
359 }
360 let symbol_id = self.add_raw_symbol(symbol);
361 self.symbol_map.insert(unmangled_name, symbol_id);
362 symbol_id
363 } else {
364 self.add_raw_symbol(symbol)
365 }
366 }
367
368 fn add_raw_symbol(&mut self, symbol: Symbol) -> SymbolId {
369 let symbol_id = SymbolId(self.symbols.len());
370 self.symbols.push(symbol);
371 symbol_id
372 }
373
374 /// Return true if the file format supports `StandardSection::UninitializedTls`.
375 #[inline]
376 pub fn has_uninitialized_tls(&self) -> bool {
377 self.format != BinaryFormat::Coff
378 }
379
380 /// Return true if the file format supports `StandardSection::Common`.
381 #[inline]
382 pub fn has_common(&self) -> bool {
383 self.format == BinaryFormat::MachO
384 }
385
386 /// Add a new common symbol and return its `SymbolId`.
387 ///
388 /// For Mach-O, this appends the symbol to the `__common` section.
389 pub fn add_common_symbol(&mut self, mut symbol: Symbol, size: u64, align: u64) -> SymbolId {
390 if self.has_common() {
391 let symbol_id = self.add_symbol(symbol);
392 let section = self.section_id(StandardSection::Common);
393 self.add_symbol_bss(symbol_id, section, size, align);
394 symbol_id
395 } else {
396 symbol.section = SymbolSection::Common;
397 symbol.size = size;
398 self.add_symbol(symbol)
399 }
400 }
401
402 /// Add a new file symbol and return its `SymbolId`.
403 pub fn add_file_symbol(&mut self, name: Vec<u8>) -> SymbolId {
404 self.add_raw_symbol(Symbol {
405 name,
406 value: 0,
407 size: 0,
408 kind: SymbolKind::File,
409 scope: SymbolScope::Compilation,
410 weak: false,
411 section: SymbolSection::None,
412 flags: SymbolFlags::None,
413 })
414 }
415
416 /// Get the symbol for a section.
417 pub fn section_symbol(&mut self, section_id: SectionId) -> SymbolId {
418 let section = &mut self.sections[section_id.0];
419 if let Some(symbol) = section.symbol {
420 return symbol;
421 }
422 let name = if self.format == BinaryFormat::Coff {
423 section.name.clone()
424 } else {
425 Vec::new()
426 };
427 let symbol_id = SymbolId(self.symbols.len());
428 self.symbols.push(Symbol {
429 name,
430 value: 0,
431 size: 0,
432 kind: SymbolKind::Section,
433 scope: SymbolScope::Compilation,
434 weak: false,
435 section: SymbolSection::Section(section_id),
436 flags: SymbolFlags::None,
437 });
438 section.symbol = Some(symbol_id);
439 symbol_id
440 }
441
442 /// Append data to an existing section, and update a symbol to refer to it.
443 ///
444 /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
445 /// symbol will indirectly point to the added data via the `__thread_vars` entry.
446 ///
447 /// Returns the section offset of the data.
448 pub fn add_symbol_data(
449 &mut self,
450 symbol_id: SymbolId,
451 section: SectionId,
452 data: &[u8],
453 align: u64,
454 ) -> u64 {
455 let offset = self.append_section_data(section, data, align);
456 self.set_symbol_data(symbol_id, section, offset, data.len() as u64);
457 offset
458 }
459
460 /// Append zero-initialized data to an existing section, and update a symbol to refer to it.
461 ///
462 /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
463 /// symbol will indirectly point to the added data via the `__thread_vars` entry.
464 ///
465 /// Returns the section offset of the data.
466 pub fn add_symbol_bss(
467 &mut self,
468 symbol_id: SymbolId,
469 section: SectionId,
470 size: u64,
471 align: u64,
472 ) -> u64 {
473 let offset = self.append_section_bss(section, size, align);
474 self.set_symbol_data(symbol_id, section, offset, size);
475 offset
476 }
477
478 /// Update a symbol to refer to the given data within a section.
479 ///
480 /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
481 /// symbol will indirectly point to the data via the `__thread_vars` entry.
482 #[allow(unused_mut)]
483 pub fn set_symbol_data(
484 &mut self,
485 mut symbol_id: SymbolId,
486 section: SectionId,
487 offset: u64,
488 size: u64,
489 ) {
490 // Defined symbols must have a scope.
491 debug_assert!(self.symbol(symbol_id).scope != SymbolScope::Unknown);
492 match self.format {
493 #[cfg(feature = "macho")]
494 BinaryFormat::MachO => symbol_id = self.macho_add_thread_var(symbol_id),
495 _ => {}
496 }
497 let symbol = self.symbol_mut(symbol_id);
498 symbol.value = offset;
499 symbol.size = size;
500 symbol.section = SymbolSection::Section(section);
501 }
502
503 /// Convert a symbol to a section symbol and offset.
504 ///
505 /// Returns `None` if the symbol does not have a section.
506 pub fn symbol_section_and_offset(&mut self, symbol_id: SymbolId) -> Option<(SymbolId, u64)> {
507 let symbol = self.symbol(symbol_id);
508 if symbol.kind == SymbolKind::Section {
509 return Some((symbol_id, 0));
510 }
511 let symbol_offset = symbol.value;
512 let section = symbol.section.id()?;
513 let section_symbol = self.section_symbol(section);
514 Some((section_symbol, symbol_offset))
515 }
516
517 /// Add a relocation to a section.
518 ///
519 /// Relocations must only be added after the referenced symbols have been added
520 /// and defined (if applicable).
521 pub fn add_relocation(&mut self, section: SectionId, mut relocation: Relocation) -> Result<()> {
522 let addend = match self.format {
523 #[cfg(feature = "coff")]
524 BinaryFormat::Coff => self.coff_fixup_relocation(&mut relocation),
525 #[cfg(feature = "elf")]
526 BinaryFormat::Elf => self.elf_fixup_relocation(&mut relocation)?,
527 #[cfg(feature = "macho")]
528 BinaryFormat::MachO => self.macho_fixup_relocation(&mut relocation),
529 #[cfg(feature = "xcoff")]
530 BinaryFormat::Xcoff => self.xcoff_fixup_relocation(&mut relocation),
531 _ => unimplemented!(),
532 };
533 if addend != 0 {
534 self.write_relocation_addend(section, &relocation, addend)?;
535 }
536 self.sections[section.0].relocations.push(relocation);
537 Ok(())
538 }
539
540 fn write_relocation_addend(
541 &mut self,
542 section: SectionId,
543 relocation: &Relocation,
544 addend: i64,
545 ) -> Result<()> {
546 let data = self.sections[section.0].data_mut();
547 let offset = relocation.offset as usize;
548 match relocation.size {
549 32 => data.write_at(offset, &U32::new(self.endian, addend as u32)),
550 64 => data.write_at(offset, &U64::new(self.endian, addend as u64)),
551 _ => {
552 return Err(Error(format!(
553 "unimplemented relocation addend {:?}",
554 relocation
555 )));
556 }
557 }
558 .map_err(|_| {
559 Error(format!(
560 "invalid relocation offset {}+{} (max {})",
561 relocation.offset,
562 relocation.size,
563 data.len()
564 ))
565 })
566 }
567
568 /// Write the object to a `Vec`.
569 pub fn write(&self) -> Result<Vec<u8>> {
570 let mut buffer = Vec::new();
571 self.emit(&mut buffer)?;
572 Ok(buffer)
573 }
574
575 /// Write the object to a `Write` implementation.
576 ///
577 /// Also flushes the writer.
578 ///
579 /// It is advisable to use a buffered writer like [`BufWriter`](std::io::BufWriter)
580 /// instead of an unbuffered writer like [`File`](std::fs::File).
581 #[cfg(feature = "std")]
582 pub fn write_stream<W: io::Write>(&self, w: W) -> result::Result<(), Box<dyn error::Error>> {
583 let mut stream = StreamingBuffer::new(w);
584 self.emit(&mut stream)?;
585 stream.result()?;
586 stream.into_inner().flush()?;
587 Ok(())
588 }
589
590 /// Write the object to a `WritableBuffer`.
591 pub fn emit(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
592 match self.format {
593 #[cfg(feature = "coff")]
594 BinaryFormat::Coff => self.coff_write(buffer),
595 #[cfg(feature = "elf")]
596 BinaryFormat::Elf => self.elf_write(buffer),
597 #[cfg(feature = "macho")]
598 BinaryFormat::MachO => self.macho_write(buffer),
599 #[cfg(feature = "xcoff")]
600 BinaryFormat::Xcoff => self.xcoff_write(buffer),
601 _ => unimplemented!(),
602 }
603 }
604 }
605
606 /// A standard segment kind.
607 #[allow(missing_docs)]
608 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
609 #[non_exhaustive]
610 pub enum StandardSegment {
611 Text,
612 Data,
613 Debug,
614 }
615
616 /// A standard section kind.
617 #[allow(missing_docs)]
618 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
619 #[non_exhaustive]
620 pub enum StandardSection {
621 Text,
622 Data,
623 ReadOnlyData,
624 ReadOnlyDataWithRel,
625 ReadOnlyString,
626 UninitializedData,
627 Tls,
628 /// Zero-fill TLS initializers. Unsupported for COFF.
629 UninitializedTls,
630 /// TLS variable structures. Only supported for Mach-O.
631 TlsVariables,
632 /// Common data. Only supported for Mach-O.
633 Common,
634 /// Notes for GNU properties. Only supported for ELF.
635 GnuProperty,
636 }
637
638 impl StandardSection {
639 /// Return the section kind of a standard section.
640 pub fn kind(self) -> SectionKind {
641 match self {
642 StandardSection::Text => SectionKind::Text,
643 StandardSection::Data => SectionKind::Data,
644 StandardSection::ReadOnlyData => SectionKind::ReadOnlyData,
645 StandardSection::ReadOnlyDataWithRel => SectionKind::ReadOnlyDataWithRel,
646 StandardSection::ReadOnlyString => SectionKind::ReadOnlyString,
647 StandardSection::UninitializedData => SectionKind::UninitializedData,
648 StandardSection::Tls => SectionKind::Tls,
649 StandardSection::UninitializedTls => SectionKind::UninitializedTls,
650 StandardSection::TlsVariables => SectionKind::TlsVariables,
651 StandardSection::Common => SectionKind::Common,
652 StandardSection::GnuProperty => SectionKind::Note,
653 }
654 }
655
656 // TODO: remembering to update this is error-prone, can we do better?
657 fn all() -> &'static [StandardSection] {
658 &[
659 StandardSection::Text,
660 StandardSection::Data,
661 StandardSection::ReadOnlyData,
662 StandardSection::ReadOnlyDataWithRel,
663 StandardSection::ReadOnlyString,
664 StandardSection::UninitializedData,
665 StandardSection::Tls,
666 StandardSection::UninitializedTls,
667 StandardSection::TlsVariables,
668 StandardSection::Common,
669 StandardSection::GnuProperty,
670 ]
671 }
672 }
673
674 /// An identifier used to reference a section.
675 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
676 pub struct SectionId(usize);
677
678 /// A section in an object file.
679 #[derive(Debug)]
680 pub struct Section<'a> {
681 segment: Vec<u8>,
682 name: Vec<u8>,
683 kind: SectionKind,
684 size: u64,
685 align: u64,
686 data: Cow<'a, [u8]>,
687 relocations: Vec<Relocation>,
688 symbol: Option<SymbolId>,
689 /// Section flags that are specific to each file format.
690 pub flags: SectionFlags,
691 }
692
693 impl<'a> Section<'a> {
694 /// Try to convert the name to a utf8 string.
695 #[inline]
696 pub fn name(&self) -> Option<&str> {
697 str::from_utf8(&self.name).ok()
698 }
699
700 /// Try to convert the segment to a utf8 string.
701 #[inline]
702 pub fn segment(&self) -> Option<&str> {
703 str::from_utf8(&self.segment).ok()
704 }
705
706 /// Return true if this section contains zerofill data.
707 #[inline]
708 pub fn is_bss(&self) -> bool {
709 self.kind.is_bss()
710 }
711
712 /// Set the data for a section.
713 ///
714 /// Must not be called for sections that already have data, or that contain uninitialized data.
715 pub fn set_data<T>(&mut self, data: T, align: u64)
716 where
717 T: Into<Cow<'a, [u8]>>,
718 {
719 debug_assert!(!self.is_bss());
720 debug_assert_eq!(align & (align - 1), 0);
721 debug_assert!(self.data.is_empty());
722 self.data = data.into();
723 self.size = self.data.len() as u64;
724 self.align = align;
725 }
726
727 /// Append data to a section.
728 ///
729 /// Must not be called for sections that contain uninitialized data.
730 pub fn append_data(&mut self, append_data: &[u8], align: u64) -> u64 {
731 debug_assert!(!self.is_bss());
732 debug_assert_eq!(align & (align - 1), 0);
733 if self.align < align {
734 self.align = align;
735 }
736 let align = align as usize;
737 let data = self.data.to_mut();
738 let mut offset = data.len();
739 if offset & (align - 1) != 0 {
740 offset += align - (offset & (align - 1));
741 data.resize(offset, 0);
742 }
743 data.extend_from_slice(append_data);
744 self.size = data.len() as u64;
745 offset as u64
746 }
747
748 /// Append uninitialized data to a section.
749 ///
750 /// Must not be called for sections that contain initialized data.
751 pub fn append_bss(&mut self, size: u64, align: u64) -> u64 {
752 debug_assert!(self.is_bss());
753 debug_assert_eq!(align & (align - 1), 0);
754 if self.align < align {
755 self.align = align;
756 }
757 let mut offset = self.size;
758 if offset & (align - 1) != 0 {
759 offset += align - (offset & (align - 1));
760 self.size = offset;
761 }
762 self.size += size;
763 offset
764 }
765
766 /// Returns the section as-built so far.
767 ///
768 /// This requires that the section is not a bss section.
769 pub fn data(&self) -> &[u8] {
770 debug_assert!(!self.is_bss());
771 &self.data
772 }
773
774 /// Returns the section as-built so far.
775 ///
776 /// This requires that the section is not a bss section.
777 pub fn data_mut(&mut self) -> &mut [u8] {
778 debug_assert!(!self.is_bss());
779 self.data.to_mut()
780 }
781 }
782
783 /// The section where a symbol is defined.
784 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
785 #[non_exhaustive]
786 pub enum SymbolSection {
787 /// The section is not applicable for this symbol (such as file symbols).
788 None,
789 /// The symbol is undefined.
790 Undefined,
791 /// The symbol has an absolute value.
792 Absolute,
793 /// The symbol is a zero-initialized symbol that will be combined with duplicate definitions.
794 Common,
795 /// The symbol is defined in the given section.
796 Section(SectionId),
797 }
798
799 impl SymbolSection {
800 /// Returns the section id for the section where the symbol is defined.
801 ///
802 /// May return `None` if the symbol is not defined in a section.
803 #[inline]
804 pub fn id(self) -> Option<SectionId> {
805 if let SymbolSection::Section(id) = self {
806 Some(id)
807 } else {
808 None
809 }
810 }
811 }
812
813 /// An identifier used to reference a symbol.
814 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
815 pub struct SymbolId(usize);
816
817 /// A symbol in an object file.
818 #[derive(Debug)]
819 pub struct Symbol {
820 /// The name of the symbol.
821 pub name: Vec<u8>,
822 /// The value of the symbol.
823 ///
824 /// If the symbol defined in a section, then this is the section offset of the symbol.
825 pub value: u64,
826 /// The size of the symbol.
827 pub size: u64,
828 /// The kind of the symbol.
829 pub kind: SymbolKind,
830 /// The scope of the symbol.
831 pub scope: SymbolScope,
832 /// Whether the symbol has weak binding.
833 pub weak: bool,
834 /// The section containing the symbol.
835 pub section: SymbolSection,
836 /// Symbol flags that are specific to each file format.
837 pub flags: SymbolFlags<SectionId, SymbolId>,
838 }
839
840 impl Symbol {
841 /// Try to convert the name to a utf8 string.
842 #[inline]
843 pub fn name(&self) -> Option<&str> {
844 str::from_utf8(&self.name).ok()
845 }
846
847 /// Return true if the symbol is undefined.
848 #[inline]
849 pub fn is_undefined(&self) -> bool {
850 self.section == SymbolSection::Undefined
851 }
852
853 /// Return true if the symbol is common data.
854 ///
855 /// Note: does not check for `SymbolSection::Section` with `SectionKind::Common`.
856 #[inline]
857 pub fn is_common(&self) -> bool {
858 self.section == SymbolSection::Common
859 }
860
861 /// Return true if the symbol scope is local.
862 #[inline]
863 pub fn is_local(&self) -> bool {
864 self.scope == SymbolScope::Compilation
865 }
866 }
867
868 /// A relocation in an object file.
869 #[derive(Debug)]
870 pub struct Relocation {
871 /// The section offset of the place of the relocation.
872 pub offset: u64,
873 /// The size in bits of the place of relocation.
874 pub size: u8,
875 /// The operation used to calculate the result of the relocation.
876 pub kind: RelocationKind,
877 /// Information about how the result of the relocation operation is encoded in the place.
878 pub encoding: RelocationEncoding,
879 /// The symbol referred to by the relocation.
880 ///
881 /// This may be a section symbol.
882 pub symbol: SymbolId,
883 /// The addend to use in the relocation calculation.
884 ///
885 /// This may be in addition to an implicit addend stored at the place of the relocation.
886 pub addend: i64,
887 }
888
889 /// An identifier used to reference a COMDAT section group.
890 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
891 pub struct ComdatId(usize);
892
893 /// A COMDAT section group.
894 #[derive(Debug)]
895 pub struct Comdat {
896 /// The COMDAT selection kind.
897 ///
898 /// This determines the way in which the linker resolves multiple definitions of the COMDAT
899 /// sections.
900 pub kind: ComdatKind,
901 /// The COMDAT symbol.
902 ///
903 /// If this symbol is referenced, then all sections in the group will be included by the
904 /// linker.
905 pub symbol: SymbolId,
906 /// The sections in the group.
907 pub sections: Vec<SectionId>,
908 }
909
910 /// The symbol name mangling scheme.
911 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
912 #[non_exhaustive]
913 pub enum Mangling {
914 /// No symbol mangling.
915 None,
916 /// Windows COFF symbol mangling.
917 Coff,
918 /// Windows COFF i386 symbol mangling.
919 CoffI386,
920 /// ELF symbol mangling.
921 Elf,
922 /// Mach-O symbol mangling.
923 MachO,
924 /// Xcoff symbol mangling.
925 Xcoff,
926 }
927
928 impl Mangling {
929 /// Return the default symboling mangling for the given format and architecture.
930 pub fn default(format: BinaryFormat, architecture: Architecture) -> Self {
931 match (format, architecture) {
932 (BinaryFormat::Coff, Architecture::I386) => Mangling::CoffI386,
933 (BinaryFormat::Coff, _) => Mangling::Coff,
934 (BinaryFormat::Elf, _) => Mangling::Elf,
935 (BinaryFormat::MachO, _) => Mangling::MachO,
936 (BinaryFormat::Xcoff, _) => Mangling::Xcoff,
937 _ => Mangling::None,
938 }
939 }
940
941 /// Return the prefix to use for global symbols.
942 pub fn global_prefix(self) -> Option<u8> {
943 match self {
944 Mangling::None | Mangling::Elf | Mangling::Coff | Mangling::Xcoff => None,
945 Mangling::CoffI386 | Mangling::MachO => Some(b'_'),
946 }
947 }
948 }