├── .classpath ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── README.md ├── bin └── com │ └── bluth │ ├── parse │ ├── ParseSO.class │ ├── ReadElf$Symbol.class │ └── ReadElf.class │ └── readelf │ ├── DataSource.class │ ├── ELFException.class │ ├── ELFFile.class │ ├── ELFFileParser$ELFFileImpl$ELFHashTableImpl.class │ ├── ELFFileParser$ELFFileImpl$ELFHeaderImpl$1.class │ ├── ELFFileParser$ELFFileImpl$ELFHeaderImpl.class │ ├── ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$1.class │ ├── ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$2.class │ ├── ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$3.class │ ├── ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl.class │ ├── ELFFileParser$ELFFileImpl$ELFStringTableImpl.class │ ├── ELFFileParser$ELFFileImpl$ELFSymbolImpl.class │ ├── ELFFileParser$ELFFileImpl.class │ ├── ELFFileParser.class │ ├── ELFHashTable.class │ ├── ELFHeader.class │ ├── ELFProgramHeader.class │ ├── ELFSectionHeader.class │ ├── ELFStringTable.class │ ├── ELFSymbol.class │ ├── MemoizedObject.class │ └── RandomAccessFileDataSource.class ├── libgetstr.so └── src └── com └── bluth ├── parse ├── ParseSO.java └── ReadElf.java └── readelf ├── DataSource.java ├── ELFException.java ├── ELFFile.java ├── ELFFileParser.java ├── ELFHashTable.java ├── ELFHeader.java ├── ELFProgramHeader.java ├── ELFSectionHeader.java ├── ELFStringTable.java ├── ELFSymbol.java ├── MemoizedObject.java └── RandomAccessFileDataSource.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | READELF 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.6 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/README.md -------------------------------------------------------------------------------- /bin/com/bluth/parse/ParseSO.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/parse/ParseSO.class -------------------------------------------------------------------------------- /bin/com/bluth/parse/ReadElf$Symbol.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/parse/ReadElf$Symbol.class -------------------------------------------------------------------------------- /bin/com/bluth/parse/ReadElf.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/parse/ReadElf.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/DataSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/DataSource.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFException.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFile.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFile.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFHashTableImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFHashTableImpl.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFHeaderImpl$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFHeaderImpl$1.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFHeaderImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFHeaderImpl.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$1.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$2.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl$3.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSectionHeaderImpl.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFStringTableImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFStringTableImpl.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSymbolImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl$ELFSymbolImpl.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser$ELFFileImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser$ELFFileImpl.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFFileParser.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFFileParser.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFHashTable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFHashTable.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFHeader.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFHeader.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFProgramHeader.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFProgramHeader.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFSectionHeader.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFSectionHeader.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFStringTable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFStringTable.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/ELFSymbol.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/ELFSymbol.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/MemoizedObject.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/MemoizedObject.class -------------------------------------------------------------------------------- /bin/com/bluth/readelf/RandomAccessFileDataSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/bin/com/bluth/readelf/RandomAccessFileDataSource.class -------------------------------------------------------------------------------- /libgetstr.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluthmatter/ReadElf/3c2cc08df8bda5854e761f7de190ee4a7f1054e2/libgetstr.so -------------------------------------------------------------------------------- /src/com/bluth/parse/ParseSO.java: -------------------------------------------------------------------------------- 1 | package com.bluth.parse; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | import java.util.Map; 8 | import java.util.Map.Entry; 9 | 10 | import com.bluth.parse.ReadElf.Symbol; 11 | import com.bluth.readelf.ELFFileParser; 12 | 13 | public class ParseSO { 14 | 15 | public static void main(String[] args) throws Exception { 16 | parseSO(); 17 | } 18 | 19 | private static void parseSO() throws Exception { 20 | ELFFileParser.main(new String[]{"libgetstr.so" }); 21 | } 22 | 23 | static void outMap(Map map) { 24 | Iterator i = map.entrySet().iterator(); 25 | while (i.hasNext()) { 26 | Map.Entry entry = (Entry) i.next(); 27 | String key = entry.getKey(); 28 | String value = entry.getValue(); 29 | System.out.println(key + "===" + value); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/com/bluth/parse/ReadElf.java: -------------------------------------------------------------------------------- 1 | package com.bluth.parse; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.RandomAccessFile; 6 | import java.util.HashMap; 7 | import java.util.Iterator; 8 | import java.util.Map; 9 | import java.util.Map.Entry; 10 | 11 | /** 12 | * A poor man's implementation of the readelf command. This program is 13 | * designed to parse ELF (Executable and Linkable Format) files. 14 | */ 15 | public class ReadElf { 16 | /** The magic values for the ELF identification. */ 17 | private static final byte[] ELF_IDENT = { 18 | (byte) 0x7F, (byte) 'E', (byte) 'L', (byte) 'F', 19 | }; 20 | 21 | /** Size of the e_ident[] structure in the ELF header. */ 22 | private static final int EI_NIDENT = 16; 23 | 24 | /** Offset from end of ident structure in half-word sizes. */ 25 | private static final int OFFSET_TYPE = 0; 26 | 27 | /** Machine type. */ 28 | private static final int OFFSET_MACHINE = 1; 29 | 30 | /** ELF version. */ 31 | private static final int OFFSET_VERSION = 2; 32 | 33 | /** 34 | * The offset to which the system transfers control. e.g., the first thing 35 | * executed. 36 | */ 37 | private static final int OFFSET_ENTRY = 4; 38 | 39 | /** Program header offset in bytes. */ 40 | private static final int OFFSET_PHOFF = 6; 41 | 42 | /** Segment header offset in bytes. */ 43 | private static final int OFFSET_SHOFF = 8; 44 | 45 | /** Processor-specific flags for binary. */ 46 | private static final int OFFSET_FLAGS = 10; 47 | 48 | /** ELF header size in bytes. */ 49 | private static final int OFFSET_EHSIZE = 12; 50 | 51 | /** All program headers entry size in bytes. */ 52 | private static final int OFFSET_PHENTSIZE = 13; 53 | 54 | /** Number of program headers in ELF. */ 55 | private static final int OFFSET_PHNUM = 14; 56 | 57 | /** All segment headers entry size in bytes. */ 58 | private static final int OFFSET_SHENTSIZE = 15; 59 | 60 | /** Number of segment headers in ELF. */ 61 | private static final int OFFSET_SHNUM = 16; 62 | 63 | /** The section header index that refers to string table. */ 64 | private static final int OFFSET_SHSTRNDX = 17; 65 | 66 | /** Program header offset for type of this program header. */ 67 | private static final int PHOFF_TYPE = 0; 68 | 69 | /** Program header offset for absolute offset in file. */ 70 | private static final int PHOFF_OFFSET = 2; 71 | 72 | /** Program header offset for virtual address. */ 73 | private static final int PHOFF_VADDR = 4; 74 | 75 | /** Program header offset for physical address. */ 76 | private static final int PHOFF_PADDR = 6; 77 | 78 | /** Program header offset for file size in bytes. */ 79 | private static final int PHOFF_FILESZ = 8; 80 | 81 | /** Program header offset for memory size in bytes. */ 82 | private static final int PHOFF_MEMSZ = 10; 83 | 84 | /** Program header offset for flags. */ 85 | private static final int PHOFF_FLAGS = 12; 86 | 87 | /** 88 | * Program header offset for required alignment. 0 or 1 means no alignment 89 | * necessary. 90 | */ 91 | private static final int PHOFF_ALIGN = 14; 92 | 93 | /** Index into string pool for segment name. */ 94 | private static final long SHOFF_NAME = 0; 95 | 96 | /** Segment header offset for type (half-words) */ 97 | private static final long SHOFF_TYPE = 2; 98 | 99 | /** Segment header offset for offset (meta!) (half-words) */ 100 | private static final long SHOFF_OFFSET = 8; 101 | 102 | /** Segment header offset for size (half-words) */ 103 | private static final long SHOFF_SIZE = 10; 104 | 105 | /** Data is presented in LSB format. */ 106 | private static final int ELFDATA2LSB = 1; 107 | 108 | /** Date is presented in MSB format. */ 109 | private static final int ELFDATA2MSB = 2; 110 | 111 | private static final int ELFCLASS32 = 1; 112 | 113 | private static final int ELFCLASS64 = 2; 114 | 115 | private static final long PT_LOAD = 1; 116 | 117 | /** Section Type: Symbol Table */ 118 | private static final int SHT_SYMTAB = 2; 119 | 120 | /** Section Type: String Table */ 121 | private static final int SHT_STRTAB = 3; 122 | 123 | /** Section Type: Dynamic **/ 124 | private static final int SHT_DYNAMIC = 6; 125 | 126 | /** Section Type: Dynamic Symbol Table */ 127 | private static final int SHT_DYNSYM = 11; 128 | 129 | /** Symbol Table Entry: Name offset */ 130 | private static final int SYMTAB_NAME = 0; 131 | 132 | /** Symbol Table Entry: SymTab Info */ 133 | private static final int SYMTAB_ST_INFO = 6; 134 | 135 | /** Symbol Table Entry size (half-words) */ 136 | private static final int SYMTAB_ENTRY_HALFWORD_SIZE = 7; 137 | 138 | /** 139 | * Symbol Table Entry size (extra in bytes) to cover "st_info" and 140 | * "st_other" 141 | */ 142 | private static final int SYMTAB_ENTRY_BYTE_EXTRA_SIZE = 2; 143 | 144 | public static class Symbol { 145 | public static final int STB_LOCAL = 0; 146 | 147 | public static final int STB_GLOBAL = 1; 148 | 149 | public static final int STB_WEAK = 2; 150 | 151 | public static final int STB_LOPROC = 13; 152 | 153 | public static final int STB_HIPROC = 15; 154 | 155 | public final String name; 156 | 157 | public final int bind; 158 | 159 | public final int type; 160 | 161 | Symbol(String name, int st_info) { 162 | this.name = name; 163 | this.bind = (st_info >> 4) & 0x0F; 164 | this.type = st_info & 0x0F; 165 | } 166 | }; 167 | 168 | private final RandomAccessFile mFile; 169 | private final byte[] mBuffer = new byte[512]; 170 | private int mClass; 171 | private int mEndian; 172 | private boolean mIsDynamic; 173 | private boolean mIsPIE; 174 | private int mType; 175 | private int mWordSize; 176 | private int mHalfWordSize; 177 | 178 | /** Symbol Table offset */ 179 | private long mSymTabOffset; 180 | 181 | /** Symbol Table size */ 182 | private long mSymTabSize; 183 | 184 | /** Dynamic Symbol Table offset */ 185 | private long mDynSymOffset; 186 | 187 | /** Dynamic Symbol Table size */ 188 | private long mDynSymSize; 189 | 190 | /** Section Header String Table offset */ 191 | private long mShStrTabOffset; 192 | 193 | /** Section Header String Table size */ 194 | private long mShStrTabSize; 195 | 196 | /** String Table offset */ 197 | private long mStrTabOffset; 198 | 199 | /** String Table size */ 200 | private long mStrTabSize; 201 | 202 | /** Dynamic String Table offset */ 203 | private long mDynStrOffset; 204 | 205 | /** Dynamic String Table size */ 206 | private long mDynStrSize; 207 | 208 | /** Symbol Table symbol names */ 209 | private Map mSymbols; 210 | 211 | /** Dynamic Symbol Table symbol names */ 212 | private Map mDynamicSymbols; 213 | 214 | static ReadElf read(File file) throws IOException { 215 | return new ReadElf(file); 216 | } 217 | 218 | boolean isDynamic() { 219 | return mIsDynamic; 220 | } 221 | 222 | int getType() { 223 | return mType; 224 | } 225 | 226 | boolean isPIE() { 227 | return mIsPIE; 228 | } 229 | 230 | private ReadElf(File file) throws IOException { 231 | mFile = new RandomAccessFile(file, "r"); 232 | 233 | readIdent(); 234 | 235 | readHeader(); 236 | } 237 | 238 | protected void finalize() throws Throwable { 239 | try { 240 | mFile.close(); 241 | } catch (IOException e) { 242 | // nothing 243 | } finally { 244 | super.finalize(); 245 | } 246 | } 247 | 248 | private void readHeader() throws IOException { 249 | mType = readHalf(getHeaderOffset(OFFSET_TYPE)); 250 | 251 | final long shOffset = readWord(getHeaderOffset(OFFSET_SHOFF)); 252 | final int shNumber = readHalf(getHeaderOffset(OFFSET_SHNUM)); 253 | final int shSize = readHalf(getHeaderOffset(OFFSET_SHENTSIZE)); 254 | final int shStrIndex = readHalf(getHeaderOffset(OFFSET_SHSTRNDX)); 255 | 256 | readSectionHeaders(shOffset, shNumber, shSize, shStrIndex); 257 | 258 | final long phOffset = readWord(getHeaderOffset(OFFSET_PHOFF)); 259 | final int phNumber = readHalf(getHeaderOffset(OFFSET_PHNUM)); 260 | final int phSize = readHalf(getHeaderOffset(OFFSET_PHENTSIZE)); 261 | 262 | readProgramHeaders(phOffset, phNumber, phSize); 263 | } 264 | 265 | private void readSectionHeaders(long tableOffset, int shNumber, int shSize, int shStrIndex) 266 | throws IOException { 267 | // Read the Section Header String Table offset first. 268 | { 269 | final long shStrTabShOffset = tableOffset + shStrIndex * shSize; 270 | final long type = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_TYPE); 271 | 272 | if (type == SHT_STRTAB) { 273 | mShStrTabOffset = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_OFFSET); 274 | mShStrTabSize = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_SIZE); 275 | } 276 | } 277 | 278 | for (int i = 0; i < shNumber; i++) { 279 | // Don't bother to re-read the Section Header StrTab. 280 | if (i == shStrIndex) { 281 | continue; 282 | } 283 | 284 | final long shOffset = tableOffset + i * shSize; 285 | 286 | final long type = readWord(shOffset + mHalfWordSize * SHOFF_TYPE); 287 | if ((type == SHT_SYMTAB) || (type == SHT_DYNSYM)) { 288 | final long nameOffset = readWord(shOffset + mHalfWordSize * SHOFF_NAME); 289 | final long offset = readWord(shOffset + mHalfWordSize * SHOFF_OFFSET); 290 | final long size = readWord(shOffset + mHalfWordSize * SHOFF_SIZE); 291 | 292 | final String symTabName = readShStrTabEntry(nameOffset); 293 | 294 | if (".symtab".equals(symTabName)) { 295 | mSymTabOffset = offset; 296 | mSymTabSize = size; 297 | } else if (".dynsym".equals(symTabName)) { 298 | mDynSymOffset = offset; 299 | mDynSymSize = size; 300 | } 301 | } else if (type == SHT_STRTAB) { 302 | final long nameOffset = readWord(shOffset + mHalfWordSize * SHOFF_NAME); 303 | final long offset = readWord(shOffset + mHalfWordSize * SHOFF_OFFSET); 304 | final long size = readWord(shOffset + mHalfWordSize * SHOFF_SIZE); 305 | 306 | final String strTabName = readShStrTabEntry(nameOffset); 307 | System.out.println(strTabName); 308 | if (".strtab".equals(strTabName)) { 309 | mStrTabOffset = offset; 310 | mStrTabSize = size; 311 | } else if (".dynstr".equals(strTabName)) { 312 | mDynStrOffset = offset; 313 | mDynStrSize = size; 314 | } 315 | } else if (type == SHT_DYNAMIC) { 316 | mIsDynamic = true; 317 | } 318 | } 319 | } 320 | 321 | private void readProgramHeaders(long phOffset, int phNumber, int phSize) throws IOException { 322 | for (int i = 0; i < phNumber; i++) { 323 | final long baseOffset = phOffset + i * phSize; 324 | final long type = readWord(baseOffset); 325 | if (type == PT_LOAD) { 326 | final long virtAddress = readWord(baseOffset + mHalfWordSize * PHOFF_VADDR); 327 | System.out.println(String.format("%h", virtAddress)); 328 | if (virtAddress == 0) { 329 | mIsPIE = true; 330 | } 331 | } 332 | } 333 | } 334 | 335 | private void readSymbolTable(Map symbolMap, long symStrOffset, long symStrSize, 336 | long symOffset, long symSize) throws IOException { 337 | final long symEnd = symOffset + symSize; 338 | for (long off = symOffset; off < symEnd; off += SYMTAB_ENTRY_HALFWORD_SIZE * mHalfWordSize 339 | + SYMTAB_ENTRY_BYTE_EXTRA_SIZE) { 340 | long strOffset = readWord(off + SYMTAB_NAME); 341 | if (strOffset == 0) { 342 | continue; 343 | } 344 | 345 | final String symName = readStrTabEntry(symStrOffset, symStrSize, strOffset); 346 | System.out.println(symName); 347 | if (symName != null) { 348 | final int st_info = readByte(off + SYMTAB_ST_INFO); 349 | symbolMap.put(symName, new Symbol(symName, st_info)); 350 | } 351 | } 352 | outMap(symbolMap); 353 | } 354 | 355 | static void outMap(Map map) { 356 | Iterator i = map.entrySet().iterator(); 357 | while (i.hasNext()) { 358 | Map.Entry entry = (Entry) i.next(); 359 | String key = entry.getKey(); 360 | Symbol value = entry.getValue(); 361 | System.out.println(key + "===" + value.name); 362 | } 363 | } 364 | 365 | private String readShStrTabEntry(long strOffset) throws IOException { 366 | if ((mShStrTabOffset == 0) || (strOffset < 0) || (strOffset >= mShStrTabSize)) { 367 | return null; 368 | } 369 | 370 | return readString(mShStrTabOffset + strOffset); 371 | } 372 | 373 | private String readStrTabEntry(long tableOffset, long tableSize, long strOffset) 374 | throws IOException { 375 | if ((tableOffset == 0) || (strOffset < 0) || (strOffset >= tableSize)) { 376 | return null; 377 | } 378 | 379 | return readString(tableOffset + strOffset); 380 | } 381 | 382 | private int getHeaderOffset(int halfWorldOffset) { 383 | return EI_NIDENT + halfWorldOffset * mHalfWordSize; 384 | } 385 | 386 | private int readByte(long offset) throws IOException { 387 | mFile.seek(offset); 388 | mFile.readFully(mBuffer, 0, 1); 389 | 390 | return mBuffer[0]; 391 | } 392 | 393 | private int readHalf(long offset) throws IOException { 394 | mFile.seek(offset); 395 | mFile.readFully(mBuffer, 0, mWordSize); 396 | 397 | final int answer; 398 | if (mEndian == ELFDATA2LSB) { 399 | answer = mBuffer[1] << 8 | mBuffer[0]; 400 | } else { 401 | answer = mBuffer[0] << 8 | mBuffer[1]; 402 | } 403 | 404 | return answer; 405 | } 406 | 407 | private long readWord(long offset) throws IOException { 408 | mFile.seek(offset); 409 | mFile.readFully(mBuffer, 0, mWordSize); 410 | 411 | int answer = 0; 412 | if (mEndian == ELFDATA2LSB) { 413 | for (int i = mWordSize - 1; i >= 0; i--) { 414 | answer = (answer << 8) | (mBuffer[i] & 0xFF); 415 | } 416 | } else { 417 | final int N = mWordSize - 1; 418 | for (int i = 0; i <= N; i++) { 419 | answer = (answer << 8) | mBuffer[i]; 420 | } 421 | } 422 | 423 | return answer; 424 | } 425 | 426 | private String readString(long offset) throws IOException { 427 | mFile.seek(offset); 428 | mFile.readFully(mBuffer, 0, (int) Math.min(mBuffer.length, mFile.length() - offset)); 429 | 430 | for (int i = 0; i < mBuffer.length; i++) { 431 | if (mBuffer[i] == 0) { 432 | return new String(mBuffer, 0, i); 433 | } 434 | } 435 | 436 | return null; 437 | } 438 | 439 | private void readIdent() throws IOException { 440 | mFile.seek(0); 441 | mFile.readFully(mBuffer, 0, EI_NIDENT); 442 | 443 | if ((mBuffer[0] != ELF_IDENT[0]) || (mBuffer[1] != ELF_IDENT[1]) 444 | || (mBuffer[2] != ELF_IDENT[2]) || (mBuffer[3] != ELF_IDENT[3])) { 445 | throw new IllegalArgumentException("Invalid ELF file"); 446 | } 447 | 448 | mClass = mBuffer[4]; 449 | if (mClass == ELFCLASS32) { 450 | mWordSize = 4; 451 | mHalfWordSize = 2; 452 | } else { 453 | throw new IOException("Invalid executable type " + mClass + ": not ELFCLASS32!"); 454 | } 455 | 456 | mEndian = mBuffer[5]; 457 | } 458 | 459 | public Symbol getSymbol(String name) { 460 | if ((mSymTabOffset == 0) && (mSymTabSize == 0)) { 461 | return null; 462 | } 463 | 464 | if (mSymbols == null) { 465 | mSymbols = new HashMap(); 466 | try { 467 | readSymbolTable(mSymbols, mStrTabOffset, mStrTabSize, mSymTabOffset, mSymTabSize); 468 | } catch (IOException e) { 469 | return null; 470 | } 471 | } 472 | 473 | return mSymbols.get(name); 474 | } 475 | 476 | public Symbol getDynamicSymbol(String name) { 477 | if ((mDynSymOffset == 0) && (mDynSymSize == 0)) { 478 | return null; 479 | } 480 | 481 | if (mDynamicSymbols == null) { 482 | mDynamicSymbols = new HashMap(); 483 | try { 484 | readSymbolTable(mDynamicSymbols, mDynStrOffset, mDynStrSize, mDynSymOffset, 485 | mDynSymSize); 486 | } catch (IOException e) { 487 | return null; 488 | } 489 | } 490 | 491 | return mDynamicSymbols.get(name); 492 | } 493 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/DataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | import java.io.*; 28 | 29 | /** An abstraction which represents a seekable data source. 30 | RandomAccessFile can be trivially mapped to this; in addition, we 31 | can support an adapter for addresses, so we can parse DLLs 32 | directly out of the remote process's address space. This class is 33 | used by the Windows COFF and Posix ELF implementations. */ 34 | 35 | public interface DataSource { 36 | public byte readByte() throws IOException; 37 | public short readShort() throws IOException; 38 | public int readInt() throws IOException; 39 | public long readLong() throws IOException; 40 | public int read(byte[] b) throws IOException; 41 | public void seek(long pos) throws IOException; 42 | public long getFilePointer() throws IOException; 43 | public void close() throws IOException; 44 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | /** Generic exception class for all exceptions which occur in this 28 | package. Since there is no mechanism built into this library for 29 | recovering from errors, the best clients can do is display the 30 | error string. */ 31 | 32 | public class ELFException extends RuntimeException { 33 | public ELFException() { 34 | super(); 35 | } 36 | 37 | public ELFException(String message) { 38 | super(message); 39 | } 40 | 41 | public ELFException(Throwable cause) { 42 | super(cause); 43 | } 44 | 45 | public ELFException(String message, Throwable cause) { 46 | super(message, cause); 47 | } 48 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | public interface ELFFile { 28 | /** ELF magic number. */ 29 | public static final byte ELF_MAGIC_NUMBER[] = { 0x7f, 'E', 'L', 'F' }; 30 | 31 | public static final byte CLASS_INVALID = 0; 32 | /** 32-bit objects. */ 33 | public static final byte CLASS_32 = 1; 34 | /** 64-bit objects. */ 35 | public static final byte CLASS_64 = 2; 36 | 37 | /** No data encoding. */ 38 | public static final byte DATA_INVALID = 0; 39 | /** LSB data encoding. */ 40 | public static final byte DATA_LSB = 1; 41 | /** MSB data encoding. */ 42 | public static final byte DATA_MSB = 2; 43 | 44 | /** No ELF header version. */ 45 | public static final byte VERSION_INVALID = 0; 46 | /** Current ELF header version. */ 47 | public static final byte VERSION_CURRENT = 1; 48 | 49 | public static final byte NDX_MAGIC_0 = 0; 50 | public static final byte NDX_MAGIC_1 = 1; 51 | public static final byte NDX_MAGIC_2 = 2; 52 | public static final byte NDX_MAGIC_3 = 3; 53 | public static final byte NDX_OBJECT_SIZE = 4; 54 | public static final byte NDX_ENCODING = 5; 55 | public static final byte NDX_VERSION = 6; 56 | 57 | public ELFHeader getHeader(); 58 | public void close(); 59 | 60 | /** Returns the 4 byte magic number for this file. This value should 61 | * match the values in ELF_MAGIC_NUMBER. */ 62 | public byte[] getMagicNumber(); 63 | /** Returns a byte identifying the size of objects used for this ELF 64 | * file. The byte will be either CLASS_INVALID, CLASS_32 or CLASS_64. */ 65 | public byte getObjectSize(); 66 | /** Returns a byte identifying the data encoding of the processor specific 67 | * data. This byte will be either DATA_INVALID, DATA_LSB or DATA_MSB. */ 68 | public byte getEncoding(); 69 | /** Returns one of the version constants. This should be VERSION_CURRENT. */ 70 | public byte getVersion(); 71 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFFileParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | import java.io.*; 28 | import java.util.*; 29 | 30 | public class ELFFileParser { 31 | private static ELFFileParser elfParser; 32 | private static final String US_ASCII = "US-ASCII"; 33 | 34 | public static ELFFileParser getParser() { 35 | if (elfParser == null) { 36 | elfParser = new ELFFileParser(); 37 | } 38 | return elfParser; 39 | } 40 | 41 | /** 42 | * Parses the data in filename and returns the ELFFile representation. 43 | */ 44 | public ELFFile parse(String filename) throws ELFException { 45 | try { 46 | RandomAccessFile file = new RandomAccessFile(filename, "r"); 47 | return parse(new RandomAccessFileDataSource(file)); 48 | } catch (FileNotFoundException e) { 49 | throw new ELFException(e); 50 | } 51 | } 52 | 53 | /** 54 | * Parses the data source and returns the ELFFile representation. 55 | */ 56 | public ELFFile parse(DataSource source) throws ELFException { 57 | return new ELFFileImpl(source); 58 | } 59 | 60 | /** 61 | * Implementation of the ELFFile interface. 62 | */ 63 | class ELFFileImpl implements ELFFile { 64 | private DataSource file; 65 | private ELFHeader header; 66 | private byte ident[] = new byte[16]; 67 | 68 | ELFFileImpl(DataSource file) throws ELFException { 69 | this.file = file; 70 | int bytesRead = readBytes(ident); 71 | if (bytesRead != ident.length) { 72 | throw new ELFException("Error reading elf header (read " + 73 | bytesRead + "bytes, expected to " + 74 | "read " + ident.length + "bytes)."); 75 | } 76 | 77 | // Check the magic number before we continue reading the file. 78 | if (!Arrays.equals(getMagicNumber(), ELF_MAGIC_NUMBER)) { 79 | throw new ELFException("Bad magic number for file."); 80 | } 81 | 82 | header = new ELFHeaderImpl(); 83 | } 84 | 85 | public ELFHeader getHeader() { return header; } 86 | 87 | public byte[] getMagicNumber() { 88 | byte magicNumber[] = new byte[4]; 89 | magicNumber[0] = ident[NDX_MAGIC_0]; 90 | magicNumber[1] = ident[NDX_MAGIC_1]; 91 | magicNumber[2] = ident[NDX_MAGIC_2]; 92 | magicNumber[3] = ident[NDX_MAGIC_3]; 93 | return magicNumber; 94 | } 95 | 96 | public byte getObjectSize() { return ident[NDX_OBJECT_SIZE]; } 97 | public byte getEncoding() { return ident[NDX_ENCODING]; } 98 | public byte getVersion() { return ident[NDX_VERSION]; } 99 | 100 | 101 | /** 102 | * Implementation of the ELFHeader interface. 103 | */ 104 | class ELFHeaderImpl implements ELFHeader { 105 | /** Marks the file as an object file and provide machine-independent 106 | * data so the contents may be decoded and interpreted. */ 107 | private byte ident[] = new byte[16]; // unsigned char 108 | /** Identifies the object file type. */ 109 | private short file_type; // Elf32_Half 110 | /** The required architecture. */ 111 | private short arch; // Elf32_Half 112 | /** Version */ 113 | private int version; // Elf32_Word 114 | /** Virtual address to which the system first transfers control. 115 | * If there is no entry point for the file the value is 0. */ 116 | private int entry_point; // Elf32_Addr 117 | /** Program header table offset in bytes. If there is no program 118 | * header table the value is 0. */ 119 | private int ph_offset; // Elf32_Off 120 | /** Section header table offset in bytes. If there is no section 121 | * header table the value is 0. */ 122 | private int sh_offset; // Elf32_Off 123 | /** Processor specific flags. */ 124 | private int flags; // Elf32_Word 125 | /** ELF header size in bytes. */ 126 | private short eh_size; // Elf32_Half 127 | /** Size of one entry in the file's program header table in bytes. 128 | * All entries are the same size. */ 129 | private short ph_entry_size; // Elf32_Half 130 | /** Number of entries in the program header table, 0 if no 131 | * entries. */ 132 | private short num_ph; // Elf32_Half 133 | /** Section header entry size in bytes. */ 134 | private short sh_entry_size; // Elf32_Half 135 | /** Number of entries in the section header table, 0 if no 136 | * entries. */ 137 | private short num_sh; // Elf32_Half 138 | /** Index into the section header table associated with the section 139 | * name string table. SH_UNDEF if there is no section name string 140 | * table. */ 141 | private short sh_string_ndx; // Elf32_Half 142 | 143 | /** MemoizedObject array of section headers associated with this 144 | * ELF file. */ 145 | private MemoizedObject[] sectionHeaders; 146 | /** MemoizedObject array of program headers associated with this 147 | * ELF file. */ 148 | private MemoizedObject[] programHeaders; 149 | 150 | /** Used to cache symbol table lookup. */ 151 | private ELFSectionHeader symbolTableSection; 152 | /** Used to cache dynamic symbol table lookup. */ 153 | private ELFSectionHeader dynamicSymbolTableSection; 154 | /** Used to cache hash table lookup. */ 155 | private ELFHashTable hashTable; 156 | 157 | /** 158 | * Reads the ELF header and sets up the section and program headers 159 | * in memoized arrays. 160 | */ 161 | ELFHeaderImpl() throws ELFException { 162 | file_type = readShort(); 163 | arch = readShort(); 164 | version = readInt(); 165 | entry_point = readInt(); 166 | ph_offset = readInt(); 167 | sh_offset = readInt(); 168 | flags = readInt(); 169 | eh_size = readShort(); 170 | ph_entry_size = readShort(); 171 | num_ph = readShort(); 172 | sh_entry_size = readShort(); 173 | num_sh = readShort(); 174 | sh_string_ndx = readShort(); 175 | 176 | // Set up the section headers 177 | sectionHeaders = new MemoizedObject[num_sh]; 178 | for (int i = 0; i < num_sh; i++) { 179 | final long sectionHeaderOffset = 180 | (long)(sh_offset + (i * sh_entry_size)); 181 | sectionHeaders[i] = new MemoizedObject() { 182 | public Object computeValue() { 183 | return new ELFSectionHeaderImpl(sectionHeaderOffset); 184 | } 185 | }; 186 | } 187 | 188 | // // Set up the program headers 189 | // programHeaders = new MemoizedObject[num_sh]; 190 | // for (int i = 0; i < num_sh; i++) { 191 | // final long programHeaderOffset = 192 | // (long)(ph_offset + (i * ph_entry_size)); 193 | // programHeaders[i] = new MemoizedObject() { 194 | // public Object computeValue() { 195 | // return new ProgramHeaderImpl(programHeaderOffset); 196 | // } 197 | // }; 198 | // } 199 | } 200 | 201 | public short getFileType() { return file_type; } 202 | public short getArch() { return arch; } 203 | public short getSectionHeaderSize() { return sh_entry_size; } 204 | public short getNumberOfSectionHeaders() { return num_sh; } 205 | 206 | // public short getProgramHeaderSize() { return ph_entry_size; } 207 | // public short getNumberOfProgramHeaders() { return num_ph; } 208 | 209 | 210 | /** 211 | * Returns the section header at the specified index. The section 212 | * header at index 0 is defined as being a undefined section. */ 213 | public ELFSectionHeader getSectionHeader(int index) { 214 | return (ELFSectionHeader)sectionHeaders[index].getValue(); 215 | } 216 | 217 | public ELFStringTable getSectionHeaderStringTable() { 218 | return getSectionHeader(sh_string_ndx).getStringTable(); 219 | } 220 | 221 | public ELFStringTable getStringTable() { 222 | return findStringTableWithName(ELFSectionHeader.STRING_TABLE_NAME); 223 | } 224 | 225 | public ELFStringTable getDynamicStringTable() { 226 | return findStringTableWithName( 227 | ELFSectionHeader.DYNAMIC_STRING_TABLE_NAME); 228 | } 229 | 230 | private ELFStringTable findStringTableWithName(String tableName) { 231 | // Loop through the section header and look for a section 232 | // header with the name "tableName". We can ignore entry 0 233 | // since it is defined as being undefined. 234 | ELFSectionHeader sh = null; 235 | for (int i = 1; i < getNumberOfSectionHeaders(); i++) { 236 | sh = getSectionHeader(i); 237 | if (tableName.equals(sh.getName())) { 238 | return sh.getStringTable(); 239 | } 240 | } 241 | return null; 242 | } 243 | 244 | /** 245 | * The ELFHashTable does not currently work. This method will 246 | * always return null. */ 247 | public ELFHashTable getHashTable() { 248 | // if (hashTable != null) { 249 | // return hashTable; 250 | // } 251 | // 252 | // ELFHashTable ht = null; 253 | // for (int i = 1; i < getNumberOfSectionHeaders(); i++) { 254 | // if ((ht = getSectionHeader(i).getHashTable()) != null) { 255 | // hashTable = ht; 256 | // return hashTable; 257 | // } 258 | // } 259 | return null; 260 | } 261 | 262 | public ELFSectionHeader getSymbolTableSection() { 263 | if (symbolTableSection != null) { 264 | return symbolTableSection; 265 | } 266 | 267 | symbolTableSection = 268 | getSymbolTableSection(ELFSectionHeader.TYPE_SYMTBL); 269 | return symbolTableSection; 270 | } 271 | 272 | public ELFSectionHeader getDynamicSymbolTableSection() { 273 | if (dynamicSymbolTableSection != null) { 274 | return dynamicSymbolTableSection; 275 | } 276 | 277 | dynamicSymbolTableSection = 278 | getSymbolTableSection(ELFSectionHeader.TYPE_DYNSYM); 279 | return dynamicSymbolTableSection; 280 | } 281 | 282 | private ELFSectionHeader getSymbolTableSection(int type) { 283 | ELFSectionHeader sh = null; 284 | for (int i = 1; i < getNumberOfSectionHeaders(); i++) { 285 | sh = getSectionHeader(i); 286 | if (sh.getType() == type) { 287 | dynamicSymbolTableSection = sh; 288 | return sh; 289 | } 290 | } 291 | return null; 292 | } 293 | 294 | public ELFSymbol getELFSymbol(String symbolName) { 295 | if (symbolName == null) { 296 | return null; 297 | } 298 | 299 | // Check dynamic symbol table for symbol name. 300 | ELFSymbol symbol = null; 301 | int numSymbols = 0; 302 | ELFSectionHeader sh = getDynamicSymbolTableSection(); 303 | if (sh != null) { 304 | numSymbols = sh.getNumberOfSymbols(); 305 | for (int i = 0; i < Math.ceil(numSymbols / 2); i++) { 306 | if (symbolName.equals( 307 | (symbol = sh.getELFSymbol(i)).getName())) { 308 | return symbol; 309 | } else if (symbolName.equals( 310 | (symbol = sh.getELFSymbol( 311 | numSymbols - 1 - i)).getName())) { 312 | return symbol; 313 | } 314 | } 315 | } 316 | 317 | // Check symbol table for symbol name. 318 | sh = getSymbolTableSection(); 319 | if (sh != null) { 320 | numSymbols = sh.getNumberOfSymbols(); 321 | for (int i = 0; i < Math.ceil(numSymbols / 2); i++) { 322 | if (symbolName.equals( 323 | (symbol = sh.getELFSymbol(i)).getName())) { 324 | return symbol; 325 | } else if (symbolName.equals( 326 | (symbol = sh.getELFSymbol( 327 | numSymbols - 1 - i)).getName())) { 328 | return symbol; 329 | } 330 | } 331 | } 332 | return null; 333 | } 334 | 335 | public ELFSymbol getELFSymbol(long address) { 336 | // Check dynamic symbol table for address. 337 | ELFSymbol symbol = null; 338 | int numSymbols = 0; 339 | long value = 0L; 340 | 341 | ELFSectionHeader sh = getDynamicSymbolTableSection(); 342 | if (sh != null) { 343 | numSymbols = sh.getNumberOfSymbols(); 344 | for (int i = 0; i < numSymbols; i++) { 345 | symbol = sh.getELFSymbol(i); 346 | value = symbol.getValue(); 347 | if (address >= value && address < value + symbol.getSize()) { 348 | return symbol; 349 | } 350 | } 351 | } 352 | 353 | // Check symbol table for symbol name. 354 | sh = getSymbolTableSection(); 355 | if (sh != null) { 356 | numSymbols = sh.getNumberOfSymbols(); 357 | for (int i = 0; i < numSymbols; i++) { 358 | symbol = sh.getELFSymbol(i); 359 | value = symbol.getValue(); 360 | if (address >= value && address < value + symbol.getSize()) { 361 | return symbol; 362 | } 363 | } 364 | } 365 | return null; 366 | } 367 | 368 | // public ProgramHeader getProgramHeader(int index) { 369 | // return (ProgramHeader)programHeaders[index].getValue(); 370 | // } 371 | } 372 | 373 | 374 | /** 375 | * Implementation of the ELFSectionHeader interface. 376 | */ 377 | class ELFSectionHeaderImpl implements ELFSectionHeader { 378 | /** Index into the section header string table which gives the 379 | * name of the section. */ 380 | private int name_ndx; // Elf32_Word 381 | /** Section content and semantics. */ 382 | private int type; // Elf32_Word 383 | /** Flags. */ 384 | private int flags; // Elf32_Word 385 | /** If the section will be in the memory image of a process this 386 | * will be the address at which the first byte of section will be 387 | * loaded. Otherwise, this value is 0. */ 388 | private int address; // Elf32_Addr 389 | /** Offset from beginning of file to first byte of the section. */ 390 | private int section_offset; // Elf32_Off 391 | /** Size in bytes of the section. TYPE_NOBITS is a special case. */ 392 | private int size; // Elf32_Word 393 | /** Section header table index link. */ 394 | private int link; // Elf32_Word 395 | /** Extra information determined by the section type. */ 396 | private int info; // Elf32_Word 397 | /** Address alignment constraints for the section. */ 398 | private int address_alignment; // Elf32_Word 399 | /** Size of a fixed-size entry, 0 if none. */ 400 | private int entry_size; // Elf32_Word 401 | 402 | /** Memoized symbol table. */ 403 | private MemoizedObject[] symbols; 404 | /** Memoized string table. */ 405 | private MemoizedObject stringTable; 406 | /** Memoized hash table. */ 407 | private MemoizedObject hashTable; 408 | 409 | /** 410 | * Reads the section header information located at offset. 411 | */ 412 | ELFSectionHeaderImpl(long offset) throws ELFException { 413 | seek(offset); 414 | name_ndx = readInt(); 415 | type = readInt(); 416 | flags = readInt(); 417 | address = readInt(); 418 | section_offset = readInt(); 419 | size = readInt(); 420 | link = readInt(); 421 | info = readInt(); 422 | address_alignment = readInt(); 423 | entry_size = readInt(); 424 | 425 | switch (type) { 426 | case ELFSectionHeader.TYPE_NULL: 427 | break; 428 | case ELFSectionHeader.TYPE_PROGBITS: 429 | break; 430 | case ELFSectionHeader.TYPE_SYMTBL: 431 | case ELFSectionHeader.TYPE_DYNSYM: 432 | // Setup the symbol table. 433 | int num_entries = size / entry_size; 434 | symbols = new MemoizedObject[num_entries]; 435 | for (int i = 0; i < num_entries; i++) { 436 | final int symbolOffset = section_offset + 437 | (i * entry_size); 438 | symbols[i] = new MemoizedObject() { 439 | public Object computeValue() { 440 | return new ELFSymbolImpl(symbolOffset,type); 441 | } 442 | }; 443 | } 444 | break; 445 | case ELFSectionHeader.TYPE_STRTBL: 446 | // Setup the string table. 447 | final int strTableOffset = section_offset; 448 | final int strTableSize = size; 449 | stringTable = new MemoizedObject() { 450 | public Object computeValue() { 451 | return new ELFStringTableImpl(strTableOffset, 452 | strTableSize); 453 | } 454 | }; 455 | break; 456 | case ELFSectionHeader.TYPE_RELO_EXPLICIT: 457 | break; 458 | case ELFSectionHeader.TYPE_HASH: 459 | final int hashTableOffset = section_offset; 460 | final int hashTableSize = size; 461 | hashTable = new MemoizedObject() { 462 | public Object computeValue() { 463 | return new ELFHashTableImpl(hashTableOffset, 464 | hashTableSize); 465 | } 466 | }; 467 | break; 468 | case ELFSectionHeader.TYPE_DYNAMIC: 469 | break; 470 | case ELFSectionHeader.TYPE_NOTE: 471 | break; 472 | case ELFSectionHeader.TYPE_NOBITS: 473 | break; 474 | case ELFSectionHeader.TYPE_RELO: 475 | break; 476 | case ELFSectionHeader.TYPE_SHLIB: 477 | break; 478 | default: 479 | break; 480 | } 481 | } 482 | 483 | public int getType() { 484 | return type; 485 | } 486 | 487 | public int getNumberOfSymbols() { 488 | if (symbols != null) { 489 | return symbols.length; 490 | } 491 | return 0; 492 | } 493 | 494 | /** 495 | * Returns the ELFSymbol at the specified index. Index 0 is 496 | * reserved for the undefined ELF symbol. */ 497 | public ELFSymbol getELFSymbol(int index) { 498 | return (ELFSymbol)symbols[index].getValue(); 499 | } 500 | 501 | public ELFStringTable getStringTable() { 502 | if (stringTable != null) { 503 | return (ELFStringTable)stringTable.getValue(); 504 | } 505 | return null; 506 | } 507 | 508 | /** 509 | * The ELFHashTable does not currently work. This method will 510 | * always return null. */ 511 | public ELFHashTable getHashTable() { 512 | if (hashTable != null) { 513 | return (ELFHashTable)hashTable.getValue(); 514 | } 515 | return null; 516 | } 517 | 518 | public String getName() { 519 | if (name_ndx == 0) { 520 | return null; 521 | } 522 | 523 | ELFStringTable tbl = getHeader().getSectionHeaderStringTable(); 524 | return tbl.get(name_ndx); 525 | } 526 | 527 | public int getLink() { 528 | return link; 529 | } 530 | 531 | public int getOffset() { 532 | return section_offset; 533 | } 534 | } 535 | 536 | 537 | // class ProgramHeaderImpl implements ProgramHeader { 538 | // /** Defines the kind of segment this element describes. */ 539 | // private int type; // Elf32_Word 540 | // /** Offset from the beginning of the file. */ 541 | // private int offset; // Elf32_Off 542 | // /** Virtual address at which the first byte of the segment 543 | // * resides in memory. */ 544 | // private int virtual_address; // Elf32_Addr 545 | // /** Reserved for the physical address of the segment on systems 546 | // * where physical addressinf is relevant. */ 547 | // private int physical_address; // Elf32_addr 548 | // /** File image size of segment in bytes, may be 0. */ 549 | // private int file_size; // Elf32_Word 550 | // /** Memory image size of segment in bytes, may be 0. */ 551 | // private int mem_size; // Elf32_Word 552 | // /** Flags relevant to this segment. Values for flags are defined 553 | // * in ELFSectionHeader. */ 554 | // private int flags; // Elf32_Word 555 | // private int alignment; // Elf32_Word 556 | // 557 | // private MemoizedObject[] symbols; 558 | // 559 | // ProgramHeaderImpl(long offset) throws ELFException { 560 | // seek(offset); 561 | // type = readInt(); 562 | // this.offset = readInt(); 563 | // virtual_address = readInt(); 564 | // physical_address = readInt(); 565 | // file_size = readInt(); 566 | // mem_size = readInt(); 567 | // flags = readInt(); 568 | // alignment = readInt(); 569 | // 570 | // switch (type) { 571 | // case ELFSectionHeader.TYPE_NULL: 572 | // break; 573 | // case ELFSectionHeader.TYPE_PROGBITS: 574 | // break; 575 | // case ELFSectionHeader.TYPE_SYMTBL: 576 | // case ELFSectionHeader.TYPE_DYNSYM: 577 | // break; 578 | // case ELFSectionHeader.TYPE_STRTBL: 579 | // // Setup the string table. 580 | // final int strTableOffset = section_offset; 581 | // final int strTableSize = size; 582 | // stringTable = new MemoizedObject() { 583 | // public Object computeValue() { 584 | // return new ELFStringTableImpl(strTableOffset, 585 | // strTableSize); 586 | // } 587 | // }; 588 | // new ELFStringTableImpl(offset, file_size); 589 | // break; 590 | // case ELFSectionHeader.TYPE_RELO_EXPLICIT: 591 | // break; 592 | // case ELFSectionHeader.TYPE_HASH: 593 | // break; 594 | // case ELFSectionHeader.TYPE_DYNAMIC: 595 | // break; 596 | // case ELFSectionHeader.TYPE_NOTE: 597 | // break; 598 | // case ELFSectionHeader.TYPE_NOBITS: 599 | // break; 600 | // case ELFSectionHeader.TYPE_RELO: 601 | // break; 602 | // case ELFSectionHeader.TYPE_SHLIB: 603 | // break; 604 | // default: 605 | // break; 606 | // } 607 | // } 608 | // 609 | // public int getType() { 610 | // return type; 611 | // } 612 | // } 613 | 614 | 615 | /** 616 | * Implementation of the ELFSymbol interface. 617 | */ 618 | class ELFSymbolImpl implements ELFSymbol { 619 | /** Index into the symbol string table that holds the character 620 | * representation of the symbols. 0 means the symbol has no 621 | * character name. */ 622 | private int name_ndx; // Elf32_Word 623 | /** Value of the associated symbol. This may be an address or 624 | * an absolute value. */ 625 | private int value; // Elf32_Addr 626 | /** Size of the symbol. 0 if the symbol has no size or the size 627 | * is unknown. */ 628 | private int size; // Elf32_Word 629 | /** Specifies the symbol type and beinding attributes. */ 630 | private byte info; // unsigned char 631 | /** Currently holds the value of 0 and has no meaning. */ 632 | private byte other; // unsigned char 633 | /** Index to the associated section header. This value will need 634 | * to be read as an unsigned short if we compare it to 635 | * ELFSectionHeader.NDX_LORESERVE and ELFSectionHeader.NDX_HIRESERVE. */ 636 | private short section_header_ndx; // Elf32_Half 637 | 638 | private int section_type; 639 | 640 | /** Offset from the beginning of the file to this symbol. */ 641 | private long offset; 642 | 643 | ELFSymbolImpl(long offset, int section_type) throws ELFException { 644 | seek(offset); 645 | this.offset = offset; 646 | name_ndx = readInt(); 647 | value = readInt(); 648 | size = readInt(); 649 | info = readByte(); 650 | other = readByte(); 651 | section_header_ndx = readShort(); 652 | 653 | this.section_type = section_type; 654 | 655 | switch (getType()) { 656 | case TYPE_NOOBJECT: 657 | break; 658 | case TYPE_OBJECT: 659 | break; 660 | case TYPE_FUNCTION: 661 | break; 662 | case TYPE_SECTION: 663 | break; 664 | case TYPE_FILE: 665 | break; 666 | case TYPE_LOPROC: 667 | break; 668 | case TYPE_HIPROC: 669 | break; 670 | default: 671 | break; 672 | } 673 | } 674 | 675 | public int getBinding() { return info >> 4; } 676 | public int getType() { return info & 0x0F; } 677 | public long getOffset() { return offset; } 678 | 679 | public String getName() { 680 | // Check to make sure this symbol has a name. 681 | if (name_ndx == 0) { 682 | return null; 683 | } 684 | 685 | // Retrieve the name of the symbol from the correct string 686 | // table. 687 | String symbol_name = null; 688 | if (section_type == ELFSectionHeader.TYPE_SYMTBL) { 689 | symbol_name = getHeader().getStringTable().get(name_ndx); 690 | } else if (section_type == ELFSectionHeader.TYPE_DYNSYM) { 691 | symbol_name = 692 | getHeader().getDynamicStringTable().get(name_ndx); 693 | } 694 | return symbol_name; 695 | } 696 | 697 | public long getValue() { 698 | return value; 699 | } 700 | 701 | public int getSize() { 702 | return size; 703 | } 704 | } 705 | 706 | /** 707 | * Implementation of the ELFStringTable interface. 708 | */ 709 | class ELFStringTableImpl implements ELFStringTable { 710 | /** The string table data. */ 711 | private byte data[]; 712 | private int numStrings; 713 | 714 | /** 715 | * Reads all the strings from [offset, length]. 716 | */ 717 | ELFStringTableImpl(long offset, int length) throws ELFException { 718 | seek(offset); 719 | data = new byte[length]; 720 | int bytesRead = readBytes(data); 721 | if (bytesRead != length) { 722 | throw new ELFException("Error reading string table (read " + 723 | bytesRead + "bytes, expected to " + 724 | "read " + data.length + "bytes)."); 725 | } 726 | 727 | // Count the strings. 728 | numStrings = 0; 729 | for (int ptr = 0; ptr < data.length; ptr++) { 730 | if (data[ptr] == '\0') { 731 | numStrings++; 732 | } 733 | } 734 | } 735 | 736 | public String get(int index) { 737 | int startPtr = index; 738 | int endPtr = index; 739 | while (data[endPtr] != '\0') { 740 | endPtr++; 741 | } 742 | return new String(data, startPtr, endPtr - startPtr); 743 | } 744 | 745 | public int getNumStrings() { 746 | return numStrings; 747 | } 748 | } 749 | 750 | 751 | /** Implementation of the ELFHashTable. */ 752 | class ELFHashTableImpl implements ELFHashTable { 753 | private int num_buckets; 754 | private int num_chains; 755 | 756 | // These could probably be memoized. 757 | private int buckets[]; 758 | private int chains[]; 759 | 760 | ELFHashTableImpl(long offset, int length) throws ELFException { 761 | seek(offset); 762 | num_buckets = readInt(); 763 | num_chains = readInt(); 764 | 765 | buckets = new int[num_buckets]; 766 | chains = new int[num_chains]; 767 | // Read the bucket data. 768 | for (int i = 0; i < num_buckets; i++) { 769 | buckets[i] = readInt(); 770 | } 771 | 772 | // Read the chain data. 773 | for (int i = 0; i < num_chains; i++) { 774 | chains[i] = readInt(); 775 | } 776 | 777 | // Make sure that the amount of bytes we were supposed to read 778 | // was what we actually read. 779 | int actual = num_buckets * 4 + num_chains * 4 + 8; 780 | if (length != actual) { 781 | throw new ELFException("Error reading string table (read " + 782 | actual + "bytes, expected to " + 783 | "read " + length + "bytes)."); 784 | } 785 | } 786 | 787 | /** 788 | * This method doesn't work every time and is unreliable. Use 789 | * ELFSection.getELFSymbol(String) to retrieve symbols by name. 790 | * NOTE: since this method is currently broken it will always 791 | * return null. */ 792 | public ELFSymbol getSymbol(String symbolName) { 793 | // if (symbolName == null) { 794 | // return null; 795 | // } 796 | // 797 | // long hash = 0; 798 | // long g = 0; 799 | // 800 | // for (int i = 0; i < symbolName.length(); i++) { 801 | // hash = (hash << 4) + symbolName.charAt(i); 802 | // if ((g = hash & 0xf0000000) != 0) { 803 | // hash ^= g >>> 24; 804 | // } 805 | // hash &= ~g; 806 | // } 807 | // 808 | // ELFSymbol symbol = null; 809 | // ELFSectionHeader dyn_sh = 810 | // getHeader().getDynamicSymbolTableSection(); 811 | // int index = (int)hash % num_buckets; 812 | // while(index != 0) { 813 | // symbol = dyn_sh.getELFSymbol(index); 814 | // if (symbolName.equals(symbol.getName())) { 815 | // break; 816 | // } 817 | // symbol = null; 818 | // index = chains[index]; 819 | // } 820 | // return symbol; 821 | return null; 822 | } 823 | } 824 | 825 | 826 | public void close() throws ELFException { 827 | try { 828 | file.close(); 829 | } catch (IOException e) { 830 | throw new ELFException(e); 831 | } 832 | } 833 | 834 | void seek(long offset) throws ELFException { 835 | try { 836 | file.seek(offset); 837 | } catch (IOException e) { 838 | throw new ELFException(e); 839 | } 840 | } 841 | 842 | long getFilePointer() throws ELFException { 843 | try { 844 | return file.getFilePointer(); 845 | } catch (IOException e) { 846 | throw new ELFException(e); 847 | } 848 | } 849 | 850 | byte readByte() throws ELFException { 851 | try { 852 | return file.readByte(); 853 | } catch (IOException e) { 854 | throw new ELFException(e); 855 | } 856 | } 857 | 858 | int readBytes(byte[] b) throws ELFException { 859 | try { 860 | return file.read(b); 861 | } catch (IOException e) { 862 | throw new ELFException(e); 863 | } 864 | } 865 | 866 | short readShort() throws ELFException { 867 | try { 868 | short val; 869 | switch (ident[NDX_ENCODING]) { 870 | case DATA_LSB: 871 | val = byteSwap(file.readShort()); 872 | break; 873 | case DATA_MSB: 874 | val = file.readShort(); 875 | break; 876 | default: 877 | throw new ELFException("Invalid encoding."); 878 | } 879 | return val; 880 | } catch (IOException e) { 881 | throw new ELFException(e); 882 | } 883 | } 884 | 885 | int readInt() throws ELFException { 886 | try { 887 | int val; 888 | switch (ident[NDX_ENCODING]) { 889 | case DATA_LSB: 890 | val = byteSwap(file.readInt()); 891 | break; 892 | case DATA_MSB: 893 | val = file.readInt(); 894 | break; 895 | default: 896 | throw new ELFException("Invalid encoding."); 897 | } 898 | return val; 899 | } catch (IOException e) { 900 | throw new ELFException(e); 901 | } 902 | } 903 | 904 | long readLong() throws ELFException { 905 | try { 906 | long val; 907 | switch (ident[NDX_ENCODING]) { 908 | case DATA_LSB: 909 | val = byteSwap(file.readLong()); 910 | break; 911 | case DATA_MSB: 912 | val = file.readLong(); 913 | break; 914 | default: 915 | throw new ELFException("Invalid encoding."); 916 | } 917 | return val; 918 | } catch (IOException e) { 919 | throw new ELFException(e); 920 | } 921 | } 922 | 923 | /** Signed byte utility functions used for converting from big-endian 924 | * (MSB) to little-endian (LSB). */ 925 | short byteSwap(short arg) { 926 | return (short) ((arg << 8) | ((arg >>> 8) & 0xFF)); 927 | } 928 | 929 | int byteSwap(int arg) { 930 | return (((int) byteSwap((short) arg)) << 16) | 931 | (((int) (byteSwap((short) (arg >>> 16)))) & 0xFFFF); 932 | } 933 | 934 | long byteSwap(long arg) { 935 | return ((((long) byteSwap((int) arg)) << 32) | 936 | (((long) byteSwap((int) (arg >>> 32))) & 0xFFFFFFFF)); 937 | } 938 | 939 | 940 | /* Unsigned byte utility functions. Since java does not have unsigned 941 | * data types we must convert values manually and we must return 942 | * unsigned values in a larger data type. Therefore we can only have 943 | * unsigned values for byte, short, and int. */ 944 | short readUnsignedByte() throws ELFException { 945 | try { 946 | return unsignedByte(file.readByte()); 947 | } catch (IOException e) { 948 | throw new ELFException(e); 949 | } 950 | } 951 | 952 | int readUnsignedShort() throws ELFException { 953 | try { 954 | int val; 955 | switch (ident[NDX_ENCODING]) { 956 | case DATA_LSB: 957 | val = unsignedByteSwap(file.readShort()); 958 | break; 959 | case DATA_MSB: 960 | val = unsignedByte(file.readShort()); 961 | break; 962 | default: 963 | throw new ELFException("Invalid encoding."); 964 | } 965 | return val; 966 | } catch (IOException e) { 967 | throw new ELFException(e); 968 | } 969 | } 970 | 971 | long readUnsignedInt() throws ELFException { 972 | try { 973 | long val; 974 | switch (ident[NDX_ENCODING]) { 975 | case DATA_LSB: 976 | val = unsignedByteSwap(file.readInt()); 977 | break; 978 | case DATA_MSB: 979 | val = unsignedByte(file.readInt()); 980 | break; 981 | default: 982 | throw new ELFException("Invalid encoding."); 983 | } 984 | return val; 985 | } catch (IOException e) { 986 | throw new ELFException(e); 987 | } 988 | } 989 | 990 | /** Returns the unsigned value of the byte. */ 991 | short unsignedByte(byte arg) { 992 | return (short)(arg & 0x00FF); 993 | } 994 | 995 | /** Returns a big-endian unsigned representation of the short. */ 996 | int unsignedByte(short arg) { 997 | int val; 998 | if (arg >= 0) { 999 | val = arg; 1000 | } else { 1001 | val = (int)(((int)unsignedByte((byte)(arg >>> 8)) << 8) | 1002 | ((byte)arg)); 1003 | } 1004 | return val; 1005 | } 1006 | 1007 | /** Returns a big-endian unsigned representation of the int. */ 1008 | long unsignedByte(int arg) { 1009 | long val; 1010 | if (arg >= 0) { 1011 | val = arg; 1012 | } else { 1013 | val = (long)(((long)unsignedByte((short)(arg >>> 16)) << 16) | 1014 | ((short)arg)); 1015 | } 1016 | return val; 1017 | } 1018 | 1019 | /** Unsigned byte utility functions used for converting from big-endian 1020 | * (MSB) to little-endian (LSB). */ 1021 | int unsignedByteSwap(short arg) { 1022 | return (int)(((int)unsignedByte((byte)arg)) << 8) | 1023 | ((int)unsignedByte((byte)(arg >>> 8))); 1024 | } 1025 | 1026 | long unsignedByteSwap(int arg) { 1027 | return (long)(((long)unsignedByteSwap((short)arg)) << 16) | 1028 | ((long)unsignedByteSwap((short)(arg >>> 16))); 1029 | } 1030 | } 1031 | 1032 | public static void main(String args[]) { 1033 | if (args.length != 1) { 1034 | System.out.println("Usage: java ELFFileParser "); 1035 | System.exit(0); 1036 | } 1037 | 1038 | // Parse the file. 1039 | ELFFile elfFile = ELFFileParser.getParser().parse(args[0]); 1040 | 1041 | ELFHeader elfHeader = elfFile.getHeader(); 1042 | System.out.println("ELF File: " + args[0]); 1043 | 1044 | System.out.println("ELF object size: " + 1045 | ((elfFile.getObjectSize() == 0) ? "Invalid Object Size" : 1046 | (elfFile.getObjectSize() == 1) ? "32-bit" : "64-bit")); 1047 | System.out.println("ELF data encoding: " + 1048 | ((elfFile.getEncoding() == 0) ? "Invalid Data Encoding" : 1049 | (elfFile.getEncoding() == 1) ? "LSB" : "MSB")); 1050 | 1051 | int h = elfHeader.getNumberOfSectionHeaders(); 1052 | System.out.println("--> Start: reading " + h + " section headers."); 1053 | for (int i = 0; i < elfHeader.getNumberOfSectionHeaders(); i++) { 1054 | ELFSectionHeader sh = elfHeader.getSectionHeader(i); 1055 | String str = sh.getName(); 1056 | System.out.println("----> Start: Section (" + i + ") " + str); 1057 | 1058 | int num = 0; 1059 | if ((num = sh.getNumberOfSymbols()) != 0) { 1060 | System.out.println("------> Start: reading " + num + " symbols."); 1061 | for (int j = 0; j < num ; j++) { 1062 | ELFSymbol sym = sh.getELFSymbol(j); 1063 | //String name = sym.getName(); 1064 | //if (name != null) { 1065 | // System.out.println(name); 1066 | //} 1067 | } 1068 | System.out.println("<------ End: reading " + num + " symbols."); 1069 | } 1070 | ELFStringTable st; 1071 | if (sh.getType() == ELFSectionHeader.TYPE_STRTBL) { 1072 | System.out.println("------> Start: reading string table."); 1073 | st = sh.getStringTable(); 1074 | System.out.println("<------ End: reading string table."); 1075 | } 1076 | if (sh.getType() == ELFSectionHeader.TYPE_HASH) { 1077 | System.out.println("------> Start: reading hash table."); 1078 | sh.getHashTable(); 1079 | System.out.println("<------ End: reading hash table."); 1080 | } 1081 | System.out.println("<---- End: Section (" + i + ") " + str); 1082 | } 1083 | System.out.println("<-- End: reading " + h + " section headers."); 1084 | /* 1085 | h = elfHeader.getNumberOfProgramHeaders(); 1086 | System.out.println("--> Start: reading " + h + " program headers."); 1087 | for (int i = 0; i < elfHeader.getNumberOfProgramHeaders(); i++) { 1088 | elfHeader.getProgramHeader(i); 1089 | } 1090 | System.out.println("<-- End: reading " + h + " program headers."); 1091 | */ 1092 | elfFile.close(); 1093 | } 1094 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFHashTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | public interface ELFHashTable { 28 | /** 29 | * Returns the ELFSymbol that has the specified name or null if no symbol 30 | * with that name exists. NOTE: Currently this method does not work and 31 | * willl always return null. 32 | */ 33 | public ELFSymbol getSymbol(String symbolName); 34 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | import java.io.FileInputStream; 28 | 29 | /** 30 | * This is a Java class that represents a ELF file header. 31 | * 32 | * @author Joshua W. Outwater 33 | */ 34 | public interface ELFHeader { 35 | /** No file type. */ 36 | public static final int FT_NONE = 0; 37 | /** Relocatable file type. */ 38 | public static final int FT_REL = 1; 39 | /** Executable file type. */ 40 | public static final int FT_EXEC = 2; 41 | /** Shared object file type. */ 42 | public static final int FT_DYN = 3; 43 | /** Core file file type. */ 44 | public static final int FT_CORE = 4; 45 | /** Processor specific. */ 46 | public static final int FT_LOCPROC = 0xff00; 47 | /** Processor specific. */ 48 | public static final int FT_HICPROC = 0xffff; 49 | 50 | /** No architecture type. */ 51 | public static final int ARCH_NONE = 0; 52 | /** AT&T architecture type. */ 53 | public static final int ARCH_ATT = 1; 54 | /** SPARC architecture type. */ 55 | public static final int ARCH_SPARC = 2; 56 | /** Intel 386 architecture type. */ 57 | public static final int ARCH_i386 = 3; 58 | /** Motorolla 68000 architecture type. */ 59 | public static final int ARCH_68k = 4; 60 | /** Motorolla 88000 architecture type. */ 61 | public static final int ARCH_88k = 5; 62 | /** Intel 860 architecture type. */ 63 | public static final int ARCH_i860 = 7; 64 | /** MIPS architecture type. */ 65 | public static final int ARCH_MIPS = 8; 66 | 67 | /** Returns a file type which is defined by the file type constants. */ 68 | public short getFileType(); 69 | /** Returns one of the architecture constants. */ 70 | public short getArch(); 71 | /** Returns the size of a section header. */ 72 | public short getSectionHeaderSize(); 73 | /** Returns the number of section headers. */ 74 | public short getNumberOfSectionHeaders(); 75 | /** Returns the section header at the specified index. The section header 76 | * at index 0 is the undefined section header. */ 77 | public ELFSectionHeader getSectionHeader(int index); 78 | /** Returns the section header string table associated with this ELF 79 | * file. */ 80 | public ELFStringTable getSectionHeaderStringTable(); 81 | /** Returns the string table associated with this ELF file. */ 82 | public ELFStringTable getStringTable(); 83 | /** Returns the dynamic string table associated with this ELF file, or null 84 | * if one does not exist. */ 85 | public ELFStringTable getDynamicStringTable(); 86 | /** Returns the hash table associated with this ELF file, or null if one 87 | * does not exist. NOTE: Currently the ELFHashTable does not work so this 88 | * method will always return null. */ 89 | public ELFHashTable getHashTable(); 90 | /** Returns the symbol table associated with this ELF file, or null if one 91 | * does not exist. */ 92 | public ELFSectionHeader getSymbolTableSection(); 93 | /** Returns the dynamic symbol table associated with this ELF file, or null 94 | * if one does not exist. */ 95 | public ELFSectionHeader getDynamicSymbolTableSection(); 96 | /** Returns the elf symbol with the specified name or null if one is not 97 | * found. */ 98 | public ELFSymbol getELFSymbol(String name); 99 | /** Returns the elf symbol with the specified address or null if one is not 100 | * found. 'address' is relative to base of shared object for .so's. */ 101 | public ELFSymbol getELFSymbol(long address); 102 | /** Returns the size of a program header. */ 103 | //public short getProgramHeaderSize(); 104 | /** Returns the number of program headers. */ 105 | //public short getNumberOfProgramHeaders(); 106 | /** Returns the program header at the specified index. */ 107 | //public ProgramHeader getProgramHeader(int index); 108 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFProgramHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | /** 28 | * This is the interface definintion for a ProgramHeader in an ELF file. 29 | * Program headers contain system information necessary for preparing a program 30 | * for execution. 31 | */ 32 | public interface ELFProgramHeader { 33 | /** Type defining that the array element is unused. Other member values 34 | * are undefined. */ 35 | public static final int TYPE_NULL = 0; 36 | /** Type defining that the array element specifies a loadable segment. */ 37 | public static final int TYPE_LOAD = 1; 38 | public static final int TYPE_DYNAMIC = 2; 39 | public static final int TYPE_INTERP = 3; 40 | public static final int TYPE_NOTE = 4; 41 | public static final int TYPE_SHLIB = 5; 42 | public static final int TYPE_PHDR = 6; 43 | public static final int TYPE_LOPROC = 0x70000000; 44 | public static final int TYPE_HIPROC = 0x7fffffff; 45 | 46 | public int getType(); 47 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFSectionHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | public interface ELFSectionHeader { 28 | /** Undefined section header index. */ 29 | public static final int NDX_UNDEFINED = 0; 30 | /** Lower bound section header index. */ 31 | public static final int NDX_LORESERVE = 0xff00; 32 | /** Lower bound section header index reserved for processor specific 33 | * semantics. */ 34 | public static final int NDX_LOPROC = 0xff00; 35 | /** Upper bound section header index reserved for processor specific 36 | * semantics. */ 37 | public static final int NDX_HIPROC = 0xff1f; 38 | /** Absolute values for the corresponding reference. Symbols defined 39 | * relative to section number NDX_ABS have absolute values and are not 40 | * affected by relocation. */ 41 | public static final int NDX_ABS = 0xfff1; 42 | /** Symbols defined relative to this section are common symbols, such 43 | * as FORTRAN, COMMON or unallocated C external variables. */ 44 | public static final int NDX_COMMON = 0xfff2; 45 | /** Upper bound section header index. */ 46 | public static final int NDX_HIRESERVE = 0xffff; 47 | 48 | /** Section is inactive. */ 49 | public static final int TYPE_NULL = 0; 50 | /** Section holds information defined by the program. */ 51 | public static final int TYPE_PROGBITS = 1; 52 | /** Section holds symbol table information for link editing. It may also 53 | * be used to store symbols for dynamic linking. */ 54 | public static final int TYPE_SYMTBL = 2; 55 | /** Section holds string table information. */ 56 | public static final int TYPE_STRTBL = 3; 57 | /** Section holds relocation entries with explicit addends. */ 58 | public static final int TYPE_RELO_EXPLICIT = 4; 59 | /** Section holds symbol hash table. */ 60 | public static final int TYPE_HASH = 5; 61 | /** Section holds information for dynamic linking. */ 62 | public static final int TYPE_DYNAMIC = 6; 63 | /** Section holds information that marks the file. */ 64 | public static final int TYPE_NOTE = 7; 65 | /** Section occupies no space but resembles TYPE_PROGBITS. */ 66 | public static final int TYPE_NOBITS = 8; 67 | /** Section holds relocation entries without explicit addends. */ 68 | public static final int TYPE_RELO = 9; 69 | /** Section is reserved but has unspecified semantics. */ 70 | public static final int TYPE_SHLIB = 10; 71 | /** Section holds a minimum set of dynamic linking symbols. */ 72 | public static final int TYPE_DYNSYM = 11; 73 | /** Lower bound section type that contains processor specific semantics. */ 74 | public static final int TYPE_LOPROC = 0x70000000; 75 | /** Upper bound section type that contains processor specific semantics. */ 76 | public static final int TYPE_HIPROC = 0x7fffffff; 77 | /** Lower bound of the range of indexes reserved for application 78 | * programs. */ 79 | public static final int TYPE_LOUSER = 0x80000000; 80 | /** Upper bound of the range of indexes reserved for application 81 | * programs. */ 82 | public static final int TYPE_HIUSER = 0xffffffff; 83 | 84 | /** Flag informing that this section contains data that should be writable 85 | * during process execution. */ 86 | public static final int FLAG_WRITE = 0x1; 87 | /** Flag informing that section occupies memory during process 88 | * execution. */ 89 | public static final int FLAG_ALLOC = 0x2; 90 | /** Flag informaing that section contains executable machine 91 | * instructions. */ 92 | public static final int FLAG_EXEC_INSTR = 0x4; 93 | /** Flag informing that all the bits in the mask are reserved for processor 94 | * specific semantics. */ 95 | public static final int FLAG_MASK = 0xf0000000; 96 | 97 | /** Section header name identifying the section as a string table. */ 98 | public static final String STRING_TABLE_NAME = ".strtab"; 99 | /** Section header name identifying the section as a dynamic string 100 | * table. */ 101 | public static final String DYNAMIC_STRING_TABLE_NAME = ".dynstr"; 102 | /** Returns the type of section header. */ 103 | public int getType(); 104 | /** Returns the number of symbols in this section or 0 if none. */ 105 | public int getNumberOfSymbols(); 106 | /** Returns the symbol at the specified index. The ELF symbol at index 0 107 | * is the undefined symbol. */ 108 | public ELFSymbol getELFSymbol(int index); 109 | /** Returns the string table for this section or null if one does not 110 | * exist. */ 111 | public ELFStringTable getStringTable(); 112 | /** Returns the hash table for this section or null if one does not 113 | * exist. NOTE: currently the ELFHashTable does not work and this method 114 | * will always return null. */ 115 | public ELFHashTable getHashTable(); 116 | public int getLink(); 117 | /** Returns the name of the section or null if the section has no name. */ 118 | public String getName(); 119 | /** Returns the offset in bytes to the beginning of the section. */ 120 | public int getOffset(); 121 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFStringTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | public interface ELFStringTable { 28 | public String get(int index); 29 | public int getNumStrings(); 30 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/ELFSymbol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | public interface ELFSymbol { 28 | /** Binding specifying that local symbols are not visible outside the 29 | * object file that contains its definition. */ 30 | public static final int BINDING_LOCAL = 0; 31 | /** Binding specifying that global symbols are visible to all object files 32 | * being combined. */ 33 | public static final int BINDING_GLOBAL = 1; 34 | /** Binding secifying that the symbol resembles a global symbol, but has 35 | * a lower precedence. */ 36 | public static final int BINDING_WEAK = 2; 37 | /** Lower bound binding values reserverd for processor specific 38 | * semantics. */ 39 | public static final int BINDING_LOPROC = 13; 40 | /** Upper bound binding values reserverd for processor specific 41 | * semantics. */ 42 | public static final int BINDING_HIPROC = 15; 43 | 44 | /** Type specifying that the symbol is unspecified. */ 45 | public static final byte TYPE_NOOBJECT = 0; 46 | /** Type specifying that the symbol is associated with an object. */ 47 | public static final byte TYPE_OBJECT = 1; 48 | /** Type specifying that the symbol is associated with a function. */ 49 | public static final byte TYPE_FUNCTION = 2; 50 | /** Type specifying that the symbol is associated with a section. Symbol 51 | * table entries of this type exist for relocation and normally have the 52 | * binding BINDING_LOCAL. */ 53 | public static final byte TYPE_SECTION = 3; 54 | /** Type defining that the symbol is associated with a file. */ 55 | public static final byte TYPE_FILE = 4; 56 | /** Lower bound type reserved for processor specific semantics. */ 57 | public static final byte TYPE_LOPROC = 13; 58 | /** Upper bound type reserved for processor specific semantics. */ 59 | public static final byte TYPE_HIPROC = 15; 60 | 61 | /** Returns the location from the beginning of the file to the symbol. */ 62 | public long getOffset(); 63 | /** Returns the name of the symbol or null if the symbol has no name. */ 64 | public String getName(); 65 | /** Returns the binding for this symbol. */ 66 | public int getBinding(); 67 | /** Returns the symbol type. */ 68 | public int getType(); 69 | 70 | /** Value of the associated symbol. This may be a relativa address for .so 71 | * or absolute address for other ELFs. */ 72 | public long getValue(); 73 | 74 | /** Size of the symbol. 0 if the symbol has no size or the size 75 | * is unknown. */ 76 | public int getSize(); 77 | } -------------------------------------------------------------------------------- /src/com/bluth/readelf/MemoizedObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 | * or visit www.oracle.com if you need additional information or have any 21 | * questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | /** A memoized object. Override {@link #computeValue} in subclasses; 28 | call {@link #getValue} in using code. */ 29 | 30 | public abstract class MemoizedObject { 31 | private boolean computed; 32 | private Object value; 33 | 34 | /** Should compute the value of this memoized object. This will only 35 | be called once, upon the first call to {@link #getValue}. */ 36 | protected abstract Object computeValue(); 37 | 38 | /** Public accessor for the memoized value. */ 39 | public Object getValue() { 40 | if (!computed) { 41 | value = computeValue(); 42 | computed = true; 43 | } 44 | return value; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/bluth/readelf/RandomAccessFileDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. 8 | * 9 | * This code is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 | * version 2 for more details (a copy is included in the LICENSE file that 13 | * accompanied this code). 14 | * 15 | * You should have received a copy of the GNU General Public License version 16 | * 2 along with this work; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 | * CA 94065 USA or visit www.oracle.com if you need additional information or 21 | * have any questions. 22 | * 23 | */ 24 | 25 | package com.bluth.readelf; 26 | 27 | import java.io.*; 28 | 29 | /* This class is used by the Windows COFF and Posix ELF implementations. */ 30 | public class RandomAccessFileDataSource implements DataSource { 31 | public RandomAccessFileDataSource(RandomAccessFile file) { 32 | this.file = file; 33 | } 34 | 35 | public byte readByte() throws IOException { return file.readByte(); } 36 | public short readShort() throws IOException { return file.readShort(); } 37 | public int readInt() throws IOException { return file.readInt(); } 38 | public long readLong() throws IOException { return file.readLong(); } 39 | public int read(byte[] b) throws IOException { return file.read(b); } 40 | public void seek(long pos) throws IOException { file.seek(pos); } 41 | public long getFilePointer() throws IOException { return file.getFilePointer(); } 42 | public void close() throws IOException { file.close(); } 43 | 44 | private RandomAccessFile file; 45 | } --------------------------------------------------------------------------------