1- extern crate libc;
2-
3- use libc:: c_int;
1+ use elf:: types:: { PF_R , PF_W , PF_X } ;
2+ use libc:: {
3+ c_int, dl_iterate_phdr, dl_phdr_info, PT_DYNAMIC , PT_GNU_EH_FRAME , PT_GNU_RELRO , PT_INTERP ,
4+ PT_LOAD , PT_LOOS , PT_NOTE , PT_NULL , PT_PHDR , PT_SHLIB , PT_TLS ,
5+ } ;
46use std:: {
57 ffi:: { CStr , CString } ,
68 fmt:: { self , Debug } ,
79 iter:: Iterator ,
810 os:: raw:: c_void,
911} ;
1012
11- // We are using bindgen to access the `dl_iterate_phdr` API and its types. The `libc` crate exposes
12- // everything we need, but only on *some* platforms. If the `libc` definitions ever become portable
13- // then it would make sense to use those instead of bindgen. There's an issue for this here:
14- // https://github.com/rust-lang/libc/issues/1066
15- //
16- // Until then, we avoid namespace pollution by containing all the auto-generated stuff inside a
17- // (private) sub-module, exposing only what we intend to be public.
18- mod p_ffi {
19- #![ allow( non_upper_case_globals) ]
20- #![ allow( non_camel_case_types) ]
21- #![ allow( non_snake_case) ]
22- #![ allow( dead_code) ]
23- #![ allow( improper_ctypes) ]
24- include ! ( concat!( env!( "OUT_DIR" ) , "/bindings.rs" ) ) ;
25-
26- // Re-define C types that are usually erased by C macros.
27- #[ cfg( target_pointer_width = "64" ) ]
28- pub type Elf_Phdr = Elf64_Phdr ;
29- #[ cfg( target_pointer_width = "32" ) ]
30- pub type Elf_Phdr = Elf32_Phdr ;
31-
32- #[ cfg( target_pointer_width = "64" ) ]
33- pub type Elf_Half = Elf64_Half ;
34- #[ cfg( target_pointer_width = "32" ) ]
35- pub type Elf_Half = Elf32_Half ;
36-
37- #[ cfg( target_pointer_width = "64" ) ]
38- pub type Elf_Addr = Elf64_Addr ;
39- #[ cfg( target_pointer_width = "32" ) ]
40- pub type Elf_Addr = Elf32_Addr ;
41-
42- #[ cfg( target_pointer_width = "64" ) ]
43- pub type Elf_Off = Elf64_Off ;
44- #[ cfg( target_pointer_width = "32" ) ]
45- pub type Elf_Off = Elf32_Off ;
46-
47- #[ cfg( target_pointer_width = "64" ) ]
48- pub type Elf_Word = Elf64_Word ;
49- #[ cfg( target_pointer_width = "32" ) ]
50- pub type Elf_Word = Elf32_Word ;
51-
52- #[ cfg( target_pointer_width = "64" ) ]
53- pub type Elf_Xword = u64 ;
54- #[ cfg( target_pointer_width = "32" ) ]
55- pub type Elf_Xword = u32 ;
56- }
13+ #[ cfg( target_pointer_width = "64" ) ]
14+ use libc:: {
15+ Elf64_Addr as Elf_Addr , Elf64_Half as Elf_Half , Elf64_Off as Elf_Off , Elf64_Phdr as Elf_Phdr ,
16+ Elf64_Word as Elf_Word , Elf64_Xword as Elf_Xword ,
17+ } ;
5718
58- pub use p_ffi :: {
59- Elf_Addr , Elf_Half , Elf_Off , Elf_Phdr , Elf_Word , Elf_Xword , PF_MASKPROC , PF_R , PF_W , PF_X ,
60- PT_DYNAMIC , PT_GNU_EH_FRAME , PT_GNU_RELRO , PT_HIOS , PT_HIPROC , PT_INTERP , PT_LOAD , PT_LOOS ,
61- PT_LOPROC , PT_NOTE , PT_NULL , PT_PHDR , PT_SHLIB , PT_TLS ,
19+ # [ cfg ( target_pointer_width = "32" ) ]
20+ use libc :: {
21+ Elf32_Addr as Elf_Addr , Elf32_Half as Elf_Half , Elf32_Off as Elf_Off , Elf32_Phdr as Elf_Phdr ,
22+ Elf32_Word as Elf_Word , Elf32_Xword as Elf_Xword ,
6223} ;
6324
25+ // At the time of writing these ELF constants are defined neither in `elf` nor `libc`.
26+ const PF_MASKPROC : u32 = 0xf0000000 ;
27+ const PT_HIOS : u32 = 0x6fffffff ;
28+ const PT_LOPROC : u32 = 0x70000000 ;
29+ const PT_HIPROC : u32 = 0x7fffffff ;
30+
6431/// Contains information about an "object" in the virtual address space.
6532/// This corresponds with a `dl_phdr_info` in C. Note that the contents of the C struct differ
6633/// between platforms. We expose only the common fields for now.
6734pub struct Object {
6835 /// The base address of the object.
69- addr : p_ffi :: Elf_Addr ,
36+ addr : Elf_Addr ,
7037 /// The name of the object.
7138 name : CString ,
7239 /// Pointer to program headers C array.
73- phdrs : * const p_ffi :: Elf_Phdr ,
40+ phdrs : * const Elf_Phdr ,
7441 /// The number of program headers.
75- num_phdrs : p_ffi :: Elf_Half ,
42+ num_phdrs : Elf_Half ,
7643}
7744
7845impl Object {
@@ -96,7 +63,7 @@ impl Object {
9663 }
9764
9865 /// Returns the number of program headers.
99- pub fn num_phdrs ( & self ) -> p_ffi :: Elf_Half {
66+ pub fn num_phdrs ( & self ) -> Elf_Half {
10067 self . num_phdrs
10168 }
10269}
@@ -111,7 +78,7 @@ impl Debug for Object {
11178 }
11279}
11380
114- pub struct ProgramHeader ( * const p_ffi :: Elf_Phdr ) ;
81+ pub struct ProgramHeader ( * const Elf_Phdr ) ;
11582
11683impl ProgramHeader {
11784 /// Returns the segment type (as one of the `PT_*` constants).
@@ -160,7 +127,6 @@ impl ProgramHeader {
160127impl Debug for ProgramHeader {
161128 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
162129 let mut to_write = String :: from ( "ProgramHeader(" ) ;
163-
164130 let type_ = self . type_ ( ) ;
165131 let type_str = match type_ {
166132 PT_NULL => "PT_NULL" ,
@@ -184,13 +150,13 @@ impl Debug for ProgramHeader {
184150
185151 let flags = self . flags ( ) ;
186152 let mut flag_strs = Vec :: new ( ) ;
187- if flags & PF_X != 0 {
153+ if flags & PF_X . 0 != 0 {
188154 flag_strs. push ( "PF_X" ) ;
189155 }
190- if flags & PF_W != 0 {
156+ if flags & PF_W . 0 != 0 {
191157 flag_strs. push ( "PF_W" ) ;
192158 }
193- if flags & PF_R != 0 {
159+ if flags & PF_R . 0 != 0 {
194160 flag_strs. push ( "PF_R" ) ;
195161 }
196162 if flags & PF_MASKPROC != 0 {
@@ -211,8 +177,8 @@ impl Debug for ProgramHeader {
211177///
212178/// Each program header describes an ELF segment loaded in the virtual adress space.
213179pub struct ProgramHeaderIterator {
214- ptr : * const p_ffi :: Elf_Phdr , // Pointer to the next raw `Elf_Phdr`.
215- num : p_ffi :: Elf_Half , // How many left.
180+ ptr : * const Elf_Phdr , // Pointer to the next raw `Elf_Phdr`.
181+ num : Elf_Half , // How many left.
216182}
217183
218184impl Iterator for ProgramHeaderIterator {
@@ -235,7 +201,7 @@ pub fn objects() -> Vec<Object> {
235201 let mut ret = Vec :: new ( ) ;
236202
237203 // Pushes an `Object` into the result vector on the behalf of C.
238- extern "C" fn push_object ( objs : & mut Vec < Object > , obj : & p_ffi :: dl_phdr_info ) {
204+ extern "C" fn push_object ( objs : & mut Vec < Object > , obj : & dl_phdr_info ) {
239205 let name = unsafe { CStr :: from_ptr ( obj. dlpi_name ) } . to_owned ( ) ;
240206 // We have to copy the `dl_phdr_info` struct out, as the same memory buffer is used for
241207 // each entry during the iteration process. Otherwise we could have used a vector of
@@ -250,16 +216,16 @@ pub fn objects() -> Vec<Object> {
250216
251217 // Callback for `dl_iterate_phdr(3)`.
252218 unsafe extern "C" fn collect_objs (
253- info : * mut p_ffi :: dl_phdr_info ,
254- _sz : u64 ,
219+ info : * mut dl_phdr_info ,
220+ _sz : usize ,
255221 data : * mut c_void ,
256222 ) -> c_int {
257223 push_object ( & mut * ( data as * mut Vec < Object > ) , & * info) ; // Get Rust to push the object.
258224 0
259225 } ;
260226
261227 let ret_void_p = & mut ret as * mut Vec < Object > as * mut c_void ;
262- unsafe { p_ffi :: dl_iterate_phdr ( Some ( collect_objs) , ret_void_p) } ;
228+ unsafe { dl_iterate_phdr ( Some ( collect_objs) , ret_void_p) } ;
263229
264230 ret
265231}
0 commit comments