Skip to content

Commit

Permalink
Merge pull request #69 from neerajsi-msft/dwarf5
Browse files Browse the repository at this point in the history
Add support for Dwarf5 as emitted by gcc-11.2
  • Loading branch information
rainers authored Dec 10, 2021
2 parents 9e0795a + 13a21e9 commit 7919a62
Show file tree
Hide file tree
Showing 11 changed files with 1,031 additions and 398 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,9 @@ jobs:
gcc -g -o hello.exe hello.c &&
bin/${{env.BUILD_CONFIGURATION}}*/cv2pdb.exe hello.exe world.exe &&
ls -l hello* world*
ls -l hello* world* &&
curl -Lo cvdump.exe https://raw.githubusercontent.com/microsoft/microsoft-pdb/HEAD/cvdump/cvdump.exe &&
./cvdump.exe world.pdb >world.cvdump &&
grep '^S_PUB32: .*, Flags: 00000000, main$' world.cvdump
67 changes: 22 additions & 45 deletions src/PEImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,6 @@ PEImage::PEImage(const TCHAR* iname)
, hdr32(0)
, hdr64(0)
, fd(-1)
, debug_aranges(0)
, debug_pubnames(0)
, debug_pubtypes(0)
, debug_info(0), debug_info_length(0)
, debug_abbrev(0), debug_abbrev_length(0)
, debug_line(0), debug_line_length(0)
, debug_frame(0), debug_frame_length(0)
, debug_str(0)
, debug_loc(0), debug_loc_length(0)
, debug_ranges(0), debug_ranges_length(0)
, codeSegment(0)
, linesSegment(-1)
, reloc(0), reloc_length(0)
, nsec(0)
, nsym(0)
, symtable(0)
Expand Down Expand Up @@ -470,6 +457,15 @@ static DWORD sizeInImage(const IMAGE_SECTION_HEADER& sec)
return sec.SizeOfRawData < sec.Misc.VirtualSize ? sec.SizeOfRawData : sec.Misc.VirtualSize;
}

void PEImage::initSec(PESection& peSec, int secNo) const
{
auto &imgSec = sec[secNo];

peSec.length = sizeInImage(imgSec);
peSec.base = DPV<byte>(imgSec.PointerToRawData, peSec.length);
peSec.secNo = secNo;
}

void PEImage::initDWARFSegments()
{
for(int s = 0; s < nsec; s++)
Expand All @@ -480,49 +476,30 @@ void PEImage::initDWARFSegments()
int off = strtol(name + 1, 0, 10);
name = strtable + off;
}
if(strcmp(name, ".debug_aranges") == 0)
debug_aranges = DPV<char>(sec[s].PointerToRawData, sizeInImage(sec[s]));
if(strcmp(name, ".debug_pubnames") == 0)
debug_pubnames = DPV<char>(sec[s].PointerToRawData, sizeInImage(sec[s]));
if(strcmp(name, ".debug_pubtypes") == 0)
debug_pubtypes = DPV<char>(sec[s].PointerToRawData, sizeInImage(sec[s]));
if(strcmp(name, ".debug_info") == 0)
debug_info = DPV<char>(sec[s].PointerToRawData, debug_info_length = sizeInImage(sec[s]));
if(strcmp(name, ".debug_abbrev") == 0)
debug_abbrev = DPV<char>(sec[s].PointerToRawData, debug_abbrev_length = sizeInImage(sec[s]));
if(strcmp(name, ".debug_line") == 0)
debug_line = DPV<char>(sec[linesSegment = s].PointerToRawData, debug_line_length = sizeInImage(sec[s]));
if (strcmp(name, ".debug_line_str") == 0)
debug_line_str = DPV<char>(sec[s].PointerToRawData, debug_line_str_length = sizeInImage(sec[s]));
if(strcmp(name, ".debug_frame") == 0)
debug_frame = DPV<char>(sec[s].PointerToRawData, debug_frame_length = sizeInImage(sec[s]));
if(strcmp(name, ".debug_str") == 0)
debug_str = DPV<char>(sec[s].PointerToRawData, sizeInImage(sec[s]));
if(strcmp(name, ".debug_loc") == 0)
debug_loc = DPV<char>(sec[s].PointerToRawData, debug_loc_length = sizeInImage(sec[s]));
if(strcmp(name, ".debug_ranges") == 0)
debug_ranges = DPV<char>(sec[s].PointerToRawData, debug_ranges_length = sizeInImage(sec[s]));
if(strcmp(name, ".reloc") == 0)
reloc = DPV<char>(sec[s].PointerToRawData, reloc_length = sizeInImage(sec[s]));
if(strcmp(name, ".text") == 0)
codeSegment = s;

for (const SectionDescriptor *sec_desc : sec_descriptors) {
if (!strcmp(name, sec_desc->name)) {
PESection& peSec = this->*(sec_desc->pSec);
initSec(peSec, s);
}
}
}
}

bool PEImage::relocateDebugLineInfo(unsigned int img_base)
{
if(!reloc || !reloc_length)
if(!reloc.isPresent())
return true;

char* relocbase = reloc;
char* relocend = reloc + reloc_length;
byte* relocbase = reloc.startByte();
byte* relocend = reloc.endByte();
while(relocbase < relocend)
{
unsigned int virtadr = *(unsigned int *) relocbase;
unsigned int chksize = *(unsigned int *) (relocbase + 4);

char* p = RVA<char> (virtadr, 1);
if(p >= debug_line && p < debug_line + debug_line_length)
if(debug_line.isPtrInside(p))
{
for (unsigned int w = 8; w < chksize; w += 2)
{
Expand All @@ -536,7 +513,7 @@ bool PEImage::relocateDebugLineInfo(unsigned int img_base)
}
}
}
if(chksize == 0 || chksize >= reloc_length)
if(chksize == 0 || chksize >= reloc.length)
break;
relocbase += chksize;
}
Expand All @@ -545,7 +522,7 @@ bool PEImage::relocateDebugLineInfo(unsigned int img_base)

int PEImage::getRelocationInLineSegment(unsigned int offset) const
{
return getRelocationInSegment(linesSegment, offset);
return getRelocationInSegment(debug_line.secNo, offset);
}

int PEImage::getRelocationInSegment(int segment, unsigned int offset) const
Expand Down
108 changes: 92 additions & 16 deletions src/PEImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,81 @@
struct OMFDirHeader;
struct OMFDirEntry;

typedef unsigned char byte;

struct SymbolInfo
{
int seg;
unsigned long off;
bool dllimport;
};

struct PESection
{
byte* base;
unsigned long length;
unsigned int secNo;

PESection()
: base(0)
, length(0)
, secNo(0)
{
}

byte* byteAt(unsigned int off) const
{
return base + off;
}

byte* startByte() const
{
return byteAt(0);
}

byte* endByte() const
{
return byteAt(0) + length;
}

bool isPresent() const
{
return base && length;
}

bool isPtrInside(const void *p) const
{
auto pInt = (uintptr_t)p;
return (pInt >= (uintptr_t)base && pInt < (uintptr_t)base + length);
}

unsigned int sectOff(void *p) const
{
return (unsigned int)((uintptr_t)p - (uintptr_t)base);
}
};

// Define the list of interesting PE sections in one place so that we can
// generate definitions needed to populate our pointers and reference each
// section.

#define SECTION_LIST() \
EXPANDSEC(debug_addr) \
EXPANDSEC(debug_info) \
EXPANDSEC(debug_abbrev) \
EXPANDSEC(debug_line) \
EXPANDSEC(debug_line_str) \
EXPANDSEC(debug_frame) \
EXPANDSEC(debug_str) \
EXPANDSEC(debug_str_offsets) \
EXPANDSEC(debug_loc) \
EXPANDSEC(debug_loclists) \
EXPANDSEC(debug_ranges) \
EXPANDSEC(debug_rnglists) \
EXPANDSEC(reloc) \
EXPANDSEC(text)


#define IMGHDR(x) (hdr32 ? hdr32->x : hdr64->x)

class PEImage : public LastError
Expand Down Expand Up @@ -70,14 +138,15 @@ class PEImage : public LastError
bool save(const TCHAR* oname);

bool replaceDebugSection (const void* data, int datalen, bool initCV);
void initSec(PESection& peSec, int secNo) const;
bool initCVPtr(bool initDbgDir);
bool initDbgPtr(bool initDbgDir);
bool initDWARFPtr(bool initDbgDir);
bool initDWARFObject();
void initDWARFSegments();
bool relocateDebugLineInfo(unsigned int img_base);

bool hasDWARF() const { return debug_line != 0; }
bool hasDWARF() const { return debug_line.isPresent(); }
bool isX64() const { return x64; }
bool isDBG() const { return dbgfile; }

Expand Down Expand Up @@ -131,23 +200,30 @@ class PEImage : public LastError

public:
//dwarf
char* debug_aranges;
char* debug_pubnames;
char* debug_pubtypes;
char* debug_info; unsigned long debug_info_length;
char* debug_abbrev; unsigned long debug_abbrev_length;
char* debug_line; unsigned long debug_line_length;
char* debug_line_str; unsigned long debug_line_str_length;
char* debug_frame; unsigned long debug_frame_length;
char* debug_str;
char* debug_loc; unsigned long debug_loc_length;
char* debug_ranges; unsigned long debug_ranges_length;
char* reloc; unsigned long reloc_length;

int linesSegment;
int codeSegment;
#define EXPANDSEC(name) PESection name;
SECTION_LIST()
#undef EXPANDSEC

int cv_base;
};

struct SectionDescriptor {
const char *name;
PESection PEImage::* pSec;
};

#define EXPANDSEC(name) constexpr SectionDescriptor sec_desc_##name { "." #name, &PEImage::name };
SECTION_LIST()
#undef EXPANDSEC

constexpr const SectionDescriptor *sec_descriptors[] =
{
#define EXPANDSEC(name) &sec_desc_##name,
SECTION_LIST()
#undef EXPANDSEC
};


#undef SECTION_LIST

#endif //__PEIMAGE_H__
20 changes: 17 additions & 3 deletions src/cv2pdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

static const int typePrefix = 4;

CV2PDB::CV2PDB(PEImage& image)
CV2PDB::CV2PDB(PEImage& image, DebugLevel debug_)
: img(image), pdb(0), dbi(0), tpi(0), ipi(0), libraries(0), rsds(0), rsdsLen(0), modules(0), globmod(0)
, segMap(0), segMapDesc(0), segFrame2Index(0), globalTypeHeader(0)
, globalTypes(0), cbGlobalTypes(0), allocGlobalTypes(0)
Expand All @@ -28,7 +28,7 @@ CV2PDB::CV2PDB(PEImage& image)
, srcLineStart(0), srcLineSections(0)
, pointerTypes(0)
, Dversion(2)
, debug(false)
, debug(debug_)
, classEnumType(0), ifaceEnumType(0), cppIfaceEnumType(0), structEnumType(0)
, classBaseType(0), ifaceBaseType(0), cppIfaceBaseType(0), structBaseType(0)
, emptyFieldListType(0)
Expand Down Expand Up @@ -149,7 +149,7 @@ bool CV2PDB::openPDB(const TCHAR* pdbname, const TCHAR* pdbref)

if (!initMsPdb ())
return setError("cannot load PDB helper DLL");
if (debug)
if (debug & DbgBasic)
{
extern HMODULE modMsPdb;
char modpath[260];
Expand Down Expand Up @@ -737,6 +737,9 @@ int CV2PDB::countNestedTypes(const codeview_reftype* fieldlist, int type)
int CV2PDB::addAggregate(codeview_type* dtype, bool clss, int n_element, int fieldlist, int property,
int derived, int vshape, int structlen, const char* name, const char* uniquename)
{
if (debug & DbgPdbTypes)
fprintf(stderr, "%s:%d: adding aggregate %s -> fieldlist:%d\n", __FUNCTION__, __LINE__, name, fieldlist);

dtype->struct_v2.id = clss ? (v3 ? LF_CLASS_V3 : LF_CLASS_V2) : (v3 ? LF_STRUCTURE_V3 : LF_STRUCTURE_V2);
dtype->struct_v2.n_element = n_element;
dtype->struct_v2.fieldlist = fieldlist;
Expand Down Expand Up @@ -771,6 +774,9 @@ int CV2PDB::addStruct(codeview_type* dtype, int n_element, int fieldlist, int pr
int CV2PDB::addEnum(codeview_type* dtype, int count, int fieldlist, int property,
int type, const char*name)
{
if (debug & DbgPdbTypes)
fprintf(stderr, "%s:%d: adding enum %s -> fieldlist:%d\n", __FUNCTION__, __LINE__, name, fieldlist);

dtype->enumeration_v2.id = (v3 ? LF_ENUM_V3 : LF_ENUM_V2);
dtype->enumeration_v2.count = count;
dtype->enumeration_v2.fieldlist = fieldlist;
Expand Down Expand Up @@ -2074,6 +2080,9 @@ int CV2PDB::appendTypedef(int type, const char* name, bool saveTranslation)
if(type == 0x78)
basetype = 0x75; // dchar type not understood by debugger, use uint instead

if (debug & DbgPdbTypes)
fprintf(stderr, "%s:%d: adding typedef %s -> %d\n", __FUNCTION__, __LINE__, name, type);

int typedefType;
if(useTypedefEnum)
{
Expand Down Expand Up @@ -2981,6 +2990,9 @@ bool CV2PDB::addPublics()
char symname[kMaxNameLen];
dsym2c((BYTE*)sym->data_v1.p_name.name, sym->data_v1.p_name.namelen, symname, sizeof(symname));
int type = translateType(sym->data_v1.symtype);
if (debug & DbgPdbSyms)
fprintf(stderr, "%s:%d: AddPublic2 %s\n", __FUNCTION__, __LINE__, (const char *)symname);

if (mod)
rc = mod->AddPublic2(symname, sym->data_v1.segment, sym->data_v1.offset, type);
else
Expand All @@ -2997,6 +3009,8 @@ bool CV2PDB::addPublics()

bool CV2PDB::initGlobalSymbols()
{
if (debug & DbgBasic)
fprintf(stderr, "%s:%d, countEntries: %d\n", __FUNCTION__, __LINE__, (int)countEntries);
for (int m = 0; m < countEntries; m++)
{
OMFDirEntry* entry = img.getCVEntry(m);
Expand Down
Loading

0 comments on commit 7919a62

Please sign in to comment.