summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/PEImage.cpp20
-rw-r--r--src/PEImage.h9
-rw-r--r--src/dwarf2pdb.cpp46
-rw-r--r--test/cvtest.d2
4 files changed, 55 insertions, 22 deletions
diff --git a/src/PEImage.cpp b/src/PEImage.cpp
index 460f2bd..2d6f03f 100644
--- a/src/PEImage.cpp
+++ b/src/PEImage.cpp
@@ -285,7 +285,7 @@ bool PEImage::initDWARFPtr(bool initDbgDir)
dbgDir = 0;
sec = hdr32 ? IMAGE_FIRST_SECTION(hdr32) : IMAGE_FIRST_SECTION(hdr64);
int nsec = IMGHDR(FileHeader.NumberOfSections);
- const char* strtable = DPV<char>(IMGHDR(FileHeader.PointerToSymbolTable) + IMGHDR(FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL));
+ const char* strtable = DPV<char>(IMGHDR(FileHeader.PointerToSymbolTable) + IMGHDR(FileHeader.NumberOfSymbols) * IMAGE_SIZEOF_SYMBOL);
for(int s = 0; s < nsec; s++)
{
const char* name = (const char*) sec[s].Name;
@@ -335,6 +335,24 @@ int PEImage::findSection(unsigned int off) const
return -1;
}
+int PEImage::findSymbol(const char* name, unsigned long& off) const
+{
+ IMAGE_SYMBOL* symtable = DPV<IMAGE_SYMBOL>(IMGHDR(FileHeader.PointerToSymbolTable));
+ int syms = IMGHDR(FileHeader.NumberOfSymbols);
+ const char* strtable = (const char*) (symtable + syms);
+ for(int i = 0; i < syms; i++)
+ {
+ IMAGE_SYMBOL* sym = symtable + i;
+ const char* symname = sym->N.Name.Short == 0 ? strtable + sym->N.Name.Long : (char*)sym->N.ShortName;
+ if(strcmp(symname, name) == 0 || (symname[0] == '_' && strcmp(symname + 1, name) == 0))
+ {
+ off = sym->Value;
+ return sym->SectionNumber;
+ }
+ }
+ return -1;
+}
+
///////////////////////////////////////////////////////////////////////
int PEImage::countCVEntries() const
{
diff --git a/src/PEImage.h b/src/PEImage.h
index 4eac1dc..f3c5511 100644
--- a/src/PEImage.h
+++ b/src/PEImage.h
@@ -22,21 +22,21 @@ public:
PEImage(const char* iname = 0);
~PEImage();
- template<class P> P* DP(int off)
+ template<class P> P* DP(int off) const
{
return (P*) ((char*) dump_base + off);
}
- template<class P> P* DPV(int off, int size)
+ template<class P> P* DPV(int off, int size) const
{
if(off < 0 || off + size > dump_total_len)
return 0;
return (P*) ((char*) dump_base + off);
}
- template<class P> P* DPV(int off)
+ template<class P> P* DPV(int off) const
{
return DPV<P>(off, sizeof(P));
}
- template<class P> P* CVP(int off)
+ template<class P> P* CVP(int off) const
{
return DPV<P>(cv_base + off, sizeof(P));
}
@@ -77,6 +77,7 @@ public:
int countSections() const { return IMGHDR(FileHeader.NumberOfSections); }
int findSection(unsigned int off) const;
+ int findSymbol(const char* name, unsigned long& off) const;
const IMAGE_SECTION_HEADER& getSection(int s) const { return sec[s]; }
unsigned long long getImageBase() const { return IMGHDR(OptionalHeader.ImageBase); }
diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp
index 17afb65..1bc942c 100644
--- a/src/dwarf2pdb.cpp
+++ b/src/dwarf2pdb.cpp
@@ -5,7 +5,6 @@
// see file LICENSE for further details
//
// todo:
-// tls vars
// display associative array
// 64 bit:
// - arguments passed by register
@@ -139,6 +138,7 @@ struct DWARF_InfoData
int hasChild;
const char* name;
+ const char* linkage_name;
const char* dir;
unsigned long byte_size;
unsigned long sibling;
@@ -150,6 +150,7 @@ struct DWARF_InfoData
unsigned long containing_type;
unsigned long specification;
unsigned long inlined;
+ unsigned long external;
unsigned long long location; // first 8 bytes
unsigned long long member_location; // first 8 bytes
unsigned long locationlist; // offset into debug_loc
@@ -432,6 +433,7 @@ bool CV2PDB::readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, un
id.hasChild = hasChild;
id.name = 0;
+ id.linkage_name = 0;
id.dir = 0;
id.byte_size = 0;
id.sibling = 0;
@@ -443,6 +445,7 @@ bool CV2PDB::readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, un
id.containing_type = 0;
id.specification = 0;
id.inlined = 0;
+ id.external = 0;
id.member_location = 0;
id.location = 0;
id.locationlist = 0;
@@ -500,12 +503,14 @@ bool CV2PDB::readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, un
case DW_AT_sibling: id.sibling = data; break;
case DW_AT_encoding: id.encoding = data; break;
case DW_AT_name: id.name = str; break;
+ case DW_AT_MIPS_linkage_name: id.linkage_name = str; break;
case DW_AT_comp_dir: id.dir = str; break;
case DW_AT_low_pc: id.pclo = addr; break;
case DW_AT_high_pc: id.pchi = addr; break;
case DW_AT_ranges: id.ranges = data; break;
case DW_AT_type: id.type = data; break;
case DW_AT_inline: id.inlined = data; break;
+ case DW_AT_external: id.external = data; break;
case DW_AT_upper_bound: id.upper_bound = data; break;
case DW_AT_lower_bound: id.lower_bound = data; break;
case DW_AT_containing_type: id.containing_type = data; break;
@@ -1236,29 +1241,38 @@ bool CV2PDB::iterateDWARFDebugInfo(int op)
#endif
break;
- case DW_TAG_formal_parameter:
- case DW_TAG_unspecified_parameters:
- case DW_TAG_inheritance:
- case DW_TAG_member:
- case DW_TAG_inlined_subroutine:
- case DW_TAG_lexical_block:
case DW_TAG_variable:
if(id.name)
{
- int cvid, off = decodeLocation(id.location, cvid);
- if(cvid == S_GDATA_V2)
+ int seg = -1;
+ unsigned long segOff;
+ if(id.location == 0 && id.external && id.linkage_name)
{
- int seg = img.findSection(off);
+ seg = img.findSymbol(id.linkage_name, segOff);
+ }
+ else
+ {
+ int cvid;
+ segOff = decodeLocation(id.location, cvid);
+ if(cvid == S_GDATA_V2)
+ seg = img.findSection(segOff);
if(seg >= 0)
- {
- int segOff = img.getImageBase() + img.getSection(seg).VirtualAddress;
- int type = getTypeByDWARFOffset(cu, id.type);
- appendGlobalVar(id.name, type, seg + 1, off - segOff);
- int rc = mod->AddPublic2(id.name, seg + 1, off - segOff, type);
- }
+ segOff -= img.getImageBase() + img.getSection(seg).VirtualAddress;
+ }
+ if(seg >= 0)
+ {
+ int type = getTypeByDWARFOffset(cu, id.type);
+ appendGlobalVar(id.name, type, seg + 1, segOff);
+ int rc = mod->AddPublic2(id.name, seg + 1, segOff, type);
}
}
break;
+ case DW_TAG_formal_parameter:
+ case DW_TAG_unspecified_parameters:
+ case DW_TAG_inheritance:
+ case DW_TAG_member:
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_lexical_block:
default:
break;
}
diff --git a/test/cvtest.d b/test/cvtest.d
index e425354..0794e9e 100644
--- a/test/cvtest.d
+++ b/test/cvtest.d
@@ -27,7 +27,7 @@ class base_class
int base_member;
};
-class derived_class : public base_class
+class derived_class : base_class
{
int derived_member;
int a1_1234;