From 970fec9245ace9808178e08a75ee15c859900c4e Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Thu, 8 Apr 2021 17:41:36 -0400 Subject: [PATCH 1/2] Add dl_iterate_phdr to Android --- libc-test/build.rs | 4 +- src/unix/linux_like/android/mod.rs | 80 ++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index 5475b509..667fc75f 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", @@ -1507,7 +1509,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), diff --git a/src/unix/linux_like/android/mod.rs b/src/unix/linux_like/android/mod.rs index 25fa462a..d68c5b21 100644 --- a/src/unix/linux_like/android/mod.rs +++ b/src/unix/linux_like/android/mod.rs @@ -26,6 +26,36 @@ pub type loff_t = ::c_longlong; pub type __kernel_loff_t = ::c_longlong; pub type __kernel_pid_t = ::c_int; +// elf.h + +pub type Elf32_Addr = u32; +pub type Elf32_Half = u16; +pub type Elf32_Lword = u64; +pub type Elf32_Off = u32; +pub type Elf32_Sword = i32; +pub type Elf32_Word = u32; + +pub type Elf64_Addr = u64; +pub type Elf64_Half = u16; +pub type Elf64_Lword = u64; +pub type Elf64_Off = u64; +pub type Elf64_Sword = i32; +pub type Elf64_Sxword = i64; +pub type Elf64_Word = u32; +pub type Elf64_Xword = u64; + +cfg_if! { + if #[cfg(target_pointer_width = "64")] { + type Elf_Addr = Elf64_Addr; + type Elf_Half = Elf64_Half; + type Elf_Phdr = Elf64_Phdr; + } else if #[cfg(target_pointer_width = "32")] { + type Elf_Addr = Elf32_Addr; + type Elf_Half = Elf32_Half; + type Elf_Phdr = Elf32_Phdr; + } +} + s! { pub struct stack_t { pub ss_sp: *mut ::c_void, @@ -244,6 +274,43 @@ s! { pub svm_cid: ::c_uint, pub svm_zero: [u8; 4] } + + // 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 { + pub dlpi_addr: Elf_Addr, + pub dlpi_name: *const ::c_char, + pub dlpi_phdr: *const Elf_Phdr, + pub dlpi_phnum: Elf_Half, + pub dlpi_adds: ::c_ulonglong, + pub dlpi_subs: ::c_ulonglong, + pub dlpi_tls_modid: usize, + pub dlpi_tls_data: *mut ::c_void, + } } s_no_extra_traits! { @@ -2715,6 +2782,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 + /// 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! { From ab1472eb086cea9d23aa267206dc040feefa673c Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Fri, 9 Apr 2021 12:22:53 -0400 Subject: [PATCH 2/2] Update dl_phdr_info definition to more closely match header files Also, update tests to skip conflicts --- libc-test/build.rs | 22 ++++++++++++++- src/unix/linux_like/android/mod.rs | 43 ++++++++++++++---------------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index 667fc75f..a39c1ce9 100755 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1471,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", @@ -1612,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| { @@ -1630,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 . + ("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 d68c5b21..52e7b9ff 100644 --- a/src/unix/linux_like/android/mod.rs +++ b/src/unix/linux_like/android/mod.rs @@ -26,36 +26,19 @@ pub type loff_t = ::c_longlong; pub type __kernel_loff_t = ::c_longlong; pub type __kernel_pid_t = ::c_int; -// elf.h +// linux/elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; -pub type Elf32_Lword = u64; pub type Elf32_Off = u32; -pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; -pub type Elf64_Lword = u64; pub type Elf64_Off = u64; -pub type Elf64_Sword = i32; -pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; -cfg_if! { - if #[cfg(target_pointer_width = "64")] { - type Elf_Addr = Elf64_Addr; - type Elf_Half = Elf64_Half; - type Elf_Phdr = Elf64_Phdr; - } else if #[cfg(target_pointer_width = "32")] { - type Elf_Addr = Elf32_Addr; - type Elf_Half = Elf32_Half; - type Elf_Phdr = Elf32_Phdr; - } -} - s! { pub struct stack_t { pub ss_sp: *mut ::c_void, @@ -275,7 +258,7 @@ s! { pub svm_zero: [u8; 4] } - // elf.h + // linux/elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, @@ -302,13 +285,27 @@ s! { // link.h pub struct dl_phdr_info { - pub dlpi_addr: Elf_Addr, + #[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, - pub dlpi_phdr: *const Elf_Phdr, - pub dlpi_phnum: Elf_Half, + + #[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: usize, + pub dlpi_tls_modid: ::size_t, pub dlpi_tls_data: *mut ::c_void, } }