mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
211 lines
6.2 KiB
Rust
211 lines
6.2 KiB
Rust
use object::{elf, Endianness};
|
|
|
|
use crate::pe::next_multiple_of;
|
|
|
|
pub fn create_dylib_elf64(custom_names: &[String]) -> object::read::Result<Vec<u8>> {
|
|
let endian = Endianness::Little;
|
|
|
|
let mut out_data = Vec::new();
|
|
let mut writer = object::write::elf::Writer::new(endian, true, &mut out_data);
|
|
|
|
const DYNAMIC_SECTION_INDEX: usize = 2;
|
|
|
|
let out_sections_index = [
|
|
writer.reserve_dynsym_section_index(),
|
|
writer.reserve_dynstr_section_index(),
|
|
writer.reserve_dynamic_section_index(),
|
|
writer.reserve_strtab_section_index(),
|
|
writer.reserve_shstrtab_section_index(),
|
|
];
|
|
|
|
// we need this later, but must allocate it here
|
|
let soname = writer.add_dynamic_string(b"libapp.so");
|
|
|
|
// Assign dynamic symbol indices.
|
|
let out_dynsyms: Vec<_> = custom_names
|
|
.iter()
|
|
.map(|name| {
|
|
(
|
|
writer.reserve_dynamic_symbol_index(),
|
|
writer.add_dynamic_string(name.as_bytes()),
|
|
)
|
|
})
|
|
.collect();
|
|
|
|
writer.reserve_file_header();
|
|
|
|
const PLACEHOLDER: u64 = 0xAAAAAAAAAAAAAAAA;
|
|
let mut program_headers = [
|
|
object::write::elf::ProgramHeader {
|
|
p_type: object::elf::PT_PHDR,
|
|
p_flags: object::elf::PF_R,
|
|
p_offset: 0x40,
|
|
p_vaddr: 0x40,
|
|
p_paddr: 0x40,
|
|
p_filesz: 0x188,
|
|
p_memsz: 0x188,
|
|
p_align: 1 << 3,
|
|
},
|
|
object::write::elf::ProgramHeader {
|
|
p_type: object::elf::PT_LOAD,
|
|
p_flags: object::elf::PF_R | object::elf::PF_W,
|
|
p_offset: PLACEHOLDER,
|
|
p_vaddr: PLACEHOLDER,
|
|
p_paddr: PLACEHOLDER,
|
|
p_filesz: PLACEHOLDER,
|
|
p_memsz: PLACEHOLDER,
|
|
p_align: 1 << 12,
|
|
},
|
|
object::write::elf::ProgramHeader {
|
|
p_type: object::elf::PT_DYNAMIC,
|
|
p_flags: object::elf::PF_R | object::elf::PF_W,
|
|
p_offset: PLACEHOLDER,
|
|
p_vaddr: PLACEHOLDER,
|
|
p_paddr: PLACEHOLDER,
|
|
p_filesz: PLACEHOLDER,
|
|
p_memsz: PLACEHOLDER,
|
|
p_align: 1 << 3,
|
|
},
|
|
object::write::elf::ProgramHeader {
|
|
p_type: object::elf::PT_GNU_RELRO,
|
|
p_flags: object::elf::PF_R,
|
|
p_offset: PLACEHOLDER,
|
|
p_vaddr: PLACEHOLDER,
|
|
p_paddr: PLACEHOLDER,
|
|
p_filesz: PLACEHOLDER,
|
|
p_memsz: PLACEHOLDER,
|
|
p_align: 1 << 1,
|
|
},
|
|
object::write::elf::ProgramHeader {
|
|
p_type: object::elf::PT_GNU_STACK,
|
|
p_flags: object::elf::PF_R,
|
|
p_offset: 0,
|
|
p_vaddr: 0,
|
|
p_paddr: 0,
|
|
p_filesz: 0,
|
|
p_memsz: 0,
|
|
p_align: 0,
|
|
},
|
|
];
|
|
|
|
writer.reserve_program_headers(program_headers.len() as u32);
|
|
|
|
let dynsym_address = writer.reserved_len();
|
|
writer.reserve_dynsym();
|
|
|
|
let dynstr_address = writer.reserved_len();
|
|
writer.reserve_dynstr();
|
|
|
|
let out_dynamic = [
|
|
(elf::DT_SONAME, 1, Some(soname)),
|
|
(elf::DT_SYMTAB, dynsym_address as u64, None),
|
|
(elf::DT_STRTAB, dynstr_address as u64, None),
|
|
(elf::DT_NULL, 0, None),
|
|
];
|
|
|
|
let dyn_size = std::mem::size_of::<elf::Dyn64<Endianness>>() * out_dynamic.len();
|
|
|
|
// aligned to the next multiple of 8
|
|
let dynamic_address = next_multiple_of(writer.reserved_len(), 8);
|
|
writer.reserve_dynamic(out_dynamic.len());
|
|
|
|
writer.reserve_strtab();
|
|
writer.reserve_shstrtab();
|
|
|
|
writer.reserve_section_headers();
|
|
|
|
// just enough program header info to satisfy the dynamic loader
|
|
for program_header in program_headers.iter_mut() {
|
|
match program_header.p_type {
|
|
elf::PT_LOAD | elf::PT_DYNAMIC | elf::PT_GNU_RELRO => {
|
|
program_header.p_offset = dynamic_address as u64;
|
|
program_header.p_vaddr = dynamic_address as u64 + 0x1000;
|
|
program_header.p_paddr = dynamic_address as u64 + 0x1000;
|
|
|
|
// this puts the dynamic section inside of the segments, so
|
|
//
|
|
// Section to Segment mapping:
|
|
// Segment Sections...
|
|
// 00
|
|
// 01 .dynamic
|
|
// 02 .dynamic
|
|
// 03 .dynamic
|
|
// 04
|
|
program_header.p_filesz = dyn_size as u64;
|
|
program_header.p_memsz = dyn_size as u64;
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
// WRITING SECTION CONTENT
|
|
|
|
writer
|
|
.write_file_header(&object::write::elf::FileHeader {
|
|
os_abi: 0,
|
|
abi_version: 0,
|
|
e_type: 3,
|
|
e_machine: 62,
|
|
e_entry: 0x1000,
|
|
e_flags: 0,
|
|
})
|
|
.unwrap();
|
|
|
|
{
|
|
writer.write_align_program_headers();
|
|
|
|
for header in program_headers {
|
|
writer.write_program_header(&header);
|
|
}
|
|
}
|
|
|
|
// dynsym content
|
|
{
|
|
writer.write_null_dynamic_symbol();
|
|
for (_index, name) in out_dynsyms {
|
|
writer.write_dynamic_symbol(&object::write::elf::Sym {
|
|
name: Some(name),
|
|
section: Some(out_sections_index[DYNAMIC_SECTION_INDEX]),
|
|
st_info: (elf::STB_GLOBAL << 4) | elf::STT_FUNC,
|
|
st_other: 0,
|
|
st_shndx: 0,
|
|
st_value: 0x1000,
|
|
st_size: 0,
|
|
});
|
|
}
|
|
}
|
|
|
|
// dynstr content
|
|
writer.write_dynstr();
|
|
|
|
// dynamic content
|
|
writer.write_align_dynamic();
|
|
for (tag, val, opt_string) in out_dynamic {
|
|
if let Some(string) = opt_string {
|
|
writer.write_dynamic_string(tag, string);
|
|
} else {
|
|
writer.write_dynamic(tag, val);
|
|
}
|
|
}
|
|
|
|
// strtab content
|
|
writer.write_strtab();
|
|
writer.write_shstrtab();
|
|
|
|
// SECTION HEADERS
|
|
|
|
writer.write_null_section_header();
|
|
|
|
writer.write_dynsym_section_header(dynsym_address as _, 1);
|
|
|
|
writer.write_dynstr_section_header(dynstr_address as _);
|
|
|
|
writer.write_dynamic_section_header(dynamic_address as u64 + 0x1000);
|
|
|
|
writer.write_strtab_section_header();
|
|
writer.write_shstrtab_section_header();
|
|
|
|
debug_assert_eq!(writer.reserved_len(), writer.len());
|
|
|
|
Ok(out_data)
|
|
}
|