correctly handle bss section in surgical linker

This commit is contained in:
Brendan Hansknecht 2023-06-02 14:29:49 -07:00
parent 7b8bd988d4
commit 86417a8457
No known key found for this signature in database
GPG key ID: 0EA784685083E75B

View file

@ -603,7 +603,7 @@ fn gen_elf_le(
} }
// Copy header and shift everything to enable more program sections. // Copy header and shift everything to enable more program sections.
let added_header_count = 2; let added_header_count = 3;
md.added_byte_count = ph_ent_size as u64 * added_header_count; md.added_byte_count = ph_ent_size as u64 * added_header_count;
md.added_byte_count = md.added_byte_count md.added_byte_count = md.added_byte_count
+ (MIN_SECTION_ALIGNMENT as u64 - md.added_byte_count % MIN_SECTION_ALIGNMENT as u64); + (MIN_SECTION_ALIGNMENT as u64 - md.added_byte_count % MIN_SECTION_ALIGNMENT as u64);
@ -1278,22 +1278,12 @@ fn surgery_elf_help(
let mut offset = sh_offset as usize; let mut offset = sh_offset as usize;
offset = align_by_constraint(offset, MIN_SECTION_ALIGNMENT); offset = align_by_constraint(offset, MIN_SECTION_ALIGNMENT);
let new_rodata_section_offset = offset;
// Align physical and virtual address of new segment. // Align physical and virtual address of new segment.
let mut virt_offset = align_to_offset_by_constraint( let mut virt_offset = align_to_offset_by_constraint(
md.last_vaddr as usize, md.last_vaddr as usize,
offset, offset,
md.load_align_constraint as usize, md.load_align_constraint as usize,
); );
let new_rodata_section_vaddr = virt_offset;
if verbose {
println!();
println!(
"New Virtual Rodata Section Address: {:+x?}",
new_rodata_section_vaddr
);
}
// First decide on sections locations and then recode every exact symbol locations. // First decide on sections locations and then recode every exact symbol locations.
@ -1375,13 +1365,40 @@ fn surgery_elf_help(
println!("Found App Function Symbols: {:+x?}", app_func_vaddr_map); println!("Found App Function Symbols: {:+x?}", app_func_vaddr_map);
} }
let (new_rodata_section_offset, new_rodata_section_vaddr) = rodata_sections
.iter()
.map(|sec| section_offset_map.get(&sec.index()).unwrap())
.min()
.unwrap();
let (new_rodata_section_offset, new_rodata_section_vaddr) = (
*new_rodata_section_offset as u64,
*new_rodata_section_vaddr as u64,
);
let (new_text_section_offset, new_text_section_vaddr) = text_sections let (new_text_section_offset, new_text_section_vaddr) = text_sections
.iter() .iter()
.map(|sec| section_offset_map.get(&sec.index()).unwrap()) .map(|sec| section_offset_map.get(&sec.index()).unwrap())
.min() .min()
.unwrap(); .unwrap();
let (new_text_section_offset, new_text_section_vaddr) = let (new_text_section_offset, new_text_section_vaddr) = (
(*new_text_section_offset, *new_text_section_vaddr); *new_text_section_offset as u64,
*new_text_section_vaddr as u64,
);
// BSS section is not guaranteed to exist.
// If it doesn't exist, just use the text section offset.
// This will make a bss section of size 0.
let bss_default = (
new_text_section_offset as usize,
new_text_section_vaddr as usize,
);
let (new_bss_section_offset, new_bss_section_vaddr) = bss_sections
.iter()
.map(|sec| section_offset_map.get(&sec.index()).unwrap())
.min()
.unwrap_or(&bss_default);
let (new_bss_section_offset, new_bss_section_vaddr) = (
*new_bss_section_offset as u64,
*new_bss_section_vaddr as u64,
);
// Move data and deal with relocations. // Move data and deal with relocations.
for sec in rodata_sections for sec in rodata_sections
@ -1494,15 +1511,15 @@ fn surgery_elf_help(
// Flush app only data to speed up write to disk. // Flush app only data to speed up write to disk.
exec_mmap exec_mmap
.flush_async_range( .flush_async_range(
new_rodata_section_offset, new_rodata_section_offset as usize,
offset - new_rodata_section_offset, offset - new_rodata_section_offset as usize,
) )
.unwrap_or_else(|e| internal_error!("{}", e)); .unwrap_or_else(|e| internal_error!("{}", e));
// TODO: look into merging symbol tables, debug info, and eh frames to enable better debugger experience. // TODO: look into merging symbol tables, debug info, and eh frames to enable better debugger experience.
// Add 2 new sections and segments. // Add 3 new sections and segments.
let new_section_count = 2; let new_section_count = 3;
offset += new_section_count * sh_ent_size as usize; offset += new_section_count * sh_ent_size as usize;
let section_headers = load_structs_inplace_mut::<elf::SectionHeader64<LE>>( let section_headers = load_structs_inplace_mut::<elf::SectionHeader64<LE>>(
exec_mmap, exec_mmap,
@ -1510,14 +1527,12 @@ fn surgery_elf_help(
sh_num as usize + new_section_count, sh_num as usize + new_section_count,
); );
let new_rodata_section_size = new_text_section_offset as u64 - new_rodata_section_offset as u64; let new_rodata_section_size = new_text_section_offset - new_rodata_section_offset;
let new_rodata_section_virtual_size = let new_bss_section_virtual_size = new_text_section_vaddr - new_bss_section_vaddr;
new_text_section_vaddr as u64 - new_rodata_section_vaddr as u64; let new_text_section_size = new_sh_offset as u64 - new_text_section_offset;
let new_text_section_vaddr = new_rodata_section_vaddr as u64 + new_rodata_section_size;
let new_text_section_size = new_sh_offset as u64 - new_text_section_offset as u64;
// set the new rodata section header // set the new rodata section header
section_headers[section_headers.len() - 2] = elf::SectionHeader64 { section_headers[section_headers.len() - 3] = elf::SectionHeader64 {
sh_name: endian::U32::new(LE, 0), sh_name: endian::U32::new(LE, 0),
sh_type: endian::U32::new(LE, elf::SHT_PROGBITS), sh_type: endian::U32::new(LE, elf::SHT_PROGBITS),
sh_flags: endian::U64::new(LE, elf::SHF_ALLOC as u64), sh_flags: endian::U64::new(LE, elf::SHF_ALLOC as u64),
@ -1530,6 +1545,20 @@ fn surgery_elf_help(
sh_entsize: endian::U64::new(LE, 0), sh_entsize: endian::U64::new(LE, 0),
}; };
// set the new bss section header
section_headers[section_headers.len() - 2] = elf::SectionHeader64 {
sh_name: endian::U32::new(LE, 0),
sh_type: endian::U32::new(LE, elf::SHT_NOBITS),
sh_flags: endian::U64::new(LE, (elf::SHF_ALLOC) as u64),
sh_addr: endian::U64::new(LE, new_bss_section_vaddr),
sh_offset: endian::U64::new(LE, new_bss_section_offset as u64),
sh_size: endian::U64::new(LE, new_bss_section_virtual_size),
sh_link: endian::U32::new(LE, 0),
sh_info: endian::U32::new(LE, 0),
sh_addralign: endian::U64::new(LE, 16),
sh_entsize: endian::U64::new(LE, 0),
};
// set the new text section header // set the new text section header
section_headers[section_headers.len() - 1] = elf::SectionHeader64 { section_headers[section_headers.len() - 1] = elf::SectionHeader64 {
sh_name: endian::U32::new(LE, 0), sh_name: endian::U32::new(LE, 0),
@ -1559,14 +1588,26 @@ fn surgery_elf_help(
); );
// set the new rodata section program header // set the new rodata section program header
program_headers[program_headers.len() - 2] = elf::ProgramHeader64 { program_headers[program_headers.len() - 3] = elf::ProgramHeader64 {
p_type: endian::U32::new(LE, elf::PT_LOAD), p_type: endian::U32::new(LE, elf::PT_LOAD),
p_flags: endian::U32::new(LE, elf::PF_R), p_flags: endian::U32::new(LE, elf::PF_R),
p_offset: endian::U64::new(LE, new_rodata_section_offset as u64), p_offset: endian::U64::new(LE, new_rodata_section_offset as u64),
p_vaddr: endian::U64::new(LE, new_rodata_section_vaddr as u64), p_vaddr: endian::U64::new(LE, new_rodata_section_vaddr as u64),
p_paddr: endian::U64::new(LE, new_rodata_section_vaddr as u64), p_paddr: endian::U64::new(LE, new_rodata_section_vaddr as u64),
p_filesz: endian::U64::new(LE, new_rodata_section_size), p_filesz: endian::U64::new(LE, new_rodata_section_size),
p_memsz: endian::U64::new(LE, new_rodata_section_virtual_size), p_memsz: endian::U64::new(LE, new_rodata_section_size),
p_align: endian::U64::new(LE, md.load_align_constraint),
};
// set the new bss section program header
program_headers[program_headers.len() - 2] = elf::ProgramHeader64 {
p_type: endian::U32::new(LE, elf::PT_LOAD),
p_flags: endian::U32::new(LE, elf::PF_R | elf::PF_W),
p_offset: endian::U64::new(LE, new_bss_section_offset as u64),
p_vaddr: endian::U64::new(LE, new_bss_section_vaddr as u64),
p_paddr: endian::U64::new(LE, new_bss_section_vaddr as u64),
p_filesz: endian::U64::new(LE, 0),
p_memsz: endian::U64::new(LE, new_bss_section_virtual_size),
p_align: endian::U64::new(LE, md.load_align_constraint), p_align: endian::U64::new(LE, md.load_align_constraint),
}; };