Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFFileParser.java @ 20456:64156d22e49d
8032247: SA: Constantpool lookup for invokedynamic is not implemented
Summary: implement constant pool lookup for invokedynamic
Reviewed-by: sla, sspitsyn
author | dsamersoff |
---|---|
date | Thu, 11 Sep 2014 11:55:30 -0700 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.debugger.posix.elf; | |
26 | |
27 import java.io.*; | |
28 import java.util.*; | |
29 import sun.jvm.hotspot.utilities.memo.*; | |
30 import sun.jvm.hotspot.debugger.DataSource; | |
31 import sun.jvm.hotspot.debugger.RandomAccessFileDataSource; | |
32 | |
33 public class ELFFileParser { | |
34 private static ELFFileParser elfParser; | |
35 private static final String US_ASCII = "US-ASCII"; | |
36 | |
37 public static ELFFileParser getParser() { | |
38 if (elfParser == null) { | |
39 elfParser = new ELFFileParser(); | |
40 } | |
41 return elfParser; | |
42 } | |
43 | |
44 /** | |
45 * Parses the data in filename and returns the ELFFile representation. | |
46 */ | |
47 public ELFFile parse(String filename) throws ELFException { | |
48 try { | |
49 RandomAccessFile file = new RandomAccessFile(filename, "r"); | |
50 return parse(new RandomAccessFileDataSource(file)); | |
51 } catch (FileNotFoundException e) { | |
52 throw new ELFException(e); | |
53 } | |
54 } | |
55 | |
56 /** | |
57 * Parses the data source and returns the ELFFile representation. | |
58 */ | |
59 public ELFFile parse(DataSource source) throws ELFException { | |
60 return new ELFFileImpl(source); | |
61 } | |
62 | |
63 /** | |
64 * Implementation of the ELFFile interface. | |
65 */ | |
66 class ELFFileImpl implements ELFFile { | |
67 private DataSource file; | |
68 private ELFHeader header; | |
69 private byte ident[] = new byte[16]; | |
70 | |
71 ELFFileImpl(DataSource file) throws ELFException { | |
72 this.file = file; | |
73 int bytesRead = readBytes(ident); | |
74 if (bytesRead != ident.length) { | |
75 throw new ELFException("Error reading elf header (read " + | |
76 bytesRead + "bytes, expected to " + | |
77 "read " + ident.length + "bytes)."); | |
78 } | |
79 | |
80 // Check the magic number before we continue reading the file. | |
81 if (!Arrays.equals(getMagicNumber(), ELF_MAGIC_NUMBER)) { | |
82 throw new ELFException("Bad magic number for file."); | |
83 } | |
84 | |
85 header = new ELFHeaderImpl(); | |
86 } | |
87 | |
88 public ELFHeader getHeader() { return header; } | |
89 | |
90 public byte[] getMagicNumber() { | |
91 byte magicNumber[] = new byte[4]; | |
92 magicNumber[0] = ident[NDX_MAGIC_0]; | |
93 magicNumber[1] = ident[NDX_MAGIC_1]; | |
94 magicNumber[2] = ident[NDX_MAGIC_2]; | |
95 magicNumber[3] = ident[NDX_MAGIC_3]; | |
96 return magicNumber; | |
97 } | |
98 | |
99 public byte getObjectSize() { return ident[NDX_OBJECT_SIZE]; } | |
100 public byte getEncoding() { return ident[NDX_ENCODING]; } | |
101 public byte getVersion() { return ident[NDX_VERSION]; } | |
102 | |
103 | |
104 /** | |
105 * Implementation of the ELFHeader interface. | |
106 */ | |
107 class ELFHeaderImpl implements ELFHeader { | |
108 /** Marks the file as an object file and provide machine-independent | |
109 * data so the contents may be decoded and interpreted. */ | |
110 private byte ident[] = new byte[16]; // unsigned char | |
111 /** Identifies the object file type. */ | |
112 private short file_type; // Elf32_Half | |
113 /** The required architecture. */ | |
114 private short arch; // Elf32_Half | |
115 /** Version */ | |
116 private int version; // Elf32_Word | |
117 /** Virtual address to which the system first transfers control. | |
118 * If there is no entry point for the file the value is 0. */ | |
119 private int entry_point; // Elf32_Addr | |
120 /** Program header table offset in bytes. If there is no program | |
121 * header table the value is 0. */ | |
122 private int ph_offset; // Elf32_Off | |
123 /** Section header table offset in bytes. If there is no section | |
124 * header table the value is 0. */ | |
125 private int sh_offset; // Elf32_Off | |
126 /** Processor specific flags. */ | |
127 private int flags; // Elf32_Word | |
128 /** ELF header size in bytes. */ | |
129 private short eh_size; // Elf32_Half | |
130 /** Size of one entry in the file's program header table in bytes. | |
131 * All entries are the same size. */ | |
132 private short ph_entry_size; // Elf32_Half | |
133 /** Number of entries in the program header table, 0 if no | |
134 * entries. */ | |
135 private short num_ph; // Elf32_Half | |
136 /** Section header entry size in bytes. */ | |
137 private short sh_entry_size; // Elf32_Half | |
138 /** Number of entries in the section header table, 0 if no | |
139 * entries. */ | |
140 private short num_sh; // Elf32_Half | |
141 /** Index into the section header table associated with the section | |
142 * name string table. SH_UNDEF if there is no section name string | |
143 * table. */ | |
144 private short sh_string_ndx; // Elf32_Half | |
145 | |
146 /** MemoizedObject array of section headers associated with this | |
147 * ELF file. */ | |
148 private MemoizedObject[] sectionHeaders; | |
149 /** MemoizedObject array of program headers associated with this | |
150 * ELF file. */ | |
151 private MemoizedObject[] programHeaders; | |
152 | |
153 /** Used to cache symbol table lookup. */ | |
154 private ELFSectionHeader symbolTableSection; | |
155 /** Used to cache dynamic symbol table lookup. */ | |
156 private ELFSectionHeader dynamicSymbolTableSection; | |
157 /** Used to cache hash table lookup. */ | |
158 private ELFHashTable hashTable; | |
159 | |
160 /** | |
161 * Reads the ELF header and sets up the section and program headers | |
162 * in memoized arrays. | |
163 */ | |
164 ELFHeaderImpl() throws ELFException { | |
165 file_type = readShort(); | |
166 arch = readShort(); | |
167 version = readInt(); | |
168 entry_point = readInt(); | |
169 ph_offset = readInt(); | |
170 sh_offset = readInt(); | |
171 flags = readInt(); | |
172 eh_size = readShort(); | |
173 ph_entry_size = readShort(); | |
174 num_ph = readShort(); | |
175 sh_entry_size = readShort(); | |
176 num_sh = readShort(); | |
177 sh_string_ndx = readShort(); | |
178 | |
179 // Set up the section headers | |
180 sectionHeaders = new MemoizedObject[num_sh]; | |
181 for (int i = 0; i < num_sh; i++) { | |
182 final long sectionHeaderOffset = | |
183 (long)(sh_offset + (i * sh_entry_size)); | |
184 sectionHeaders[i] = new MemoizedObject() { | |
185 public Object computeValue() { | |
186 return new ELFSectionHeaderImpl(sectionHeaderOffset); | |
187 } | |
188 }; | |
189 } | |
190 | |
191 // // Set up the program headers | |
192 // programHeaders = new MemoizedObject[num_sh]; | |
193 // for (int i = 0; i < num_sh; i++) { | |
194 // final long programHeaderOffset = | |
195 // (long)(ph_offset + (i * ph_entry_size)); | |
196 // programHeaders[i] = new MemoizedObject() { | |
197 // public Object computeValue() { | |
198 // return new ProgramHeaderImpl(programHeaderOffset); | |
199 // } | |
200 // }; | |
201 // } | |
202 } | |
203 | |
204 public short getFileType() { return file_type; } | |
205 public short getArch() { return arch; } | |
206 public short getSectionHeaderSize() { return sh_entry_size; } | |
207 public short getNumberOfSectionHeaders() { return num_sh; } | |
208 | |
209 // public short getProgramHeaderSize() { return ph_entry_size; } | |
210 // public short getNumberOfProgramHeaders() { return num_ph; } | |
211 | |
212 | |
213 /** | |
214 * Returns the section header at the specified index. The section | |
215 * header at index 0 is defined as being a undefined section. */ | |
216 public ELFSectionHeader getSectionHeader(int index) { | |
217 return (ELFSectionHeader)sectionHeaders[index].getValue(); | |
218 } | |
219 | |
220 public ELFStringTable getSectionHeaderStringTable() { | |
221 return getSectionHeader(sh_string_ndx).getStringTable(); | |
222 } | |
223 | |
224 public ELFStringTable getStringTable() { | |
225 return findStringTableWithName(ELFSectionHeader.STRING_TABLE_NAME); | |
226 } | |
227 | |
228 public ELFStringTable getDynamicStringTable() { | |
229 return findStringTableWithName( | |
230 ELFSectionHeader.DYNAMIC_STRING_TABLE_NAME); | |
231 } | |
232 | |
233 private ELFStringTable findStringTableWithName(String tableName) { | |
234 // Loop through the section header and look for a section | |
235 // header with the name "tableName". We can ignore entry 0 | |
236 // since it is defined as being undefined. | |
237 ELFSectionHeader sh = null; | |
238 for (int i = 1; i < getNumberOfSectionHeaders(); i++) { | |
239 sh = getSectionHeader(i); | |
240 if (tableName.equals(sh.getName())) { | |
241 return sh.getStringTable(); | |
242 } | |
243 } | |
244 return null; | |
245 } | |
246 | |
247 /** | |
248 * The ELFHashTable does not currently work. This method will | |
249 * always return null. */ | |
250 public ELFHashTable getHashTable() { | |
251 // if (hashTable != null) { | |
252 // return hashTable; | |
253 // } | |
254 // | |
255 // ELFHashTable ht = null; | |
256 // for (int i = 1; i < getNumberOfSectionHeaders(); i++) { | |
257 // if ((ht = getSectionHeader(i).getHashTable()) != null) { | |
258 // hashTable = ht; | |
259 // return hashTable; | |
260 // } | |
261 // } | |
262 return null; | |
263 } | |
264 | |
265 public ELFSectionHeader getSymbolTableSection() { | |
266 if (symbolTableSection != null) { | |
267 return symbolTableSection; | |
268 } | |
269 | |
270 symbolTableSection = | |
271 getSymbolTableSection(ELFSectionHeader.TYPE_SYMTBL); | |
272 return symbolTableSection; | |
273 } | |
274 | |
275 public ELFSectionHeader getDynamicSymbolTableSection() { | |
276 if (dynamicSymbolTableSection != null) { | |
277 return dynamicSymbolTableSection; | |
278 } | |
279 | |
280 dynamicSymbolTableSection = | |
281 getSymbolTableSection(ELFSectionHeader.TYPE_DYNSYM); | |
282 return dynamicSymbolTableSection; | |
283 } | |
284 | |
285 private ELFSectionHeader getSymbolTableSection(int type) { | |
286 ELFSectionHeader sh = null; | |
287 for (int i = 1; i < getNumberOfSectionHeaders(); i++) { | |
288 sh = getSectionHeader(i); | |
289 if (sh.getType() == type) { | |
290 dynamicSymbolTableSection = sh; | |
291 return sh; | |
292 } | |
293 } | |
294 return null; | |
295 } | |
296 | |
297 public ELFSymbol getELFSymbol(String symbolName) { | |
298 if (symbolName == null) { | |
299 return null; | |
300 } | |
301 | |
302 // Check dynamic symbol table for symbol name. | |
303 ELFSymbol symbol = null; | |
304 int numSymbols = 0; | |
305 ELFSectionHeader sh = getDynamicSymbolTableSection(); | |
306 if (sh != null) { | |
307 numSymbols = sh.getNumberOfSymbols(); | |
308 for (int i = 0; i < Math.ceil(numSymbols / 2); i++) { | |
309 if (symbolName.equals( | |
310 (symbol = sh.getELFSymbol(i)).getName())) { | |
311 return symbol; | |
312 } else if (symbolName.equals( | |
313 (symbol = sh.getELFSymbol( | |
314 numSymbols - 1 - i)).getName())) { | |
315 return symbol; | |
316 } | |
317 } | |
318 } | |
319 | |
320 // Check symbol table for symbol name. | |
321 sh = getSymbolTableSection(); | |
322 if (sh != null) { | |
323 numSymbols = sh.getNumberOfSymbols(); | |
324 for (int i = 0; i < Math.ceil(numSymbols / 2); i++) { | |
325 if (symbolName.equals( | |
326 (symbol = sh.getELFSymbol(i)).getName())) { | |
327 return symbol; | |
328 } else if (symbolName.equals( | |
329 (symbol = sh.getELFSymbol( | |
330 numSymbols - 1 - i)).getName())) { | |
331 return symbol; | |
332 } | |
333 } | |
334 } | |
335 return null; | |
336 } | |
337 | |
338 public ELFSymbol getELFSymbol(long address) { | |
339 // Check dynamic symbol table for address. | |
340 ELFSymbol symbol = null; | |
341 int numSymbols = 0; | |
342 long value = 0L; | |
343 | |
344 ELFSectionHeader sh = getDynamicSymbolTableSection(); | |
345 if (sh != null) { | |
346 numSymbols = sh.getNumberOfSymbols(); | |
347 for (int i = 0; i < numSymbols; i++) { | |
348 symbol = sh.getELFSymbol(i); | |
349 value = symbol.getValue(); | |
350 if (address >= value && address < value + symbol.getSize()) { | |
351 return symbol; | |
352 } | |
353 } | |
354 } | |
355 | |
356 // Check symbol table for symbol name. | |
357 sh = getSymbolTableSection(); | |
358 if (sh != null) { | |
359 numSymbols = sh.getNumberOfSymbols(); | |
360 for (int i = 0; i < numSymbols; i++) { | |
361 symbol = sh.getELFSymbol(i); | |
362 value = symbol.getValue(); | |
363 if (address >= value && address < value + symbol.getSize()) { | |
364 return symbol; | |
365 } | |
366 } | |
367 } | |
368 return null; | |
369 } | |
370 | |
371 // public ProgramHeader getProgramHeader(int index) { | |
372 // return (ProgramHeader)programHeaders[index].getValue(); | |
373 // } | |
374 } | |
375 | |
376 | |
377 /** | |
378 * Implementation of the ELFSectionHeader interface. | |
379 */ | |
380 class ELFSectionHeaderImpl implements ELFSectionHeader { | |
381 /** Index into the section header string table which gives the | |
382 * name of the section. */ | |
383 private int name_ndx; // Elf32_Word | |
384 /** Section content and semantics. */ | |
385 private int type; // Elf32_Word | |
386 /** Flags. */ | |
387 private int flags; // Elf32_Word | |
388 /** If the section will be in the memory image of a process this | |
389 * will be the address at which the first byte of section will be | |
390 * loaded. Otherwise, this value is 0. */ | |
391 private int address; // Elf32_Addr | |
392 /** Offset from beginning of file to first byte of the section. */ | |
393 private int section_offset; // Elf32_Off | |
394 /** Size in bytes of the section. TYPE_NOBITS is a special case. */ | |
395 private int size; // Elf32_Word | |
396 /** Section header table index link. */ | |
397 private int link; // Elf32_Word | |
398 /** Extra information determined by the section type. */ | |
399 private int info; // Elf32_Word | |
400 /** Address alignment constraints for the section. */ | |
401 private int address_alignment; // Elf32_Word | |
402 /** Size of a fixed-size entry, 0 if none. */ | |
403 private int entry_size; // Elf32_Word | |
404 | |
405 /** Memoized symbol table. */ | |
406 private MemoizedObject[] symbols; | |
407 /** Memoized string table. */ | |
408 private MemoizedObject stringTable; | |
409 /** Memoized hash table. */ | |
410 private MemoizedObject hashTable; | |
411 | |
412 /** | |
413 * Reads the section header information located at offset. | |
414 */ | |
415 ELFSectionHeaderImpl(long offset) throws ELFException { | |
416 seek(offset); | |
417 name_ndx = readInt(); | |
418 type = readInt(); | |
419 flags = readInt(); | |
420 address = readInt(); | |
421 section_offset = readInt(); | |
422 size = readInt(); | |
423 link = readInt(); | |
424 info = readInt(); | |
425 address_alignment = readInt(); | |
426 entry_size = readInt(); | |
427 | |
428 switch (type) { | |
429 case ELFSectionHeader.TYPE_NULL: | |
430 break; | |
431 case ELFSectionHeader.TYPE_PROGBITS: | |
432 break; | |
433 case ELFSectionHeader.TYPE_SYMTBL: | |
434 case ELFSectionHeader.TYPE_DYNSYM: | |
435 // Setup the symbol table. | |
436 int num_entries = size / entry_size; | |
437 symbols = new MemoizedObject[num_entries]; | |
438 for (int i = 0; i < num_entries; i++) { | |
439 final int symbolOffset = section_offset + | |
440 (i * entry_size); | |
441 symbols[i] = new MemoizedObject() { | |
442 public Object computeValue() { | |
443 return new ELFSymbolImpl(symbolOffset,type); | |
444 } | |
445 }; | |
446 } | |
447 break; | |
448 case ELFSectionHeader.TYPE_STRTBL: | |
449 // Setup the string table. | |
450 final int strTableOffset = section_offset; | |
451 final int strTableSize = size; | |
452 stringTable = new MemoizedObject() { | |
453 public Object computeValue() { | |
454 return new ELFStringTableImpl(strTableOffset, | |
455 strTableSize); | |
456 } | |
457 }; | |
458 break; | |
459 case ELFSectionHeader.TYPE_RELO_EXPLICIT: | |
460 break; | |
461 case ELFSectionHeader.TYPE_HASH: | |
462 final int hashTableOffset = section_offset; | |
463 final int hashTableSize = size; | |
464 hashTable = new MemoizedObject() { | |
465 public Object computeValue() { | |
466 return new ELFHashTableImpl(hashTableOffset, | |
467 hashTableSize); | |
468 } | |
469 }; | |
470 break; | |
471 case ELFSectionHeader.TYPE_DYNAMIC: | |
472 break; | |
473 case ELFSectionHeader.TYPE_NOTE: | |
474 break; | |
475 case ELFSectionHeader.TYPE_NOBITS: | |
476 break; | |
477 case ELFSectionHeader.TYPE_RELO: | |
478 break; | |
479 case ELFSectionHeader.TYPE_SHLIB: | |
480 break; | |
481 default: | |
482 break; | |
483 } | |
484 } | |
485 | |
486 public int getType() { | |
487 return type; | |
488 } | |
489 | |
490 public int getNumberOfSymbols() { | |
491 if (symbols != null) { | |
492 return symbols.length; | |
493 } | |
494 return 0; | |
495 } | |
496 | |
497 /** | |
498 * Returns the ELFSymbol at the specified index. Index 0 is | |
499 * reserved for the undefined ELF symbol. */ | |
500 public ELFSymbol getELFSymbol(int index) { | |
501 return (ELFSymbol)symbols[index].getValue(); | |
502 } | |
503 | |
504 public ELFStringTable getStringTable() { | |
505 if (stringTable != null) { | |
506 return (ELFStringTable)stringTable.getValue(); | |
507 } | |
508 return null; | |
509 } | |
510 | |
511 /** | |
512 * The ELFHashTable does not currently work. This method will | |
513 * always return null. */ | |
514 public ELFHashTable getHashTable() { | |
515 if (hashTable != null) { | |
516 return (ELFHashTable)hashTable.getValue(); | |
517 } | |
518 return null; | |
519 } | |
520 | |
521 public String getName() { | |
522 if (name_ndx == 0) { | |
523 return null; | |
524 } | |
525 | |
526 ELFStringTable tbl = getHeader().getSectionHeaderStringTable(); | |
527 return tbl.get(name_ndx); | |
528 } | |
529 | |
530 public int getLink() { | |
531 return link; | |
532 } | |
533 | |
534 public int getOffset() { | |
535 return section_offset; | |
536 } | |
537 } | |
538 | |
539 | |
540 // class ProgramHeaderImpl implements ProgramHeader { | |
541 // /** Defines the kind of segment this element describes. */ | |
542 // private int type; // Elf32_Word | |
543 // /** Offset from the beginning of the file. */ | |
544 // private int offset; // Elf32_Off | |
545 // /** Virtual address at which the first byte of the segment | |
546 // * resides in memory. */ | |
547 // private int virtual_address; // Elf32_Addr | |
548 // /** Reserved for the physical address of the segment on systems | |
549 // * where physical addressinf is relevant. */ | |
550 // private int physical_address; // Elf32_addr | |
551 // /** File image size of segment in bytes, may be 0. */ | |
552 // private int file_size; // Elf32_Word | |
553 // /** Memory image size of segment in bytes, may be 0. */ | |
554 // private int mem_size; // Elf32_Word | |
555 // /** Flags relevant to this segment. Values for flags are defined | |
556 // * in ELFSectionHeader. */ | |
557 // private int flags; // Elf32_Word | |
558 // private int alignment; // Elf32_Word | |
559 // | |
560 // private MemoizedObject[] symbols; | |
561 // | |
562 // ProgramHeaderImpl(long offset) throws ELFException { | |
563 // seek(offset); | |
564 // type = readInt(); | |
565 // this.offset = readInt(); | |
566 // virtual_address = readInt(); | |
567 // physical_address = readInt(); | |
568 // file_size = readInt(); | |
569 // mem_size = readInt(); | |
570 // flags = readInt(); | |
571 // alignment = readInt(); | |
572 // | |
573 // switch (type) { | |
574 // case ELFSectionHeader.TYPE_NULL: | |
575 // break; | |
576 // case ELFSectionHeader.TYPE_PROGBITS: | |
577 // break; | |
578 // case ELFSectionHeader.TYPE_SYMTBL: | |
579 // case ELFSectionHeader.TYPE_DYNSYM: | |
580 // break; | |
581 // case ELFSectionHeader.TYPE_STRTBL: | |
582 // // Setup the string table. | |
583 // final int strTableOffset = section_offset; | |
584 // final int strTableSize = size; | |
585 // stringTable = new MemoizedObject() { | |
586 // public Object computeValue() { | |
587 // return new ELFStringTableImpl(strTableOffset, | |
588 // strTableSize); | |
589 // } | |
590 // }; | |
591 // new ELFStringTableImpl(offset, file_size); | |
592 // break; | |
593 // case ELFSectionHeader.TYPE_RELO_EXPLICIT: | |
594 // break; | |
595 // case ELFSectionHeader.TYPE_HASH: | |
596 // break; | |
597 // case ELFSectionHeader.TYPE_DYNAMIC: | |
598 // break; | |
599 // case ELFSectionHeader.TYPE_NOTE: | |
600 // break; | |
601 // case ELFSectionHeader.TYPE_NOBITS: | |
602 // break; | |
603 // case ELFSectionHeader.TYPE_RELO: | |
604 // break; | |
605 // case ELFSectionHeader.TYPE_SHLIB: | |
606 // break; | |
607 // default: | |
608 // break; | |
609 // } | |
610 // } | |
611 // | |
612 // public int getType() { | |
613 // return type; | |
614 // } | |
615 // } | |
616 | |
617 | |
618 /** | |
619 * Implementation of the ELFSymbol interface. | |
620 */ | |
621 class ELFSymbolImpl implements ELFSymbol { | |
622 /** Index into the symbol string table that holds the character | |
623 * representation of the symbols. 0 means the symbol has no | |
624 * character name. */ | |
625 private int name_ndx; // Elf32_Word | |
626 /** Value of the associated symbol. This may be an address or | |
627 * an absolute value. */ | |
628 private int value; // Elf32_Addr | |
629 /** Size of the symbol. 0 if the symbol has no size or the size | |
630 * is unknown. */ | |
631 private int size; // Elf32_Word | |
632 /** Specifies the symbol type and beinding attributes. */ | |
633 private byte info; // unsigned char | |
634 /** Currently holds the value of 0 and has no meaning. */ | |
635 private byte other; // unsigned char | |
636 /** Index to the associated section header. This value will need | |
637 * to be read as an unsigned short if we compare it to | |
638 * ELFSectionHeader.NDX_LORESERVE and ELFSectionHeader.NDX_HIRESERVE. */ | |
639 private short section_header_ndx; // Elf32_Half | |
640 | |
641 private int section_type; | |
642 | |
643 /** Offset from the beginning of the file to this symbol. */ | |
644 private long offset; | |
645 | |
646 ELFSymbolImpl(long offset, int section_type) throws ELFException { | |
647 seek(offset); | |
648 this.offset = offset; | |
649 name_ndx = readInt(); | |
650 value = readInt(); | |
651 size = readInt(); | |
652 info = readByte(); | |
653 other = readByte(); | |
654 section_header_ndx = readShort(); | |
655 | |
656 this.section_type = section_type; | |
657 | |
658 switch (getType()) { | |
659 case TYPE_NOOBJECT: | |
660 break; | |
661 case TYPE_OBJECT: | |
662 break; | |
663 case TYPE_FUNCTION: | |
664 break; | |
665 case TYPE_SECTION: | |
666 break; | |
667 case TYPE_FILE: | |
668 break; | |
669 case TYPE_LOPROC: | |
670 break; | |
671 case TYPE_HIPROC: | |
672 break; | |
673 default: | |
674 break; | |
675 } | |
676 } | |
677 | |
678 public int getBinding() { return info >> 4; } | |
679 public int getType() { return info & 0x0F; } | |
680 public long getOffset() { return offset; } | |
681 | |
682 public String getName() { | |
683 // Check to make sure this symbol has a name. | |
684 if (name_ndx == 0) { | |
685 return null; | |
686 } | |
687 | |
688 // Retrieve the name of the symbol from the correct string | |
689 // table. | |
690 String symbol_name = null; | |
691 if (section_type == ELFSectionHeader.TYPE_SYMTBL) { | |
692 symbol_name = getHeader().getStringTable().get(name_ndx); | |
693 } else if (section_type == ELFSectionHeader.TYPE_DYNSYM) { | |
694 symbol_name = | |
695 getHeader().getDynamicStringTable().get(name_ndx); | |
696 } | |
697 return symbol_name; | |
698 } | |
699 | |
700 public long getValue() { | |
701 return value; | |
702 } | |
703 | |
704 public int getSize() { | |
705 return size; | |
706 } | |
707 } | |
708 | |
709 /** | |
710 * Implementation of the ELFStringTable interface. | |
711 */ | |
712 class ELFStringTableImpl implements ELFStringTable { | |
713 /** The string table data. */ | |
714 private byte data[]; | |
715 private int numStrings; | |
716 | |
717 /** | |
718 * Reads all the strings from [offset, length]. | |
719 */ | |
720 ELFStringTableImpl(long offset, int length) throws ELFException { | |
721 seek(offset); | |
722 data = new byte[length]; | |
723 int bytesRead = readBytes(data); | |
724 if (bytesRead != length) { | |
725 throw new ELFException("Error reading string table (read " + | |
726 bytesRead + "bytes, expected to " + | |
727 "read " + data.length + "bytes)."); | |
728 } | |
729 | |
730 // Count the strings. | |
731 numStrings = 0; | |
732 for (int ptr = 0; ptr < data.length; ptr++) { | |
733 if (data[ptr] == '\0') { | |
734 numStrings++; | |
735 } | |
736 } | |
737 } | |
738 | |
739 public String get(int index) { | |
740 int startPtr = index; | |
741 int endPtr = index; | |
742 while (data[endPtr] != '\0') { | |
743 endPtr++; | |
744 } | |
745 return new String(data, startPtr, endPtr - startPtr); | |
746 } | |
747 | |
748 public int getNumStrings() { | |
749 return numStrings; | |
750 } | |
751 } | |
752 | |
753 | |
754 /** Implementation of the ELFHashTable. */ | |
755 class ELFHashTableImpl implements ELFHashTable { | |
756 private int num_buckets; | |
757 private int num_chains; | |
758 | |
759 // These could probably be memoized. | |
760 private int buckets[]; | |
761 private int chains[]; | |
762 | |
763 ELFHashTableImpl(long offset, int length) throws ELFException { | |
764 seek(offset); | |
765 num_buckets = readInt(); | |
766 num_chains = readInt(); | |
767 | |
768 buckets = new int[num_buckets]; | |
769 chains = new int[num_chains]; | |
770 // Read the bucket data. | |
771 for (int i = 0; i < num_buckets; i++) { | |
772 buckets[i] = readInt(); | |
773 } | |
774 | |
775 // Read the chain data. | |
776 for (int i = 0; i < num_chains; i++) { | |
777 chains[i] = readInt(); | |
778 } | |
779 | |
780 // Make sure that the amount of bytes we were supposed to read | |
781 // was what we actually read. | |
782 int actual = num_buckets * 4 + num_chains * 4 + 8; | |
783 if (length != actual) { | |
784 throw new ELFException("Error reading string table (read " + | |
785 actual + "bytes, expected to " + | |
786 "read " + length + "bytes)."); | |
787 } | |
788 } | |
789 | |
790 /** | |
791 * This method doesn't work every time and is unreliable. Use | |
792 * ELFSection.getELFSymbol(String) to retrieve symbols by name. | |
793 * NOTE: since this method is currently broken it will always | |
794 * return null. */ | |
795 public ELFSymbol getSymbol(String symbolName) { | |
796 // if (symbolName == null) { | |
797 // return null; | |
798 // } | |
799 // | |
800 // long hash = 0; | |
801 // long g = 0; | |
802 // | |
803 // for (int i = 0; i < symbolName.length(); i++) { | |
804 // hash = (hash << 4) + symbolName.charAt(i); | |
805 // if ((g = hash & 0xf0000000) != 0) { | |
806 // hash ^= g >>> 24; | |
807 // } | |
808 // hash &= ~g; | |
809 // } | |
810 // | |
811 // ELFSymbol symbol = null; | |
812 // ELFSectionHeader dyn_sh = | |
813 // getHeader().getDynamicSymbolTableSection(); | |
814 // int index = (int)hash % num_buckets; | |
815 // while(index != 0) { | |
816 // symbol = dyn_sh.getELFSymbol(index); | |
817 // if (symbolName.equals(symbol.getName())) { | |
818 // break; | |
819 // } | |
820 // symbol = null; | |
821 // index = chains[index]; | |
822 // } | |
823 // return symbol; | |
824 return null; | |
825 } | |
826 } | |
827 | |
828 | |
829 public void close() throws ELFException { | |
830 try { | |
831 file.close(); | |
832 } catch (IOException e) { | |
833 throw new ELFException(e); | |
834 } | |
835 } | |
836 | |
837 void seek(long offset) throws ELFException { | |
838 try { | |
839 file.seek(offset); | |
840 } catch (IOException e) { | |
841 throw new ELFException(e); | |
842 } | |
843 } | |
844 | |
845 long getFilePointer() throws ELFException { | |
846 try { | |
847 return file.getFilePointer(); | |
848 } catch (IOException e) { | |
849 throw new ELFException(e); | |
850 } | |
851 } | |
852 | |
853 byte readByte() throws ELFException { | |
854 try { | |
855 return file.readByte(); | |
856 } catch (IOException e) { | |
857 throw new ELFException(e); | |
858 } | |
859 } | |
860 | |
861 int readBytes(byte[] b) throws ELFException { | |
862 try { | |
863 return file.read(b); | |
864 } catch (IOException e) { | |
865 throw new ELFException(e); | |
866 } | |
867 } | |
868 | |
869 short readShort() throws ELFException { | |
870 try { | |
871 short val; | |
872 switch (ident[NDX_ENCODING]) { | |
873 case DATA_LSB: | |
874 val = byteSwap(file.readShort()); | |
875 break; | |
876 case DATA_MSB: | |
877 val = file.readShort(); | |
878 break; | |
879 default: | |
880 throw new ELFException("Invalid encoding."); | |
881 } | |
882 return val; | |
883 } catch (IOException e) { | |
884 throw new ELFException(e); | |
885 } | |
886 } | |
887 | |
888 int readInt() throws ELFException { | |
889 try { | |
890 int val; | |
891 switch (ident[NDX_ENCODING]) { | |
892 case DATA_LSB: | |
893 val = byteSwap(file.readInt()); | |
894 break; | |
895 case DATA_MSB: | |
896 val = file.readInt(); | |
897 break; | |
898 default: | |
899 throw new ELFException("Invalid encoding."); | |
900 } | |
901 return val; | |
902 } catch (IOException e) { | |
903 throw new ELFException(e); | |
904 } | |
905 } | |
906 | |
907 long readLong() throws ELFException { | |
908 try { | |
909 long val; | |
910 switch (ident[NDX_ENCODING]) { | |
911 case DATA_LSB: | |
912 val = byteSwap(file.readLong()); | |
913 break; | |
914 case DATA_MSB: | |
915 val = file.readLong(); | |
916 break; | |
917 default: | |
918 throw new ELFException("Invalid encoding."); | |
919 } | |
920 return val; | |
921 } catch (IOException e) { | |
922 throw new ELFException(e); | |
923 } | |
924 } | |
925 | |
926 /** Signed byte utility functions used for converting from big-endian | |
927 * (MSB) to little-endian (LSB). */ | |
928 short byteSwap(short arg) { | |
929 return (short) ((arg << 8) | ((arg >>> 8) & 0xFF)); | |
930 } | |
931 | |
932 int byteSwap(int arg) { | |
933 return (((int) byteSwap((short) arg)) << 16) | | |
934 (((int) (byteSwap((short) (arg >>> 16)))) & 0xFFFF); | |
935 } | |
936 | |
937 long byteSwap(long arg) { | |
938 return ((((long) byteSwap((int) arg)) << 32) | | |
939 (((long) byteSwap((int) (arg >>> 32))) & 0xFFFFFFFF)); | |
940 } | |
941 | |
942 | |
943 /* Unsigned byte utility functions. Since java does not have unsigned | |
944 * data types we must convert values manually and we must return | |
945 * unsigned values in a larger data type. Therefore we can only have | |
946 * unsigned values for byte, short, and int. */ | |
947 short readUnsignedByte() throws ELFException { | |
948 try { | |
949 return unsignedByte(file.readByte()); | |
950 } catch (IOException e) { | |
951 throw new ELFException(e); | |
952 } | |
953 } | |
954 | |
955 int readUnsignedShort() throws ELFException { | |
956 try { | |
957 int val; | |
958 switch (ident[NDX_ENCODING]) { | |
959 case DATA_LSB: | |
960 val = unsignedByteSwap(file.readShort()); | |
961 break; | |
962 case DATA_MSB: | |
963 val = unsignedByte(file.readShort()); | |
964 break; | |
965 default: | |
966 throw new ELFException("Invalid encoding."); | |
967 } | |
968 return val; | |
969 } catch (IOException e) { | |
970 throw new ELFException(e); | |
971 } | |
972 } | |
973 | |
974 long readUnsignedInt() throws ELFException { | |
975 try { | |
976 long val; | |
977 switch (ident[NDX_ENCODING]) { | |
978 case DATA_LSB: | |
979 val = unsignedByteSwap(file.readInt()); | |
980 break; | |
981 case DATA_MSB: | |
982 val = unsignedByte(file.readInt()); | |
983 break; | |
984 default: | |
985 throw new ELFException("Invalid encoding."); | |
986 } | |
987 return val; | |
988 } catch (IOException e) { | |
989 throw new ELFException(e); | |
990 } | |
991 } | |
992 | |
993 /** Returns the unsigned value of the byte. */ | |
994 short unsignedByte(byte arg) { | |
995 return (short)(arg & 0x00FF); | |
996 } | |
997 | |
998 /** Returns a big-endian unsigned representation of the short. */ | |
999 int unsignedByte(short arg) { | |
1000 int val; | |
1001 if (arg >= 0) { | |
1002 val = arg; | |
1003 } else { | |
1004 val = (int)(((int)unsignedByte((byte)(arg >>> 8)) << 8) | | |
1005 ((byte)arg)); | |
1006 } | |
1007 return val; | |
1008 } | |
1009 | |
1010 /** Returns a big-endian unsigned representation of the int. */ | |
1011 long unsignedByte(int arg) { | |
1012 long val; | |
1013 if (arg >= 0) { | |
1014 val = arg; | |
1015 } else { | |
1016 val = (long)(((long)unsignedByte((short)(arg >>> 16)) << 16) | | |
1017 ((short)arg)); | |
1018 } | |
1019 return val; | |
1020 } | |
1021 | |
1022 /** Unsigned byte utility functions used for converting from big-endian | |
1023 * (MSB) to little-endian (LSB). */ | |
1024 int unsignedByteSwap(short arg) { | |
1025 return (int)(((int)unsignedByte((byte)arg)) << 8) | | |
1026 ((int)unsignedByte((byte)(arg >>> 8))); | |
1027 } | |
1028 | |
1029 long unsignedByteSwap(int arg) { | |
1030 return (long)(((long)unsignedByteSwap((short)arg)) << 16) | | |
1031 ((long)unsignedByteSwap((short)(arg >>> 16))); | |
1032 } | |
1033 } | |
1034 | |
1035 public static void main(String args[]) { | |
1036 if (args.length != 1) { | |
1037 System.out.println("Usage: java ELFFileParser <elf file>"); | |
1038 System.exit(0); | |
1039 } | |
1040 | |
1041 // Parse the file. | |
1042 ELFFile elfFile = ELFFileParser.getParser().parse(args[0]); | |
1043 | |
1044 ELFHeader elfHeader = elfFile.getHeader(); | |
1045 System.out.println("ELF File: " + args[0]); | |
1046 | |
1047 System.out.println("ELF object size: " + | |
1048 ((elfFile.getObjectSize() == 0) ? "Invalid Object Size" : | |
1049 (elfFile.getObjectSize() == 1) ? "32-bit" : "64-bit")); | |
1050 System.out.println("ELF data encoding: " + | |
1051 ((elfFile.getEncoding() == 0) ? "Invalid Data Encoding" : | |
1052 (elfFile.getEncoding() == 1) ? "LSB" : "MSB")); | |
1053 | |
1054 int h = elfHeader.getNumberOfSectionHeaders(); | |
1055 System.out.println("--> Start: reading " + h + " section headers."); | |
1056 for (int i = 0; i < elfHeader.getNumberOfSectionHeaders(); i++) { | |
1057 ELFSectionHeader sh = elfHeader.getSectionHeader(i); | |
1058 String str = sh.getName(); | |
1059 System.out.println("----> Start: Section (" + i + ") " + str); | |
1060 | |
1061 int num = 0; | |
1062 if ((num = sh.getNumberOfSymbols()) != 0) { | |
1063 System.out.println("------> Start: reading " + num + " symbols."); | |
1064 for (int j = 0; j < num ; j++) { | |
1065 ELFSymbol sym = sh.getELFSymbol(j); | |
1066 //String name = sym.getName(); | |
1067 //if (name != null) { | |
1068 // System.out.println(name); | |
1069 //} | |
1070 } | |
1071 System.out.println("<------ End: reading " + num + " symbols."); | |
1072 } | |
1073 ELFStringTable st; | |
1074 if (sh.getType() == ELFSectionHeader.TYPE_STRTBL) { | |
1075 System.out.println("------> Start: reading string table."); | |
1076 st = sh.getStringTable(); | |
1077 System.out.println("<------ End: reading string table."); | |
1078 } | |
1079 if (sh.getType() == ELFSectionHeader.TYPE_HASH) { | |
1080 System.out.println("------> Start: reading hash table."); | |
1081 sh.getHashTable(); | |
1082 System.out.println("<------ End: reading hash table."); | |
1083 } | |
1084 System.out.println("<---- End: Section (" + i + ") " + str); | |
1085 } | |
1086 System.out.println("<-- End: reading " + h + " section headers."); | |
1087 /* | |
1088 h = elfHeader.getNumberOfProgramHeaders(); | |
1089 System.out.println("--> Start: reading " + h + " program headers."); | |
1090 for (int i = 0; i < elfHeader.getNumberOfProgramHeaders(); i++) { | |
1091 elfHeader.getProgramHeader(i); | |
1092 } | |
1093 System.out.println("<-- End: reading " + h + " program headers."); | |
1094 */ | |
1095 elfFile.close(); | |
1096 } | |
1097 } |