Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeodor Madan2014-01-17 07:22:36 -0500
committerTeodor Madan2014-01-21 04:12:53 -0500
commitd3a8e639c8dcb6a270d3e140f4e62144203a3c7c (patch)
tree34cb3ba2f5bba46c61a0c70fce97e99f276a363a
parentfd074ab029192695eec04970dbe62738a242f925 (diff)
downloadorg.eclipse.cdt-d3a8e639c8dcb6a270d3e140f4e62144203a3c7c.tar.gz
org.eclipse.cdt-d3a8e639c8dcb6a270d3e140f4e62144203a3c7c.tar.xz
org.eclipse.cdt-d3a8e639c8dcb6a270d3e140f4e62144203a3c7c.zip
Bug 425955: NPE in DwarfReader
- Fix parsing .debug_line section in version format, part of Dwarf 4. - Refactor in a separate method reading initial length field to consistently handle 64-bit dwarf format Change-Id: I9f32862ed91540c24ce33227eeb384a5d6b141da Signed-off-by: Teodor Madan <teodor.madan@freescale.com> Reviewed-on: https://git.eclipse.org/r/20830
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java63
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java71
2 files changed, 96 insertions, 38 deletions
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java
index 068df13236a..e54140e38eb 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java
@@ -372,19 +372,15 @@ public class Dwarf {
try {
while (data.hasRemaining()) {
CompilationUnitHeader header = new CompilationUnitHeader();
- header.length = read_4_bytes(data) & 0xffffffffL;
-
- if (header.length == 0xffffffffL) {
- header.length = read_8_bytes(data);
- header.offsetSize = 8;
- } else if (header.length == 0) { // IRIX
- header.length = read_8_bytes(data);
- header.offsetSize = 8;
- } else
- header.offsetSize = 4;
+ InitialLengthValue sectionLength = readInitialLengthField(data);
+ header.length = sectionLength.length;
+ header.offsetSize = sectionLength.offsetSize;
header.version = read_2_bytes(data);
- header.abbreviationOffset = read_4_bytes(data);
+ if (header.offsetSize == 8)
+ header.abbreviationOffset = (int)read_8_bytes(data);
+ else
+ header.abbreviationOffset = read_4_bytes(data);
header.addressSize = data.get();
if (printEnabled) {
@@ -394,12 +390,13 @@ public class Dwarf {
// read the abbrev section.
Map<Long, AbbreviationEntry> abbrevs = parseDebugAbbreviation(header);
- // Note "length+4" is the total size in bytes of the CU data.
+ // A 4-byte or 12-byte unsigned integer representing the length of the .debug_info
+ // contribution for that compilation unit, not including the length field itself.
ByteBuffer entryBuffer = data.slice();
- entryBuffer.limit(((int) header.length) + 4 - 11);
+ entryBuffer.limit(((int)header.length) - (header.offsetSize == 8 ? 11 : 7));
parseDebugInfoEntry(requestor, entryBuffer, abbrevs, header);
- data.position(data.position() + ((int) header.length) + 4 - 11);
+ data.position(data.position() + ((int)header.length) - (header.offsetSize == 8 ? 11 : 7));
if (printEnabled)
System.out.println();
@@ -410,6 +407,44 @@ public class Dwarf {
}
}
+ /**
+ *
+ */
+ class InitialLengthValue {
+ /**
+ * section length
+ */
+ long length;
+
+ /**
+ * section offset size in bytes.
+ */
+ byte offsetSize; //
+ }
+
+ /**
+ * Read section length field from the beginning of dwarf section.
+ *
+ * <p>See Chapter 7.4 32-Bit and 64-Bit DWARF Formats</p>
+ * @param data - byte buffer positioned at the start of section length record
+ * @return section length info. Cannot be null.
+ * @throws IOException
+ */
+ InitialLengthValue readInitialLengthField(ByteBuffer data) throws IOException {
+ InitialLengthValue info = new InitialLengthValue();
+ info.length = read_4_bytes(data) & 0xffffffffL;
+
+ if (info.length == 0xffffffffL) {
+ info.length = read_8_bytes(data);
+ info.offsetSize = 8;
+ } else if (info.length == 0) { // IRIX
+ info.length = read_8_bytes(data);
+ info.offsetSize = 8;
+ } else
+ info.offsetSize = 4;
+ return info;
+ }
+
Map<Long, AbbreviationEntry> parseDebugAbbreviation(CompilationUnitHeader header) throws IOException {
Integer key = new Integer(header.abbreviationOffset);
Map<Long, AbbreviationEntry> abbrevs = abbreviationMaps.get(key);
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java
index e784ec56d18..fd9ef9eaf6d 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java
@@ -50,7 +50,7 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
private String[] m_fileNames = null;
private boolean m_parsed = false;
private final ArrayList<Integer> m_parsedLineTableOffsets = new ArrayList<Integer>();
- private int m_parsedLineTableSize = 0;
+ private long m_parsedLineTableSize = 0;
public DwarfReader(String file) throws IOException {
super(file);
@@ -143,10 +143,11 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
/* Read line table header:
*
- * total_length: 4 bytes (excluding itself)
+ * total_length: 4/12 bytes (excluding itself)
* version: 2
- * prologue length: 4
+ * prologue length: 4/8 bytes (depending on section version)
* minimum_instruction_len: 1
+ * maximum_operations_per_instruction 1 - it is defined for version >= 4
* default_is_stmt: 1
* line_base: 1
* line_range: 1
@@ -156,20 +157,30 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
// Remember the CU line tables we've parsed.
Integer cuOffset = new Integer(cuStmtList);
+
+ boolean dwarf64Bit = false;
if (! m_parsedLineTableOffsets.contains(cuOffset)) {
m_parsedLineTableOffsets.add(cuOffset);
- int length = read_4_bytes(data) + 4;
- m_parsedLineTableSize += length + 4;
+ // Note the length does not including the "length" field(s) itself.
+ InitialLengthValue length = readInitialLengthField(data);
+ dwarf64Bit = length.offsetSize == 8;
+ m_parsedLineTableSize += length.length + (dwarf64Bit ? 12 : 4);
}
else {
// Compiler like ARM RVCT may produce several CUs for the
// same source files.
return;
}
-
+
+ short version = read_2_bytes(data);
// Skip the following till "opcode_base"
- data.position(data.position() + 10);
+ short skip_bytes = 8;
+ if (version >= 4)
+ skip_bytes += 1; // see maximum_operations_per_instruction
+ if (dwarf64Bit)
+ skip_bytes += 4; // see prologue length for 64-bit DWARF format
+ data.position(data.position() + skip_bytes);
int opcode_base = data.get();
data.position(data.position() + opcode_base - 1);
@@ -248,16 +259,16 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
/*
* Line table header for one compile_unit:
*
- * total_length: 4 bytes (excluding itself)
- * version: 2
- * prologue length: 4
+ * total_length: 4/12 bytes (excluding itself)
+ * version: 2
+ * prologue length: 4/8 bytes (depending on section version)
* minimum_instruction_len: 1
- * default_is_stmt: 1
- * line_base: 1
- * line_range: 1
- * opcode_base: 1
- * standard_opcode_lengths: (value of opcode_base)
- */
+ * maximum_operations_per_instruction 1 - it is defined for version >= 4
+ * default_is_stmt: 1
+ * line_base: 1
+ * line_range: 1
+ * opcode_base: 1
+ * standard_opcode_lengths: (value of opcode_base) */
int lineTableStart = 0; // offset in the .debug_line section
@@ -268,11 +279,15 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
Integer currLineTableStart = new Integer(lineTableStart);
// Read length of the line table for one compile unit
- // Note the length does not including the "length" field itself.
- int tableLength = read_4_bytes(data);
-
+ // Note the length does not including the "length" field(s) itself.
+ InitialLengthValue sectionLength = readInitialLengthField(data);
+
+
// Record start of next CU line table
- lineTableStart += tableLength + 4;
+ boolean dwarf64Bit = sectionLength.offsetSize == 8;
+ lineTableStart += (int)(sectionLength.length + (dwarf64Bit ? 12 : 4));
+
+ m_parsedLineTableSize += sectionLength.length + (dwarf64Bit ? 12 : 4);
// According to Dwarf standard, the "tableLength" should cover the
// the whole CU line table. But some compilers (e.g. ARM RVCT 2.2)
@@ -289,14 +304,15 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
int savedPosition = data.position();
data.position(lineTableStart);
- int ltLength = read_4_bytes(data);
+ long ltLength = dwarf64Bit ? read_8_bytes(data) : read_4_bytes(data);
+
int dwarfVer = read_2_bytes(data);
- int minInstLengh = data.get(data.position() + 4);
+ int minInstLengh = data.get(data.position() + (dwarf64Bit ? 8 : 4));
boolean dataValid =
ltLength > minHeaderSize &&
ltLength < 16*64*1024 && // One source file has that much line data ?
- dwarfVer > 0 && dwarfVer < 4 && // ver 3 is still draft at present.
+ dwarfVer > 0 && dwarfVer < 5 && // ver 5 is still draft at present.
minInstLengh > 0 && minInstLengh <= 8;
if (! dataValid) // padding exists !
@@ -309,8 +325,15 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
// current line table has already been parsed, skip it.
continue;
+ short version = read_2_bytes(data);
+
// Skip following fields till "opcode_base"
- data.position(data.position() + 10);
+ short skip_bytes = 8;
+ if (version >= 4)
+ skip_bytes += 1; // see maximum_operations_per_instruction
+ if (dwarf64Bit)
+ skip_bytes += 4; // see prologue length for 64-bit DWARF format
+ data.position(data.position() + skip_bytes);
int opcode_base = data.get();
data.position(data.position() + opcode_base - 1);

Back to the top