Skip to content

Commit 24bf5cf

Browse files
committed
[WIP] Produce symbol file for gdb in the jit
1 parent 4d0b725 commit 24bf5cf

3 files changed

Lines changed: 123 additions & 4 deletions

File tree

src/debuginfo/unwind.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,17 +257,19 @@ impl UnwindContext {
257257
}
258258

259259
#[cfg(all(feature = "jit", windows))]
260-
pub(crate) unsafe fn register_jit(self, _jit_module: &cranelift_jit::JITModule) {}
260+
pub(crate) unsafe fn register_jit(self, _jit_module: &cranelift_jit::JITModule) -> Vec<u8> {
261+
vec![]
262+
}
261263

262264
#[cfg(all(feature = "jit", not(windows)))]
263-
pub(crate) unsafe fn register_jit(self, jit_module: &cranelift_jit::JITModule) {
265+
pub(crate) unsafe fn register_jit(self, jit_module: &cranelift_jit::JITModule) -> Vec<u8> {
264266
use std::mem::ManuallyDrop;
265267

266268
let mut eh_frame = EhFrame::from(super::emit::WriterRelocate::new(self.endian));
267269
self.frame_table.write_eh_frame(&mut eh_frame).unwrap();
268270

269271
if eh_frame.0.writer.slice().is_empty() {
270-
return;
272+
return vec![];
271273
}
272274

273275
let mut eh_frame = eh_frame.0.relocate_for_jit(jit_module);
@@ -307,6 +309,8 @@ impl UnwindContext {
307309
// On other platforms, `__register_frame` will walk the FDEs until an entry of length 0
308310
unsafe { __register_frame(eh_frame.as_ptr()) };
309311
}
312+
313+
(*eh_frame).clone()
310314
}
311315
}
312316

src/driver/jit.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,8 @@ fn dep_symbol_lookup_fn(
213213
None
214214
})
215215
}
216+
217+
#[unsafe(no_mangle)]
218+
extern "C" fn print_backtrace() {
219+
println!("{:#}", std::backtrace::Backtrace::force_capture());
220+
}

src/unwind_module.rs

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,121 @@ impl UnwindModule<ObjectModule> {
3535
impl UnwindModule<cranelift_jit::JITModule> {
3636
pub(crate) fn finalize_definitions(mut self) -> cranelift_jit::JITModule {
3737
self.module.finalize_definitions().unwrap();
38-
unsafe { self.unwind_context.register_jit(&self.module) };
38+
let eh_frame = unsafe { self.unwind_context.register_jit(&self.module) };
39+
40+
let mut symbol_obj = object::write::Object::new(
41+
object::BinaryFormat::Elf,
42+
object::Architecture::Aarch64,
43+
object::Endianness::Little,
44+
);
45+
let eh_frame_section = symbol_obj.add_section(
46+
vec![],
47+
b".eh_frame".to_vec(),
48+
object::SectionKind::ReadOnlyData,
49+
);
50+
symbol_obj.append_section_data(eh_frame_section, &eh_frame, 1);
51+
52+
let mut lowest_symbol = u64::MAX;
53+
let mut highest_symbol = u64::MIN;
54+
for (func_id, func_decl) in self.module.declarations().get_functions() {
55+
if !func_decl.linkage.is_final() {
56+
continue;
57+
}
58+
let name = func_decl.linkage_name(func_id).into_owned().into_bytes();
59+
let addr = self.module.get_finalized_function(func_id).addr() as u64;
60+
if addr < lowest_symbol {
61+
lowest_symbol = addr;
62+
}
63+
if addr + 1 > highest_symbol {
64+
highest_symbol = addr + 1;
65+
}
66+
symbol_obj.add_symbol(object::write::Symbol {
67+
name,
68+
value: addr,
69+
size: 1,
70+
kind: object::write::SymbolKind::Text,
71+
scope: object::write::SymbolScope::Dynamic,
72+
weak: false,
73+
section: object::write::SymbolSection::Absolute,
74+
flags: object::write::SymbolFlags::None,
75+
});
76+
}
77+
78+
let mut symbol_obj = symbol_obj.write().unwrap();
79+
80+
convert_object_elf_to_loadable_file::<object::LittleEndian>(
81+
&mut symbol_obj,
82+
(lowest_symbol as *const u8, (highest_symbol - lowest_symbol) as usize),
83+
);
84+
85+
std::fs::write("symbols.elf", symbol_obj).unwrap();
86+
87+
/*#[unsafe(no_mangle)]
88+
static mut SYMBOL_OBJECT: *mut u8 = std::ptr::null_mut();
89+
unsafe {
90+
SYMBOL_OBJECT = Vec::leak(symbol_obj).as_mut_ptr();
91+
}*/
92+
3993
self.module
4094
}
4195
}
4296

97+
#[cfg(feature = "jit")]
98+
fn convert_object_elf_to_loadable_file<E: object::Endian>(
99+
bytes: &mut Vec<u8>,
100+
code_region: (*const u8, usize),
101+
) {
102+
use object::elf::{ET_DYN, ET_EXEC, FileHeader64, ProgramHeader64, SectionHeader64};
103+
use object::read::elf::{FileHeader, SectionHeader};
104+
105+
let e = E::default();
106+
107+
let header = FileHeader64::<E>::parse(&bytes[..]).unwrap();
108+
let sections = header.sections(e, &bytes[..]).unwrap();
109+
let text_range = match sections.section_by_name(e, b".text") {
110+
Some((i, text)) => {
111+
let range = text.file_range(e);
112+
let e_shoff = usize::try_from(header.e_shoff.get(e)).unwrap();
113+
let off = e_shoff + i.0 * header.e_shentsize.get(e) as usize;
114+
115+
let section: &mut SectionHeader64<E> =
116+
object::from_bytes_mut(&mut bytes[off..]).unwrap().0;
117+
// Patch vaddr, and save file location and its size.
118+
section.sh_addr.set(e, code_region.0 as u64);
119+
range
120+
}
121+
None => None,
122+
};
123+
124+
// LLDB wants segment with virtual address set, placing them at the end of ELF.
125+
let ph_off = bytes.len();
126+
let e_phentsize = size_of::<ProgramHeader64<E>>();
127+
let mut e_phnum = 1;
128+
bytes.resize(ph_off + e_phentsize * e_phnum, 0);
129+
//if let Some((sh_offset, sh_size)) = text_range {
130+
use object::elf::PT_LOAD;
131+
132+
let (v_offset, size) = code_region;
133+
let program: &mut ProgramHeader64<E> = object::from_bytes_mut(&mut bytes[ph_off..]).unwrap().0;
134+
program.p_type.set(e, PT_LOAD);
135+
program.p_offset.set(e, /*sh_offset*/ 0);
136+
program.p_vaddr.set(e, v_offset as u64);
137+
program.p_paddr.set(e, v_offset as u64);
138+
program.p_filesz.set(e, /*sh_size*/ 0);
139+
program.p_memsz.set(e, size as u64);
140+
/*} else {
141+
//unreachable!();
142+
e_phnum = 0;
143+
}*/
144+
145+
// It is somewhat loadable ELF file at this moment.
146+
let header: &mut FileHeader64<E> = object::from_bytes_mut(bytes).unwrap().0;
147+
header.e_type.set(e, ET_EXEC);
148+
header.e_phoff.set(e, ph_off as u64);
149+
header.e_phentsize.set(e, u16::try_from(e_phentsize).unwrap());
150+
header.e_phnum.set(e, u16::try_from(e_phnum).unwrap());
151+
}
152+
43153
impl<T: Module> Module for UnwindModule<T> {
44154
fn isa(&self) -> &dyn TargetIsa {
45155
self.module.isa()

0 commit comments

Comments
 (0)