Skip to content

Commit d3ca6a7

Browse files
committed
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`](rust-lang/backtrace-rs#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!
2 parents 4d0cd9a + ab1472e commit d3ca6a7

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

libc-test/build.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,11 +1384,13 @@ fn test_android(target: &str) {
13841384
"ctype.h",
13851385
"dirent.h",
13861386
"dlfcn.h",
1387+
"elf.h",
13871388
"errno.h",
13881389
"fcntl.h",
13891390
"grp.h",
13901391
"ifaddrs.h",
13911392
"limits.h",
1393+
"link.h",
13921394
"locale.h",
13931395
"malloc.h",
13941396
"net/ethernet.h",
@@ -1469,6 +1471,7 @@ fn test_android(target: &str) {
14691471
"asm/mman.h",
14701472
"linux/auxvec.h",
14711473
"linux/dccp.h",
1474+
"linux/elf.h",
14721475
"linux/errqueue.h",
14731476
"linux/falloc.h",
14741477
"linux/futex.h",
@@ -1507,7 +1510,7 @@ fn test_android(target: &str) {
15071510
cfg.type_name(move |ty, is_struct, is_union| {
15081511
match ty {
15091512
// Just pass all these through, no need for a "struct" prefix
1510-
"FILE" | "fd_set" | "Dl_info" => ty.to_string(),
1513+
"FILE" | "fd_set" | "Dl_info" | "Elf32_Phdr" | "Elf64_Phdr" => ty.to_string(),
15111514

15121515
t if is_union => format!("union {}", t),
15131516

@@ -1610,7 +1613,12 @@ fn test_android(target: &str) {
16101613
// This is a weird union, don't check the type.
16111614
(struct_ == "ifaddrs" && field == "ifa_ifu") ||
16121615
// sigval is actually a union, but we pretend it's a struct
1613-
(struct_ == "sigevent" && field == "sigev_value")
1616+
(struct_ == "sigevent" && field == "sigev_value") ||
1617+
// FIXME: `sa_sigaction` has type `sighandler_t` but that type is
1618+
// incorrect, see: https://github.com/rust-lang/libc/issues/1359
1619+
(struct_ == "sigaction" && field == "sa_sigaction") ||
1620+
// signalfd had SIGSYS fields added in Android 4.19, but CI does not have that version yet.
1621+
(struct_ == "signalfd_siginfo" && field == "ssi_call_addr")
16141622
});
16151623

16161624
cfg.skip_field(move |struct_, field| {
@@ -1628,6 +1636,20 @@ fn test_android(target: &str) {
16281636
field == "ssi_arch"))
16291637
});
16301638

1639+
cfg.skip_field(|struct_, field| {
1640+
match (struct_, field) {
1641+
// conflicting with `p_type` macro from <resolve.h>.
1642+
("Elf32_Phdr", "p_type") => true,
1643+
("Elf64_Phdr", "p_type") => true,
1644+
1645+
// this is actually a union on linux, so we can't represent it well and
1646+
// just insert some padding.
1647+
("siginfo_t", "_pad") => true,
1648+
1649+
_ => false,
1650+
}
1651+
});
1652+
16311653
cfg.generate("../src/lib.rs", "main.rs");
16321654

16331655
test_linux_like_apis(target);

src/unix/linux_like/android/mod.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ pub type loff_t = ::c_longlong;
2626
pub type __kernel_loff_t = ::c_longlong;
2727
pub type __kernel_pid_t = ::c_int;
2828

29+
// linux/elf.h
30+
31+
pub type Elf32_Addr = u32;
32+
pub type Elf32_Half = u16;
33+
pub type Elf32_Off = u32;
34+
pub type Elf32_Word = u32;
35+
36+
pub type Elf64_Addr = u64;
37+
pub type Elf64_Half = u16;
38+
pub type Elf64_Off = u64;
39+
pub type Elf64_Word = u32;
40+
pub type Elf64_Xword = u64;
41+
2942
s! {
3043
pub struct stack_t {
3144
pub ss_sp: *mut ::c_void,
@@ -244,6 +257,57 @@ s! {
244257
pub svm_cid: ::c_uint,
245258
pub svm_zero: [u8; 4]
246259
}
260+
261+
// linux/elf.h
262+
263+
pub struct Elf32_Phdr {
264+
pub p_type: Elf32_Word,
265+
pub p_offset: Elf32_Off,
266+
pub p_vaddr: Elf32_Addr,
267+
pub p_paddr: Elf32_Addr,
268+
pub p_filesz: Elf32_Word,
269+
pub p_memsz: Elf32_Word,
270+
pub p_flags: Elf32_Word,
271+
pub p_align: Elf32_Word,
272+
}
273+
274+
pub struct Elf64_Phdr {
275+
pub p_type: Elf64_Word,
276+
pub p_flags: Elf64_Word,
277+
pub p_offset: Elf64_Off,
278+
pub p_vaddr: Elf64_Addr,
279+
pub p_paddr: Elf64_Addr,
280+
pub p_filesz: Elf64_Xword,
281+
pub p_memsz: Elf64_Xword,
282+
pub p_align: Elf64_Xword,
283+
}
284+
285+
// link.h
286+
287+
pub struct dl_phdr_info {
288+
#[cfg(target_pointer_width = "64")]
289+
pub dlpi_addr: Elf64_Addr,
290+
#[cfg(target_pointer_width = "32")]
291+
pub dlpi_addr: Elf32_Addr,
292+
293+
pub dlpi_name: *const ::c_char,
294+
295+
#[cfg(target_pointer_width = "64")]
296+
pub dlpi_phdr: *const Elf64_Phdr,
297+
#[cfg(target_pointer_width = "32")]
298+
pub dlpi_phdr: *const Elf32_Phdr,
299+
300+
#[cfg(target_pointer_width = "64")]
301+
pub dlpi_phnum: Elf64_Half,
302+
#[cfg(target_pointer_width = "32")]
303+
pub dlpi_phnum: Elf32_Half,
304+
305+
// These fields were added in Android R
306+
pub dlpi_adds: ::c_ulonglong,
307+
pub dlpi_subs: ::c_ulonglong,
308+
pub dlpi_tls_modid: ::size_t,
309+
pub dlpi_tls_data: *mut ::c_void,
310+
}
247311
}
248312

249313
s_no_extra_traits! {
@@ -2715,6 +2779,19 @@ extern "C" {
27152779

27162780
pub fn __system_property_set(__name: *const ::c_char, __value: *const ::c_char) -> ::c_int;
27172781
pub fn __system_property_get(__name: *const ::c_char, __value: *mut ::c_char) -> ::c_int;
2782+
2783+
// #include <link.h>
2784+
/// Only available in API Version 21+
2785+
pub fn dl_iterate_phdr(
2786+
callback: ::Option<
2787+
unsafe extern "C" fn(
2788+
info: *mut dl_phdr_info,
2789+
size: usize,
2790+
data: *mut ::c_void,
2791+
) -> ::c_int,
2792+
>,
2793+
data: *mut ::c_void,
2794+
) -> ::c_int;
27182795
}
27192796

27202797
cfg_if! {

0 commit comments

Comments
 (0)