@@ -15,6 +15,7 @@ version (Posix):
15
15
16
16
import core.memory : pageSize;
17
17
import core.lifetime : move;
18
+ import core.stdc.stdlib : malloc, free;
18
19
import core.sys.posix.fcntl ;
19
20
import core.sys.posix.sys.mman ;
20
21
import core.sys.posix.unistd ;
@@ -361,23 +362,132 @@ private struct MMapRegion
361
362
public const (ubyte )[] data;
362
363
}
363
364
365
+ @nogc nothrow :
366
+
367
+ version (OpenBSD )
368
+ private extern (C ) const (char )* getprogname();
369
+
370
+ // / Returns the path to the process' executable as newly allocated C string
371
+ // / (free() when done), or null on error.
372
+ version (LinuxOrBSD)
373
+ char * thisExePath ()
374
+ {
375
+ version (linux )
376
+ {
377
+ return readLink (" /proc/self/exe" );
378
+ }
379
+ else version (Solaris )
380
+ {
381
+ import core.stdc.stdio : snprintf;
382
+ import core.sys.posix.unistd : getpid;
383
+
384
+ // only Solaris 10 and later
385
+ char [32 ] buffer = void ;
386
+ const numWritten = snprintf(buffer.ptr, sizeof(buffer), " /proc/%d/path/a.out" , getpid());
387
+ assert (numWritten > 0 && numWritten < sizeof(buffer));
388
+ assert (buffer[numWritten] == 0 );
389
+
390
+ return readLink (buffer.ptr);
391
+ }
392
+ else version (OpenBSD )
393
+ {
394
+ // there's apparently no proper way :/
395
+ import core.stdc.string : strdup;
396
+ return strdup (getprogname());
397
+ }
398
+ else
399
+ {
400
+ version (DragonFlyBSD )
401
+ {
402
+ import core.sys.dragonflybsd.sys.sysctl : sysctl, CTL_KERN , KERN_PROC , KERN_PROC_PATHNAME ;
403
+ int [4 ] mib = [CTL_KERN , KERN_PROC , KERN_PROC_PATHNAME , - 1 ];
404
+ }
405
+ else version (FreeBSD )
406
+ {
407
+ import core.sys.freebsd.sys.sysctl : sysctl, CTL_KERN , KERN_PROC , KERN_PROC_PATHNAME ;
408
+ int [4 ] mib = [CTL_KERN , KERN_PROC , KERN_PROC_PATHNAME , - 1 ];
409
+ }
410
+ else version (NetBSD )
411
+ {
412
+ import core.sys.netbsd.sys.sysctl : sysctl, CTL_KERN , KERN_PROC_ARGS , KERN_PROC_PATHNAME ;
413
+ int [4 ] mib = [CTL_KERN , KERN_PROC_ARGS , - 1 , KERN_PROC_PATHNAME ];
414
+ }
415
+ else
416
+ static assert (0 , " Unsupported platform" );
417
+
418
+ // get the length of the path
419
+ size_t len;
420
+ auto result = sysctl(mib.ptr, mib.length, null , &len, null , 0 );
421
+ if (result != 0 )
422
+ return null ;
423
+
424
+ auto buffer = cast (char * ) malloc(len);
425
+ if (! buffer)
426
+ return null ;
427
+ result = sysctl(mib.ptr, mib.length, buffer, &len, null , 0 );
428
+ if (result != 0 )
429
+ {
430
+ free(buffer);
431
+ return null ;
432
+ }
433
+
434
+ assert (buffer[len - 1 ] == 0 );
435
+ return buffer;
436
+ }
437
+ }
438
+
439
+ // Tries to read the target of the specified link as newly allocated C string.
440
+ // Returns null on error; free() result otherwise when done.
441
+ private char * readLink (const (char )* link)
442
+ {
443
+ for (size_t bufferSize = 128 ; bufferSize < 131_072; bufferSize *= 2 )
444
+ {
445
+ auto buffer = cast (char * ) malloc(bufferSize);
446
+ if (! buffer)
447
+ return null ;
448
+
449
+ const numWritten = readlink(link, buffer, bufferSize);
450
+ if (numWritten == - 1 )
451
+ {
452
+ free(buffer);
453
+ return null ;
454
+ }
455
+
456
+ enum maxCodeUnits = 6 ;
457
+ if (numWritten <= bufferSize - maxCodeUnits)
458
+ {
459
+ buffer[numWritten] = 0 ; // null-terminate
460
+ return buffer;
461
+ }
462
+ else
463
+ free(buffer);
464
+ }
465
+
466
+ return null ;
467
+ }
468
+
364
469
version (LinuxOrBSD)
365
470
unittest
366
471
{
367
- import core.internal.elf.dl , core.stdc.stdio ;
472
+ import core.internal.elf.dl : SharedObject;
473
+ import core.stdc.stdio : printf;
368
474
369
- SharedObject exe = SharedObject.thisExecutable();
475
+ char * exePath = thisExePath();
476
+ assert (exePath);
477
+ scope (exit) free (exePath);
370
478
371
479
ElfFile file;
372
- bool success = ElfFile.open(exe.name.ptr, file);
373
- assert (success, " cannot open ELF file" );
480
+ bool success = ElfFile.open(exePath, file);
481
+ assert (success, " cannot open ELF executable" );
482
+
483
+ const exeBaseAddress = SharedObject.thisExecutable().baseAddress;
374
484
375
485
foreach (index, name, sectionHeader; file.namedSections)
376
486
{
377
487
printf(" section %3d %-32s" , cast (int ) index, name.ptr);
378
488
if (const offset = sectionHeader.shdr.sh_addr)
379
489
{
380
- auto beg = exe.baseAddress + offset;
490
+ auto beg = exeBaseAddress + offset;
381
491
printf(" %p - %p\n " , beg, beg + sectionHeader.shdr.sh_size);
382
492
}
383
493
else
0 commit comments