Coder Social home page Coder Social logo

framehop's People

Contributors

afranchuk avatar kraktus avatar mstange avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

framehop's Issues

Add more caching

According to this post by Julian Seward, valgrind has a cache with 509 slots for caching the unwinding rules for addresses that it has seen before.

It would probably be worth adding something like this.

Aarch64 signature masking (intended for macOS arm64e) is too aggressive for Linux

We currently assume 24 bits hash + 40 bits pointer:

/// On macOS arm64, system libraries are arm64e binaries, and arm64e can do pointer authentication:
/// The low bits of the pointer are the actual pointer value, and the high bits are an encrypted hash.
/// During stackwalking, we need to strip off this hash.
/// I don't know of an easy way to get the correct mask dynamically - all the potential functions
/// I've seen for this are no-ops when called from regular arm64 code.
/// So for now, we hardcode a mask that seems to work today, and worry about it if it stops working.
/// 24 bits hash + 40 bits pointer
const PTR_MASK: u64 = (1 << 40) - 1;

This assumption seems to be wrong on Linux. At least in the Ubuntu aarch64 VM that I tested on, there are libraries mapped at addresses like this:

0x0000aaaab54f7000-0x0000aaaab5e0a000 /home/ubuntu/.cargo/bin/rustup
0x0000ffffa3206000-0x0000ffffa323a000 /usr/lib/aarch64-linux-gnu/ld-2.31.so

Only the top 16 bits of these addresses are zero. The remaining 48 bits are used. The current mask masks off 8 bits too many.

Updating, gimli, object and fallible-iterator

Hi,

I am one of the Debian rust team and I am currently working on updating the backtrace crate and it's dependencies in Debian. Backtrace itself is not semver breaking but several of the crates it depends on are semver breaking. While we do have a mechanism to package multiple versions of a crate it is something we try to avoid where possible.

Therefore I have been going through the reverse dependencies of addr2line, fallible-iterator, gimli and object and preparing updates. Your crate depends on three of theese crates, gimli, object and faillible-iterator.

After bumping the dependencies I got a build failure because an enum was now marked as "non_exhaustive", causing a match statement to fail to compile because it didn't have a fallback case. After looking at the existing cases it appeared to me that returning None was the correct thing to do in the fallback case.

After preparing a patch doing that the package built successfully and tests passed.

Our patch can be found at https://salsa.debian.org/rust-team/debcargo-conf/-/blob/5c2b008f2853a6f9382f303b71f6acaeb5e9e484/src/framehop/debian/patches/gimli-0.28-etc.patch any comments would be appreciated.

Support compressed sections in the `unwinder::object` ModuleSectionInfo impl.

This should be fairly easy; rather than D: From<&'data [u8]>, there should be something like

enum SectionData<'data> {
    Uncompressed {
        data: &'data [u8],
        file_offset: usize,
    }
    Compressed {
        decompressed_data: Vec<u8>
    }
}

and D: From<SectionData>. The file_offset is for the common case where someone has MMaped data and they want to "drop" the lifetime by referencing the MMap instead.

Epilog detection unreliable when ip is on jmp with an 0x58 immediate before it

This is a very rare case of epilog analysis false-positive I found when checking epilog detection robustness for the WIP SEH backend, but I thought it was worth reporting.

The sample landed on an in-function jump:

0x35911b800      488b4258       mov rax, qword [rdx + 0x58] ; 0x58 looks like a pop but is actually an offset
0x35911b804      eba9           jmp 0x35911b7af             ; sample ip here

The function starts at 0x35911b6c0 and ends at 0x35911ba8c.

It looks like the current heuristic can break if you stress it with millions of samples. :P

// This must be the first iteration. Look backwards.
if let Some(potential_pop_byte) = slice_from_start.last() {
// Get the previous byte. We have no idea how long the previous instruction
// is, so we might be looking at a random last byte of a wider instruction.
// Let's just pray that this is not the case.
if potential_pop_byte & 0xf8 == 0x58 {
// Assuming we haven't just misinterpreted the last byte of a wider
// instruction, this is a `pop rXX`.
break;
}
}

Wine uses something different: It checks if the jump lands within function bounds.

https://github.com/wine-mirror/wine/blob/d0ce5a77c60e0a9613f1af03d67d13b89816441b/dlls/ntdll/signal_x86_64.c#L720

This could be potentially more robust, but needs testing.

Add prologue / epilogue detection for the top-most stack frame

A small but noticeable number of samples in the profiles I've taken with framehop incorrectly unwind the top-most stack frame. Sometimes the return address is entirely garbage, and sometimes it just skips the immediate caller and goes to the grandparent. Most of the time this seems to happen because the pc is inside the function prologue or epilogue. The unwind information doesn't account for them.

My goal is to have two entry points, unwind_one_frame_from_pc and unwind_one_frame_from_return_address. The latter can assume that it's somewhere in the "middle" of the function. And the former can have extra smarts to deal with prologues and epilogues.

The extra smarts will vary on the type of unwinder and on the architecture. We'll need to disassemble instructions around the pc and detect common prologue / epilogue matches. This seems to be a normal thing for an unwinder to do, for example it's also part of the PE exception unwinding process. It's also mentioned in Keno's unwinding notes: "Unwinders will generally avoid this problem by looking at the next instruction and compensating if it looks like the standard prologue instructions."

Dwarf unwinding results in truncated stacks

I'm trying to make a replacement for perf script with linux-perf-data, framehop, and wholesym. Thank you for providing the building blocks!

Currently I'm running into an issue with framehop giving me truncated stacks when using ModuleUnwindData::DebugFrame. It works great with ModuleUnwindData::EhFrameHdrAndEhFrame, which is how it works out of the box for rust programs with samply.

For Rust I'm getting TruncatedStackMarker, but for Go I'm also seeing just short stacks with a couple of frames and that's it.

My reference is perf script linked against libdw (libunwind likes to truncate as well, so I'm avoiding it).

I'm on aarch64-linux (via qemu VM on macOS).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.