Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Refactor unwind; add FDE support. #1320

Merged
merged 7 commits into from
Jan 13, 2020

Conversation

yurydelendik
Copy link
Collaborator

@yurydelendik yurydelendik commented Jan 7, 2020

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

cranelift-codegen/src/isa/x86/abi.rs Outdated Show resolved Hide resolved
cranelift-codegen/src/isa/x86/fde.rs Outdated Show resolved Hide resolved
cranelift-codegen/src/isa/x86/fde.rs Outdated Show resolved Hide resolved
@yurydelendik yurydelendik force-pushed the unwind-fde branch 2 times, most recently from 29b824e to 58046ee Compare January 7, 2020 23:02
cranelift-codegen/src/context.rs Show resolved Hide resolved
cranelift-codegen/src/isa/x86/abi.rs Outdated Show resolved Hide resolved
@yurydelendik yurydelendik marked this pull request as ready for review January 8, 2020 20:28
Copy link
Member

@peterhuene peterhuene left a 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.

@yurydelendik yurydelendik force-pushed the unwind-fde branch 2 times, most recently from 4a70f72 to fc09d34 Compare January 10, 2020 22:12
@yurydelendik
Copy link
Collaborator Author

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.

Yeah, currently I added "test_fde.rs" -- it will match how wasmtime will use the functionality, by using FrameUnwindKind parameter.

@peterhuene
Copy link
Member

peterhuene commented Jan 10, 2020

👍

I think in a future PR we might want to unify the unwind and fde subtests so that it'll print out the right thing depending on the given function's ABI and calling convention.

I feel that unwind is too generic a term to mean just Windows unwind information, so it might lead to confusion in the long run. Perhaps something to revisit when we further abstract things.

@iximeow
Copy link
Collaborator

iximeow commented Jan 13, 2020

sorry for the late comments - I was out last week and as a result wasn't checking cranelift too closely. I do have a few comments, but I expect them to be subsequent PRs, and would like to discuss a bit first.

@@ -0,0 +1,354 @@
//! Support for FDE data generation.
Copy link
Collaborator

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 {
Copy link
Collaborator

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,
Copy link
Collaborator

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)
Copy link
Collaborator

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

Copy link
Collaborator Author

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;
Copy link
Collaborator

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?

Copy link
Contributor

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?

@yurydelendik
Copy link
Collaborator Author

I do have a few comments, but I expect them to be subsequent PRs

@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();
Copy link
Contributor

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().

@bnjbvr
Copy link
Member

bnjbvr commented Jan 15, 2020

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?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants