@@ -40,6 +40,7 @@ cfg_if::cfg_if! {
40
40
target_os = "macos" ,
41
41
target_os = "openbsd" ,
42
42
target_os = "solaris" ,
43
+ target_os = "illumos" ,
43
44
) ) ] {
44
45
#[ path = "gimli/mmap_unix.rs" ]
45
46
mod mmap;
@@ -359,6 +360,110 @@ cfg_if::cfg_if! {
359
360
bias: slide,
360
361
} )
361
362
}
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
+ }
362
467
} else if #[ cfg( all(
363
468
any(
364
469
target_os = "linux" ,
0 commit comments