-
Notifications
You must be signed in to change notification settings - Fork 201
Refactor unwind; add FDE support. #1320
Refactor unwind; add FDE support. #1320
Conversation
29b824e
to
58046ee
Compare
038bb20
to
dd0f8b0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
I think some tests for fde.rs
might be warranted to test the FDE data emission.
I also think a follow-up PR to make test_unwind.rs
more generic so that it supports FDE generation in addition to Windows unwind information would be ideal. That would enable us to author some clif-based tests for checking the FDE data for non-fastcall functions.
4a70f72
to
fc09d34
Compare
Yeah, currently I added "test_fde.rs" -- it will match how wasmtime will use the functionality, by using FrameUnwindKind parameter. |
👍 I think in a future PR we might want to unify the I feel that |
Co-Authored-By: Philip Craig <philipjcraig@gmail.com>
fc09d34
to
7cfc4c9
Compare
sorry for the late comments - I was out last week and as a result wasn't checking |
@@ -0,0 +1,354 @@ | |||
//! Support for FDE data generation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
other than the register mapping, and possibly code/data alignment, FDE
generation is architecture-agnostic. I assume you rather this code in cranelift-codegen
for use in wasmtime, but I'd like to have a very clear path to supporting other architectures. Is there another reason this would be in isa/x86/
? If not I'd like to move it to somewhere like cranelift-codegen/src/binemit/unwind.rs
that is more clearly independent of a specific architecture.
} | ||
} | ||
|
||
fn return_address_reg(isa: &dyn TargetIsa) -> Register { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also on the point of being architecture agnostic, I'd specifically wanted DwarfRegMapper
to clearly indicate how to add support for non-x86_64 architectures. You mentioned wanting cranelift-module
changed for other reasons, is there something unsuitable about struct DwarfRegMapper
in #902? If it was sufficient, and we're just deferring non-x86 thought for the moment, I'd like to revive DwarfRegMapper
in a subsequent PR.
fn to_cfi( | ||
isa: &dyn TargetIsa, | ||
change: &FrameLayoutChange, | ||
cfa_def_reg: &mut Register, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I strongly prefer isa::RegUnit
here for debugging reasons - going backwards from Register
to isa::RegUnit
. Does something necessitate this being gimli::Register
?
FrameLayoutChange::ReturnAddressAt { cfa_offset } => { | ||
assert!(cfa_offset % -8 == 0); | ||
let cfa_offset = *cfa_offset as i32; | ||
CallFrameInstruction::Offset(X86_64::RA, cfa_offset) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
quibble: if X86_64::RA
were replaced with return_address_reg(isa)
, to_cfi
would not have any x86-specific details anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, that's a bug
for (off, r) in relocs { | ||
sink.reloc(r, off + unwind_start); | ||
} | ||
let fde_offset = unsafe { ptr::read::<u32>(bytes.as_ptr() as *const u32) } as usize + 4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this just snuck by in review or not, but I'd at the very least want an explanation next to this pointer read with why it will be safe. I'd like to replace this with u32::from_le_bytes(bytes.as_slice()[..8].try_into())
- since the checks here aren't in a particularly hot path it seems like that shouldn't be an issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole thing is fighting against the gimli API a bit. You're using FrameTable
to write a single CIE and FDE, and then trying to figure out the FDE offset.
How about if gimli made the CIE/FDE write methods public, and then you can call those methods instead of using FrameTable
, and get the FDE offset simply as bytes.len()
prior to calling the FDE write?
@iximeow thank you for review, I'll try to get back to them shortly after bytecodealliance/wasmtime#759 . As @peterhuene noted, there will be more refactoring connected with generalizing unwind information. |
let mut eh_frame = EhFrame::from(FDEWriter::new()); | ||
frames.write_eh_frame(&mut eh_frame).unwrap(); | ||
|
||
let (bytes, relocs) = eh_frame.clone().into_vec_and_relocs(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use eh_frame.0
instead of eh_frame.clone()
.
Random drive-by comment for a future PR: can you explicit what the acronym FDE means, at the top of the fde.rs file, for instance? |
Currently, codegen produces unwind information only for Windows platform. We need to produce this type of information for all platforms to properly produce backtrace. See bytecodealliance/wasmtime#759
TODO (and requires feedback):
cc @peterhuene @iximeow