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

FrameLayoutChange-based .eh_frame support #902

Closed

Conversation

iximeow
Copy link
Collaborator

@iximeow iximeow commented Aug 15, 2019

This teaches cranelift-faerie how to write .eh_frame sections that are appropriate with respect to call frames for functions that produce layout information.

This builds quite directly on #679, which is still open, and whose changes are alongside this as a result. For the time being, my changes on top of @yurydelendik 's PR are best seen as a diff between our branches.

Being dependent on an already-floating PR, I want to mostly call attention to the points that:

I do have some comments in-line in case any readers do take a closer look at the changes here, but I'm not sure it makes sense to sweat the details until #679 is figured out, since it seems like we've bitrotted with respect to today's master anyway.

reg_info: RegInfo,
}

impl<'a> DwarfRegMapper<'a> {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned this on irc a few days ago but DwarfRegMapper could arguably live in cranelift-codegen as it's fundamentally an int->int function, and doesn't need to return a gimli::Register. This and CFIEncoder might also make sense in cranelift-module as they are, pulling in a gimli dependency there and not in cranelift-codegen. @yurydelendik would cranelift-module be a useful place to share this logic translating FrameLocationChange to CFI instructions for your use in wasmtime?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue #729 is about the register mapping.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved this to cranelift-module and noted some reasoning in that issue. I'll leave this unresolved until we decide here or there what to do with DwarfRegMapper.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yurydelendik would cranelift-module be a useful place to share this logic translating FrameLocationChange to CFI instructions for your use in wasmtime?

@iximeow yes, and in fact, I would like to have entire cratelift-module change for other reasons.

gimli::Encoding {
format: gimli::Format::Dwarf32,
version: 1,
address_size: 4,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably should be 8. Not sure if it will be used for the data you are writing though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should only be 8 on x86_64.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had definitely misunderstood the point of the address_size field here to be "size of an encoded pointer", rather than "size of a pointer for the target ISA". I'll make this pick the right size for the target.

4 and the asserts later about address size/pointer encoding, are a relic of trying to match CIE bytes I'd known work, in tracking down a crash in libgcc. In reality, I eventually figured out the issue I'd had is that libgcc doesn't handle escaped length fields in 64-bit DWARF, so I just tried absptr encodings and it still works fine! 🎉

I ought to add a note about why this specifically uses Dwarf32 regardless of architecture - in other places I at least wanted to at least comment about architecture-specific magic values, so format deserves a Do not change this! mention.

Thinking through my confusion with the meaning of this and the write_eh_pointer argument, it seems like write_eh_pointer ought to not take address_size as a parameter. Since it only matters for absolute pointer encodings, I think it could work better to provide address_size as a field of an absptr variant for DwEhPe? Then it would be clear just from the function signature that the implementer is to write an address matching the encoding, and that gimli is not making assumptions about the number of bytes that would be written via address_size. If that sounds interesting, I can sketch out a PR to gimli to try that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Encoding::address_size field is used for all DWARF, where the normal format of an address is an unencoded pointer. .eh_frame is different from DWARF in that it encodes pointers, but even then it can't be the encoded pointer size because it is possible to use multiple encodings of different sizes.

DwEhPe is used to represent the constants, so it can't be changed. The size parameter to write_eh_pointer is documented as only being used for absolute pointers. I'm not sure we can do better than that. Maybe renaming the parameter to absolute_address_size would be worthwhile.

We may want to add a check in gimli to ensure you don't write .eh_frame with Dwarf64, since the LSB requires 32-bit length fields.

cranelift-faerie/src/backend.rs Outdated Show resolved Hide resolved
cranelift-faerie/src/backend.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@bjorn3 bjorn3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Next step will be running user code during cleanup.

cranelift-faerie/src/backend.rs Outdated Show resolved Hide resolved
cranelift-faerie/src/backend.rs Outdated Show resolved Hide resolved
cranelift-faerie/src/backend.rs Outdated Show resolved Hide resolved
.link_with(
faerie::Link {
to: name,
from: ".eh_frame",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this __eh_frame for machO?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question, I'll at least see what other toolchains name it. I also need to use a machO-appropriate relocation.

cranelift-faerie/src/backend.rs Outdated Show resolved Hide resolved
cranelift-faerie/src/backend.rs Outdated Show resolved Hide resolved

frame_sink.add_fde(cie, fd_entry);
} else {
// we have a frame sink to write .eh_frames into, but are not collecting debug
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please panic here to make it easier to debug in that case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized this morning that there's a case where we will reach this arm but not be a bug: if the user of cranelift has a per-function nounwind-like attribute, a nounwind function wouldn't need unwind information collected, even though there still would be a frame sink for other functions. Right now it happens to be that Lucet is all-or-nothing on unwind info, but as a rustc backend for example I could see some function being opt-out.

Given that, would you rather a panic to identify the case for later discussion, or should I discard the else entirely?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but as a rustc backend for example I could see some function being opt-out.

I believe unwinding enabled/disabled is done per crate (using -Cpanic=abort), not per function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rustc has the unstable #[unwind(allowed/aborts)] to control per function, as well I think it has different requirements for extern "C", but I don't know the details of that and it is under ongoing discussion.

// we need to retain function names to hand out usize identifiers for FDE addresses,
// which are then used to look up function names again for relocations, when `write_address` is
// called.
fn_names: Vec<String>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ModuleContents does already contain something like this, not sure if it is worth trying to reuse that, but maybe FuncId::as_u32 can be the identifier.

@alexcrichton
Copy link
Member

Thanks for the PR again, and as a procedural note the Cranelift repository has now merged into the wasmtime repository.

PRs are no longer landing in this repository, and unfortunately there's no "one button" solution to move a PR to the wasmtime repository. A script has been prepared, however, to assist you in transferring this PR to the wasmtime repo. Feel free to reach out on Zulip with any questions!

@iximeow
Copy link
Collaborator Author

iximeow commented Mar 3, 2020

Closing this with the hope that either #1181 will result in a change that supplants PR, or that this will be significantly different when #1181 is resolved.

@iximeow iximeow closed this Mar 3, 2020
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.

5 participants