Add arch support for LoongArch64#50
Conversation
…tional register storage
…ter handling and streamline assembly code generation
|
related PR discussions for using |
|
Hi there, I have tested the For the bare-metal application tests on [dependencies.unwinding]
path = "../unwinding" # my porting fork for loongarch64
default-features = false
features = ["fde-gnu-eh-frame-hdr", "panic", "personality", "unwinder"]The bare-metal app successfully triggers a panic using src/test.rs // ... ...
pub fn test_panic() {
println!("testing loongarch64 baremetal unwinding...");
panic!("test panic for baremetal application using unwinding library");
}
// ... ...src/panic.rs use core::ffi::c_void;
use gimli::Register;
use unwinding::abi::{
_Unwind_Backtrace, _Unwind_FindEnclosingFunction, _Unwind_GetGR, _Unwind_GetIP, UnwindContext,
UnwindReasonCode,
};
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
unsafe extern "Rust" {
pub fn __panic_handler(info: &core::panic::PanicInfo) -> !;
}
unsafe { __panic_handler(info) }
}
#[unsafe(no_mangle)]
pub fn __panic_handler(info: &core::panic::PanicInfo) -> ! {
println!(
"(__panic_handler) panic at {:?}, reason: {:?}",
info.location().unwrap(),
info.message().as_str().unwrap_or("")
);
print_stack_trace();
println!("halting, now we reach the end of the program");
loop {}
}
pub fn print_stack_trace() {
println!("printing stack trace...");
struct CallbackData {
counter: usize,
}
extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
println!("callback...");
let data = unsafe { &mut *(arg as *mut CallbackData) };
data.counter += 1;
let pc = _Unwind_GetIP(unwind_ctx);
if pc > 0 {
let fde_initial_address = _Unwind_FindEnclosingFunction(pc as *mut c_void) as usize;
println!(
"{:4}: fn {:#18x} - pc {:#18x} / registers:",
data.counter, fde_initial_address, pc,
);
}
// Print the first 8 general registers for any architecture. The register number follows
// the DWARF standard.
for i in 0..8u16 {
let reg_i = _Unwind_GetGR(unwind_ctx, i as i32);
// we are only testing on loongarch64 for now :D
let reg_name = gimli::LoongArch::register_name(Register(i)).unwrap_or("unknown");
if i % 4 == 0 {
print!("\n ");
}
print!(" {} {:#18x};", reg_name, reg_i);
}
print!("\n\n");
UnwindReasonCode::NO_REASON
}
let mut data = CallbackData { counter: 0 };
_Unwind_Backtrace(callback, &mut data as *mut _ as _);
}Test results:
To reproduce this result: # install qemu-system-loongarch64 through package manager or just compile it from official QEMU git repo
# note: ./configure --target-list="loongarch64-softmmu"
git clone https://github.com/enkerewpo/unwinding
git clone https://github.com/enkerewpo/baremetal-loongarch64-unwinding-test
cd baremetal-loongarch64-unwinding-test
./build.sh
./run_qemu.sh |
src/unwinder/arch/loongarch64.rs
Outdated
| " | ||
| st.d $r1, $r3, 0x200 | ||
| ", | ||
| maybe_cfi!(".cfi_offset 1, -16"), // ra |
There was a problem hiding this comment.
Does loongarch assembler not support more friendly names in cfi_offset?
There was a problem hiding this comment.
Have you tried .cfi_offset $ra, -16 (note the $ sign)
|
For the current number of https://github.com/gcc-mirror/gcc/blob/48ef4af2274a0a1ad945ac14217806c1c1d8ccb2/gcc/defaults.h#L409 |
src/unwinder/arch/loongarch64.rs
Outdated
| " | ||
| st.d $r1, $r3, 0x200 | ||
| ", | ||
| maybe_cfi!(".cfi_offset 1, -16"), // ra |
There was a problem hiding this comment.
Have you tried .cfi_offset $ra, -16 (note the $ sign)
|
Starting in LLVM 20, CFI directive can use register names: llvm/llvm-project#117120 |
nbdd0121
left a comment
There was a problem hiding this comment.
Sorry for the late review.. This was completely lost from my radar.
…rity and stack space efficiency.
|
OK :D |
|
Thank you! |







loongarch64assembly codes for unwinding support (https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html)loongarch64target