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:
parent
f0893c8b81
commit
7ef8d28991
3 changed files with 146 additions and 177 deletions
|
@ -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,28 +324,30 @@ 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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -420,30 +414,6 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
|
||||||
str = sb.toString();
|
str = sb.toString();
|
||||||
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
|
||||||
|
|
|
@ -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) {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue