@@ -68,6 +68,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
68
68
use std:: ffi:: { CStr , OsStr } ;
69
69
use std:: os:: unix:: prelude:: * ;
70
70
71
+ #[ cfg( not( target_os = "aix" ) ) ]
71
72
unsafe {
72
73
let addr = current_dll_path as usize as * mut _ ;
73
74
let mut info = std:: mem:: zeroed ( ) ;
@@ -81,6 +82,49 @@ fn current_dll_path() -> Result<PathBuf, String> {
81
82
let os = OsStr :: from_bytes ( bytes) ;
82
83
Ok ( PathBuf :: from ( os) )
83
84
}
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
+ }
84
128
}
85
129
86
130
#[ cfg( windows) ]
0 commit comments