1 module bc.core.system.linux.elf;
2 
3 version (D_BetterC) {}
4 else:
5 
6 // Copy from normally unavailable https://github.com/dlang/druntime/blob/master/src/rt/backtrace/elf.d
7 
8 version (linux)
9 {
10     import core.sys.linux.elf;
11     version = LinuxOrBSD;
12 }
13 else version (FreeBSD)
14 {
15     import core.sys.freebsd.sys.elf;
16     version = LinuxOrBSD;
17 }
18 else version (DragonFlyBSD)
19 {
20     import core.sys.dragonflybsd.sys.elf;
21     version = LinuxOrBSD;
22 }
23 
24 version (LinuxOrBSD):
25 
26 import core.internal.elf.dl;
27 import core.internal.elf.io;
28 
29 struct Image
30 {
31     private ElfFile file;
32 
33     nothrow @nogc:
34 
35     static Image openSelf()
36     {
37         // see: https://github.com/dlang/druntime/commit/e3c8f38141cd148e92bc949fd88a3e50d0054807
38         // const(char)* selfPath = SharedObject.thisExecutable().name().ptr;
39         const(char)* selfPath;
40         foreach (object; SharedObjects)
41         {
42             // the first object is the main binary
43             selfPath = object.name().ptr;
44             break;
45         }
46 
47         Image image;
48         if (!ElfFile.open(selfPath, image.file))
49             image.file = ElfFile.init;
50 
51         return image;
52     }
53 
54     @property bool isValid()
55     {
56         return file != ElfFile.init;
57     }
58 
59     T processDebugLineSectionData(S, T)(ref S sink, const(void*)[] callstack, const char** frameList,
60         scope T function(ref S, ref Image, const(void*)[], const char**, const(ubyte)[]) nothrow @nogc processor)
61     {
62         ElfSectionHeader dbgSectionHeader;
63         ElfSection dbgSection;
64 
65         if (file.findSectionHeaderByName(".debug_line", dbgSectionHeader))
66         {
67             // we don't support compressed debug sections
68             if (!(dbgSectionHeader.shdr.sh_flags & SHF_COMPRESSED))
69                 dbgSection = ElfSection(file, dbgSectionHeader);
70         }
71 
72         return processor(sink, this, callstack, frameList, cast(const(ubyte)[])dbgSection.data());
73     }
74 
75     @property size_t baseAddress()
76     {
77         // the DWARF addresses for DSOs are relative
78         const isDynamicSharedObject = (file.ehdr.e_type == ET_DYN);
79         if (!isDynamicSharedObject)
80             return 0;
81 
82         // see: https://github.com/dlang/druntime/commit/e3c8f38141cd148e92bc949fd88a3e50d0054807
83         // return cast(size_t) SharedObject.thisExecutable().baseAddress;
84 
85         size_t base = 0;
86         foreach (object; SharedObjects)
87         {
88             // only take the first address as this will be the main binary
89             base = cast(size_t) object.baseAddress;
90             break;
91         }
92 
93         return base;
94     }
95 }