@@ -68,6 +68,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
6868 use std:: ffi:: { CStr , OsStr } ;
6969 use std:: os:: unix:: prelude:: * ;
7070
71+ #[ cfg( not( target_os = "aix" ) ) ]
7172 unsafe {
7273 let addr = current_dll_path as usize as * mut _ ;
7374 let mut info = std:: mem:: zeroed ( ) ;
@@ -81,6 +82,49 @@ fn current_dll_path() -> Result<PathBuf, String> {
8182 let os = OsStr :: from_bytes ( bytes) ;
8283 Ok ( PathBuf :: from ( os) )
8384 }
85+
86+ #[ cfg( target_os = "aix" ) ]
87+ unsafe {
88+ // On AIX, the symbol `current_dll_path` references a function descriptor.
89+ // A function descriptor is consisted of (See https://reviews.llvm.org/D62532)
90+ // * The address of the entry point of the function.
91+ // * The TOC base address for the function.
92+ // * The environment pointer.
93+ // The function descriptor is in the data section.
94+ let addr = current_dll_path as u64 ;
95+ let mut buffer = vec ! [ std:: mem:: zeroed:: <libc:: ld_info>( ) ; 64 ] ;
96+ loop {
97+ if libc:: loadquery (
98+ libc:: L_GETINFO ,
99+ buffer. as_mut_ptr ( ) as * mut i8 ,
100+ ( std:: mem:: size_of :: < libc:: ld_info > ( ) * buffer. len ( ) ) as u32 ,
101+ ) >= 0
102+ {
103+ break ;
104+ } else {
105+ if std:: io:: Error :: last_os_error ( ) . raw_os_error ( ) . unwrap ( ) != libc:: ENOMEM {
106+ return Err ( "loadquery failed" . into ( ) ) ;
107+ }
108+ buffer. resize ( buffer. len ( ) * 2 , std:: mem:: zeroed :: < libc:: ld_info > ( ) ) ;
109+ }
110+ }
111+ let mut current = buffer. as_mut_ptr ( ) as * mut libc:: ld_info ;
112+ loop {
113+ let data_base = ( * current) . ldinfo_dataorg as u64 ;
114+ let data_end = data_base + ( * current) . ldinfo_datasize ;
115+ if ( data_base..data_end) . contains ( & addr) {
116+ let bytes = CStr :: from_ptr ( & ( * current) . ldinfo_filename [ 0 ] ) . to_bytes ( ) ;
117+ let os = OsStr :: from_bytes ( bytes) ;
118+ return Ok ( PathBuf :: from ( os) ) ;
119+ }
120+ if ( * current) . ldinfo_next == 0 {
121+ break ;
122+ }
123+ current =
124+ ( current as * mut i8 ) . offset ( ( * current) . ldinfo_next as isize ) as * mut libc:: ld_info ;
125+ }
126+ return Err ( format ! ( "current dll's address {} is not in the load map" , addr) ) ;
127+ }
84128}
85129
86130#[ cfg( windows) ]
0 commit comments