Add basic elf relocation handling

This commit is contained in:
Brendan Hansknecht 2020-11-18 23:50:42 -08:00
parent 2b6039d683
commit a4b823a269

View File

@ -1,9 +1,11 @@
use crate::x86_64::X86_64Backend;
use crate::{Backend, Env};
use crate::{Backend, Env, Relocation};
use bumpalo::collections::Vec;
use object::write;
use object::write::{Object, StandardSection, Symbol, SymbolSection};
use object::{
Architecture, BinaryFormat, Endianness, SectionKind, SymbolFlags, SymbolKind, SymbolScope,
Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind,
SymbolFlags, SymbolKind, SymbolScope,
};
use roc_collections::all::MutMap;
use roc_module::symbol;
@ -23,6 +25,7 @@ pub fn build_module<'a>(
let mut output =
Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little);
let text = output.section_id(StandardSection::Text);
let data_section = output.section_id(StandardSection::Data);
let comment = output.add_section(vec![], b"comment".to_vec(), SectionKind::OtherString);
output.append_section_data(
comment,
@ -55,15 +58,75 @@ pub fn build_module<'a>(
flags: SymbolFlags::None,
};
let proc_id = output.add_symbol(proc_symbol);
procs.push((proc_id, proc));
procs.push((fn_name, proc_id, proc));
}
// Build procedures.
let mut backend: X86_64Backend = Backend::new(env, target)?;
for (proc_id, proc) in procs {
let (proc_data, _relocations) = backend.build_proc(proc)?;
// TODO: handle relocations.
output.add_symbol_data(proc_id, text, proc_data, 16);
let mut local_data_index = 0;
for (fn_name, proc_id, proc) in procs {
let (proc_data, relocations) = backend.build_proc(proc)?;
let proc_offset = output.add_symbol_data(proc_id, text, proc_data, 16);
for reloc in relocations {
let elfreloc = match reloc {
Relocation::LocalData { offset, data } => {
let data_symbol = write::Symbol {
name: format!("{}.data{}", fn_name, local_data_index)
.as_bytes()
.to_vec(),
value: 0,
size: 0,
kind: SymbolKind::Data,
scope: SymbolScope::Compilation,
weak: false,
section: write::SymbolSection::Section(data_section),
flags: SymbolFlags::None,
};
local_data_index += 1;
let data_id = output.add_symbol(data_symbol);
output.add_symbol_data(data_id, data_section, data, 4);
write::Relocation {
offset: *offset + proc_offset,
size: 32,
kind: RelocationKind::Relative,
encoding: RelocationEncoding::Generic,
symbol: data_id,
addend: -4,
}
}
Relocation::LinkedData { offset, name } => {
if let Some(sym_id) = output.symbol_id(name.as_bytes()) {
write::Relocation {
offset: *offset + proc_offset,
size: 32,
kind: RelocationKind::GotRelative,
encoding: RelocationEncoding::Generic,
symbol: sym_id,
addend: -4,
}
} else {
return Err(format!("failed to find symbol for {:?}", name));
}
}
Relocation::LinkedFunction { offset, name } => {
if let Some(sym_id) = output.symbol_id(name.as_bytes()) {
write::Relocation {
offset: *offset + proc_offset,
size: 32,
kind: RelocationKind::PltRelative,
encoding: RelocationEncoding::Generic,
symbol: sym_id,
addend: -4,
}
} else {
return Err(format!("failed to find symbol for {:?}", name));
}
}
};
output
.add_relocation(text, elfreloc)
.map_err(|e| format!("{:?}", e))?;
}
}
Ok(output)
}