Skip to content

Commit 3b90740

Browse files
authored
Merge pull request #25 from philipc/gimli
Update gimli to 0.17.0
2 parents 1813bf0 + f5fbf20 commit 3b90740

File tree

9 files changed

+99
-104
lines changed

9 files changed

+99
-104
lines changed

unwind/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
authors = ["main() <[email protected]>"]
55

66
[dependencies]
7-
gimli = "0.16.1"
7+
gimli = "0.17"
88
libc = "0.2"
99
fallible-iterator = "0.1"
1010
log = "0.4"
@@ -18,3 +18,4 @@ env_logger = "0.6"
1818

1919
[features]
2020
nightly = []
21+
asm = ["nightly"]

unwind/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ extern crate gcc;
22
use std::env;
33

44
fn main() {
5-
match env::var("CARGO_FEATURE_NIGHTLY") {
5+
match env::var("CARGO_FEATURE_ASM") {
66
Err(env::VarError::NotPresent) => {
77
gcc::Build::new()
88
.file("src/unwind_helper.c")

unwind/src/find_cfi/baremetal.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,20 @@ pub fn find_cfi_sections() -> Vec<EhRef> {
1414
unsafe {
1515
// Safety: None of those are actual accesses - we only get the address
1616
// of those values.
17-
let text_start = &__text_start as *const _ as u64;
18-
let text_end = &__text_end as *const _ as u64;
19-
let cfi_start = &__ehframehdr_start as *const _ as u64;
20-
let cfi_end = &__ehframehdr_end as *const _ as u64;
21-
let ehframe_end = &__ehframe_end as *const _ as u64;
17+
let text = AddrRange {
18+
start: &__text_start as *const _ as u64,
19+
end: &__text_end as *const _ as u64,
20+
};
21+
let eh_frame_hdr = AddrRange {
22+
start: &__ehframehdr_start as *const _ as u64,
23+
end: &__ehframehdr_end as *const _ as u64,
24+
};
25+
let eh_frame_end = &__ehframe_end as *const _ as u64;
2226

2327
cfi.push(EhRef {
24-
obj_base: 0,
25-
text: AddrRange { start: text_start, end: text_end },
26-
cfi: AddrRange { start: cfi_start, end: cfi_end },
27-
ehframe_end,
28+
text,
29+
eh_frame_hdr,
30+
eh_frame_end,
2831
});
2932
}
3033
trace!("CFI sections: {:?}", cfi);

unwind/src/find_cfi/ld.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,17 @@ extern "C" fn callback(info: *const DlPhdrInfo, size: usize, data: *mut c_void)
5858
let phdr = slice::from_raw_parts((*info).phdr, (*info).phnum as usize);
5959

6060
if let Some(text) = phdr.iter().filter(|x| x.type_ == PT_LOAD && x.flags & PF_X != 0).next() {
61-
if let Some(eh_frame) = phdr.iter().filter(|x| x.type_ == PT_GNU_EH_FRAME).next() {
61+
if let Some(eh_frame_hdr) = phdr.iter().filter(|x| x.type_ == PT_GNU_EH_FRAME).next() {
6262
let start_addr = (*info).addr + text.vaddr;
63-
let cfi_start = (*info).addr + eh_frame.vaddr;
63+
let eh_frame_hdr_start = (*info).addr + eh_frame_hdr.vaddr;
6464
let max_vaddr = phdr.iter().filter(|x| x.type_ == PT_LOAD)
6565
.fold(0, |vaddr, x| cmp::max(vaddr, x.vaddr + x.memsz));
6666
// This is an upper bound, not the exact address.
67-
let ehframe_end = (*info).addr + max_vaddr;
67+
let eh_frame_end = (*info).addr + max_vaddr;
6868
(*data).push(EhRef {
69-
obj_base: (*info).addr,
7069
text: AddrRange { start: start_addr, end: start_addr + text.memsz },
71-
cfi: AddrRange { start: cfi_start, end: cfi_start + eh_frame.memsz },
72-
ehframe_end,
70+
eh_frame_hdr: AddrRange { start: eh_frame_hdr_start, end: eh_frame_hdr_start + eh_frame_hdr.memsz },
71+
eh_frame_end,
7372
});
7473
}
7574
}

unwind/src/find_cfi/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ use range::AddrRange;
22

33
#[derive(Debug)]
44
pub struct EhRef {
5-
pub obj_base: u64,
65
pub text: AddrRange,
7-
pub cfi: AddrRange,
8-
pub ehframe_end: u64,
6+
pub eh_frame_hdr: AddrRange,
7+
pub eh_frame_end: u64,
98
}
109

1110
#[cfg(unix)]

unwind/src/glue.rs

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1+
use gimli::X86_64;
12
use super::{UnwindPayload, StackFrames};
2-
use registers::{Registers, DwarfRegister};
3+
use registers::Registers;
34

45
#[allow(improper_ctypes)] // trampoline just forwards the ptr
56
extern "C" {
6-
#[cfg(not(feature = "nightly"))]
7+
#[cfg(not(feature = "asm"))]
78
pub fn unwind_trampoline(payload: *mut UnwindPayload);
8-
#[cfg(not(feature = "nightly"))]
9+
#[cfg(not(feature = "asm"))]
910
fn unwind_lander(regs: *const LandingRegisters);
1011
}
1112

12-
#[cfg(feature = "nightly")]
13+
#[cfg(feature = "asm")]
1314
#[naked]
1415
pub unsafe extern fn unwind_trampoline(_payload: *mut UnwindPayload) {
1516
asm!("
@@ -33,7 +34,7 @@ pub unsafe extern fn unwind_trampoline(_payload: *mut UnwindPayload) {
3334
::std::hint::unreachable_unchecked();
3435
}
3536

36-
#[cfg(feature = "nightly")]
37+
#[cfg(feature = "asm")]
3738
#[naked]
3839
unsafe extern fn unwind_lander(_regs: *const LandingRegisters) {
3940
asm!("
@@ -96,14 +97,14 @@ pub unsafe extern "C" fn unwind_recorder(payload: *mut UnwindPayload, stack: u64
9697
let saved_regs = &*saved_regs;
9798

9899
let mut registers = Registers::default();
99-
registers[DwarfRegister::Rbx] = Some(saved_regs.rbx);
100-
registers[DwarfRegister::Rbp] = Some(saved_regs.rbp);
101-
registers[DwarfRegister::SP] = Some(stack + 8);
102-
registers[DwarfRegister::R12] = Some(saved_regs.r12);
103-
registers[DwarfRegister::R13] = Some(saved_regs.r13);
104-
registers[DwarfRegister::R14] = Some(saved_regs.r14);
105-
registers[DwarfRegister::R15] = Some(saved_regs.r15);
106-
registers[DwarfRegister::IP] = Some(*(stack as *const u64));
100+
registers[X86_64::RBX] = Some(saved_regs.rbx);
101+
registers[X86_64::RBP] = Some(saved_regs.rbp);
102+
registers[X86_64::RSP] = Some(stack + 8);
103+
registers[X86_64::R12] = Some(saved_regs.r12);
104+
registers[X86_64::R13] = Some(saved_regs.r13);
105+
registers[X86_64::R14] = Some(saved_regs.r14);
106+
registers[X86_64::R15] = Some(saved_regs.r15);
107+
registers[X86_64::RA] = Some(*(stack as *const u64));
107108

108109
let mut frames = StackFrames {
109110
unwinder: payload.unwinder,
@@ -116,24 +117,24 @@ pub unsafe extern "C" fn unwind_recorder(payload: *mut UnwindPayload, stack: u64
116117

117118
pub unsafe fn land(regs: &Registers) {
118119
let mut lr = LandingRegisters {
119-
rax: regs[DwarfRegister::Rax].unwrap_or(0),
120-
rbx: regs[DwarfRegister::Rbx].unwrap_or(0),
121-
rcx: regs[DwarfRegister::Rcx].unwrap_or(0),
122-
rdx: regs[DwarfRegister::Rdx].unwrap_or(0),
123-
rdi: regs[DwarfRegister::Rdi].unwrap_or(0),
124-
rsi: regs[DwarfRegister::Rsi].unwrap_or(0),
125-
rbp: regs[DwarfRegister::Rbp].unwrap_or(0),
126-
r8: regs[DwarfRegister::R8 ].unwrap_or(0),
127-
r9: regs[DwarfRegister::R9 ].unwrap_or(0),
128-
r10: regs[DwarfRegister::R10].unwrap_or(0),
129-
r11: regs[DwarfRegister::R11].unwrap_or(0),
130-
r12: regs[DwarfRegister::R12].unwrap_or(0),
131-
r13: regs[DwarfRegister::R13].unwrap_or(0),
132-
r14: regs[DwarfRegister::R14].unwrap_or(0),
133-
r15: regs[DwarfRegister::R15].unwrap_or(0),
134-
rsp: regs[DwarfRegister::SP].unwrap(),
120+
rax: regs[X86_64::RAX].unwrap_or(0),
121+
rbx: regs[X86_64::RBX].unwrap_or(0),
122+
rcx: regs[X86_64::RCX].unwrap_or(0),
123+
rdx: regs[X86_64::RDX].unwrap_or(0),
124+
rdi: regs[X86_64::RDI].unwrap_or(0),
125+
rsi: regs[X86_64::RSI].unwrap_or(0),
126+
rbp: regs[X86_64::RBP].unwrap_or(0),
127+
r8: regs[X86_64::R8 ].unwrap_or(0),
128+
r9: regs[X86_64::R9 ].unwrap_or(0),
129+
r10: regs[X86_64::R10].unwrap_or(0),
130+
r11: regs[X86_64::R11].unwrap_or(0),
131+
r12: regs[X86_64::R12].unwrap_or(0),
132+
r13: regs[X86_64::R13].unwrap_or(0),
133+
r14: regs[X86_64::R14].unwrap_or(0),
134+
r15: regs[X86_64::R15].unwrap_or(0),
135+
rsp: regs[X86_64::RSP].unwrap(),
135136
};
136137
lr.rsp -= 8;
137-
*(lr.rsp as *mut u64) = regs[DwarfRegister::IP].unwrap();
138+
*(lr.rsp as *mut u64) = regs[X86_64::RA].unwrap();
138139
unwind_lander(&lr);
139140
}

unwind/src/lib.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
#![cfg_attr(feature = "nightly", feature(asm, naked_functions))]
1+
#![cfg_attr(feature = "nightly", feature(unwind_attributes))]
2+
#![cfg_attr(feature = "asm", feature(asm, naked_functions))]
23

34
extern crate gimli;
45
extern crate libc;
56
extern crate fallible_iterator;
67
#[macro_use] extern crate log;
78

8-
use gimli::{UnwindSection, UnwindTable, UnwindTableRow, EhFrame, BaseAddresses, UninitializedUnwindContext, Pointer, Reader, EndianSlice, NativeEndian, CfaRule, RegisterRule, EhFrameHdr, ParsedEhFrameHdr};
9+
use gimli::{UnwindSection, UnwindTable, UnwindTableRow, EhFrame, BaseAddresses, UninitializedUnwindContext, Pointer, Reader, EndianSlice, NativeEndian, CfaRule, RegisterRule, EhFrameHdr, ParsedEhFrameHdr, X86_64};
910
use fallible_iterator::FallibleIterator;
1011

1112
mod registers;
1213
mod find_cfi;
1314
mod range;
1415
pub mod libunwind_shim;
1516
pub mod glue;
16-
use registers::{Registers, DwarfRegister};
17+
use registers::Registers;
1718
use find_cfi::EhRef;
1819

1920

@@ -28,7 +29,6 @@ pub struct StackFrame {
2829
personality: Option<u64>,
2930
lsda: Option<u64>,
3031
initial_address: u64,
31-
pub object_base: u64, // FIXME hack, remove this
3232
}
3333

3434
pub trait Unwinder: Default {
@@ -53,20 +53,23 @@ impl Default for DwarfUnwinder {
5353
fn default() -> DwarfUnwinder {
5454
let cfi = find_cfi::find_cfi_sections().into_iter().map(|er| {
5555
unsafe {
56-
let bases = BaseAddresses::default().set_cfi(er.cfi.start);
56+
// TODO: set_got()
57+
let bases = BaseAddresses::default()
58+
.set_eh_frame_hdr(er.eh_frame_hdr.start)
59+
.set_text(er.text.start);
5760

58-
let eh_frame_hdr: &'static [u8] = std::slice::from_raw_parts(er.cfi.start as *const u8, er.cfi.len() as usize);
61+
let eh_frame_hdr: &'static [u8] = std::slice::from_raw_parts(er.eh_frame_hdr.start as *const u8, er.eh_frame_hdr.len() as usize);
5962

6063
let eh_frame_hdr = EhFrameHdr::new(eh_frame_hdr, NativeEndian).parse(&bases, 8).unwrap();
6164

62-
let cfi_addr = deref_ptr(eh_frame_hdr.eh_frame_ptr());
63-
let cfi_sz = er.ehframe_end.saturating_sub(cfi_addr);
65+
let eh_frame_addr = deref_ptr(eh_frame_hdr.eh_frame_ptr());
66+
let eh_frame_sz = er.eh_frame_end.saturating_sub(eh_frame_addr);
6467

65-
let eh_frame: &'static [u8] = std::slice::from_raw_parts(cfi_addr as *const u8, cfi_sz as usize);
66-
trace!("cfi at {:p} sz {:x}", cfi_addr as *const u8, cfi_sz);
68+
let eh_frame: &'static [u8] = std::slice::from_raw_parts(eh_frame_addr as *const u8, eh_frame_sz as usize);
69+
trace!("eh_frame at {:p} sz {:x}", eh_frame_addr as *const u8, eh_frame_sz);
6770
let eh_frame = EhFrame::new(eh_frame, NativeEndian);
6871

69-
let bases = bases.set_cfi(cfi_addr).set_data(er.cfi.start);
72+
let bases = bases.set_eh_frame(eh_frame_addr);
7073

7174
ObjectRecord { er, eh_frame_hdr, eh_frame, bases }
7275
}
@@ -167,10 +170,10 @@ impl<'a> FallibleIterator for StackFrames<'a> {
167170

168171
if let Some((row, cfa)) = self.state.take() {
169172
let mut newregs = registers.clone();
170-
newregs[DwarfRegister::IP] = None;
173+
newregs[X86_64::RA] = None;
171174
for &(reg, ref rule) in row.registers() {
172-
trace!("rule {} {:?}", reg, rule);
173-
assert!(reg != 7); // stack = cfa
175+
trace!("rule {:?} {:?}", reg, rule);
176+
assert!(reg != X86_64::RSP); // stack = cfa
174177
newregs[reg] = match *rule {
175178
RegisterRule::Undefined => unreachable!(), // registers[reg],
176179
RegisterRule::SameValue => Some(registers[reg].unwrap()), // not sure why this exists
@@ -189,7 +192,7 @@ impl<'a> FallibleIterator for StackFrames<'a> {
189192
}
190193

191194

192-
if let Some(mut caller) = registers[DwarfRegister::IP] {
195+
if let Some(mut caller) = registers[X86_64::RA] {
193196
caller -= 1; // THIS IS NECESSARY
194197
debug!("caller is 0x{:x}", caller);
195198

@@ -210,7 +213,6 @@ impl<'a> FallibleIterator for StackFrames<'a> {
210213
self.state = Some((row, cfa));
211214

212215
Ok(Some(StackFrame {
213-
object_base: rec.er.obj_base,
214216
personality: personality.map(|x| unsafe { deref_ptr(x) }),
215217
lsda: lsda.map(|x| unsafe { deref_ptr(x) }),
216218
initial_address,

unwind/src/libunwind_shim.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
use libc::{c_void, c_int};
44
use fallible_iterator::FallibleIterator;
5+
use gimli::X86_64;
56

6-
use registers::{Registers, DwarfRegister};
7+
use registers::Registers;
78
use super::{DwarfUnwinder, Unwinder};
89

910
#[repr(C)]
@@ -53,6 +54,8 @@ pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c
5354
-> _Unwind_Reason_Code;
5455
type PersonalityRoutine = extern "C" fn(version: c_int, actions: c_int, class: u64, object: *mut _Unwind_Exception, context: *mut _Unwind_Context) -> _Unwind_Reason_Code;
5556

57+
// FIXME: we skip over this function when unwinding, so we should ensure
58+
// it never needs any cleanup. Currently this is not true.
5659
#[no_mangle]
5760
pub unsafe extern "C" fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> ! {
5861
DwarfUnwinder::default().trace(|frames| unwind_tracer(frames, exception));
@@ -87,12 +90,12 @@ pub unsafe extern "C" fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Conte
8790

8891
#[no_mangle]
8992
pub unsafe extern "C" fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
90-
(*(*ctx).registers)[reg_index as u8] = Some(value as u64);
93+
(*(*ctx).registers)[reg_index as u16] = Some(value as u64);
9194
}
9295

9396
#[no_mangle]
9497
pub unsafe extern "C" fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word) {
95-
(*(*ctx).registers)[DwarfRegister::IP] = Some(value as u64);
98+
(*(*ctx).registers)[X86_64::RA] = Some(value as u64);
9699
}
97100

98101
#[no_mangle]
@@ -107,6 +110,13 @@ pub unsafe extern "C" fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut
107110
pc // FIXME: implement this
108111
}
109112

113+
// FIXME: Set `unwind(allowed)` because we need to be able to unwind this function as
114+
// part of its operation. But this means any panics in this function are undefined
115+
// behaviour, and we don't currently ensure it doesn't panic.
116+
//
117+
// On stable (1.32), `unwind(allowed)` is the default, but this will change in 1.33, with
118+
// no stable way of setting `unwind(allowed)`, so this function will always abort in 1.33.
119+
#[cfg_attr(feature = "nightly", unwind(allowed))]
110120
#[no_mangle]
111121
pub unsafe extern "C" fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
112122
(*exception).private_contptr = None;
@@ -118,7 +128,7 @@ unsafe fn unwind_tracer(frames: &mut ::StackFrames, exception: *mut _Unwind_Exce
118128
if let Some(contptr) = (*exception).private_contptr {
119129
loop {
120130
if let Some(frame) = frames.next().unwrap() {
121-
if frames.registers()[DwarfRegister::SP].unwrap() == contptr {
131+
if frames.registers()[X86_64::RSP].unwrap() == contptr {
122132
break;
123133
}
124134
} else {
@@ -134,12 +144,12 @@ unsafe fn unwind_tracer(frames: &mut ::StackFrames, exception: *mut _Unwind_Exce
134144

135145
let mut ctx = _Unwind_Context {
136146
lsda: frame.lsda.unwrap(),
137-
ip: frames.registers()[DwarfRegister::IP].unwrap(),
147+
ip: frames.registers()[X86_64::RA].unwrap(),
138148
initial_address: frame.initial_address,
139149
registers: frames.registers(),
140150
};
141151

142-
(*exception).private_contptr = frames.registers()[DwarfRegister::SP];
152+
(*exception).private_contptr = frames.registers()[X86_64::RSP];
143153

144154
// ABI specifies that phase 1 is optional, so we just run phase 2 (CLEANUP_PHASE)
145155
match personality(1, _Unwind_Action::_UA_CLEANUP_PHASE as c_int, (*exception).exception_class,
@@ -160,7 +170,7 @@ pub unsafe extern "C" fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
160170
while let Some(frame) = frames.next().unwrap() {
161171
let mut ctx = _Unwind_Context {
162172
lsda: frame.lsda.unwrap_or(0),
163-
ip: frames.registers()[DwarfRegister::IP].unwrap(),
173+
ip: frames.registers()[X86_64::RA].unwrap(),
164174
initial_address: frame.initial_address,
165175
registers: frames.registers(),
166176
};

0 commit comments

Comments
 (0)