summaryrefslogtreecommitdiffstats
path: root/src/readDwarf.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/readDwarf.h')
-rw-r--r--src/readDwarf.h308
1 files changed, 308 insertions, 0 deletions
diff --git a/src/readDwarf.h b/src/readDwarf.h
new file mode 100644
index 0000000..c0587b4
--- /dev/null
+++ b/src/readDwarf.h
@@ -0,0 +1,308 @@
+#ifndef __READDWARF_H__
+#define __READDWARF_H__
+
+#include <string>
+#include <vector>
+#include "mspdb.h"
+
+inline unsigned int LEB128(unsigned char* &p)
+{
+ unsigned int x = 0;
+ int shift = 0;
+ while (*p & 0x80)
+ {
+ x |= (*p & 0x7f) << shift;
+ shift += 7;
+ p++;
+ }
+ x |= *p << shift;
+ p++;
+ return x;
+}
+
+inline int SLEB128(unsigned char* &p)
+{
+ unsigned int x = 0;
+ int shift = 0;
+ while (*p & 0x80)
+ {
+ x |= (*p & 0x7f) << shift;
+ shift += 7;
+ p++;
+ }
+ x |= *p << shift;
+ if (*p & 0x40)
+ x |= -(1 << (shift + 7)); // sign extend
+ p++;
+ return x;
+}
+
+inline unsigned int RD2(unsigned char* p)
+{
+ unsigned int x = *p++;
+ x |= *p++ << 8;
+ return x;
+}
+
+inline unsigned int RD4(unsigned char* p)
+{
+ unsigned int x = *p++;
+ x |= *p++ << 8;
+ x |= *p++ << 16;
+ x |= *p++ << 24;
+ return x;
+}
+
+inline unsigned long long RD8(unsigned char* p)
+{
+ unsigned long long x = *p++;
+ for (int shift = 8; shift < 64; shift += 8)
+ x |= (unsigned long long) *p++ << shift;
+ return x;
+}
+
+inline unsigned long long RDsize(unsigned char* p, int size)
+{
+ if (size > 8)
+ size = 8;
+ unsigned long long x = *p++;
+ for (int shift = 8; shift < size * 8; shift += 8)
+ x |= (unsigned long long) *p++ << shift;
+ return x;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "pshpack1.h"
+
+struct DWARF_CompilationUnit
+{
+ unsigned int unit_length; // 12 byte in DWARF-64
+ unsigned short version;
+ unsigned int debug_abbrev_offset; // 8 byte in DWARF-64
+ unsigned char address_size;
+
+ bool isDWARF64() const { return unit_length == ~0; }
+ int refSize() const { return unit_length == ~0 ? 8 : 4; }
+};
+
+struct DWARF_FileName
+{
+ const char* file_name;
+ unsigned int dir_index;
+ unsigned long lastModification;
+ unsigned long fileLength;
+
+ void read(unsigned char* &p)
+ {
+ file_name = (const char*)p;
+ p += strlen((const char*)p) + 1;
+ dir_index = LEB128(p);
+ lastModification = LEB128(p);
+ fileLength = LEB128(p);
+ }
+};
+
+struct DWARF_InfoData
+{
+ int entryOff;
+ int code;
+ int tag;
+ int hasChild;
+
+ const char* name;
+ const char* linkage_name;
+ const char* dir;
+ unsigned long byte_size;
+ unsigned long sibling;
+ unsigned long encoding;
+ unsigned long pclo;
+ unsigned long pchi;
+ unsigned long ranges;
+ unsigned long type;
+ unsigned long containing_type;
+ unsigned long specification;
+ unsigned long inlined;
+ unsigned long external;
+ unsigned char*location_ptr;
+ unsigned long location_len;
+ unsigned char*member_location_ptr;
+ unsigned long member_location_len;
+ unsigned long member_location_data;
+ unsigned long locationlist; // offset into debug_loc
+ long frame_base;
+ long upper_bound;
+ long lower_bound;
+ unsigned char* abbrev;
+
+ void clear()
+ {
+ entryOff = 0;
+ code = 0;
+ tag = 0;
+ hasChild = 0;
+
+ name = 0;
+ linkage_name = 0;
+ dir = 0;
+ byte_size = 0;
+ sibling = 0;
+ encoding = 0;
+ pclo = 0;
+ pchi = 0;
+ ranges = 0;
+ type = 0;
+ containing_type = 0;
+ specification = 0;
+ inlined = 0;
+ external = 0;
+ member_location_ptr = 0;
+ member_location_len = 0;
+ member_location_data = 0;
+ location_ptr = 0;
+ location_len = 0;
+ locationlist = 0;
+ frame_base = -1;
+ upper_bound = 0;
+ lower_bound = 0;
+ abbrev = 0;
+ }
+};
+
+static const int maximum_operations_per_instruction = 1;
+
+struct DWARF_LineNumberProgramHeader
+{
+ unsigned int unit_length; // 12 byte in DWARF-64
+ unsigned short version;
+ unsigned int header_length; // 8 byte in DWARF-64
+ unsigned char minimum_instruction_length;
+ //unsigned char maximum_operations_per_instruction; (// not in DWARF 2
+ unsigned char default_is_stmt;
+ signed char line_base;
+ unsigned char line_range;
+ unsigned char opcode_base;
+ //LEB128 standard_opcode_lengths[opcode_base];
+ // string include_directories[] // zero byte terminated
+ // DWARF_FileNames file_names[] // zero byte terminated
+};
+
+struct DWARF_LineState
+{
+ // hdr info
+ std::vector<const char*> include_dirs;
+ std::vector<DWARF_FileName> files;
+
+ unsigned long address;
+ unsigned int op_index;
+ unsigned int file;
+ unsigned int line;
+ unsigned int column;
+ bool is_stmt;
+ bool basic_block;
+ bool end_sequence;
+ bool prologue_end;
+ bool epilogue_end;
+ unsigned int isa;
+ unsigned int discriminator;
+
+ // not part of the "documented" state
+ DWARF_FileName* file_ptr;
+ unsigned long seg_offset;
+ unsigned long last_addr;
+ std::vector<mspdb::LineInfoEntry> lineInfo;
+
+ DWARF_LineState()
+ {
+ seg_offset = 0x400000;
+ init(0);
+ }
+
+ void init(DWARF_LineNumberProgramHeader* hdr)
+ {
+ address = 0;
+ op_index = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = hdr && hdr->default_is_stmt != 0;
+ basic_block = false;
+ end_sequence = false;
+ prologue_end = false;
+ epilogue_end = false;
+ isa = 0;
+ discriminator = 0;
+ }
+
+ void advance_addr(DWARF_LineNumberProgramHeader* hdr, int operation_advance)
+ {
+ int address_advance = hdr->minimum_instruction_length * ((op_index + operation_advance) / maximum_operations_per_instruction);
+ address += address_advance;
+ op_index = (op_index + operation_advance) % maximum_operations_per_instruction;
+ }
+
+ void addLineInfo()
+ {
+#if 0
+ const char* fname = (file == 0 ? file_ptr->file_name : files[file - 1].file_name);
+ printf("Adr:%08x Line: %5d File: %s\n", address, line, fname);
+#endif
+ if (address < seg_offset)
+ return;
+ mspdb::LineInfoEntry entry;
+ entry.offset = address - seg_offset;
+ entry.line = line;
+ lineInfo.push_back(entry);
+ }
+};
+
+#include "poppack.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+long decodeLocation(unsigned char* loc, long len, bool push0, int &id, int& size);
+
+inline long decodeLocation(unsigned char*loc, long len, bool push0, int &id)
+{
+ int size;
+ return decodeLocation(loc, len, push0, id, size);
+}
+
+
+class PEImage;
+
+// Debug Information Entry Cursor
+class DIECursor
+{
+public:
+ DWARF_CompilationUnit* cu;
+ unsigned char* ptr;
+ int level;
+ bool hasChild; // indicates whether the last read DIE has children
+ unsigned int sibling;
+
+ unsigned char* getDWARFAbbrev(unsigned off, unsigned findcode);
+
+public:
+
+ static void setContext(PEImage* img_);
+
+ // Create a new DIECursor from compilation unit with offset relative to the CU.
+ DIECursor(DWARF_CompilationUnit* cu_, unsigned long offset);
+
+ // Reads next sibling DIE. If the last read DIE had any children, they will be skipped over.
+ // Returns 'false' upon reaching the last sibling on the current level.
+ bool readSibling(DWARF_InfoData& id);
+
+ // Returns cursor that will enumerate children of the last read DIE.
+ DIECursor getSubtreeCursor();
+
+ // Reads the next DIE in physical order, returns 'true' if succeeds.
+ // If stopAtNull is true, readNext() will stop upon reaching a null DIE (end of the current tree level).
+ // Otherwise, it will skip null DIEs and stop only at the end of the subtree for which this DIECursor was created.
+ bool readNext(DWARF_InfoData& id, bool stopAtNull = false);
+};
+
+#endif \ No newline at end of file