5 use crate::write
::string
::*;
6 use crate::write
::util
::*;
8 use crate::AddressSize
;
10 #[derive(Default, Clone, Copy)]
11 struct SectionOffsets
{
18 #[derive(Default, Clone, Copy)]
19 struct SymbolOffsets
{
22 str_id
: Option
<StringId
>,
26 pub(crate) fn macho_set_subsections_via_symbols(&mut self) {
27 let flags
= match self.flags
{
28 FileFlags
::MachO { flags }
=> flags
,
31 self.flags
= FileFlags
::MachO
{
32 flags
: flags
| macho
::MH_SUBSECTIONS_VIA_SYMBOLS
,
36 pub(crate) fn macho_segment_name(&self, segment
: StandardSegment
) -> &'
static [u8] {
38 StandardSegment
::Text
=> &b
"__TEXT"[..],
39 StandardSegment
::Data
=> &b
"__DATA"[..],
40 StandardSegment
::Debug
=> &b
"__DWARF"[..],
44 pub(crate) fn macho_section_info(
46 section
: StandardSection
,
47 ) -> (&'
static [u8], &'
static [u8], SectionKind
) {
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
)
54 StandardSection
::ReadOnlyDataWithRel
=> {
55 (&b
"__DATA"[..], &b
"__const"[..], SectionKind
::ReadOnlyData
)
57 StandardSection
::ReadOnlyString
=> (
60 SectionKind
::ReadOnlyString
,
62 StandardSection
::UninitializedData
=> (
65 SectionKind
::UninitializedData
,
67 StandardSection
::Tls
=> (&b
"__DATA"[..], &b
"__thread_data"[..], SectionKind
::Tls
),
68 StandardSection
::UninitializedTls
=> (
71 SectionKind
::UninitializedTls
,
73 StandardSection
::TlsVariables
=> (
75 &b
"__thread_vars"[..],
76 SectionKind
::TlsVariables
,
78 StandardSection
::Common
=> (&b
"__DATA"[..], &b
"__common"[..], SectionKind
::Common
),
82 fn macho_tlv_bootstrap(&mut self) -> SymbolId
{
83 match self.tlv_bootstrap
{
86 let id
= self.add_symbol(Symbol
{
87 name
: b
"_tlv_bootstrap".to_vec(),
90 kind
: SymbolKind
::Text
,
91 scope
: SymbolScope
::Dynamic
,
93 section
: SymbolSection
::Undefined
,
94 flags
: SymbolFlags
::None
,
96 self.tlv_bootstrap
= Some(id
);
102 /// Create the `__thread_vars` entry for a TLS variable.
104 /// The symbol given by `symbol_id` will be updated to point to this entry.
106 /// A new `SymbolId` will be returned. The caller must update this symbol
107 /// to point to the initializer.
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
{
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
{
123 kind
: SymbolKind
::Tls
,
124 scope
: SymbolScope
::Compilation
,
126 section
: SymbolSection
::Undefined
,
127 flags
: SymbolFlags
::None
,
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
));
141 let tlv_bootstrap
= self.macho_tlv_bootstrap();
146 size
: address_size
* 8,
147 kind
: RelocationKind
::Absolute
,
148 encoding
: RelocationEncoding
::Generic
,
149 symbol
: tlv_bootstrap
,
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
,
167 // Update the symbol to point to the tlv.
168 let symbol
= self.symbol_mut(symbol_id
);
169 symbol
.value
= offset
;
171 symbol
.section
= SymbolSection
::Section(section
);
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
,
183 relocation
.addend
-= constant
;
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
,
196 let pointer_align
= address_size
.bytes() as usize;
198 // Calculate offsets of everything, and build strtab.
201 // Calculate size of Mach-O header.
202 offset
+= macho
.mach_header_size();
204 // Calculate size of commands.
206 let command_offset
= offset
;
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
;
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
;
221 let sizeofcmds
= offset
- command_offset
;
223 // Calculate size of section data.
224 let mut segment_file_offset
= None
;
225 let mut section_offsets
= vec
![SectionOffsets
::default(); self.sections
.len()];
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();
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
);
239 section_offsets
[index
].offset
= offset
;
241 address
= align_u64(address
, section
.align
);
242 section_offsets
[index
].address
= address
;
243 address
+= section
.size
;
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
;
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
);
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()];
262 for (index
, symbol
) in self.symbols
.iter().enumerate() {
263 // The unified API allows creating symbols that we don't emit, so filter
266 // Since we don't actually emit the symbol kind, we validate it here too.
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(""),
278 SymbolKind
::Null
| SymbolKind
::Label
=> {
279 return Err(Error(format
!(
280 "unimplemented symbol `{}` kind {:?}",
281 symbol
.name().unwrap_or(""),
286 symbol_offsets
[index
].emit
= true;
287 symbol_offsets
[index
].index
= nsyms
;
289 if !symbol
.name
.is_empty() {
290 symbol_offsets
[index
].str_id
= Some(strtab
.add(&symbol
.name
));
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
;
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();
307 // Calculate size of relocations.
308 for (index
, section
) in self.sections
.iter().enumerate() {
309 let count
= section
.relocations
.len();
311 offset
= align(offset
, 4);
312 section_offsets
[index
].reloc_offset
= offset
;
313 let len
= count
* mem
::size_of
::<macho
::Relocation
<Endianness
>>();
321 .map_err(|_
| Error(String
::from("Cannot allocate buffer")))?
;
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
),
330 return Err(Error(format
!(
331 "unimplemented architecture {:?}",
337 let flags
= match self.flags
{
338 FileFlags
::MachO { flags }
=> flags
,
341 macho
.write_mach_header(
346 filetype
: macho
::MH_OBJECT
,
348 sizeofcmds
: sizeofcmds
as u32,
353 // Write segment command.
354 debug_assert_eq
!(segment_command_offset
, buffer
.len());
355 macho
.write_segment_command(
358 cmdsize
: segment_command_len
as u32,
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,
371 // Write section headers.
372 for (index
, section
) in self.sections
.iter().enumerate() {
373 let mut sectname
= [0; 16];
375 .get_mut(..section
.name
.len())
378 "section name `{}` is too long",
379 section
.name().unwrap_or(""),
382 .copy_from_slice(§ion
.name
);
383 let mut segname
= [0; 16];
385 .get_mut(..section
.segment
.len())
388 "segment name `{}` is too long",
389 section
.segment().unwrap_or(""),
392 .copy_from_slice(§ion
.segment
);
393 let flags
= if let SectionFlags
::MachO { flags }
= section
.flags
{
397 SectionKind
::Text
=> {
398 macho
::S_ATTR_PURE_INSTRUCTIONS
| macho
::S_ATTR_SOME_INSTRUCTIONS
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(""),
424 addr
: section_offsets
[index
].address
,
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,
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),
445 buffer
.write(&symtab_command
);
447 // Write section data.
448 for (index
, section
) in self.sections
.iter().enumerate() {
449 let len
= section
.data
.len();
451 write_align(buffer
, section
.align
as usize);
452 debug_assert_eq
!(section_offsets
[index
].offset
, buffer
.len());
453 buffer
.write_bytes(§ion
.data
);
456 debug_assert_eq
!(segment_file_offset
+ segment_file_size
, buffer
.len());
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
{
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(""),
479 SymbolScope
::Unknown
| SymbolScope
::Compilation
=> {}
480 SymbolScope
::Linkage
=> {
481 n_type
|= macho
::N_EXT
| macho
::N_PEXT
;
483 SymbolScope
::Dynamic
=> {
484 n_type
|= macho
::N_EXT
;
488 let n_desc
= if let SymbolFlags
::MachO { n_desc }
= symbol
.flags
{
493 if symbol
.is_undefined() {
494 n_desc
|= macho
::N_WEAK_REF
;
496 n_desc
|= macho
::N_WEAK_DEF
;
502 let n_value
= match symbol
.section
.id() {
503 Some(section
) => section_offsets
[section
.0].address
+ symbol
.value
,
504 None
=> symbol
.value
,
507 let n_strx
= symbol_offsets
[index
]
509 .map(|id
| strtab
.get_offset(id
))
515 n_strx
: n_strx
as u32,
517 n_sect
: n_sect
as u8,
525 debug_assert_eq
!(strtab_offset
, buffer
.len());
526 buffer
.write_bytes(&strtab_data
);
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 §ion
.relocations
{
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;
541 r_symbolnum
= symbol_offsets
[reloc
.symbol
.0].index
as u32;
544 let r_length
= match reloc
.size
{
549 _
=> return Err(Error(format
!("unimplemented reloc size {:?}", reloc
))),
551 let (r_pcrel
, r_type
) = match self.architecture
{
552 Architecture
::I386
=> match reloc
.kind
{
553 RelocationKind
::Absolute
=> (false, macho
::GENERIC_RELOC_VANILLA
),
555 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
558 Architecture
::X86_64
=> match (reloc
.kind
, reloc
.encoding
, reloc
.addend
) {
559 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 0) => {
560 (false, macho
::X86_64_RELOC_UNSIGNED
)
562 (RelocationKind
::Relative
, RelocationEncoding
::Generic
, -4) => {
563 (true, macho
::X86_64_RELOC_SIGNED
)
565 (RelocationKind
::Relative
, RelocationEncoding
::X86RipRelative
, -4) => {
566 (true, macho
::X86_64_RELOC_SIGNED
)
568 (RelocationKind
::Relative
, RelocationEncoding
::X86Branch
, -4) => {
569 (true, macho
::X86_64_RELOC_BRANCH
)
571 (RelocationKind
::PltRelative
, RelocationEncoding
::X86Branch
, -4) => {
572 (true, macho
::X86_64_RELOC_BRANCH
)
574 (RelocationKind
::GotRelative
, RelocationEncoding
::Generic
, -4) => {
575 (true, macho
::X86_64_RELOC_GOT
)
578 RelocationKind
::GotRelative
,
579 RelocationEncoding
::X86RipRelativeMovq
,
581 ) => (true, macho
::X86_64_RELOC_GOT_LOAD
),
582 (RelocationKind
::MachO { value, relative }
, _
, _
) => (relative
, value
),
584 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
588 return Err(Error(format
!(
589 "unimplemented architecture {:?}",
594 let reloc_info
= macho
::RelocationInfo
{
595 r_address
: reloc
.offset
as u32,
602 buffer
.write(&reloc_info
.relocation(endian
));
607 debug_assert_eq
!(offset
, buffer
.len());
622 struct SegmentCommand
{
635 pub struct SectionHeader
{
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
);
670 impl<E
: Endian
> MachO
for MachO32
<E
> {
671 fn mach_header_size(&self) -> usize {
672 mem
::size_of
::<macho
::MachHeader32
<E
>>()
675 fn segment_command_size(&self) -> usize {
676 mem
::size_of
::<macho
::SegmentCommand32
<E
>>()
679 fn section_header_size(&self) -> usize {
680 mem
::size_of
::<macho
::Section32
<E
>>()
683 fn nlist_size(&self) -> usize {
684 mem
::size_of
::<macho
::Nlist32
<E
>>()
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() {
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
),
703 buffer
.write(&header
);
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
),
721 buffer
.write(&segment
);
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(),
739 buffer
.write(§ion
);
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),
751 buffer
.write(&nlist
);
759 impl<E
: Endian
> MachO
for MachO64
<E
> {
760 fn mach_header_size(&self) -> usize {
761 mem
::size_of
::<macho
::MachHeader64
<E
>>()
764 fn segment_command_size(&self) -> usize {
765 mem
::size_of
::<macho
::SegmentCommand64
<E
>>()
768 fn section_header_size(&self) -> usize {
769 mem
::size_of
::<macho
::Section64
<E
>>()
772 fn nlist_size(&self) -> usize {
773 mem
::size_of
::<macho
::Nlist64
<E
>>()
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() {
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(),
793 buffer
.write(&header
);
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
),
811 buffer
.write(&segment
);
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(),
830 buffer
.write(§ion
);
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
),
842 buffer
.write(&nlist
);