1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-04 14:55:41 +02:00

use mapping of sections for dwarf parser rather than allocating memory which avoids out of memory exceptions for large symbol files.

This commit is contained in:
Warren Paul 2009-04-03 15:57:29 +00:00
parent f0893c8b81
commit 7ef8d28991
3 changed files with 146 additions and 177 deletions

View file

@ -11,10 +11,9 @@
package org.eclipse.cdt.utils.debug.dwarf; package org.eclipse.cdt.utils.debug.dwarf;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -160,7 +159,7 @@ public class Dwarf {
int identifierCase; int identifierCase;
} }
Map<String, byte[]> dwarfSections = new HashMap<String, byte[]>(); Map<String, ByteBuffer> dwarfSections = new HashMap<String, ByteBuffer>();
Map<Integer, Map<Long, AbbreviationEntry>> abbreviationMaps = new HashMap<Integer, Map<Long, AbbreviationEntry>>(); Map<Integer, Map<Long, AbbreviationEntry>> abbreviationMaps = new HashMap<Integer, Map<Long, AbbreviationEntry>>();
boolean isLE; boolean isLE;
@ -188,113 +187,105 @@ public class Dwarf {
String name = section.toString(); String name = section.toString();
for (String element : DWARF_SCNNAMES) { for (String element : DWARF_SCNNAMES) {
if (name.equals(element)) { if (name.equals(element)) {
dwarfSections.put(element, section.loadSectionData()); try {
dwarfSections.put(element, section.mapSectionData());
} catch (Exception e) {
e.printStackTrace();
CCorePlugin.log(e);
}
} }
} }
} }
} }
int read_4_bytes(InputStream in) throws IOException { int read_4_bytes(ByteBuffer in) throws IOException {
try { try {
byte[] bytes = new byte[4]; byte[] bytes = new byte[4];
int n = in.read(bytes, 0, bytes.length); in.get(bytes);
if (n != 4) { return read_4_bytes(bytes);
throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$ } catch (Exception e) {
}
return read_4_bytes(bytes, 0);
} catch (IndexOutOfBoundsException e) {
throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$
} }
} }
// FIXME:This is wrong, it's signed. // FIXME:This is wrong, it's signed.
int read_4_bytes(byte[] bytes, int offset) throws IndexOutOfBoundsException { int read_4_bytes(byte[] bytes) throws IndexOutOfBoundsException {
if (isLE) { if (isLE) {
return ( return (
((bytes[offset + 3] & 0xff) << 24) ((bytes[3] & 0xff) << 24)
| ((bytes[offset + 2] & 0xff) << 16) | ((bytes[2] & 0xff) << 16)
| ((bytes[offset + 1] & 0xff) << 8) | ((bytes[1] & 0xff) << 8)
| (bytes[offset] & 0xff)); | (bytes[0] & 0xff));
} }
return ( return (
((bytes[offset] & 0xff) << 24) ((bytes[0] & 0xff) << 24)
| ((bytes[offset + 1] & 0xff) << 16) | ((bytes[1] & 0xff) << 16)
| ((bytes[offset + 2] & 0xff) << 8) | ((bytes[2] & 0xff) << 8)
| (bytes[offset + 3] & 0xff)); | (bytes[3] & 0xff));
} }
long read_8_bytes(InputStream in) throws IOException { long read_8_bytes(ByteBuffer in) throws IOException {
try { try {
byte[] bytes = new byte[8]; byte[] bytes = new byte[8];
int n = in.read(bytes, 0, bytes.length); in.get(bytes);
if (n != 8) { return read_8_bytes(bytes);
throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$ } catch (Exception e) {
}
return read_8_bytes(bytes, 0);
} catch (IndexOutOfBoundsException e) {
throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$
} }
} }
// FIXME:This is wrong, for unsigned. // FIXME:This is wrong, for unsigned.
long read_8_bytes(byte[] bytes, int offset) throws IndexOutOfBoundsException { long read_8_bytes(byte[] bytes) throws IndexOutOfBoundsException {
if (isLE) { if (isLE) {
return (((bytes[offset + 7] & 0xff) << 56) return (((bytes[7] & 0xff) << 56)
| ((bytes[offset + 6] & 0xff) << 48) | ((bytes[6] & 0xff) << 48)
| ((bytes[offset + 5] & 0xff) << 40) | ((bytes[5] & 0xff) << 40)
| ((bytes[offset + 4] & 0xff) << 32) | ((bytes[4] & 0xff) << 32)
| ((bytes[offset + 3] & 0xff) << 24) | ((bytes[3] & 0xff) << 24)
| ((bytes[offset + 2] & 0xff) << 16) | ((bytes[2] & 0xff) << 16)
| ((bytes[offset + 1] & 0xff) << 8) | ((bytes[1] & 0xff) << 8)
| (bytes[offset] & 0xff)); | (bytes[0] & 0xff));
} }
return (((bytes[offset] & 0xff) << 56) return (((bytes[0] & 0xff) << 56)
| ((bytes[offset + 1] & 0xff) << 48) | ((bytes[1] & 0xff) << 48)
| ((bytes[offset + 2] & 0xff) << 40) | ((bytes[2] & 0xff) << 40)
| ((bytes[offset + 3] & 0xff) << 32) | ((bytes[3] & 0xff) << 32)
| ((bytes[offset + 4] & 0xff) << 24) | ((bytes[4] & 0xff) << 24)
| ((bytes[offset + 5] & 0xff) << 16) | ((bytes[5] & 0xff) << 16)
| ((bytes[offset + 6] & 0xff) << 8) | ((bytes[6] & 0xff) << 8)
| (bytes[offset] & 0xff)); | (bytes[7] & 0xff));
} }
short read_2_bytes(InputStream in) throws IOException { short read_2_bytes(ByteBuffer in) throws IOException {
try { try {
byte[] bytes = new byte[2]; byte[] bytes = new byte[2];
int n = in.read(bytes, 0, bytes.length); in.get(bytes);
if (n != 2) { return read_2_bytes(bytes);
throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$ } catch (Exception e) {
}
return read_2_bytes(bytes, 0);
} catch (IndexOutOfBoundsException e) {
throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("Util.exception.missingBytes")); //$NON-NLS-1$
} }
} }
short read_2_bytes(byte[] bytes, int offset) throws IndexOutOfBoundsException { short read_2_bytes(byte[] bytes) throws IndexOutOfBoundsException {
if (isLE) { if (isLE) {
return (short) (((bytes[offset + 1] & 0xff) << 8) + (bytes[offset] & 0xff)); return (short) (((bytes[1] & 0xff) << 8) + (bytes[0] & 0xff));
} }
return (short) (((bytes[offset] & 0xff) << 8) + (bytes[offset + 1] & 0xff)); return (short) (((bytes[0] & 0xff) << 8) + (bytes[1] & 0xff));
} }
private int num_leb128_read;
/* unsigned */ /* unsigned */
long read_unsigned_leb128(InputStream in) throws IOException { long read_unsigned_leb128(ByteBuffer in) throws IOException {
/* unsigned */ /* unsigned */
long result = 0; long result = 0;
num_leb128_read = 0;
int shift = 0; int shift = 0;
short b; short b;
while (true) { while (true) {
b = (short) in.read(); b = in.get();
if (b == -1) if (!in.hasRemaining())
break; //throw new IOException("no more data"); break; //throw new IOException("no more data");
num_leb128_read++;
result |= ((long) (b & 0x7f) << shift); result |= ((long) (b & 0x7f) << shift);
if ((b & 0x80) == 0) { if ((b & 0x80) == 0) {
break; break;
@ -305,19 +296,17 @@ public class Dwarf {
} }
/* unsigned */ /* unsigned */
long read_signed_leb128(InputStream in) throws IOException { long read_signed_leb128(ByteBuffer in) throws IOException {
/* unsigned */ /* unsigned */
long result = 0; long result = 0;
int shift = 0; int shift = 0;
int size = 32; int size = 32;
num_leb128_read = 0;
short b; short b;
while (true) { while (true) {
b = (short) in.read(); b = in.get();
if (b == -1) if (!in.hasRemaining())
throw new IOException(CCorePlugin.getResourceString("Util.exception.noData")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("Util.exception.noData")); //$NON-NLS-1$
num_leb128_read++;
result |= ((long) (b & 0x7f) << shift); result |= ((long) (b & 0x7f) << shift);
shift += 7; shift += 7;
if ((b & 0x80) == 0) { if ((b & 0x80) == 0) {
@ -335,27 +324,29 @@ public class Dwarf {
} }
void parseDebugInfo(IDebugEntryRequestor requestor) { void parseDebugInfo(IDebugEntryRequestor requestor) {
byte[] data = dwarfSections.get(DWARF_DEBUG_INFO); ByteBuffer data = dwarfSections.get(DWARF_DEBUG_INFO);
if (data != null) { if (data != null) {
try { try {
int length = 0; while (data.hasRemaining()) {
for (int offset = 0; offset < data.length; offset += (length + 4)) {
CompilationUnitHeader header = new CompilationUnitHeader(); CompilationUnitHeader header = new CompilationUnitHeader();
header.length = length = read_4_bytes(data, offset); header.length = read_4_bytes(data);
header.version = read_2_bytes(data, offset + 4); header.version = read_2_bytes(data);
header.abbreviationOffset = read_4_bytes(data, offset + 6); header.abbreviationOffset = read_4_bytes(data);
header.addressSize = data[offset + 10]; header.addressSize = data.get();
if (printEnabled) { if (printEnabled) {
System.out.println("Compilation Unit @ " + Long.toHexString(offset)); //$NON-NLS-1$ System.out.println("Compilation Unit @ " + Long.toHexString(data.position())); //$NON-NLS-1$
System.out.println(header); System.out.println(header);
} }
// read the abbrev section. // read the abbrev section.
// Note "length+4" is the total size in bytes of the CU data.
InputStream in = new ByteArrayInputStream(data, offset + 11, length+4-11);
Map<Long, AbbreviationEntry> abbrevs = parseDebugAbbreviation(header); Map<Long, AbbreviationEntry> abbrevs = parseDebugAbbreviation(header);
parseDebugInfoEntry(requestor, in, abbrevs, header); // Note "length+4" is the total size in bytes of the CU data.
ByteBuffer entryBuffer = data.slice();
entryBuffer.limit(header.length + 4 - 11);
parseDebugInfoEntry(requestor, entryBuffer, abbrevs, header);
data.position(data.position() + header.length + 4 - 11);
if (printEnabled) if (printEnabled)
System.out.println(); System.out.println();
@ -367,23 +358,21 @@ public class Dwarf {
} }
Map<Long, AbbreviationEntry> parseDebugAbbreviation(CompilationUnitHeader header) throws IOException { Map<Long, AbbreviationEntry> parseDebugAbbreviation(CompilationUnitHeader header) throws IOException {
int offset = header.abbreviationOffset; Integer key = new Integer(header.abbreviationOffset);
Integer key = new Integer(offset);
Map<Long, AbbreviationEntry> abbrevs = abbreviationMaps.get(key); Map<Long, AbbreviationEntry> abbrevs = abbreviationMaps.get(key);
if (abbrevs == null) { if (abbrevs == null) {
abbrevs = new HashMap<Long, AbbreviationEntry>(); abbrevs = new HashMap<Long, AbbreviationEntry>();
abbreviationMaps.put(key, abbrevs); abbreviationMaps.put(key, abbrevs);
byte[] data = dwarfSections.get(DWARF_DEBUG_ABBREV); ByteBuffer data = dwarfSections.get(DWARF_DEBUG_ABBREV);
if (data != null) { if (data != null) {
InputStream in = new ByteArrayInputStream(data); data.position(header.abbreviationOffset);
in.skip(offset); while (data.remaining() > 0) {
while (in.available() > 0) { long code = read_unsigned_leb128(data);
long code = read_unsigned_leb128(in);
if (code == 0) { if (code == 0) {
break; break;
} }
long tag = read_unsigned_leb128(in); long tag = read_unsigned_leb128(data);
byte hasChildren = (byte) in.read(); byte hasChildren = data.get();
AbbreviationEntry entry = new AbbreviationEntry(code, tag, hasChildren); AbbreviationEntry entry = new AbbreviationEntry(code, tag, hasChildren);
//System.out.println("\tAbrev Entry: " + code + " " + Long.toHexString(entry.tag) + " " + entry.hasChildren); //System.out.println("\tAbrev Entry: " + code + " " + Long.toHexString(entry.tag) + " " + entry.hasChildren);
@ -392,8 +381,8 @@ public class Dwarf {
long name = 0; long name = 0;
long form = 0; long form = 0;
do { do {
name = read_unsigned_leb128(in); name = read_unsigned_leb128(data);
form = read_unsigned_leb128(in); form = read_unsigned_leb128(data);
if (name != 0) { if (name != 0) {
entry.attributes.add(new Attribute(name, form)); entry.attributes.add(new Attribute(name, form));
} }
@ -406,9 +395,9 @@ public class Dwarf {
return abbrevs; return abbrevs;
} }
void parseDebugInfoEntry(IDebugEntryRequestor requestor, InputStream in, Map<Long, AbbreviationEntry> abbrevs, CompilationUnitHeader header) void parseDebugInfoEntry(IDebugEntryRequestor requestor, ByteBuffer in, Map<Long, AbbreviationEntry> abbrevs, CompilationUnitHeader header)
throws IOException { throws IOException {
while (in.available() > 0) { while (in.remaining() > 0) {
long code = read_unsigned_leb128(in); long code = read_unsigned_leb128(in);
AbbreviationEntry entry = abbrevs.get(new Long(code)); AbbreviationEntry entry = abbrevs.get(new Long(code));
if (entry != null) { if (entry != null) {
@ -428,7 +417,7 @@ public class Dwarf {
} }
} }
Object readAttribute(int form, InputStream in, CompilationUnitHeader header) throws IOException { Object readAttribute(int form, ByteBuffer in, CompilationUnitHeader header) throws IOException {
Object obj = null; Object obj = null;
switch (form) { switch (form) {
case DwarfConstants.DW_FORM_addr : case DwarfConstants.DW_FORM_addr :
@ -440,16 +429,16 @@ public class Dwarf {
{ {
int size = (int) read_unsigned_leb128(in); int size = (int) read_unsigned_leb128(in);
byte[] bytes = new byte[size]; byte[] bytes = new byte[size];
in.read(bytes, 0, size); in.get(bytes);
obj = bytes; obj = bytes;
} }
break; break;
case DwarfConstants.DW_FORM_block1 : case DwarfConstants.DW_FORM_block1 :
{ {
int size = in.read(); int size = in.get();
byte[] bytes = new byte[size]; byte[] bytes = new byte[size];
in.read(bytes, 0, size); in.get(bytes);
obj = bytes; obj = bytes;
} }
break; break;
@ -458,7 +447,7 @@ public class Dwarf {
{ {
int size = read_2_bytes(in); int size = read_2_bytes(in);
byte[] bytes = new byte[size]; byte[] bytes = new byte[size];
in.read(bytes, 0, size); in.get(bytes);
obj = bytes; obj = bytes;
} }
break; break;
@ -467,13 +456,13 @@ public class Dwarf {
{ {
int size = read_4_bytes(in); int size = read_4_bytes(in);
byte[] bytes = new byte[size]; byte[] bytes = new byte[size];
in.read(bytes, 0, size); in.get(bytes);
obj = bytes; obj = bytes;
} }
break; break;
case DwarfConstants.DW_FORM_data1 : case DwarfConstants.DW_FORM_data1 :
obj = new Byte((byte) in.read()); obj = new Byte(in.get());
break; break;
case DwarfConstants.DW_FORM_data2 : case DwarfConstants.DW_FORM_data2 :
@ -500,7 +489,7 @@ public class Dwarf {
{ {
int c; int c;
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
while ((c = in.read()) != -1) { while ((c = in.get()) != -1) {
if (c == 0) { if (c == 0) {
break; break;
} }
@ -511,21 +500,22 @@ public class Dwarf {
break; break;
case DwarfConstants.DW_FORM_flag : case DwarfConstants.DW_FORM_flag :
obj = new Byte((byte) in.read()); obj = new Byte(in.get());
break; break;
case DwarfConstants.DW_FORM_strp : case DwarfConstants.DW_FORM_strp :
{ {
int offset = read_4_bytes(in); int offset = read_4_bytes(in);
byte[] data = dwarfSections.get(DWARF_DEBUG_STR); ByteBuffer data = dwarfSections.get(DWARF_DEBUG_STR);
if (data == null) { if (data == null) {
obj = new String(); obj = new String();
} else if (offset < 0 || offset > data.length) { } else if (offset < 0 || offset > data.capacity()) {
obj = new String(); obj = new String();
} else { } else {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
for (; offset < data.length; offset++) { data.position(offset);
byte c = data[offset]; while (data.hasRemaining()) {
byte c = data.get();
if (c == 0) { if (c == 0) {
break; break;
} }
@ -537,7 +527,7 @@ public class Dwarf {
break; break;
case DwarfConstants.DW_FORM_ref1 : case DwarfConstants.DW_FORM_ref1 :
obj = new Byte((byte) in.read()); obj = new Byte(in.get());
break; break;
case DwarfConstants.DW_FORM_ref2 : case DwarfConstants.DW_FORM_ref2 :
@ -647,7 +637,7 @@ public class Dwarf {
} }
} }
Long readAddress(InputStream in, CompilationUnitHeader header) throws IOException { Long readAddress(ByteBuffer in, CompilationUnitHeader header) throws IOException {
long value = 0; long value = 0;
switch (header.addressSize) { switch (header.addressSize) {

View file

@ -14,10 +14,12 @@ package org.eclipse.cdt.utils.debug.dwarf;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ISymbolReader; import org.eclipse.cdt.core.ISymbolReader;
import org.eclipse.cdt.utils.debug.IDebugEntryRequestor; import org.eclipse.cdt.utils.debug.IDebugEntryRequestor;
import org.eclipse.cdt.utils.elf.Elf; import org.eclipse.cdt.utils.elf.Elf;
@ -45,7 +47,6 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
private String m_exeFileWin32Drive; // Win32 drive of the exe file. private String m_exeFileWin32Drive; // Win32 drive of the exe file.
private boolean m_onWindows; private boolean m_onWindows;
private boolean m_parsed = false; private boolean m_parsed = false;
private int m_leb128Size = 0;
private ArrayList<Integer> m_parsedLineTableOffsets = new ArrayList<Integer>(); private ArrayList<Integer> m_parsedLineTableOffsets = new ArrayList<Integer>();
private int m_parsedLineTableSize = 0; private int m_parsedLineTableSize = 0;
@ -77,9 +78,10 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
// problem itself, but will at least continue to load the other // problem itself, but will at least continue to load the other
// sections. // sections.
try { try {
dwarfSections.put(element, section.loadSectionData()); dwarfSections.put(element, section.mapSectionData());
} catch (OutOfMemoryError e) { } catch (Exception e) {
// Don't log this error, handle it silently without any UI. e.printStackTrace();
CCorePlugin.log(e);
} }
} }
} }
@ -104,10 +106,10 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
String cuCompDir, // compilation directory of the CU String cuCompDir, // compilation directory of the CU
int cuStmtList) // offset of the CU line table in .debug_line section int cuStmtList) // offset of the CU line table in .debug_line section
{ {
byte[] data = dwarfSections.get(DWARF_DEBUG_LINE); ByteBuffer data = dwarfSections.get(DWARF_DEBUG_LINE);
if (data != null) { if (data != null) {
try { try {
int offset = cuStmtList; data.position(cuStmtList);
/* Read line table header: /* Read line table header:
* *
@ -127,7 +129,7 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
if (! m_parsedLineTableOffsets.contains(cuOffset)) { if (! m_parsedLineTableOffsets.contains(cuOffset)) {
m_parsedLineTableOffsets.add(cuOffset); m_parsedLineTableOffsets.add(cuOffset);
int length = read_4_bytes(data, offset) + 4; int length = read_4_bytes(data) + 4;
m_parsedLineTableSize += length + 4; m_parsedLineTableSize += length + 4;
} }
else { else {
@ -137,9 +139,9 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
} }
// Skip the following till "opcode_base" // Skip the following till "opcode_base"
offset = offset + 14; data.position(data.position() + 10);
int opcode_base = data[offset++]; int opcode_base = data.get();
offset += opcode_base - 1; data.position(data.position() + opcode_base - 1);
// Read in directories. // Read in directories.
// //
@ -151,38 +153,32 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
String str, fileName; String str, fileName;
while (true) { while (true) {
str = readString(data, offset); str = readString(data);
if (str.length() == 0) if (str.length() == 0)
break; break;
dirList.add(str); dirList.add(str);
offset += str.length()+1;
} }
offset++;
// Read file names // Read file names
// //
long leb128; long leb128;
while (true) { while (true) {
fileName = readString(data, offset); fileName = readString(data);
if (fileName.length() == 0) // no more file entry if (fileName.length() == 0) // no more file entry
break; break;
offset += fileName.length()+1;
// dir index // dir index
leb128 = read_unsigned_leb128(data, offset); leb128 = read_unsigned_leb128(data);
offset += m_leb128Size;
addSourceFile(dirList.get((int)leb128), fileName); addSourceFile(dirList.get((int)leb128), fileName);
// Skip the followings // Skip the followings
// //
// modification time // modification time
leb128 = read_unsigned_leb128(data, offset); leb128 = read_unsigned_leb128(data);
offset += m_leb128Size;
// file size in bytes // file size in bytes
leb128 = read_unsigned_leb128(data, offset); leb128 = read_unsigned_leb128(data);
offset += m_leb128Size;
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -200,11 +196,11 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
*/ */
private void getSourceFilesFromDebugLineSection() private void getSourceFilesFromDebugLineSection()
{ {
byte[] data = dwarfSections.get(DWARF_DEBUG_LINE); ByteBuffer data = dwarfSections.get(DWARF_DEBUG_LINE);
if (data == null) if (data == null)
return; return;
int sectionSize = data.length; int sectionSize = data.capacity();
int minHeaderSize = 16; int minHeaderSize = 16;
// Check if there is data in .debug_line section that is not parsed // Check if there is data in .debug_line section that is not parsed
@ -233,13 +229,13 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
try { try {
while (lineTableStart < sectionSize - minHeaderSize) { while (lineTableStart < sectionSize - minHeaderSize) {
int offset = lineTableStart; data.position(lineTableStart);
Integer currLineTableStart = new Integer(lineTableStart); Integer currLineTableStart = new Integer(lineTableStart);
// Read length of the line table for one compile unit // Read length of the line table for one compile unit
// Note the length does not including the "length" field itself. // Note the length does not including the "length" field itself.
int tableLength = read_4_bytes(data, offset); int tableLength = read_4_bytes(data);
// Record start of next CU line table // Record start of next CU line table
lineTableStart += tableLength + 4; lineTableStart += tableLength + 4;
@ -256,9 +252,12 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
if (lineTableStart < sectionSize - minHeaderSize && if (lineTableStart < sectionSize - minHeaderSize &&
(lineTableStart & 0x3) != 0) (lineTableStart & 0x3) != 0)
{ {
int ltLength = read_4_bytes(data, lineTableStart); int savedPosition = data.position();
int dwarfVer = read_2_bytes(data, lineTableStart+4); data.position(lineTableStart);
int minInstLengh = data[lineTableStart+4+2+4];
int ltLength = read_4_bytes(data);
int dwarfVer = read_2_bytes(data);
int minInstLengh = data.get(data.position() + 4);
boolean dataValid = boolean dataValid =
ltLength > minHeaderSize && ltLength > minHeaderSize &&
@ -268,6 +267,8 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
if (! dataValid) // padding exists ! if (! dataValid) // padding exists !
lineTableStart = (lineTableStart+3) & ~0x3; lineTableStart = (lineTableStart+3) & ~0x3;
data.position(savedPosition);
} }
if (m_parsedLineTableOffsets.contains(currLineTableStart)) if (m_parsedLineTableOffsets.contains(currLineTableStart))
@ -275,9 +276,9 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
continue; continue;
// Skip following fields till "opcode_base" // Skip following fields till "opcode_base"
offset = offset + 14; data.position(data.position() + 10);
int opcode_base = data[offset++]; int opcode_base = data.get();
offset += opcode_base - 1; data.position(data.position() + opcode_base - 1);
// Read in directories. // Read in directories.
// //
@ -289,38 +290,32 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
dirList.add(""); //$NON-NLS-1$ dirList.add(""); //$NON-NLS-1$
while (true) { while (true) {
str = readString(data, offset); str = readString(data);
if (str.length() == 0) if (str.length() == 0)
break; break;
dirList.add(str); dirList.add(str);
offset += str.length() + 1;
} }
offset++;
// Read file names // Read file names
// //
long leb128; long leb128;
while (true) { while (true) {
fileName = readString(data, offset); fileName = readString(data);
if (fileName.length() == 0) // no more file entry if (fileName.length() == 0) // no more file entry
break; break;
offset += fileName.length() + 1;
// dir index. Note "0" is reserved for compilation directory. // dir index. Note "0" is reserved for compilation directory.
leb128 = read_unsigned_leb128(data, offset); leb128 = read_unsigned_leb128(data);
offset += m_leb128Size;
addSourceFile(dirList.get((int) leb128), fileName); addSourceFile(dirList.get((int) leb128), fileName);
// Skip the followings // Skip the followings
// //
// modification time // modification time
leb128 = read_unsigned_leb128(data, offset); leb128 = read_unsigned_leb128(data);
offset += m_leb128Size;
// file size in bytes // file size in bytes
leb128 = read_unsigned_leb128(data, offset); leb128 = read_unsigned_leb128(data);
offset += m_leb128Size;
} }
} }
} catch (IOException e) { } catch (IOException e) {
@ -400,17 +395,16 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
} }
/** /**
* Read a null-ended string from the given "data" stream starting at the given "offset". * Read a null-ended string from the given "data" stream.
* data : IN, byte stream * data : IN, byte buffer
* offset: IN, offset in the stream
*/ */
String readString(byte[] data, int offset) String readString(ByteBuffer data)
{ {
String str; String str;
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
for (; offset < data.length; offset++) { while (data.hasRemaining()) {
byte c = data[offset]; byte c = data.get();
if (c == 0) { if (c == 0) {
break; break;
} }
@ -421,30 +415,6 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
return str; return str;
} }
// Note this method modifies a data member
//
long read_unsigned_leb128(byte[] data, int offset) throws IOException {
/* unsigned */
long result = 0;
int shift = 0;
short b;
m_leb128Size = 0;
while (true) {
b = data[offset++];
if (data.length == offset)
break; //throw new IOException("no more data");
m_leb128Size++;
result |= ((long) (b & 0x7f) << shift);
if ((b & 0x80) == 0) {
break;
}
shift += 7;
}
return result;
}
// Override parent: only handle TAG_Compile_Unit. // Override parent: only handle TAG_Compile_Unit.
@Override @Override
void processDebugInfoEntry(IDebugEntryRequestor requestor, AbbreviationEntry entry, List<Dwarf.AttributeValue> list) { void processDebugInfoEntry(IDebugEntryRequestor requestor, AbbreviationEntry entry, List<Dwarf.AttributeValue> list) {

View file

@ -13,6 +13,8 @@ package org.eclipse.cdt.utils.elf;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel.MapMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
@ -333,6 +335,10 @@ public class Elf {
public long sh_addralign; public long sh_addralign;
public long sh_entsize; public long sh_entsize;
public ByteBuffer mapSectionData() throws IOException {
return efile.getChannel().map(MapMode.READ_ONLY, sh_offset, sh_size).load().asReadOnlyBuffer();
}
public byte[] loadSectionData() throws IOException { public byte[] loadSectionData() throws IOException {
byte[] data = new byte[(int)sh_size]; byte[] data = new byte[(int)sh_size];
efile.seek(sh_offset); efile.seek(sh_offset);
@ -943,6 +949,9 @@ public class Elf {
if (efile != null) { if (efile != null) {
efile.close(); efile.close();
efile = null; efile = null;
// ensure the mappings get cleaned up
System.gc();
} }
} catch (IOException e) { } catch (IOException e) {
} }