@@ -40,6 +40,7 @@ cfg_if::cfg_if! {
4040 target_os = "macos" ,
4141 target_os = "openbsd" ,
4242 target_os = "solaris" ,
43+ target_os = "illumos" ,
4344 ) ) ] {
4445 #[ path = "gimli/mmap_unix.rs" ]
4546 mod mmap;
@@ -359,6 +360,110 @@ cfg_if::cfg_if! {
359360 bias: slide,
360361 } )
361362 }
363+ } else if #[ cfg( target_os = "illumos" ) ] {
364+ use mystd:: os:: unix:: prelude:: * ;
365+ use mystd:: ffi:: { OsStr , CStr } ;
366+ use object:: NativeEndian ;
367+
368+ #[ cfg( target_pointer_width = "64" ) ]
369+ use object:: elf:: {
370+ FileHeader64 as FileHeader ,
371+ ProgramHeader64 as ProgramHeader
372+ } ;
373+
374+ type EHdr = FileHeader <NativeEndian >;
375+ type PHdr = ProgramHeader <NativeEndian >;
376+
377+ mod elf;
378+ use self :: elf:: Object ;
379+
380+ #[ repr( C ) ]
381+ struct LinkMap {
382+ l_addr: libc:: c_ulong,
383+ l_name: * const libc:: c_char,
384+ l_ld: * const libc:: c_void,
385+ l_next: * const LinkMap ,
386+ l_prev: * const LinkMap ,
387+ l_refname: * const libc:: c_char,
388+ }
389+
390+ const RTLD_SELF : * const libc:: c_void = -3isize as * const libc:: c_void;
391+ const RTLD_DI_LINKMAP : libc:: c_int = 2 ;
392+
393+ extern "C" {
394+ fn dlinfo(
395+ handle: * const libc:: c_void,
396+ request: libc:: c_int,
397+ p: * mut libc:: c_void,
398+ ) -> libc:: c_int;
399+ }
400+
401+ fn native_libraries( ) -> Vec <Library > {
402+ let mut libs = Vec :: new( ) ;
403+
404+ // Request the current link map from the runtime linker:
405+ let map = unsafe {
406+ let mut map: * const LinkMap = std:: mem:: zeroed( ) ;
407+ if dlinfo(
408+ RTLD_SELF ,
409+ RTLD_DI_LINKMAP ,
410+ ( & mut map) as * mut * const LinkMap as * mut libc:: c_void
411+ ) != 0 {
412+ return libs;
413+ }
414+ map
415+ } ;
416+
417+ // Each entry in the link map represents a loaded object:
418+ let mut l = map;
419+ while !l. is_null( ) {
420+ // Fetch the fully qualified path of the loaded object:
421+ let bytes = unsafe { CStr :: from_ptr( ( * l) . l_name) } . to_bytes( ) ;
422+ let name = OsStr :: from_bytes( bytes) . to_owned( ) ;
423+
424+ // The base address of the object loaded into memory:
425+ let addr = unsafe { ( * l) . l_addr } ;
426+
427+ // Use the ELF header for this object to locate the program
428+ // header:
429+ let e: * const EHdr = unsafe { ( * l) . l_addr as * const EHdr } ;
430+ let phoff = unsafe { ( * e) . e_phoff } . get( NativeEndian ) ;
431+ let phnum = unsafe { ( * e) . e_phnum } . get( NativeEndian ) ;
432+ let etype = unsafe { ( * e) . e_type } . get( NativeEndian ) ;
433+
434+ let phdr: * const PHdr = ( addr + phoff) as * const PHdr ;
435+ let phdr = unsafe {
436+ core:: slice:: from_raw_parts( phdr, phnum as usize )
437+ } ;
438+
439+ libs. push( Library {
440+ name,
441+ segments: phdr
442+ . iter( )
443+ . map( |p| {
444+ let memsz = p. p_memsz. get( NativeEndian ) ;
445+ let vaddr = p. p_vaddr. get( NativeEndian ) ;
446+ LibrarySegment {
447+ len: memsz as usize ,
448+ stated_virtual_memory_address: vaddr as usize ,
449+ }
450+ } )
451+ . collect( ) ,
452+ bias: if etype == object:: elf:: ET_EXEC {
453+ // Program header addresses for the base executable are
454+ // already absolute.
455+ 0
456+ } else {
457+ // Other addresses are relative to the object base.
458+ addr as usize
459+ } ,
460+ } ) ;
461+
462+ l = unsafe { ( * l) . l_next } ;
463+ }
464+
465+ libs
466+ }
362467 } else if #[ cfg( all(
363468 any(
364469 target_os = "linux" ,
0 commit comments