1 // Copyright Yazan Dabain 2014. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 module elf.sections.symboltable; 7 8 import std.exception; 9 import std.conv : to; 10 import elf, elf.low, elf.low32, elf.low64, elf.meta; 11 12 static if (__VERSION__ >= 2079) 13 alias elfEnforce = enforce!ELFException; 14 else 15 alias elfEnforce = enforceEx!ELFException; 16 17 18 struct SymbolTable { 19 private SymbolTableImpl m_impl; 20 21 this(ELFSection section) { 22 if (section.bits == 32) { 23 m_impl = new SymbolTable32Impl(section); 24 } else { 25 m_impl = new SymbolTable64Impl(section); 26 } 27 } 28 29 ELFSymbol getSymbolAt(size_t index) { 30 return m_impl.getSymbolAt(index); 31 } 32 33 auto symbols() { 34 static struct Symbols { 35 private SymbolTableImpl m_impl; 36 private size_t m_currentIndex = 0; 37 38 @property bool empty() { return m_currentIndex >= m_impl.length; } 39 40 @property ELFSymbol front() { 41 elfEnforce(!empty, "out of bounds exception"); 42 return m_impl.getSymbolAt(m_currentIndex); 43 } 44 45 void popFront() { 46 elfEnforce(!empty, "out of bounds exception"); 47 this.m_currentIndex++; 48 } 49 50 @property typeof(this) save() { 51 return this; 52 } 53 54 this(SymbolTableImpl impl) { 55 this.m_impl = impl; 56 } 57 } 58 59 return Symbols(this.m_impl); 60 } 61 } 62 63 private interface SymbolTableImpl { 64 ELFSymbol getSymbolAt(size_t index); 65 @property ulong length(); 66 } 67 68 private class SymbolTable32Impl : SymbolTableImpl { 69 private ELFSection32 m_section; 70 71 this(ELFSection section) { 72 elfEnforce(section.bits == 32); 73 this(cast(ELFSection32) section); 74 } 75 76 this(ELFSection32 section) { 77 this.m_section = section; 78 } 79 80 ELFSymbol getSymbolAt(size_t index) { 81 elfEnforce(index * ELFSymbol32L.sizeof < m_section.size); 82 ELFSymbol32L symbol; 83 symbol = *cast(ELFSymbol32L*) m_section.contents[index * ELFSymbol32L.sizeof .. (index + 1) * ELFSymbol32L.sizeof].ptr; 84 return new ELFSymbol32(m_section, symbol); 85 } 86 87 @property ulong length() { 88 return m_section.size / ELFSymbol32L.sizeof; 89 } 90 } 91 92 private class SymbolTable64Impl : SymbolTableImpl { 93 private ELFSection64 m_section; 94 95 this(ELFSection section) { 96 elfEnforce(section.bits == 64); 97 this(cast(ELFSection64) section); 98 } 99 100 this(ELFSection64 section) { 101 this.m_section = section; 102 } 103 104 ELFSymbol getSymbolAt(size_t index) { 105 elfEnforce(index * ELFSymbol64L.sizeof < m_section.size); 106 ELFSymbol64L symbol; 107 symbol = *cast(ELFSymbol64L*) m_section.contents[index * ELFSymbol64L.sizeof .. (index + 1) * ELFSymbol64L.sizeof].ptr; 108 return new ELFSymbol64(m_section, symbol); 109 } 110 111 @property ulong length() { 112 return m_section.size / ELFSymbol64L.sizeof; 113 } 114 } 115 116 abstract class ELFSymbol { 117 private ELFSection m_section; 118 119 @property: 120 @ReadFrom("name") ELF_Word nameIndex(); 121 @ReadFrom("info") ubyte info(); 122 @ReadFrom("other") ubyte other(); 123 @ReadFrom("shndx") ELF_Section sectionIndex(); 124 @ReadFrom("value") ELF_Addr value(); 125 @ReadFrom("size") ELF_XWord size(); 126 127 string name() { 128 StringTable strtab = StringTable(m_section.m_elf.sections[m_section.link()]); 129 return strtab.getStringAt(nameIndex); 130 } 131 132 SymbolBinding binding() { 133 return cast(SymbolBinding) (this.info() >> 4); 134 } 135 136 SymbolType type() { 137 return cast(SymbolType) (this.info() & 0xF); 138 } 139 } 140 141 final class ELFSymbol32 : ELFSymbol { 142 private ELFSymbol32L m_symbol; 143 mixin(generateVirtualReads!(ELFSymbol, "m_symbol")); 144 145 this(ELFSection32 section, ELFSymbol32L symbol) { 146 this.m_section = section; 147 this.m_symbol = symbol; 148 } 149 } 150 151 final class ELFSymbol64 : ELFSymbol { 152 private ELFSymbol64L m_symbol; 153 mixin(generateVirtualReads!(ELFSymbol, "m_symbol")); 154 155 this(ELFSection64 section, ELFSymbol64L symbol) { 156 this.m_section = section; 157 this.m_symbol = symbol; 158 } 159 } 160 161 enum SymbolBinding { 162 local = 0, 163 global = 1, 164 weak = 2, 165 loproc = 13, 166 hiproc = 15, 167 } 168 169 enum SymbolType { 170 notype = 0, 171 object = 1, 172 func = 2, 173 section = 3, 174 file = 4, 175 loproc = 13, 176 hiproc = 15, 177 }