diff options
author | bors <bors@rust-lang.org> | 2021-04-12 07:33:36 +0000 |
---|---|---|
committer | bors <bors@rust-lang.org> | 2021-04-12 07:33:36 +0000 |
commit | d3ca6a751eab8aa87f52e03b76b93a5d550f0e37 (patch) | |
tree | 73905c5c741bd965f18deb89fa826b2c4417cbd3 | |
parent | 4d0cd9ae1034582a49c1cc8532cb9591ef0ef179 (diff) | |
parent | ab1472eb086cea9d23aa267206dc040feefa673c (diff) | |
download | rust-libc-d3ca6a751eab8aa87f52e03b76b93a5d550f0e37.tar.gz |
Auto merge of #2144 - kjvalencik:master, r=JohnTitor
Add dl_iterate_phdr to Android
Adds the `dl_iterate_phdr` function for Android targets. This is required for Android support in `gimli` and by proxy, `backtrace`.
I tested this in [`backtrace`](https://github.com/rust-lang/backtrace-rs/pull/415) both in an i686 emulator and a physical arm64 device.
This API is only available on Version 21+. I'm not sure how that's typically handled in `libc`, so I added a doc comment.
Let me know what else is needed!
-rwxr-xr-x | libc-test/build.rs | 26 | ||||
-rw-r--r-- | src/unix/linux_like/android/mod.rs | 77 |
2 files changed, 101 insertions, 2 deletions
diff --git a/libc-test/build.rs b/libc-test/build.rs index 5475b5093e..a39c1ce903 100755 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1384,11 +1384,13 @@ fn test_android(target: &str) { "ctype.h", "dirent.h", "dlfcn.h", + "elf.h", "errno.h", "fcntl.h", "grp.h", "ifaddrs.h", "limits.h", + "link.h", "locale.h", "malloc.h", "net/ethernet.h", @@ -1469,6 +1471,7 @@ fn test_android(target: &str) { "asm/mman.h", "linux/auxvec.h", "linux/dccp.h", + "linux/elf.h", "linux/errqueue.h", "linux/falloc.h", "linux/futex.h", @@ -1507,7 +1510,7 @@ fn test_android(target: &str) { cfg.type_name(move |ty, is_struct, is_union| { match ty { // Just pass all these through, no need for a "struct" prefix - "FILE" | "fd_set" | "Dl_info" => ty.to_string(), + "FILE" | "fd_set" | "Dl_info" | "Elf32_Phdr" | "Elf64_Phdr" => ty.to_string(), t if is_union => format!("union {}", t), @@ -1610,7 +1613,12 @@ fn test_android(target: &str) { // This is a weird union, don't check the type. (struct_ == "ifaddrs" && field == "ifa_ifu") || // sigval is actually a union, but we pretend it's a struct - (struct_ == "sigevent" && field == "sigev_value") + (struct_ == "sigevent" && field == "sigev_value") || + // FIXME: `sa_sigaction` has type `sighandler_t` but that type is + // incorrect, see: https://github.com/rust-lang/libc/issues/1359 + (struct_ == "sigaction" && field == "sa_sigaction") || + // signalfd had SIGSYS fields added in Android 4.19, but CI does not have that version yet. + (struct_ == "signalfd_siginfo" && field == "ssi_call_addr") }); cfg.skip_field(move |struct_, field| { @@ -1628,6 +1636,20 @@ fn test_android(target: &str) { field == "ssi_arch")) }); + cfg.skip_field(|struct_, field| { + match (struct_, field) { + // conflicting with `p_type` macro from <resolve.h>. + ("Elf32_Phdr", "p_type") => true, + ("Elf64_Phdr", "p_type") => true, + + // this is actually a union on linux, so we can't represent it well and + // just insert some padding. + ("siginfo_t", "_pad") => true, + + _ => false, + } + }); + cfg.generate("../src/lib.rs", "main.rs"); test_linux_like_apis(target); diff --git a/src/unix/linux_like/android/mod.rs b/src/unix/linux_like/android/mod.rs index 25fa462add..52e7b9ff41 100644 --- a/src/unix/linux_like/android/mod.rs +++ b/src/unix/linux_like/android/mod.rs @@ -26,6 +26,19 @@ pub type loff_t = ::c_longlong; pub type __kernel_loff_t = ::c_longlong; pub type __kernel_pid_t = ::c_int; +// linux/elf.h + +pub type Elf32_Addr = u32; +pub type Elf32_Half = u16; +pub type Elf32_Off = u32; +pub type Elf32_Word = u32; + +pub type Elf64_Addr = u64; +pub type Elf64_Half = u16; +pub type Elf64_Off = u64; +pub type Elf64_Word = u32; +pub type Elf64_Xword = u64; + s! { pub struct stack_t { pub ss_sp: *mut ::c_void, @@ -244,6 +257,57 @@ s! { pub svm_cid: ::c_uint, pub svm_zero: [u8; 4] } + + // linux/elf.h + + pub struct Elf32_Phdr { + pub p_type: Elf32_Word, + pub p_offset: Elf32_Off, + pub p_vaddr: Elf32_Addr, + pub p_paddr: Elf32_Addr, + pub p_filesz: Elf32_Word, + pub p_memsz: Elf32_Word, + pub p_flags: Elf32_Word, + pub p_align: Elf32_Word, + } + + pub struct Elf64_Phdr { + pub p_type: Elf64_Word, + pub p_flags: Elf64_Word, + pub p_offset: Elf64_Off, + pub p_vaddr: Elf64_Addr, + pub p_paddr: Elf64_Addr, + pub p_filesz: Elf64_Xword, + pub p_memsz: Elf64_Xword, + pub p_align: Elf64_Xword, + } + + // link.h + + pub struct dl_phdr_info { + #[cfg(target_pointer_width = "64")] + pub dlpi_addr: Elf64_Addr, + #[cfg(target_pointer_width = "32")] + pub dlpi_addr: Elf32_Addr, + + pub dlpi_name: *const ::c_char, + + #[cfg(target_pointer_width = "64")] + pub dlpi_phdr: *const Elf64_Phdr, + #[cfg(target_pointer_width = "32")] + pub dlpi_phdr: *const Elf32_Phdr, + + #[cfg(target_pointer_width = "64")] + pub dlpi_phnum: Elf64_Half, + #[cfg(target_pointer_width = "32")] + pub dlpi_phnum: Elf32_Half, + + // These fields were added in Android R + pub dlpi_adds: ::c_ulonglong, + pub dlpi_subs: ::c_ulonglong, + pub dlpi_tls_modid: ::size_t, + pub dlpi_tls_data: *mut ::c_void, + } } s_no_extra_traits! { @@ -2715,6 +2779,19 @@ extern "C" { pub fn __system_property_set(__name: *const ::c_char, __value: *const ::c_char) -> ::c_int; pub fn __system_property_get(__name: *const ::c_char, __value: *mut ::c_char) -> ::c_int; + + // #include <link.h> + /// Only available in API Version 21+ + pub fn dl_iterate_phdr( + callback: ::Option< + unsafe extern "C" fn( + info: *mut dl_phdr_info, + size: usize, + data: *mut ::c_void, + ) -> ::c_int, + >, + data: *mut ::c_void, + ) -> ::c_int; } cfg_if! { |