1 | /// A CPU architecture. |
2 | #[allow (missing_docs)] |
3 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
4 | #[non_exhaustive ] |
5 | pub enum Architecture { |
6 | Unknown, |
7 | Aarch64, |
8 | #[allow (non_camel_case_types)] |
9 | Aarch64_Ilp32, |
10 | Arm, |
11 | Avr, |
12 | Bpf, |
13 | Csky, |
14 | E2K32, |
15 | E2K64, |
16 | I386, |
17 | X86_64, |
18 | #[allow (non_camel_case_types)] |
19 | X86_64_X32, |
20 | Hexagon, |
21 | LoongArch64, |
22 | M68k, |
23 | Mips, |
24 | Mips64, |
25 | #[allow (non_camel_case_types)] |
26 | Mips64_N32, |
27 | Msp430, |
28 | PowerPc, |
29 | PowerPc64, |
30 | Riscv32, |
31 | Riscv64, |
32 | S390x, |
33 | Sbf, |
34 | Sharc, |
35 | Sparc, |
36 | Sparc32Plus, |
37 | Sparc64, |
38 | Wasm32, |
39 | Wasm64, |
40 | Xtensa, |
41 | } |
42 | |
43 | /// A CPU sub-architecture. |
44 | #[allow (missing_docs)] |
45 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
46 | #[non_exhaustive ] |
47 | pub enum SubArchitecture { |
48 | Arm64E, |
49 | Arm64EC, |
50 | } |
51 | |
52 | impl Architecture { |
53 | /// The size of an address value for this architecture. |
54 | /// |
55 | /// Returns `None` for unknown architectures. |
56 | pub fn address_size(self) -> Option<AddressSize> { |
57 | match self { |
58 | Architecture::Unknown => None, |
59 | Architecture::Aarch64 => Some(AddressSize::U64), |
60 | Architecture::Aarch64_Ilp32 => Some(AddressSize::U32), |
61 | Architecture::Arm => Some(AddressSize::U32), |
62 | Architecture::Avr => Some(AddressSize::U8), |
63 | Architecture::Bpf => Some(AddressSize::U64), |
64 | Architecture::Csky => Some(AddressSize::U32), |
65 | Architecture::E2K32 => Some(AddressSize::U32), |
66 | Architecture::E2K64 => Some(AddressSize::U64), |
67 | Architecture::I386 => Some(AddressSize::U32), |
68 | Architecture::X86_64 => Some(AddressSize::U64), |
69 | Architecture::X86_64_X32 => Some(AddressSize::U32), |
70 | Architecture::Hexagon => Some(AddressSize::U32), |
71 | Architecture::LoongArch64 => Some(AddressSize::U64), |
72 | Architecture::M68k => Some(AddressSize::U32), |
73 | Architecture::Mips => Some(AddressSize::U32), |
74 | Architecture::Mips64 => Some(AddressSize::U64), |
75 | Architecture::Mips64_N32 => Some(AddressSize::U32), |
76 | Architecture::Msp430 => Some(AddressSize::U16), |
77 | Architecture::PowerPc => Some(AddressSize::U32), |
78 | Architecture::PowerPc64 => Some(AddressSize::U64), |
79 | Architecture::Riscv32 => Some(AddressSize::U32), |
80 | Architecture::Riscv64 => Some(AddressSize::U64), |
81 | Architecture::S390x => Some(AddressSize::U64), |
82 | Architecture::Sbf => Some(AddressSize::U64), |
83 | Architecture::Sharc => Some(AddressSize::U32), |
84 | Architecture::Sparc => Some(AddressSize::U32), |
85 | Architecture::Sparc32Plus => Some(AddressSize::U32), |
86 | Architecture::Sparc64 => Some(AddressSize::U64), |
87 | Architecture::Wasm32 => Some(AddressSize::U32), |
88 | Architecture::Wasm64 => Some(AddressSize::U64), |
89 | Architecture::Xtensa => Some(AddressSize::U32), |
90 | } |
91 | } |
92 | } |
93 | |
94 | /// The size of an address value for an architecture. |
95 | /// |
96 | /// This may differ from the address size supported by the file format (such as for COFF). |
97 | #[allow (missing_docs)] |
98 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
99 | #[non_exhaustive ] |
100 | #[repr (u8)] |
101 | pub enum AddressSize { |
102 | U8 = 1, |
103 | U16 = 2, |
104 | U32 = 4, |
105 | U64 = 8, |
106 | } |
107 | |
108 | impl AddressSize { |
109 | /// The size in bytes of an address value. |
110 | #[inline ] |
111 | pub fn bytes(self) -> u8 { |
112 | self as u8 |
113 | } |
114 | } |
115 | |
116 | /// A binary file format. |
117 | #[allow (missing_docs)] |
118 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
119 | #[non_exhaustive ] |
120 | pub enum BinaryFormat { |
121 | Coff, |
122 | Elf, |
123 | MachO, |
124 | Pe, |
125 | Wasm, |
126 | Xcoff, |
127 | } |
128 | |
129 | impl BinaryFormat { |
130 | /// The target's native binary format for relocatable object files. |
131 | /// |
132 | /// Defaults to `Elf` for unknown platforms. |
133 | pub fn native_object() -> BinaryFormat { |
134 | if cfg!(target_os = "windows" ) { |
135 | BinaryFormat::Coff |
136 | } else if cfg!(target_os = "macos" ) { |
137 | BinaryFormat::MachO |
138 | } else { |
139 | BinaryFormat::Elf |
140 | } |
141 | } |
142 | } |
143 | |
144 | /// The kind of a section. |
145 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
146 | #[non_exhaustive ] |
147 | pub enum SectionKind { |
148 | /// The section kind is unknown. |
149 | Unknown, |
150 | /// An executable code section. |
151 | /// |
152 | /// Example ELF sections: `.text` |
153 | /// |
154 | /// Example Mach-O sections: `__TEXT/__text` |
155 | Text, |
156 | /// A data section. |
157 | /// |
158 | /// Example ELF sections: `.data` |
159 | /// |
160 | /// Example Mach-O sections: `__DATA/__data` |
161 | Data, |
162 | /// A read only data section. |
163 | /// |
164 | /// Example ELF sections: `.rodata` |
165 | /// |
166 | /// Example Mach-O sections: `__TEXT/__const`, `__DATA/__const`, `__TEXT/__literal4` |
167 | ReadOnlyData, |
168 | /// A read only data section with relocations. |
169 | /// |
170 | /// This is the same as either `Data` or `ReadOnlyData`, depending on the file format. |
171 | /// This value is only used in the API for writing files. It is never returned when reading files. |
172 | ReadOnlyDataWithRel, |
173 | /// A loadable string section. |
174 | /// |
175 | /// Example ELF sections: `.rodata.str` |
176 | /// |
177 | /// Example Mach-O sections: `__TEXT/__cstring` |
178 | ReadOnlyString, |
179 | /// An uninitialized data section. |
180 | /// |
181 | /// Example ELF sections: `.bss` |
182 | /// |
183 | /// Example Mach-O sections: `__DATA/__bss` |
184 | UninitializedData, |
185 | /// An uninitialized common data section. |
186 | /// |
187 | /// Example Mach-O sections: `__DATA/__common` |
188 | Common, |
189 | /// A TLS data section. |
190 | /// |
191 | /// Example ELF sections: `.tdata` |
192 | /// |
193 | /// Example Mach-O sections: `__DATA/__thread_data` |
194 | Tls, |
195 | /// An uninitialized TLS data section. |
196 | /// |
197 | /// Example ELF sections: `.tbss` |
198 | /// |
199 | /// Example Mach-O sections: `__DATA/__thread_bss` |
200 | UninitializedTls, |
201 | /// A TLS variables section. |
202 | /// |
203 | /// This contains TLS variable structures, rather than the variable initializers. |
204 | /// |
205 | /// Example Mach-O sections: `__DATA/__thread_vars` |
206 | TlsVariables, |
207 | /// A non-loadable string section. |
208 | /// |
209 | /// Example ELF sections: `.comment`, `.debug_str` |
210 | OtherString, |
211 | /// Some other non-loadable section. |
212 | /// |
213 | /// Example ELF sections: `.debug_info` |
214 | Other, |
215 | /// Debug information. |
216 | /// |
217 | /// Example Mach-O sections: `__DWARF/__debug_info` |
218 | Debug, |
219 | /// Debug strings. |
220 | /// |
221 | /// This is the same as either `Debug` or `OtherString`, depending on the file format. |
222 | /// This value is only used in the API for writing files. It is never returned when reading files. |
223 | DebugString, |
224 | /// Information for the linker. |
225 | /// |
226 | /// Example COFF sections: `.drectve` |
227 | Linker, |
228 | /// ELF note section. |
229 | Note, |
230 | /// Metadata such as symbols or relocations. |
231 | /// |
232 | /// Example ELF sections: `.symtab`, `.strtab`, `.group` |
233 | Metadata, |
234 | /// Some other ELF section type. |
235 | /// |
236 | /// This is the `sh_type` field in the section header. |
237 | /// The meaning may be dependent on the architecture. |
238 | Elf(u32), |
239 | } |
240 | |
241 | impl SectionKind { |
242 | /// Return true if this section contains zerofill data. |
243 | pub fn is_bss(self) -> bool { |
244 | self == SectionKind::UninitializedData |
245 | || self == SectionKind::UninitializedTls |
246 | || self == SectionKind::Common |
247 | } |
248 | } |
249 | |
250 | /// The selection kind for a COMDAT section group. |
251 | /// |
252 | /// This determines the way in which the linker resolves multiple definitions of the COMDAT |
253 | /// sections. |
254 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
255 | #[non_exhaustive ] |
256 | pub enum ComdatKind { |
257 | /// The selection kind is unknown. |
258 | Unknown, |
259 | /// Multiple definitions are allowed. |
260 | /// |
261 | /// An arbitrary definition is selected, and the rest are removed. |
262 | /// |
263 | /// This is the only supported selection kind for ELF. |
264 | Any, |
265 | /// Multiple definitions are not allowed. |
266 | /// |
267 | /// This is used to group sections without allowing duplicates. |
268 | NoDuplicates, |
269 | /// Multiple definitions must have the same size. |
270 | /// |
271 | /// An arbitrary definition is selected, and the rest are removed. |
272 | SameSize, |
273 | /// Multiple definitions must match exactly. |
274 | /// |
275 | /// An arbitrary definition is selected, and the rest are removed. |
276 | ExactMatch, |
277 | /// Multiple definitions are allowed, and the largest is selected. |
278 | /// |
279 | /// An arbitrary definition with the largest size is selected, and the rest are removed. |
280 | Largest, |
281 | /// Multiple definitions are allowed, and the newest is selected. |
282 | Newest, |
283 | } |
284 | |
285 | /// The kind of a symbol. |
286 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
287 | #[non_exhaustive ] |
288 | pub enum SymbolKind { |
289 | /// The symbol kind is unknown. |
290 | Unknown, |
291 | /// The symbol is for executable code. |
292 | Text, |
293 | /// The symbol is for a data object. |
294 | Data, |
295 | /// The symbol is for a section. |
296 | Section, |
297 | /// The symbol is the name of a file. It precedes symbols within that file. |
298 | File, |
299 | /// The symbol is for a code label. |
300 | Label, |
301 | /// The symbol is for a thread local storage entity. |
302 | Tls, |
303 | } |
304 | |
305 | /// A symbol scope. |
306 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
307 | pub enum SymbolScope { |
308 | /// Unknown scope. |
309 | Unknown, |
310 | /// Symbol is visible to the compilation unit. |
311 | Compilation, |
312 | /// Symbol is visible to the static linkage unit. |
313 | Linkage, |
314 | /// Symbol is visible to dynamically linked objects. |
315 | Dynamic, |
316 | } |
317 | |
318 | /// The operation used to calculate the result of the relocation. |
319 | /// |
320 | /// The relocation descriptions use the following definitions. Note that |
321 | /// these definitions probably don't match any ELF ABI. |
322 | /// |
323 | /// * A - The value of the addend. |
324 | /// * G - The address of the symbol's entry within the global offset table. |
325 | /// * L - The address of the symbol's entry within the procedure linkage table. |
326 | /// * P - The address of the place of the relocation. |
327 | /// * S - The address of the symbol. |
328 | /// * GotBase - The address of the global offset table. |
329 | /// * Image - The base address of the image. |
330 | /// * Section - The address of the section containing the symbol. |
331 | /// |
332 | /// 'XxxRelative' means 'Xxx + A - P'. 'XxxOffset' means 'S + A - Xxx'. |
333 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
334 | #[non_exhaustive ] |
335 | pub enum RelocationKind { |
336 | /// The operation is unknown. |
337 | Unknown, |
338 | /// S + A |
339 | Absolute, |
340 | /// S + A - P |
341 | Relative, |
342 | /// G + A - GotBase |
343 | Got, |
344 | /// G + A - P |
345 | GotRelative, |
346 | /// GotBase + A - P |
347 | GotBaseRelative, |
348 | /// S + A - GotBase |
349 | GotBaseOffset, |
350 | /// L + A - P |
351 | PltRelative, |
352 | /// S + A - Image |
353 | ImageOffset, |
354 | /// S + A - Section |
355 | SectionOffset, |
356 | /// The index of the section containing the symbol. |
357 | SectionIndex, |
358 | } |
359 | |
360 | /// Information about how the result of the relocation operation is encoded in the place. |
361 | /// |
362 | /// This is usually architecture specific, such as specifying an addressing mode or |
363 | /// a specific instruction. |
364 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
365 | #[non_exhaustive ] |
366 | pub enum RelocationEncoding { |
367 | /// The relocation encoding is unknown. |
368 | Unknown, |
369 | /// Generic encoding. |
370 | Generic, |
371 | |
372 | /// x86 sign extension at runtime. |
373 | /// |
374 | /// Used with `RelocationKind::Absolute`. |
375 | X86Signed, |
376 | /// x86 rip-relative addressing. |
377 | /// |
378 | /// The `RelocationKind` must be PC relative. |
379 | X86RipRelative, |
380 | /// x86 rip-relative addressing in movq instruction. |
381 | /// |
382 | /// The `RelocationKind` must be PC relative. |
383 | X86RipRelativeMovq, |
384 | /// x86 branch instruction. |
385 | /// |
386 | /// The `RelocationKind` must be PC relative. |
387 | X86Branch, |
388 | |
389 | /// s390x PC-relative offset shifted right by one bit. |
390 | /// |
391 | /// The `RelocationKind` must be PC relative. |
392 | S390xDbl, |
393 | |
394 | /// AArch64 call target. |
395 | /// |
396 | /// The `RelocationKind` must be PC relative. |
397 | AArch64Call, |
398 | |
399 | /// LoongArch branch offset with two trailing zeros. |
400 | /// |
401 | /// The `RelocationKind` must be PC relative. |
402 | LoongArchBranch, |
403 | |
404 | /// SHARC+ 48-bit Type A instruction |
405 | /// |
406 | /// Represents these possible variants, each with a corresponding |
407 | /// `R_SHARC_*` constant: |
408 | /// |
409 | /// * 24-bit absolute address |
410 | /// * 32-bit absolute address |
411 | /// * 6-bit relative address |
412 | /// * 24-bit relative address |
413 | /// * 6-bit absolute address in the immediate value field |
414 | /// * 16-bit absolute address in the immediate value field |
415 | SharcTypeA, |
416 | |
417 | /// SHARC+ 32-bit Type B instruction |
418 | /// |
419 | /// Represents these possible variants, each with a corresponding |
420 | /// `R_SHARC_*` constant: |
421 | /// |
422 | /// * 6-bit absolute address in the immediate value field |
423 | /// * 7-bit absolute address in the immediate value field |
424 | /// * 16-bit absolute address |
425 | /// * 6-bit relative address |
426 | SharcTypeB, |
427 | |
428 | /// E2K 64-bit value stored in two LTS |
429 | /// |
430 | /// Memory representation: |
431 | /// ```text |
432 | /// 0: LTS1 = value[63:32] |
433 | /// 4: LTS0 = value[31:0] |
434 | /// ``` |
435 | E2KLit, |
436 | |
437 | /// E2K 28-bit value stored in CS0 |
438 | E2KDisp, |
439 | } |
440 | |
441 | /// File flags that are specific to each file format. |
442 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
443 | #[non_exhaustive ] |
444 | pub enum FileFlags { |
445 | /// No file flags. |
446 | None, |
447 | /// ELF file flags. |
448 | Elf { |
449 | /// `os_abi` field in the ELF file header. |
450 | os_abi: u8, |
451 | /// `abi_version` field in the ELF file header. |
452 | abi_version: u8, |
453 | /// `e_flags` field in the ELF file header. |
454 | e_flags: u32, |
455 | }, |
456 | /// Mach-O file flags. |
457 | MachO { |
458 | /// `flags` field in the Mach-O file header. |
459 | flags: u32, |
460 | }, |
461 | /// COFF file flags. |
462 | Coff { |
463 | /// `Characteristics` field in the COFF file header. |
464 | characteristics: u16, |
465 | }, |
466 | /// XCOFF file flags. |
467 | Xcoff { |
468 | /// `f_flags` field in the XCOFF file header. |
469 | f_flags: u16, |
470 | }, |
471 | } |
472 | |
473 | /// Segment flags that are specific to each file format. |
474 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
475 | #[non_exhaustive ] |
476 | pub enum SegmentFlags { |
477 | /// No segment flags. |
478 | None, |
479 | /// ELF segment flags. |
480 | Elf { |
481 | /// `p_flags` field in the segment header. |
482 | p_flags: u32, |
483 | }, |
484 | /// Mach-O segment flags. |
485 | MachO { |
486 | /// `flags` field in the segment header. |
487 | flags: u32, |
488 | /// `maxprot` field in the segment header. |
489 | maxprot: u32, |
490 | /// `initprot` field in the segment header. |
491 | initprot: u32, |
492 | }, |
493 | /// COFF segment flags. |
494 | Coff { |
495 | /// `Characteristics` field in the segment header. |
496 | characteristics: u32, |
497 | }, |
498 | } |
499 | |
500 | /// Section flags that are specific to each file format. |
501 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
502 | #[non_exhaustive ] |
503 | pub enum SectionFlags { |
504 | /// No section flags. |
505 | None, |
506 | /// ELF section flags. |
507 | Elf { |
508 | /// `sh_flags` field in the section header. |
509 | sh_flags: u64, |
510 | }, |
511 | /// Mach-O section flags. |
512 | MachO { |
513 | /// `flags` field in the section header. |
514 | flags: u32, |
515 | }, |
516 | /// COFF section flags. |
517 | Coff { |
518 | /// `Characteristics` field in the section header. |
519 | characteristics: u32, |
520 | }, |
521 | /// XCOFF section flags. |
522 | Xcoff { |
523 | /// `s_flags` field in the section header. |
524 | s_flags: u32, |
525 | }, |
526 | } |
527 | |
528 | /// Symbol flags that are specific to each file format. |
529 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
530 | #[non_exhaustive ] |
531 | pub enum SymbolFlags<Section, Symbol> { |
532 | /// No symbol flags. |
533 | None, |
534 | /// ELF symbol flags. |
535 | Elf { |
536 | /// `st_info` field in the ELF symbol. |
537 | st_info: u8, |
538 | /// `st_other` field in the ELF symbol. |
539 | st_other: u8, |
540 | }, |
541 | /// Mach-O symbol flags. |
542 | MachO { |
543 | /// `n_desc` field in the Mach-O symbol. |
544 | n_desc: u16, |
545 | }, |
546 | /// COFF flags for a section symbol. |
547 | CoffSection { |
548 | /// `Selection` field in the auxiliary symbol for the section. |
549 | selection: u8, |
550 | /// `Number` field in the auxiliary symbol for the section. |
551 | associative_section: Option<Section>, |
552 | }, |
553 | /// XCOFF symbol flags. |
554 | Xcoff { |
555 | /// `n_sclass` field in the XCOFF symbol. |
556 | n_sclass: u8, |
557 | /// `x_smtyp` field in the CSECT auxiliary symbol. |
558 | /// |
559 | /// Only valid if `n_sclass` is `C_EXT`, `C_WEAKEXT`, or `C_HIDEXT`. |
560 | x_smtyp: u8, |
561 | /// `x_smclas` field in the CSECT auxiliary symbol. |
562 | /// |
563 | /// Only valid if `n_sclass` is `C_EXT`, `C_WEAKEXT`, or `C_HIDEXT`. |
564 | x_smclas: u8, |
565 | /// The containing csect for the symbol. |
566 | /// |
567 | /// Only valid if `x_smtyp` is `XTY_LD`. |
568 | containing_csect: Option<Symbol>, |
569 | }, |
570 | } |
571 | |
572 | /// Relocation fields that are specific to each file format and architecture. |
573 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
574 | #[non_exhaustive ] |
575 | pub enum RelocationFlags { |
576 | /// Format independent representation. |
577 | Generic { |
578 | /// The operation used to calculate the result of the relocation. |
579 | kind: RelocationKind, |
580 | /// Information about how the result of the relocation operation is encoded in the place. |
581 | encoding: RelocationEncoding, |
582 | /// The size in bits of the place of relocation. |
583 | size: u8, |
584 | }, |
585 | /// ELF relocation fields. |
586 | Elf { |
587 | /// `r_type` field in the ELF relocation. |
588 | r_type: u32, |
589 | }, |
590 | /// Mach-O relocation fields. |
591 | MachO { |
592 | /// `r_type` field in the Mach-O relocation. |
593 | r_type: u8, |
594 | /// `r_pcrel` field in the Mach-O relocation. |
595 | r_pcrel: bool, |
596 | /// `r_length` field in the Mach-O relocation. |
597 | r_length: u8, |
598 | }, |
599 | /// COFF relocation fields. |
600 | Coff { |
601 | /// `typ` field in the COFF relocation. |
602 | typ: u16, |
603 | }, |
604 | /// XCOFF relocation fields. |
605 | Xcoff { |
606 | /// `r_rtype` field in the XCOFF relocation. |
607 | r_rtype: u8, |
608 | /// `r_rsize` field in the XCOFF relocation. |
609 | r_rsize: u8, |
610 | }, |
611 | } |
612 | |