]> git.proxmox.com Git - rustc.git/blob - vendor/object-0.26.2/src/write/macho.rs
New upstream version 1.58.1+dfsg1
[rustc.git] / vendor / object-0.26.2 / src / write / macho.rs
1 use std::mem;
2
3 use crate::endian::*;
4 use crate::macho;
5 use crate::write::string::*;
6 use crate::write::util::*;
7 use crate::write::*;
8 use crate::AddressSize;
9
10 #[derive(Default, Clone, Copy)]
11 struct SectionOffsets {
12 index: usize,
13 offset: usize,
14 address: u64,
15 reloc_offset: usize,
16 }
17
18 #[derive(Default, Clone, Copy)]
19 struct SymbolOffsets {
20 emit: bool,
21 index: usize,
22 str_id: Option<StringId>,
23 }
24
25 impl Object {
26 pub(crate) fn macho_set_subsections_via_symbols(&mut self) {
27 let flags = match self.flags {
28 FileFlags::MachO { flags } => flags,
29 _ => 0,
30 };
31 self.flags = FileFlags::MachO {
32 flags: flags | macho::MH_SUBSECTIONS_VIA_SYMBOLS,
33 };
34 }
35
36 pub(crate) fn macho_segment_name(&self, segment: StandardSegment) -> &'static [u8] {
37 match segment {
38 StandardSegment::Text => &b"__TEXT"[..],
39 StandardSegment::Data => &b"__DATA"[..],
40 StandardSegment::Debug => &b"__DWARF"[..],
41 }
42 }
43
44 pub(crate) fn macho_section_info(
45 &self,
46 section: StandardSection,
47 ) -> (&'static [u8], &'static [u8], SectionKind) {
48 match section {
49 StandardSection::Text => (&b"__TEXT"[..], &b"__text"[..], SectionKind::Text),
50 StandardSection::Data => (&b"__DATA"[..], &b"__data"[..], SectionKind::Data),
51 StandardSection::ReadOnlyData => {
52 (&b"__TEXT"[..], &b"__const"[..], SectionKind::ReadOnlyData)
53 }
54 StandardSection::ReadOnlyDataWithRel => {
55 (&b"__DATA"[..], &b"__const"[..], SectionKind::ReadOnlyData)
56 }
57 StandardSection::ReadOnlyString => (
58 &b"__TEXT"[..],
59 &b"__cstring"[..],
60 SectionKind::ReadOnlyString,
61 ),
62 StandardSection::UninitializedData => (
63 &b"__DATA"[..],
64 &b"__bss"[..],
65 SectionKind::UninitializedData,
66 ),
67 StandardSection::Tls => (&b"__DATA"[..], &b"__thread_data"[..], SectionKind::Tls),
68 StandardSection::UninitializedTls => (
69 &b"__DATA"[..],
70 &b"__thread_bss"[..],
71 SectionKind::UninitializedTls,
72 ),
73 StandardSection::TlsVariables => (
74 &b"__DATA"[..],
75 &b"__thread_vars"[..],
76 SectionKind::TlsVariables,
77 ),
78 StandardSection::Common => (&b"__DATA"[..], &b"__common"[..], SectionKind::Common),
79 }
80 }
81
82 fn macho_tlv_bootstrap(&mut self) -> SymbolId {
83 match self.tlv_bootstrap {
84 Some(id) => id,
85 None => {
86 let id = self.add_symbol(Symbol {
87 name: b"_tlv_bootstrap".to_vec(),
88 value: 0,
89 size: 0,
90 kind: SymbolKind::Text,
91 scope: SymbolScope::Dynamic,
92 weak: false,
93 section: SymbolSection::Undefined,
94 flags: SymbolFlags::None,
95 });
96 self.tlv_bootstrap = Some(id);
97 id
98 }
99 }
100 }
101
102 /// Create the `__thread_vars` entry for a TLS variable.
103 ///
104 /// The symbol given by `symbol_id` will be updated to point to this entry.
105 ///
106 /// A new `SymbolId` will be returned. The caller must update this symbol
107 /// to point to the initializer.
108 ///
109 /// If `symbol_id` is not for a TLS variable, then it is returned unchanged.
110 pub(crate) fn macho_add_thread_var(&mut self, symbol_id: SymbolId) -> SymbolId {
111 let symbol = self.symbol_mut(symbol_id);
112 if symbol.kind != SymbolKind::Tls {
113 return symbol_id;
114 }
115
116 // Create the initializer symbol.
117 let mut name = symbol.name.clone();
118 name.extend_from_slice(b"$tlv$init");
119 let init_symbol_id = self.add_raw_symbol(Symbol {
120 name,
121 value: 0,
122 size: 0,
123 kind: SymbolKind::Tls,
124 scope: SymbolScope::Compilation,
125 weak: false,
126 section: SymbolSection::Undefined,
127 flags: SymbolFlags::None,
128 });
129
130 // Add the tlv entry.
131 // Three pointers in size:
132 // - __tlv_bootstrap - used to make sure support exists
133 // - spare pointer - used when mapped by the runtime
134 // - pointer to symbol initializer
135 let section = self.section_id(StandardSection::TlsVariables);
136 let address_size = self.architecture.address_size().unwrap().bytes();
137 let size = u64::from(address_size) * 3;
138 let data = vec![0; size as usize];
139 let offset = self.append_section_data(section, &data, u64::from(address_size));
140
141 let tlv_bootstrap = self.macho_tlv_bootstrap();
142 self.add_relocation(
143 section,
144 Relocation {
145 offset,
146 size: address_size * 8,
147 kind: RelocationKind::Absolute,
148 encoding: RelocationEncoding::Generic,
149 symbol: tlv_bootstrap,
150 addend: 0,
151 },
152 )
153 .unwrap();
154 self.add_relocation(
155 section,
156 Relocation {
157 offset: offset + u64::from(address_size) * 2,
158 size: address_size * 8,
159 kind: RelocationKind::Absolute,
160 encoding: RelocationEncoding::Generic,
161 symbol: init_symbol_id,
162 addend: 0,
163 },
164 )
165 .unwrap();
166
167 // Update the symbol to point to the tlv.
168 let symbol = self.symbol_mut(symbol_id);
169 symbol.value = offset;
170 symbol.size = size;
171 symbol.section = SymbolSection::Section(section);
172
173 init_symbol_id
174 }
175
176 pub(crate) fn macho_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> i64 {
177 let constant = match relocation.kind {
178 RelocationKind::Relative
179 | RelocationKind::GotRelative
180 | RelocationKind::PltRelative => relocation.addend + 4,
181 _ => relocation.addend,
182 };
183 relocation.addend -= constant;
184 constant
185 }
186
187 pub(crate) fn macho_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
188 let address_size = self.architecture.address_size().unwrap();
189 let endian = self.endian;
190 let macho32 = MachO32 { endian };
191 let macho64 = MachO64 { endian };
192 let macho: &dyn MachO = match address_size {
193 AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => &macho32,
194 AddressSize::U64 => &macho64,
195 };
196 let pointer_align = address_size.bytes() as usize;
197
198 // Calculate offsets of everything, and build strtab.
199 let mut offset = 0;
200
201 // Calculate size of Mach-O header.
202 offset += macho.mach_header_size();
203
204 // Calculate size of commands.
205 let mut ncmds = 0;
206 let command_offset = offset;
207
208 // Calculate size of segment command and section headers.
209 let segment_command_offset = offset;
210 let segment_command_len =
211 macho.segment_command_size() + self.sections.len() * macho.section_header_size();
212 offset += segment_command_len;
213 ncmds += 1;
214
215 // Calculate size of symtab command.
216 let symtab_command_offset = offset;
217 let symtab_command_len = mem::size_of::<macho::SymtabCommand<Endianness>>();
218 offset += symtab_command_len;
219 ncmds += 1;
220
221 let sizeofcmds = offset - command_offset;
222
223 // Calculate size of section data.
224 let mut segment_file_offset = None;
225 let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()];
226 let mut address = 0;
227 for (index, section) in self.sections.iter().enumerate() {
228 section_offsets[index].index = 1 + index;
229 if !section.is_bss() {
230 let len = section.data.len();
231 if len != 0 {
232 offset = align(offset, section.align as usize);
233 section_offsets[index].offset = offset;
234 if segment_file_offset.is_none() {
235 segment_file_offset = Some(offset);
236 }
237 offset += len;
238 } else {
239 section_offsets[index].offset = offset;
240 }
241 address = align_u64(address, section.align);
242 section_offsets[index].address = address;
243 address += section.size;
244 }
245 }
246 for (index, section) in self.sections.iter().enumerate() {
247 if section.kind.is_bss() {
248 assert!(section.data.is_empty());
249 address = align_u64(address, section.align);
250 section_offsets[index].address = address;
251 address += section.size;
252 }
253 }
254 let segment_file_offset = segment_file_offset.unwrap_or(offset);
255 let segment_file_size = offset - segment_file_offset;
256 debug_assert!(segment_file_size as u64 <= address);
257
258 // Count symbols and add symbol strings to strtab.
259 let mut strtab = StringTable::default();
260 let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()];
261 let mut nsyms = 0;
262 for (index, symbol) in self.symbols.iter().enumerate() {
263 // The unified API allows creating symbols that we don't emit, so filter
264 // them out here.
265 //
266 // Since we don't actually emit the symbol kind, we validate it here too.
267 match symbol.kind {
268 SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls => {}
269 SymbolKind::File | SymbolKind::Section => continue,
270 SymbolKind::Unknown => {
271 if symbol.section != SymbolSection::Undefined {
272 return Err(Error(format!(
273 "defined symbol `{}` with unknown kind",
274 symbol.name().unwrap_or(""),
275 )));
276 }
277 }
278 SymbolKind::Null | SymbolKind::Label => {
279 return Err(Error(format!(
280 "unimplemented symbol `{}` kind {:?}",
281 symbol.name().unwrap_or(""),
282 symbol.kind
283 )));
284 }
285 }
286 symbol_offsets[index].emit = true;
287 symbol_offsets[index].index = nsyms;
288 nsyms += 1;
289 if !symbol.name.is_empty() {
290 symbol_offsets[index].str_id = Some(strtab.add(&symbol.name));
291 }
292 }
293
294 // Calculate size of symtab.
295 offset = align(offset, pointer_align);
296 let symtab_offset = offset;
297 let symtab_len = nsyms * macho.nlist_size();
298 offset += symtab_len;
299
300 // Calculate size of strtab.
301 let strtab_offset = offset;
302 // Start with null name.
303 let mut strtab_data = vec![0];
304 strtab.write(1, &mut strtab_data);
305 offset += strtab_data.len();
306
307 // Calculate size of relocations.
308 for (index, section) in self.sections.iter().enumerate() {
309 let count = section.relocations.len();
310 if count != 0 {
311 offset = align(offset, 4);
312 section_offsets[index].reloc_offset = offset;
313 let len = count * mem::size_of::<macho::Relocation<Endianness>>();
314 offset += len;
315 }
316 }
317
318 // Start writing.
319 buffer
320 .reserve(offset)
321 .map_err(|_| Error(String::from("Cannot allocate buffer")))?;
322
323 // Write file header.
324 let (cputype, cpusubtype) = match self.architecture {
325 Architecture::Arm => (macho::CPU_TYPE_ARM, macho::CPU_SUBTYPE_ARM_ALL),
326 Architecture::Aarch64 => (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64_ALL),
327 Architecture::I386 => (macho::CPU_TYPE_X86, macho::CPU_SUBTYPE_I386_ALL),
328 Architecture::X86_64 => (macho::CPU_TYPE_X86_64, macho::CPU_SUBTYPE_X86_64_ALL),
329 _ => {
330 return Err(Error(format!(
331 "unimplemented architecture {:?}",
332 self.architecture
333 )));
334 }
335 };
336
337 let flags = match self.flags {
338 FileFlags::MachO { flags } => flags,
339 _ => 0,
340 };
341 macho.write_mach_header(
342 buffer,
343 MachHeader {
344 cputype,
345 cpusubtype,
346 filetype: macho::MH_OBJECT,
347 ncmds,
348 sizeofcmds: sizeofcmds as u32,
349 flags,
350 },
351 );
352
353 // Write segment command.
354 debug_assert_eq!(segment_command_offset, buffer.len());
355 macho.write_segment_command(
356 buffer,
357 SegmentCommand {
358 cmdsize: segment_command_len as u32,
359 segname: [0; 16],
360 vmaddr: 0,
361 vmsize: address,
362 fileoff: segment_file_offset as u64,
363 filesize: segment_file_size as u64,
364 maxprot: macho::VM_PROT_READ | macho::VM_PROT_WRITE | macho::VM_PROT_EXECUTE,
365 initprot: macho::VM_PROT_READ | macho::VM_PROT_WRITE | macho::VM_PROT_EXECUTE,
366 nsects: self.sections.len() as u32,
367 flags: 0,
368 },
369 );
370
371 // Write section headers.
372 for (index, section) in self.sections.iter().enumerate() {
373 let mut sectname = [0; 16];
374 sectname
375 .get_mut(..section.name.len())
376 .ok_or_else(|| {
377 Error(format!(
378 "section name `{}` is too long",
379 section.name().unwrap_or(""),
380 ))
381 })?
382 .copy_from_slice(&section.name);
383 let mut segname = [0; 16];
384 segname
385 .get_mut(..section.segment.len())
386 .ok_or_else(|| {
387 Error(format!(
388 "segment name `{}` is too long",
389 section.segment().unwrap_or(""),
390 ))
391 })?
392 .copy_from_slice(&section.segment);
393 let flags = if let SectionFlags::MachO { flags } = section.flags {
394 flags
395 } else {
396 match section.kind {
397 SectionKind::Text => {
398 macho::S_ATTR_PURE_INSTRUCTIONS | macho::S_ATTR_SOME_INSTRUCTIONS
399 }
400 SectionKind::Data => 0,
401 SectionKind::ReadOnlyData => 0,
402 SectionKind::ReadOnlyString => macho::S_CSTRING_LITERALS,
403 SectionKind::UninitializedData | SectionKind::Common => macho::S_ZEROFILL,
404 SectionKind::Tls => macho::S_THREAD_LOCAL_REGULAR,
405 SectionKind::UninitializedTls => macho::S_THREAD_LOCAL_ZEROFILL,
406 SectionKind::TlsVariables => macho::S_THREAD_LOCAL_VARIABLES,
407 SectionKind::Debug => macho::S_ATTR_DEBUG,
408 SectionKind::OtherString => macho::S_CSTRING_LITERALS,
409 SectionKind::Other | SectionKind::Linker | SectionKind::Metadata => 0,
410 SectionKind::Note | SectionKind::Unknown | SectionKind::Elf(_) => {
411 return Err(Error(format!(
412 "unimplemented section `{}` kind {:?}",
413 section.name().unwrap_or(""),
414 section.kind
415 )));
416 }
417 }
418 };
419 macho.write_section(
420 buffer,
421 SectionHeader {
422 sectname,
423 segname,
424 addr: section_offsets[index].address,
425 size: section.size,
426 offset: section_offsets[index].offset as u32,
427 align: section.align.trailing_zeros(),
428 reloff: section_offsets[index].reloc_offset as u32,
429 nreloc: section.relocations.len() as u32,
430 flags,
431 },
432 );
433 }
434
435 // Write symtab command.
436 debug_assert_eq!(symtab_command_offset, buffer.len());
437 let symtab_command = macho::SymtabCommand {
438 cmd: U32::new(endian, macho::LC_SYMTAB),
439 cmdsize: U32::new(endian, symtab_command_len as u32),
440 symoff: U32::new(endian, symtab_offset as u32),
441 nsyms: U32::new(endian, nsyms as u32),
442 stroff: U32::new(endian, strtab_offset as u32),
443 strsize: U32::new(endian, strtab_data.len() as u32),
444 };
445 buffer.write(&symtab_command);
446
447 // Write section data.
448 for (index, section) in self.sections.iter().enumerate() {
449 let len = section.data.len();
450 if len != 0 {
451 write_align(buffer, section.align as usize);
452 debug_assert_eq!(section_offsets[index].offset, buffer.len());
453 buffer.write_bytes(&section.data);
454 }
455 }
456 debug_assert_eq!(segment_file_offset + segment_file_size, buffer.len());
457
458 // Write symtab.
459 write_align(buffer, pointer_align);
460 debug_assert_eq!(symtab_offset, buffer.len());
461 for (index, symbol) in self.symbols.iter().enumerate() {
462 if !symbol_offsets[index].emit {
463 continue;
464 }
465 // TODO: N_STAB
466 let (mut n_type, n_sect) = match symbol.section {
467 SymbolSection::Undefined => (macho::N_UNDF | macho::N_EXT, 0),
468 SymbolSection::Absolute => (macho::N_ABS, 0),
469 SymbolSection::Section(id) => (macho::N_SECT, id.0 + 1),
470 SymbolSection::None | SymbolSection::Common => {
471 return Err(Error(format!(
472 "unimplemented symbol `{}` section {:?}",
473 symbol.name().unwrap_or(""),
474 symbol.section
475 )));
476 }
477 };
478 match symbol.scope {
479 SymbolScope::Unknown | SymbolScope::Compilation => {}
480 SymbolScope::Linkage => {
481 n_type |= macho::N_EXT | macho::N_PEXT;
482 }
483 SymbolScope::Dynamic => {
484 n_type |= macho::N_EXT;
485 }
486 }
487
488 let n_desc = if let SymbolFlags::MachO { n_desc } = symbol.flags {
489 n_desc
490 } else {
491 let mut n_desc = 0;
492 if symbol.weak {
493 if symbol.is_undefined() {
494 n_desc |= macho::N_WEAK_REF;
495 } else {
496 n_desc |= macho::N_WEAK_DEF;
497 }
498 }
499 n_desc
500 };
501
502 let n_value = match symbol.section.id() {
503 Some(section) => section_offsets[section.0].address + symbol.value,
504 None => symbol.value,
505 };
506
507 let n_strx = symbol_offsets[index]
508 .str_id
509 .map(|id| strtab.get_offset(id))
510 .unwrap_or(0);
511
512 macho.write_nlist(
513 buffer,
514 Nlist {
515 n_strx: n_strx as u32,
516 n_type,
517 n_sect: n_sect as u8,
518 n_desc,
519 n_value,
520 },
521 );
522 }
523
524 // Write strtab.
525 debug_assert_eq!(strtab_offset, buffer.len());
526 buffer.write_bytes(&strtab_data);
527
528 // Write relocations.
529 for (index, section) in self.sections.iter().enumerate() {
530 if !section.relocations.is_empty() {
531 write_align(buffer, 4);
532 debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len());
533 for reloc in &section.relocations {
534 let r_extern;
535 let r_symbolnum;
536 let symbol = &self.symbols[reloc.symbol.0];
537 if symbol.kind == SymbolKind::Section {
538 r_symbolnum = section_offsets[symbol.section.id().unwrap().0].index as u32;
539 r_extern = false;
540 } else {
541 r_symbolnum = symbol_offsets[reloc.symbol.0].index as u32;
542 r_extern = true;
543 }
544 let r_length = match reloc.size {
545 8 => 0,
546 16 => 1,
547 32 => 2,
548 64 => 3,
549 _ => return Err(Error(format!("unimplemented reloc size {:?}", reloc))),
550 };
551 let (r_pcrel, r_type) = match self.architecture {
552 Architecture::I386 => match reloc.kind {
553 RelocationKind::Absolute => (false, macho::GENERIC_RELOC_VANILLA),
554 _ => {
555 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
556 }
557 },
558 Architecture::X86_64 => match (reloc.kind, reloc.encoding, reloc.addend) {
559 (RelocationKind::Absolute, RelocationEncoding::Generic, 0) => {
560 (false, macho::X86_64_RELOC_UNSIGNED)
561 }
562 (RelocationKind::Relative, RelocationEncoding::Generic, -4) => {
563 (true, macho::X86_64_RELOC_SIGNED)
564 }
565 (RelocationKind::Relative, RelocationEncoding::X86RipRelative, -4) => {
566 (true, macho::X86_64_RELOC_SIGNED)
567 }
568 (RelocationKind::Relative, RelocationEncoding::X86Branch, -4) => {
569 (true, macho::X86_64_RELOC_BRANCH)
570 }
571 (RelocationKind::PltRelative, RelocationEncoding::X86Branch, -4) => {
572 (true, macho::X86_64_RELOC_BRANCH)
573 }
574 (RelocationKind::GotRelative, RelocationEncoding::Generic, -4) => {
575 (true, macho::X86_64_RELOC_GOT)
576 }
577 (
578 RelocationKind::GotRelative,
579 RelocationEncoding::X86RipRelativeMovq,
580 -4,
581 ) => (true, macho::X86_64_RELOC_GOT_LOAD),
582 (RelocationKind::MachO { value, relative }, _, _) => (relative, value),
583 _ => {
584 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
585 }
586 },
587 _ => {
588 return Err(Error(format!(
589 "unimplemented architecture {:?}",
590 self.architecture
591 )));
592 }
593 };
594 let reloc_info = macho::RelocationInfo {
595 r_address: reloc.offset as u32,
596 r_symbolnum,
597 r_pcrel,
598 r_length,
599 r_extern,
600 r_type,
601 };
602 buffer.write(&reloc_info.relocation(endian));
603 }
604 }
605 }
606
607 debug_assert_eq!(offset, buffer.len());
608
609 Ok(())
610 }
611 }
612
613 struct MachHeader {
614 cputype: u32,
615 cpusubtype: u32,
616 filetype: u32,
617 ncmds: u32,
618 sizeofcmds: u32,
619 flags: u32,
620 }
621
622 struct SegmentCommand {
623 cmdsize: u32,
624 segname: [u8; 16],
625 vmaddr: u64,
626 vmsize: u64,
627 fileoff: u64,
628 filesize: u64,
629 maxprot: u32,
630 initprot: u32,
631 nsects: u32,
632 flags: u32,
633 }
634
635 pub struct SectionHeader {
636 sectname: [u8; 16],
637 segname: [u8; 16],
638 addr: u64,
639 size: u64,
640 offset: u32,
641 align: u32,
642 reloff: u32,
643 nreloc: u32,
644 flags: u32,
645 }
646
647 struct Nlist {
648 n_strx: u32,
649 n_type: u8,
650 n_sect: u8,
651 n_desc: u16,
652 n_value: u64,
653 }
654
655 trait MachO {
656 fn mach_header_size(&self) -> usize;
657 fn segment_command_size(&self) -> usize;
658 fn section_header_size(&self) -> usize;
659 fn nlist_size(&self) -> usize;
660 fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, section: MachHeader);
661 fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand);
662 fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader);
663 fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist);
664 }
665
666 struct MachO32<E> {
667 endian: E,
668 }
669
670 impl<E: Endian> MachO for MachO32<E> {
671 fn mach_header_size(&self) -> usize {
672 mem::size_of::<macho::MachHeader32<E>>()
673 }
674
675 fn segment_command_size(&self) -> usize {
676 mem::size_of::<macho::SegmentCommand32<E>>()
677 }
678
679 fn section_header_size(&self) -> usize {
680 mem::size_of::<macho::Section32<E>>()
681 }
682
683 fn nlist_size(&self) -> usize {
684 mem::size_of::<macho::Nlist32<E>>()
685 }
686
687 fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, header: MachHeader) {
688 let endian = self.endian;
689 let magic = if endian.is_big_endian() {
690 macho::MH_MAGIC
691 } else {
692 macho::MH_CIGAM
693 };
694 let header = macho::MachHeader32 {
695 magic: U32::new(BigEndian, magic),
696 cputype: U32::new(endian, header.cputype),
697 cpusubtype: U32::new(endian, header.cpusubtype),
698 filetype: U32::new(endian, header.filetype),
699 ncmds: U32::new(endian, header.ncmds),
700 sizeofcmds: U32::new(endian, header.sizeofcmds),
701 flags: U32::new(endian, header.flags),
702 };
703 buffer.write(&header);
704 }
705
706 fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand) {
707 let endian = self.endian;
708 let segment = macho::SegmentCommand32 {
709 cmd: U32::new(endian, macho::LC_SEGMENT),
710 cmdsize: U32::new(endian, segment.cmdsize),
711 segname: segment.segname,
712 vmaddr: U32::new(endian, segment.vmaddr as u32),
713 vmsize: U32::new(endian, segment.vmsize as u32),
714 fileoff: U32::new(endian, segment.fileoff as u32),
715 filesize: U32::new(endian, segment.filesize as u32),
716 maxprot: U32::new(endian, segment.maxprot),
717 initprot: U32::new(endian, segment.initprot),
718 nsects: U32::new(endian, segment.nsects),
719 flags: U32::new(endian, segment.flags),
720 };
721 buffer.write(&segment);
722 }
723
724 fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
725 let endian = self.endian;
726 let section = macho::Section32 {
727 sectname: section.sectname,
728 segname: section.segname,
729 addr: U32::new(endian, section.addr as u32),
730 size: U32::new(endian, section.size as u32),
731 offset: U32::new(endian, section.offset),
732 align: U32::new(endian, section.align),
733 reloff: U32::new(endian, section.reloff),
734 nreloc: U32::new(endian, section.nreloc),
735 flags: U32::new(endian, section.flags),
736 reserved1: U32::default(),
737 reserved2: U32::default(),
738 };
739 buffer.write(&section);
740 }
741
742 fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist) {
743 let endian = self.endian;
744 let nlist = macho::Nlist32 {
745 n_strx: U32::new(endian, nlist.n_strx),
746 n_type: nlist.n_type,
747 n_sect: nlist.n_sect,
748 n_desc: U16::new(endian, nlist.n_desc),
749 n_value: U32::new(endian, nlist.n_value as u32),
750 };
751 buffer.write(&nlist);
752 }
753 }
754
755 struct MachO64<E> {
756 endian: E,
757 }
758
759 impl<E: Endian> MachO for MachO64<E> {
760 fn mach_header_size(&self) -> usize {
761 mem::size_of::<macho::MachHeader64<E>>()
762 }
763
764 fn segment_command_size(&self) -> usize {
765 mem::size_of::<macho::SegmentCommand64<E>>()
766 }
767
768 fn section_header_size(&self) -> usize {
769 mem::size_of::<macho::Section64<E>>()
770 }
771
772 fn nlist_size(&self) -> usize {
773 mem::size_of::<macho::Nlist64<E>>()
774 }
775
776 fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, header: MachHeader) {
777 let endian = self.endian;
778 let magic = if endian.is_big_endian() {
779 macho::MH_MAGIC_64
780 } else {
781 macho::MH_CIGAM_64
782 };
783 let header = macho::MachHeader64 {
784 magic: U32::new(BigEndian, magic),
785 cputype: U32::new(endian, header.cputype),
786 cpusubtype: U32::new(endian, header.cpusubtype),
787 filetype: U32::new(endian, header.filetype),
788 ncmds: U32::new(endian, header.ncmds),
789 sizeofcmds: U32::new(endian, header.sizeofcmds),
790 flags: U32::new(endian, header.flags),
791 reserved: U32::default(),
792 };
793 buffer.write(&header);
794 }
795
796 fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand) {
797 let endian = self.endian;
798 let segment = macho::SegmentCommand64 {
799 cmd: U32::new(endian, macho::LC_SEGMENT_64),
800 cmdsize: U32::new(endian, segment.cmdsize),
801 segname: segment.segname,
802 vmaddr: U64::new(endian, segment.vmaddr),
803 vmsize: U64::new(endian, segment.vmsize),
804 fileoff: U64::new(endian, segment.fileoff),
805 filesize: U64::new(endian, segment.filesize),
806 maxprot: U32::new(endian, segment.maxprot),
807 initprot: U32::new(endian, segment.initprot),
808 nsects: U32::new(endian, segment.nsects),
809 flags: U32::new(endian, segment.flags),
810 };
811 buffer.write(&segment);
812 }
813
814 fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
815 let endian = self.endian;
816 let section = macho::Section64 {
817 sectname: section.sectname,
818 segname: section.segname,
819 addr: U64::new(endian, section.addr),
820 size: U64::new(endian, section.size),
821 offset: U32::new(endian, section.offset),
822 align: U32::new(endian, section.align),
823 reloff: U32::new(endian, section.reloff),
824 nreloc: U32::new(endian, section.nreloc),
825 flags: U32::new(endian, section.flags),
826 reserved1: U32::default(),
827 reserved2: U32::default(),
828 reserved3: U32::default(),
829 };
830 buffer.write(&section);
831 }
832
833 fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist) {
834 let endian = self.endian;
835 let nlist = macho::Nlist64 {
836 n_strx: U32::new(endian, nlist.n_strx),
837 n_type: nlist.n_type,
838 n_sect: nlist.n_sect,
839 n_desc: U16::new(endian, nlist.n_desc),
840 n_value: U64Bytes::new(endian, nlist.n_value),
841 };
842 buffer.write(&nlist);
843 }
844 }