Skip to content

arm64 android missing a bunch of ptrace apis? #1678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Gankra opened this issue Mar 15, 2022 · 3 comments
Open

arm64 android missing a bunch of ptrace apis? #1678

Gankra opened this issue Mar 15, 2022 · 3 comments

Comments

@Gankra
Copy link

Gankra commented Mar 15, 2022

I'm on a bit of a yakshave here, but hopefully this is comprehensible.

I'm working on porting minidump_writer_linux to ARM64 Android.

One of its primary jobs is to grab the registers of every thread and dump them to a file. It currently uses the ptrace::getregs and (getfpregs) call to get them on x64.

Unfortunately, nix seems to explicitly if-def around this possibility:

/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
#[cfg(all(
    target_os = "linux",
    any(all(target_arch = "x86_64",
            any(target_env = "gnu", target_env = "musl")),
        all(target_arch = "x86", target_env = "gnu"))
))]
pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
    ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
}

I expect part of the reason for this is because the ARM64 simd registers are defined in terms of __int128 which is known to not be FFI-safe in rust due to a long-standing llvm bug (that also makes clang and gcc have incompatible ABIs for SysV x64 __int128-passed-on-stack)!

However I have recently demonstrated that this isn't actually an issue on ARM64, where llvm uses the right definition everywhere (and rust and clang both inherit it).

I have a PR in place to introduce conditional typedefs in libc so there is in some sense a "higher authority" you can rely on for where these types are safe, and use the kernel definitions for the register save structs.

Is all of this sufficient to properly add getregs/getfpregs for ARM64 android/linux, or are there other outstanding issues? I'm not really sure how to "look up" what parts of ptrace work specifically on specific linux/android targets -- the ptrace docs note that getregs/getfpregs aren't actually available on all platforms, and it looks like getregset exists as the "new" replacement? It's fine if we just need to expose that instead.

Alternatively if Android is just really weird and has none of this: what are you supposed to use for this functionality?

@asomers
Copy link
Member

asomers commented Mar 15, 2022

You can certainly try implementing that stuff for arm64. The main reason that Nix doesn't already is simply because ptrace is complicated and non-portable, so nobody's done it yet. Plus, we didn't use to have any CI for aarch64, but now we do!

@Gankra
Copy link
Author

Gankra commented Mar 15, 2022

Some investigation running this test file on ARM64 android via termux:

  • ptrace GETREGS/GETFPREGS doesn't exist
  • ptrace GETREGSET (NT_PRSTATUS, NT_PRFPREG) does exist

And emits:

  • NT_PRSTATUS: user_regs_struct (actually user_pt_regs, but identical layout)
  • NT_PRFPREG: user_fpsimd_state (actually fxregs_state, but identical layout)

Brain completely fried by how terrible linux docs/headers are to dig through, will look at this more later...

@kxxt
Copy link

kxxt commented Apr 8, 2023

I am interested in implementing nix::ptrace::getregset(). But it seems that this function should be unsafe and I didn't find any other pub unsafe functions under the ptrace mod.

My plan is to write a function:

pub unsafe fn getregset(pid: Pid, addr: libc::size_t, data: *mut c_void) -> Result<()>

But it doesn't look rusty enough. Any advice to get me started?

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

No branches or pull requests

3 participants