Correct use of NativeEndian to LittleEndian

This should specify the endian read from and written to.
In our case, we are using elf/macho. So, the endian is always little.
This commit is contained in:
Brendan Hansknecht 2023-04-27 07:14:47 -07:00
parent 8a76937cff
commit e88d759331
No known key found for this signature in database
GPG Key ID: 0EA784685083E75B
2 changed files with 237 additions and 312 deletions

View File

@ -2,9 +2,9 @@ use iced_x86::{Decoder, DecoderOptions, Instruction, OpCodeOperandKind, OpKind};
use memmap2::MmapMut;
use object::{elf, endian};
use object::{
CompressedFileRange, CompressionFormat, LittleEndian as LE, NativeEndian, Object,
ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex,
SectionKind, Symbol, SymbolIndex, SymbolSection,
CompressedFileRange, CompressionFormat, LittleEndian as LE, Object, ObjectSection,
ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex, SectionKind, Symbol,
SymbolIndex, SymbolSection,
};
use roc_collections::all::MutMap;
use roc_error_macros::{internal_error, user_error};
@ -517,12 +517,12 @@ fn gen_elf_le(
verbose: bool,
) -> MmapMut {
let exec_header = load_struct_inplace::<elf::FileHeader64<LE>>(exec_data, 0);
let ph_offset = exec_header.e_phoff.get(NativeEndian);
let ph_ent_size = exec_header.e_phentsize.get(NativeEndian);
let ph_num = exec_header.e_phnum.get(NativeEndian);
let sh_offset = exec_header.e_shoff.get(NativeEndian);
let sh_ent_size = exec_header.e_shentsize.get(NativeEndian);
let sh_num = exec_header.e_shnum.get(NativeEndian);
let ph_offset = exec_header.e_phoff.get(LE);
let ph_ent_size = exec_header.e_phentsize.get(LE);
let ph_num = exec_header.e_phnum.get(LE);
let sh_offset = exec_header.e_shoff.get(LE);
let sh_ent_size = exec_header.e_shentsize.get(LE);
let sh_num = exec_header.e_shnum.get(LE);
if verbose {
println!();
@ -555,11 +555,11 @@ fn gen_elf_le(
let mut first_load_found = false;
let mut virtual_shift_start = 0;
for ph in program_headers.iter() {
let p_type = ph.p_type.get(NativeEndian);
if p_type == elf::PT_LOAD && ph.p_offset.get(NativeEndian) == 0 {
let p_type = ph.p_type.get(LE);
if p_type == elf::PT_LOAD && ph.p_offset.get(LE) == 0 {
first_load_found = true;
md.load_align_constraint = ph.p_align.get(NativeEndian);
virtual_shift_start = physical_shift_start + ph.p_vaddr.get(NativeEndian);
md.load_align_constraint = ph.p_align.get(LE);
virtual_shift_start = physical_shift_start + ph.p_vaddr.get(LE);
}
}
if !first_load_found {
@ -574,18 +574,18 @@ fn gen_elf_le(
// Shift all of the program headers.
for ph in program_headers.iter_mut() {
let p_type = ph.p_type.get(NativeEndian);
let p_offset = ph.p_offset.get(NativeEndian);
let p_type = ph.p_type.get(LE);
let p_offset = ph.p_offset.get(LE);
if (p_type == elf::PT_LOAD && p_offset == 0) || p_type == elf::PT_PHDR {
// Extend length for the first segment and the program header.
ph.p_filesz = endian::U64::new(LE, ph.p_filesz.get(NativeEndian) + md.added_byte_count);
ph.p_memsz = endian::U64::new(LE, ph.p_memsz.get(NativeEndian) + md.added_byte_count);
ph.p_filesz = endian::U64::new(LE, ph.p_filesz.get(LE) + md.added_byte_count);
ph.p_memsz = endian::U64::new(LE, ph.p_memsz.get(LE) + md.added_byte_count);
} else {
// Shift if needed.
if physical_shift_start <= p_offset {
ph.p_offset = endian::U64::new(LE, p_offset + md.added_byte_count);
}
let p_vaddr = ph.p_vaddr.get(NativeEndian);
let p_vaddr = ph.p_vaddr.get(LE);
if virtual_shift_start <= p_vaddr {
ph.p_vaddr = endian::U64::new(LE, p_vaddr + md.added_byte_count);
ph.p_paddr = endian::U64::new(LE, p_vaddr + md.added_byte_count);
@ -597,8 +597,8 @@ fn gen_elf_le(
let last_segment_vaddr = program_headers
.iter()
.filter_map(|ph| {
if ph.p_type.get(NativeEndian) != elf::PT_GNU_STACK {
Some(ph.p_vaddr.get(NativeEndian) + ph.p_memsz.get(NativeEndian))
if ph.p_type.get(LE) != elf::PT_GNU_STACK {
Some(ph.p_vaddr.get(LE) + ph.p_memsz.get(LE))
} else {
None
}
@ -620,8 +620,8 @@ fn gen_elf_le(
let mut rel_sections: Vec<(u64, u64)> = vec![];
let mut rela_sections: Vec<(usize, u64, u64)> = vec![];
for (i, sh) in section_headers.iter_mut().enumerate() {
let sh_offset = sh.sh_offset.get(NativeEndian);
let sh_addr = sh.sh_addr.get(NativeEndian);
let sh_offset = sh.sh_offset.get(LE);
let sh_addr = sh.sh_addr.get(LE);
if physical_shift_start <= sh_offset {
sh.sh_offset = endian::U64::new(LE, sh_offset + md.added_byte_count);
}
@ -630,18 +630,18 @@ fn gen_elf_le(
}
// Record every relocation section.
let sh_type = sh.sh_type.get(NativeEndian);
let sh_type = sh.sh_type.get(LE);
if sh_type == elf::SHT_REL {
rel_sections.push((sh_offset, sh.sh_size.get(NativeEndian)));
rel_sections.push((sh_offset, sh.sh_size.get(LE)));
} else if sh_type == elf::SHT_RELA {
rela_sections.push((i, sh_offset, sh.sh_size.get(NativeEndian)));
rela_sections.push((i, sh_offset, sh.sh_size.get(LE)));
}
}
// Get last section virtual address.
let last_section_vaddr = section_headers
.iter()
.map(|sh| sh.sh_addr.get(NativeEndian) + sh.sh_size.get(NativeEndian))
.map(|sh| sh.sh_addr.get(LE) + sh.sh_size.get(LE))
.max()
.unwrap();
@ -658,7 +658,7 @@ fn gen_elf_le(
sec_size as usize / mem::size_of::<elf::Rel64<LE>>(),
);
for rel in relocations.iter_mut() {
let r_offset = rel.r_offset.get(NativeEndian);
let r_offset = rel.r_offset.get(LE);
if virtual_shift_start <= r_offset {
rel.r_offset = endian::U64::new(LE, r_offset + md.added_byte_count);
}
@ -673,7 +673,7 @@ fn gen_elf_le(
sec_size as usize / mem::size_of::<elf::Rela64<LE>>(),
);
for (i, rel) in relocations.iter_mut().enumerate() {
let r_offset = rel.r_offset.get(NativeEndian);
let r_offset = rel.r_offset.get(LE);
if virtual_shift_start <= r_offset {
rel.r_offset = endian::U64::new(LE, r_offset + md.added_byte_count);
// Deal with potential adjusts to absolute jumps.
@ -684,9 +684,9 @@ fn gen_elf_le(
}
}
// If the relocation goes to a roc function, we need to surgically link it and change it to relative.
let r_type = rel.r_type(NativeEndian, false);
let r_type = rel.r_type(LE, false);
if r_type == elf::R_X86_64_GLOB_DAT {
let r_sym = rel.r_sym(NativeEndian, false);
let r_sym = rel.r_sym(LE, false);
for (name, index) in got_app_syms.iter() {
if *index as u32 == r_sym {
rel.set_r_info(LE, false, 0, elf::R_X86_64_RELATIVE);
@ -715,8 +715,8 @@ fn gen_elf_le(
.iter()
.enumerate()
.filter_map(|(i, rel)| {
let r_type = rel.r_type(NativeEndian, false);
let r_sym = rel.r_sym(NativeEndian, false);
let r_type = rel.r_type(LE, false);
let r_sym = rel.r_sym(LE, false);
if r_type == elf::R_X86_64_JUMP_SLOT && app_sym_indices.contains(&(r_sym as usize))
{
Some(i)
@ -733,7 +733,7 @@ fn gen_elf_le(
let mut j = relocations.len() - 1;
for i in to_remove.iter() {
relocations.swap(*i, j);
let r_sym = relocations[j].r_sym(NativeEndian, false);
let r_sym = relocations[j].r_sym(LE, false);
relocations[j].set_r_info(LE, false, r_sym, elf::R_X86_64_NONE);
j -= 1;
}
@ -744,12 +744,12 @@ fn gen_elf_le(
sh_num as usize,
);
let old_size = section_headers[sec_index].sh_size.get(NativeEndian);
let old_size = section_headers[sec_index].sh_size.get(LE);
let removed_count = to_remove.len();
let removed_size = removed_count * std::mem::size_of::<elf::Rela64<LE>>();
section_headers[sec_index]
.sh_size
.set(NativeEndian, old_size - removed_size as u64);
.set(LE, old_size - removed_size as u64);
let dyns = load_structs_inplace_mut::<elf::Dyn64<LE>>(
&mut out_mmap,
@ -759,30 +759,30 @@ fn gen_elf_le(
let is_rela_dyn = dyns
.iter()
.filter(|d| {
let tag = d.d_tag.get(NativeEndian) as u32;
let tag = d.d_tag.get(LE) as u32;
tag == elf::DT_RELA
})
.any(|d| d.d_val.get(NativeEndian) == sec_offset);
.any(|d| d.d_val.get(LE) == sec_offset);
let is_rela_plt = dyns
.iter()
.filter(|d| {
let tag = d.d_tag.get(NativeEndian) as u32;
let tag = d.d_tag.get(LE) as u32;
tag == elf::DT_JMPREL
})
.any(|d| d.d_val.get(NativeEndian) == sec_offset);
.any(|d| d.d_val.get(LE) == sec_offset);
for d in dyns.iter_mut() {
match d.d_tag.get(NativeEndian) as u32 {
match d.d_tag.get(LE) as u32 {
elf::DT_RELACOUNT if is_rela_dyn => {
let old_count = d.d_val.get(NativeEndian);
let old_count = d.d_val.get(LE);
d.d_val.set(LE, old_count - removed_count as u64);
}
elf::DT_RELASZ if is_rela_dyn => {
let old_size = d.d_val.get(NativeEndian);
let old_size = d.d_val.get(LE);
d.d_val.set(LE, old_size - removed_size as u64);
}
elf::DT_PLTRELSZ if is_rela_plt => {
let old_size = d.d_val.get(NativeEndian);
let old_size = d.d_val.get(LE);
d.d_val.set(LE, old_size - removed_size as u64);
}
_ => {}
@ -797,7 +797,7 @@ fn gen_elf_le(
dynamic_lib_count,
);
for mut d in dyns {
match d.d_tag.get(NativeEndian) as u32 {
match d.d_tag.get(LE) as u32 {
// I believe this is the list of symbols that need to be update if addresses change.
// I am less sure about the symbols from GNU_HASH down.
elf::DT_INIT
@ -828,7 +828,7 @@ fn gen_elf_le(
| elf::DT_VERSYM
| elf::DT_VERDEF
| elf::DT_VERNEED => {
let d_addr = d.d_val.get(NativeEndian);
let d_addr = d.d_val.get(LE);
if virtual_shift_start <= d_addr {
d.d_val = endian::U64::new(LE, d_addr + md.added_byte_count);
}
@ -848,7 +848,7 @@ fn gen_elf_le(
);
for sym in symbols {
let addr = sym.st_value.get(NativeEndian);
let addr = sym.st_value.get(LE);
if virtual_shift_start <= addr {
sym.st_value = endian::U64::new(LE, addr + md.added_byte_count);
}
@ -862,7 +862,7 @@ fn gen_elf_le(
size / mem::size_of::<endian::U64<LE>>(),
);
for go in global_offsets.iter_mut() {
let go_addr = go.get(NativeEndian);
let go_addr = go.get(LE);
if physical_shift_start <= go_addr {
go.set(LE, go_addr + md.added_byte_count);
}
@ -883,11 +883,8 @@ fn gen_elf_le(
// Update main elf header for extra data.
let mut file_header = load_struct_inplace_mut::<elf::FileHeader64<LE>>(&mut out_mmap, 0);
file_header.e_shoff = endian::U64::new(
LE,
file_header.e_shoff.get(NativeEndian) + md.added_byte_count,
);
let e_entry = file_header.e_entry.get(NativeEndian);
file_header.e_shoff = endian::U64::new(LE, file_header.e_shoff.get(LE) + md.added_byte_count);
let e_entry = file_header.e_entry.get(LE);
if virtual_shift_start <= e_entry {
file_header.e_entry = endian::U64::new(LE, e_entry + md.added_byte_count);
}
@ -1185,12 +1182,12 @@ fn surgery_elf_help(
}
let exec_header = load_struct_inplace::<elf::FileHeader64<LE>>(exec_mmap, 0);
let ph_offset = exec_header.e_phoff.get(NativeEndian);
let ph_ent_size = exec_header.e_phentsize.get(NativeEndian);
let ph_num = exec_header.e_phnum.get(NativeEndian);
let sh_offset = exec_header.e_shoff.get(NativeEndian);
let sh_ent_size = exec_header.e_shentsize.get(NativeEndian);
let sh_num = exec_header.e_shnum.get(NativeEndian);
let ph_offset = exec_header.e_phoff.get(LE);
let ph_ent_size = exec_header.e_phentsize.get(LE);
let ph_num = exec_header.e_phnum.get(LE);
let sh_offset = exec_header.e_shoff.get(LE);
let sh_ent_size = exec_header.e_shentsize.get(LE);
let sh_num = exec_header.e_shnum.get(LE);
if verbose {
println!();

View File

@ -3,7 +3,7 @@ use iced_x86::{Decoder, DecoderOptions, Instruction, OpCodeOperandKind, OpKind};
use memmap2::MmapMut;
use object::macho;
use object::{
CompressedFileRange, CompressionFormat, LittleEndian, NativeEndian, Object, ObjectSection,
CompressedFileRange, CompressionFormat, LittleEndian as LE, Object, ObjectSection,
ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex, SectionKind, Symbol,
SymbolIndex, SymbolSection,
};
@ -325,8 +325,8 @@ pub(crate) fn preprocess_macho(
{
use macho::{DyldInfoCommand, DylibCommand, Section64, SegmentCommand64};
let exec_header = load_struct_inplace::<macho::MachHeader64<LittleEndian>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(NativeEndian);
let exec_header = load_struct_inplace::<macho::MachHeader64<LE>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(LE);
let mut offset = mem::size_of_val(exec_header);
@ -334,17 +334,17 @@ pub(crate) fn preprocess_macho(
let mut stubs_symbol_count = None;
'cmds: for _ in 0..num_load_cmds {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, offset);
let cmd = info.cmd.get(NativeEndian);
let cmdsize = info.cmdsize.get(NativeEndian);
let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, offset);
let cmd = info.cmd.get(LE);
let cmdsize = info.cmdsize.get(LE);
if cmd == macho::LC_SEGMENT_64 {
let info = load_struct_inplace::<SegmentCommand64<LittleEndian>>(exec_data, offset);
let info = load_struct_inplace::<SegmentCommand64<LE>>(exec_data, offset);
if &info.segname[0..6] == b"__TEXT" {
let sections = info.nsects.get(NativeEndian);
let sections = info.nsects.get(LE);
let sections_info = load_structs_inplace::<Section64<LittleEndian>>(
let sections_info = load_structs_inplace::<Section64<LE>>(
exec_data,
offset + mem::size_of_val(info),
sections as usize,
@ -352,9 +352,9 @@ pub(crate) fn preprocess_macho(
for section_info in sections_info {
if &section_info.sectname[0..7] == b"__stubs" {
stubs_symbol_index = Some(section_info.reserved1.get(NativeEndian));
stubs_symbol_index = Some(section_info.reserved1.get(LE));
stubs_symbol_count =
Some(section_info.size.get(NativeEndian) / STUB_ADDRESS_OFFSET);
Some(section_info.size.get(LE) / STUB_ADDRESS_OFFSET);
break 'cmds;
}
@ -378,14 +378,14 @@ pub(crate) fn preprocess_macho(
let shared_lib_filename = shared_lib.file_name();
for _ in 0..num_load_cmds {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, offset);
let cmd = info.cmd.get(NativeEndian);
let cmdsize = info.cmdsize.get(NativeEndian);
let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, offset);
let cmd = info.cmd.get(LE);
let cmdsize = info.cmdsize.get(LE);
if cmd == macho::LC_DYLD_INFO_ONLY {
let info = load_struct_inplace::<DyldInfoCommand<LittleEndian>>(exec_data, offset);
let info = load_struct_inplace::<DyldInfoCommand<LE>>(exec_data, offset);
let lazy_bind_offset = info.lazy_bind_off.get(NativeEndian) as usize;
let lazy_bind_offset = info.lazy_bind_off.get(LE) as usize;
let lazy_bind_symbols = mach_object::LazyBind::parse(
&exec_data[lazy_bind_offset..],
@ -412,8 +412,8 @@ pub(crate) fn preprocess_macho(
}
}
} else if cmd == macho::LC_LOAD_DYLIB {
let info = load_struct_inplace::<DylibCommand<LittleEndian>>(exec_data, offset);
let name_offset = info.dylib.name.offset.get(NativeEndian) as usize;
let info = load_struct_inplace::<DylibCommand<LE>>(exec_data, offset);
let name_offset = info.dylib.name.offset.get(LE) as usize;
let str_start_index = offset + name_offset;
let str_end_index = offset + cmdsize as usize;
let str_bytes = &exec_data[str_start_index..str_end_index];
@ -600,19 +600,18 @@ fn gen_macho_le(
use macho::{Section64, SegmentCommand64};
let exec_header = load_struct_inplace::<macho::MachHeader64<LittleEndian>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(NativeEndian);
let size_of_cmds = exec_header.sizeofcmds.get(NativeEndian) as usize;
let exec_header = load_struct_inplace::<macho::MachHeader64<LE>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(LE);
let size_of_cmds = exec_header.sizeofcmds.get(LE) as usize;
// Add a new text segment and data segment
let segment_cmd_size = mem::size_of::<SegmentCommand64<LittleEndian>>();
let section_size = mem::size_of::<Section64<LittleEndian>>();
let segment_cmd_size = mem::size_of::<SegmentCommand64<LE>>();
let section_size = mem::size_of::<Section64<LE>>();
// We need the full command size, including the dynamic-length string at the end.
// To get that, we need to load the command.
let info =
load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, macho_load_so_offset);
let total_cmd_size = info.cmdsize.get(NativeEndian) as usize;
let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, macho_load_so_offset);
let total_cmd_size = info.cmdsize.get(LE) as usize;
// ======================== Important TODO ==========================
// TODO: we accidentally instroduced a big change here.
@ -654,16 +653,16 @@ fn gen_macho_le(
out_mmap[start_index..start_index + rest_of_data.len()].copy_from_slice(rest_of_data);
let out_header = load_struct_inplace_mut::<macho::MachHeader64<LittleEndian>>(&mut out_mmap, 0);
let out_header = load_struct_inplace_mut::<macho::MachHeader64<LE>>(&mut out_mmap, 0);
// TODO: this needs to change to adding the 2 new commands when we are ready.
// -1 because we're deleting 1 load command and then NOT adding 2 new ones.
{
let added_bytes = -(total_cmd_size as isize); // TODO: Change when add the new sections.
out_header.ncmds.set(LittleEndian, num_load_cmds - 1);
out_header.ncmds.set(LE, num_load_cmds - 1);
out_header
.sizeofcmds
.set(LittleEndian, (size_of_cmds as isize + added_bytes) as u32);
.set(LE, (size_of_cmds as isize + added_bytes) as u32);
}
// Go through every command and shift it by added_bytes if it's absolute, unless it's inside the command header
@ -681,50 +680,37 @@ fn gen_macho_le(
// minus one because we "deleted" a load command
for _ in 0..(num_load_cmds - 1) {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(&out_mmap, offset);
let cmd_size = info.cmdsize.get(NativeEndian) as usize;
let info = load_struct_inplace::<macho::LoadCommand<LE>>(&out_mmap, offset);
let cmd_size = info.cmdsize.get(LE) as usize;
match info.cmd.get(NativeEndian) {
match info.cmd.get(LE) {
macho::LC_SEGMENT_64 => {
let cmd = load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::SegmentCommand64<LE>>(&mut out_mmap, offset);
// Ignore page zero, it never moves.
if cmd.segname == "__PAGEZERO\0\0\0\0\0\0".as_bytes()
|| cmd.vmaddr.get(NativeEndian) == 0
{
if cmd.segname == "__PAGEZERO\0\0\0\0\0\0".as_bytes() || cmd.vmaddr.get(LE) == 0 {
offset += cmd_size;
continue;
}
let old_file_offest = cmd.fileoff.get(NativeEndian);
let old_file_offest = cmd.fileoff.get(LE);
// The segment with file offset zero also includes the header.
// As such, its file offset does not change.
// Instead, its file size should be increased.
if old_file_offest > 0 {
cmd.fileoff
.set(LittleEndian, old_file_offest + md.added_byte_count);
cmd.vmaddr.set(
LittleEndian,
cmd.vmaddr.get(NativeEndian) + md.added_byte_count,
);
cmd.fileoff.set(LE, old_file_offest + md.added_byte_count);
cmd.vmaddr.set(LE, cmd.vmaddr.get(LE) + md.added_byte_count);
} else {
cmd.filesize.set(
LittleEndian,
cmd.filesize.get(NativeEndian) + md.added_byte_count,
);
cmd.vmsize.set(
LittleEndian,
cmd.vmsize.get(NativeEndian) + md.added_byte_count,
);
cmd.filesize
.set(LE, cmd.filesize.get(LE) + md.added_byte_count);
cmd.vmsize.set(LE, cmd.vmsize.get(LE) + md.added_byte_count);
}
// let num_sections = cmd.nsects.get(NativeEndian);
// let sections = load_structs_inplace_mut::<macho::Section64<LittleEndian>>(
// let num_sections = cmd.nsects.get(LE);
// let sections = load_structs_inplace_mut::<macho::Section64<LE >>(
// &mut out_mmap,
// offset + mem::size_of::<macho::SegmentCommand64<LittleEndian>>(),
// offset + mem::size_of::<macho::SegmentCommand64<LE >>(),
// num_sections as usize,
// );
// struct Relocation {
@ -736,34 +722,34 @@ fn gen_macho_le(
// for section in sections {
// section.addr.set(
// LittleEndian,
// section.addr.get(NativeEndian) + md.added_byte_count as u64,
// LE ,
// section.addr.get(LE) + md.added_byte_count as u64,
// );
// // If offset is zero, don't update it.
// // Zero is used for things like BSS that don't exist in the file.
// let old_offset = section.offset.get(NativeEndian);
// let old_offset = section.offset.get(LE);
// if old_offset > 0 {
// section
// .offset
// .set(LittleEndian, old_offset + md.added_byte_count as u32);
// .set(LE , old_offset + md.added_byte_count as u32);
// }
// // dbg!(&section.reloff.get(NativeEndian));
// // dbg!(section.reloff.get(NativeEndian) as i32);
// // dbg!(&section.reloff.get(LE));
// // dbg!(section.reloff.get(LE) as i32);
// // dbg!(&section);
// // dbg!(&md.added_byte_count);
// // dbg!(String::from_utf8_lossy(&section.sectname));
// if section.nreloc.get(NativeEndian) > 0 {
// if section.nreloc.get(LE) > 0 {
// section.reloff.set(
// LittleEndian,
// section.reloff.get(NativeEndian) + md.added_byte_count as u32,
// LE ,
// section.reloff.get(LE) + md.added_byte_count as u32,
// );
// }
// relocation_offsets.push(Relocation {
// offset: section.reloff.get(NativeEndian),
// num_relocations: section.nreloc.get(NativeEndian),
// offset: section.reloff.get(LE),
// num_relocations: section.nreloc.get(LE),
// });
// }
@ -773,7 +759,7 @@ fn gen_macho_le(
// num_relocations,
// } in relocation_offsets
// {
// let relos = load_structs_inplace_mut::<macho::Relocation<LittleEndian>>(
// let relos = load_structs_inplace_mut::<macho::Relocation<LE >>(
// &mut out_mmap,
// offset as usize,
// num_relocations as usize,
@ -781,13 +767,13 @@ fn gen_macho_le(
// // TODO this has never been tested, because scattered relocations only come up on ARM!
// for relo in relos.iter_mut() {
// if relo.r_scattered(LittleEndian, cpu_type) {
// let mut scattered_info = relo.scattered_info(NativeEndian);
// if relo.r_scattered(LE , cpu_type) {
// let mut scattered_info = relo.scattered_info(LE);
// if !scattered_info.r_pcrel {
// scattered_info.r_value += md.added_byte_count as u32;
// let new_info = scattered_info.relocation(LittleEndian);
// let new_info = scattered_info.relocation(LE );
// relo.r_word0 = new_info.r_word0;
// relo.r_word1 = new_info.r_word1;
@ -797,30 +783,25 @@ fn gen_macho_le(
// }
// TODO this seems to be wrong and unnecessary, and should probably be deleted.
// offset += num_sections as usize * mem::size_of::<macho::Section64<LittleEndian>>();
// offset += num_sections as usize * mem::size_of::<macho::Section64<LE >>();
}
macho::LC_SYMTAB => {
let cmd = load_struct_inplace_mut::<macho::SymtabCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::SymtabCommand<LE>>(&mut out_mmap, offset);
let sym_offset = cmd.symoff.get(NativeEndian);
let num_syms = cmd.nsyms.get(NativeEndian);
let sym_offset = cmd.symoff.get(LE);
let num_syms = cmd.nsyms.get(LE);
if num_syms > 0 {
cmd.symoff
.set(LittleEndian, sym_offset + md.added_byte_count as u32);
cmd.symoff.set(LE, sym_offset + md.added_byte_count as u32);
}
if cmd.strsize.get(NativeEndian) > 0 {
cmd.stroff.set(
LittleEndian,
cmd.stroff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.strsize.get(LE) > 0 {
cmd.stroff
.set(LE, cmd.stroff.get(LE) + md.added_byte_count as u32);
}
let table = load_structs_inplace_mut::<macho::Nlist64<LittleEndian>>(
let table = load_structs_inplace_mut::<macho::Nlist64<LE>>(
&mut out_mmap,
sym_offset as usize + md.added_byte_count as usize,
num_syms as usize,
@ -829,59 +810,44 @@ fn gen_macho_le(
for entry in table {
let entry_type = entry.n_type & macho::N_TYPE;
if entry_type == macho::N_ABS || entry_type == macho::N_SECT {
entry.n_value.set(
LittleEndian,
entry.n_value.get(NativeEndian) + md.added_byte_count,
);
entry
.n_value
.set(LE, entry.n_value.get(LE) + md.added_byte_count);
}
}
}
macho::LC_DYSYMTAB => {
let cmd = load_struct_inplace_mut::<macho::DysymtabCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::DysymtabCommand<LE>>(&mut out_mmap, offset);
if cmd.ntoc.get(NativeEndian) > 0 {
cmd.tocoff.set(
LittleEndian,
cmd.tocoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.ntoc.get(LE) > 0 {
cmd.tocoff
.set(LE, cmd.tocoff.get(LE) + md.added_byte_count as u32);
}
if cmd.nmodtab.get(NativeEndian) > 0 {
cmd.modtaboff.set(
LittleEndian,
cmd.modtaboff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nmodtab.get(LE) > 0 {
cmd.modtaboff
.set(LE, cmd.modtaboff.get(LE) + md.added_byte_count as u32);
}
if cmd.nextrefsyms.get(NativeEndian) > 0 {
cmd.extrefsymoff.set(
LittleEndian,
cmd.extrefsymoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nextrefsyms.get(LE) > 0 {
cmd.extrefsymoff
.set(LE, cmd.extrefsymoff.get(LE) + md.added_byte_count as u32);
}
if cmd.nindirectsyms.get(NativeEndian) > 0 {
cmd.indirectsymoff.set(
LittleEndian,
cmd.indirectsymoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nindirectsyms.get(LE) > 0 {
cmd.indirectsymoff
.set(LE, cmd.indirectsymoff.get(LE) + md.added_byte_count as u32);
}
if cmd.nextrel.get(NativeEndian) > 0 {
cmd.extreloff.set(
LittleEndian,
cmd.extreloff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nextrel.get(LE) > 0 {
cmd.extreloff
.set(LE, cmd.extreloff.get(LE) + md.added_byte_count as u32);
}
if cmd.nlocrel.get(NativeEndian) > 0 {
cmd.locreloff.set(
LittleEndian,
cmd.locreloff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nlocrel.get(LE) > 0 {
cmd.locreloff
.set(LE, cmd.locreloff.get(LE) + md.added_byte_count as u32);
}
// TODO maybe we need to update something else too - relocations maybe?
@ -889,29 +855,25 @@ fn gen_macho_le(
// Look at otool -I at least for the indirect symbols.
}
macho::LC_TWOLEVEL_HINTS => {
let cmd = load_struct_inplace_mut::<macho::TwolevelHintsCommand<LittleEndian>>(
let cmd = load_struct_inplace_mut::<macho::TwolevelHintsCommand<LE>>(
&mut out_mmap,
offset,
);
if cmd.nhints.get(NativeEndian) > 0 {
cmd.offset.set(
LittleEndian,
cmd.offset.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nhints.get(LE) > 0 {
cmd.offset
.set(LE, cmd.offset.get(LE) + md.added_byte_count as u32);
}
}
macho::LC_FUNCTION_STARTS => {
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LittleEndian>>(
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LE>>(
&mut out_mmap,
offset,
);
if cmd.datasize.get(NativeEndian) > 0 {
cmd.dataoff.set(
LittleEndian,
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.datasize.get(LE) > 0 {
cmd.dataoff
.set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
// TODO: This lists the start of every function. Which, of course, have moved.
// That being said, to my understanding this section is optional and may just be debug information.
// As such, updating it should not be required.
@ -920,36 +882,30 @@ fn gen_macho_le(
}
macho::LC_DATA_IN_CODE => {
let (offset, size) = {
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LittleEndian>>(
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LE>>(
&mut out_mmap,
offset,
);
if cmd.datasize.get(NativeEndian) > 0 {
cmd.dataoff.set(
LittleEndian,
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.datasize.get(LE) > 0 {
cmd.dataoff
.set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
}
(
cmd.dataoff.get(NativeEndian),
cmd.datasize.get(NativeEndian),
)
(cmd.dataoff.get(LE), cmd.datasize.get(LE))
};
// Update every data in code entry.
if size > 0 {
let entry_size = mem::size_of::<macho::DataInCodeEntry<LittleEndian>>();
let entries = load_structs_inplace_mut::<macho::DataInCodeEntry<LittleEndian>>(
let entry_size = mem::size_of::<macho::DataInCodeEntry<LE>>();
let entries = load_structs_inplace_mut::<macho::DataInCodeEntry<LE>>(
&mut out_mmap,
offset as usize,
size as usize / entry_size,
);
for entry in entries.iter_mut() {
entry.offset.set(
LittleEndian,
entry.offset.get(NativeEndian) + md.added_byte_count as u32,
)
entry
.offset
.set(LE, entry.offset.get(LE) + md.added_byte_count as u32)
}
}
}
@ -959,63 +915,49 @@ fn gen_macho_le(
| macho::LC_LINKER_OPTIMIZATION_HINT
| macho::LC_DYLD_EXPORTS_TRIE
| macho::LC_DYLD_CHAINED_FIXUPS => {
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LittleEndian>>(
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LE>>(
&mut out_mmap,
offset,
);
if cmd.datasize.get(NativeEndian) > 0 {
cmd.dataoff.set(
LittleEndian,
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.datasize.get(LE) > 0 {
cmd.dataoff
.set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
}
}
macho::LC_ENCRYPTION_INFO_64 => {
let cmd = load_struct_inplace_mut::<macho::EncryptionInfoCommand64<LittleEndian>>(
let cmd = load_struct_inplace_mut::<macho::EncryptionInfoCommand64<LE>>(
&mut out_mmap,
offset,
);
if cmd.cryptsize.get(NativeEndian) > 0 {
cmd.cryptoff.set(
LittleEndian,
cmd.cryptoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.cryptsize.get(LE) > 0 {
cmd.cryptoff
.set(LE, cmd.cryptoff.get(LE) + md.added_byte_count as u32);
}
}
macho::LC_DYLD_INFO | macho::LC_DYLD_INFO_ONLY => {
let cmd = load_struct_inplace_mut::<macho::DyldInfoCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::DyldInfoCommand<LE>>(&mut out_mmap, offset);
if cmd.rebase_size.get(NativeEndian) > 0 {
cmd.rebase_off.set(
LittleEndian,
cmd.rebase_off.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.rebase_size.get(LE) > 0 {
cmd.rebase_off
.set(LE, cmd.rebase_off.get(LE) + md.added_byte_count as u32);
}
if cmd.bind_size.get(NativeEndian) > 0 {
cmd.bind_off.set(
LittleEndian,
cmd.bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.bind_size.get(LE) > 0 {
cmd.bind_off
.set(LE, cmd.bind_off.get(LE) + md.added_byte_count as u32);
}
if cmd.weak_bind_size.get(NativeEndian) > 0 {
cmd.weak_bind_off.set(
LittleEndian,
cmd.weak_bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.weak_bind_size.get(LE) > 0 {
cmd.weak_bind_off
.set(LE, cmd.weak_bind_off.get(LE) + md.added_byte_count as u32);
}
if cmd.lazy_bind_size.get(NativeEndian) > 0 {
cmd.lazy_bind_off.set(
LittleEndian,
cmd.lazy_bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.lazy_bind_size.get(LE) > 0 {
cmd.lazy_bind_off
.set(LE, cmd.lazy_bind_off.get(LE) + md.added_byte_count as u32);
}
// TODO: Parse and update the related tables here.
@ -1026,40 +968,26 @@ fn gen_macho_le(
// Also `xcrun dyldinfo` is useful for debugging this.
}
macho::LC_SYMSEG => {
let cmd = load_struct_inplace_mut::<macho::SymsegCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::SymsegCommand<LE>>(&mut out_mmap, offset);
if cmd.size.get(NativeEndian) > 0 {
cmd.offset.set(
LittleEndian,
cmd.offset.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.size.get(LE) > 0 {
cmd.offset
.set(LE, cmd.offset.get(LE) + md.added_byte_count as u32);
}
}
macho::LC_MAIN => {
let cmd = load_struct_inplace_mut::<macho::EntryPointCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::EntryPointCommand<LE>>(&mut out_mmap, offset);
cmd.entryoff.set(
LittleEndian,
cmd.entryoff.get(NativeEndian) + md.added_byte_count,
);
cmd.entryoff
.set(LE, cmd.entryoff.get(LE) + md.added_byte_count);
}
macho::LC_NOTE => {
let cmd = load_struct_inplace_mut::<macho::NoteCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd = load_struct_inplace_mut::<macho::NoteCommand<LE>>(&mut out_mmap, offset);
if cmd.size.get(NativeEndian) > 0 {
cmd.offset.set(
LittleEndian,
cmd.offset.get(NativeEndian) + md.added_byte_count,
);
if cmd.size.get(LE) > 0 {
cmd.offset.set(LE, cmd.offset.get(LE) + md.added_byte_count);
}
}
macho::LC_ID_DYLIB
@ -1459,89 +1387,89 @@ fn surgery_macho_help(
// // Load this section (we made room for it earlier) and then mutate all its data to make it the desired command
// {
// let cmd =
// load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LittleEndian>>() as u32;
// load_struct_inplace_mut::<macho::SegmentCommand64<LE >>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LE >>() as u32;
// let size_of_cmd = mem::size_of_val(cmd);
// cmd_offset += size_of_cmd;
// cmd.cmd.set(LittleEndian, macho::LC_SEGMENT_64);
// cmd.cmd.set(LE , macho::LC_SEGMENT_64);
// cmd.cmdsize
// .set(LittleEndian, size_of_section + size_of_cmd as u32);
// .set(LE , size_of_section + size_of_cmd as u32);
// cmd.segname = *b"__DATA_CONST\0\0\0\0";
// cmd.vmaddr
// .set(LittleEndian, new_rodata_section_vaddr as u64);
// .set(LE , new_rodata_section_vaddr as u64);
// cmd.vmsize.set(
// LittleEndian,
// LE ,
// (new_text_section_vaddr - new_rodata_section_vaddr) as u64,
// );
// cmd.fileoff
// .set(LittleEndian, new_rodata_section_offset as u64);
// .set(LE , new_rodata_section_offset as u64);
// cmd.filesize.set(
// LittleEndian,
// LE ,
// (new_text_section_offset - new_rodata_section_offset) as u64,
// );
// cmd.nsects.set(LittleEndian, 1);
// cmd.maxprot.set(LittleEndian, 0x00000003);
// cmd.initprot.set(LittleEndian, 0x00000003);
// cmd.nsects.set(LE , 1);
// cmd.maxprot.set(LE , 0x00000003);
// cmd.initprot.set(LE , 0x00000003);
// // TODO set protection
// }
// {
// let cmd = load_struct_inplace_mut::<macho::Section64<LittleEndian>>(exec_mmap, cmd_offset);
// let cmd = load_struct_inplace_mut::<macho::Section64<LE >>(exec_mmap, cmd_offset);
// let size_of_cmd = mem::size_of_val(cmd);
// cmd_offset += size_of_cmd;
// cmd.sectname = *b"__const\0\0\0\0\0\0\0\0\0";
// cmd.segname = *b"__DATA_CONST\0\0\0\0";
// cmd.addr.set(LittleEndian, new_rodata_section_vaddr as u64);
// cmd.addr.set(LE , new_rodata_section_vaddr as u64);
// cmd.size.set(
// LittleEndian,
// LE ,
// (new_text_section_offset - new_rodata_section_offset) as u64,
// );
// cmd.offset.set(LittleEndian, 0); // TODO is this offset since the start of the file, or segment offset?
// cmd.align.set(LittleEndian, 12); // TODO should this be 4096?
// cmd.reloff.set(LittleEndian, 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// cmd.offset.set(LE , 0); // TODO is this offset since the start of the file, or segment offset?
// cmd.align.set(LE , 12); // TODO should this be 4096?
// cmd.reloff.set(LE , 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// }
// {
// let cmd =
// load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LittleEndian>>() as u32;
// load_struct_inplace_mut::<macho::SegmentCommand64<LE >>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LE >>() as u32;
// let size_of_cmd = mem::size_of_val(cmd);
// cmd_offset += size_of_cmd;
// cmd.cmd.set(LittleEndian, macho::LC_SEGMENT_64);
// cmd.cmd.set(LE , macho::LC_SEGMENT_64);
// cmd.cmdsize
// .set(LittleEndian, size_of_section + size_of_cmd as u32);
// .set(LE , size_of_section + size_of_cmd as u32);
// cmd.segname = *b"__TEXT\0\0\0\0\0\0\0\0\0\0";
// cmd.vmaddr.set(LittleEndian, new_text_section_vaddr as u64);
// cmd.vmaddr.set(LE , new_text_section_vaddr as u64);
// cmd.vmsize
// .set(LittleEndian, (offset - new_text_section_offset) as u64);
// .set(LE , (offset - new_text_section_offset) as u64);
// cmd.fileoff
// .set(LittleEndian, new_text_section_offset as u64);
// .set(LE , new_text_section_offset as u64);
// cmd.filesize
// .set(LittleEndian, (offset - new_text_section_offset) as u64);
// cmd.nsects.set(LittleEndian, 1);
// cmd.maxprot.set(LittleEndian, 0x00000005); // this is what a zig-generated host had
// cmd.initprot.set(LittleEndian, 0x00000005); // this is what a zig-generated host had
// .set(LE , (offset - new_text_section_offset) as u64);
// cmd.nsects.set(LE , 1);
// cmd.maxprot.set(LE , 0x00000005); // this is what a zig-generated host had
// cmd.initprot.set(LE , 0x00000005); // this is what a zig-generated host had
// }
// {
// let cmd = load_struct_inplace_mut::<macho::Section64<LittleEndian>>(exec_mmap, cmd_offset);
// let cmd = load_struct_inplace_mut::<macho::Section64<LE >>(exec_mmap, cmd_offset);
// cmd.segname = *b"__TEXT\0\0\0\0\0\0\0\0\0\0";
// cmd.sectname = *b"__text\0\0\0\0\0\0\0\0\0\0";
// cmd.addr.set(LittleEndian, new_text_section_vaddr as u64);
// cmd.addr.set(LE , new_text_section_vaddr as u64);
// cmd.size
// .set(LittleEndian, (offset - new_text_section_offset) as u64);
// cmd.offset.set(LittleEndian, 0); // TODO is this offset since the start of the file, or segment offset?
// cmd.align.set(LittleEndian, 12); // TODO this is 4096 (2^12) - which load_align_constraint does, above - but should it?
// cmd.flags.set(LittleEndian, 0x80000400); // TODO this is what a zig-generated host had
// cmd.reloff.set(LittleEndian, 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// .set(LE , (offset - new_text_section_offset) as u64);
// cmd.offset.set(LE , 0); // TODO is this offset since the start of the file, or segment offset?
// cmd.align.set(LE , 12); // TODO this is 4096 (2^12) - which load_align_constraint does, above - but should it?
// cmd.flags.set(LE , 0x80000400); // TODO this is what a zig-generated host had
// cmd.reloff.set(LE , 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// }
// Update calls from platform and dynamic symbols.
@ -1618,13 +1546,13 @@ fn surgery_macho_help(
// Commented out because it doesn't apply to mach-o
// if let Some(i) = md.dynamic_symbol_indices.get(func_name) {
// let sym = load_struct_inplace_mut::<elf::Sym64<LittleEndian>>(
// let sym = load_struct_inplace_mut::<elf::Sym64<LE >>(
// exec_mmap,
// dynsym_offset as usize + *i as usize * mem::size_of::<elf::Sym64<LittleEndian>>(),
// dynsym_offset as usize + *i as usize * mem::size_of::<elf::Sym64<LE >>(),
// );
// sym.st_value = endian::U64::new(LittleEndian, func_virt_offset as u64);
// sym.st_value = endian::U64::new(LE , func_virt_offset as u64);
// sym.st_size = endian::U64::new(
// LittleEndian,
// LE ,
// match app_func_size_map.get(func_name) {
// Some(size) => *size,
// None => {