summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsagitario <sagitario@fc51e93f-b9fe-4711-8d8d-3ae870c5f7d8>2012-02-12 16:05:27 (GMT)
committersagitario <sagitario@fc51e93f-b9fe-4711-8d8d-3ae870c5f7d8>2012-02-12 16:05:27 (GMT)
commit96e6e9fa7388b010f55cf8d122ef03a2a8ab87e4 (patch)
tree43bfb85629d0fa32de2d88d04997642a0828c128
parent805aac230223f45acc7db218eb64589a4adb390e (diff)
downloadcv2pdb-96e6e9fa7388b010f55cf8d122ef03a2a8ab87e4.zip
cv2pdb-96e6e9fa7388b010f55cf8d122ef03a2a8ab87e4.tar.gz
cv2pdb-96e6e9fa7388b010f55cf8d122ef03a2a8ab87e4.tar.bz2
* disabled named enumerator for D basic types to avoid debugger troubles displaying arrays
* added command line switch -e to enable using named enumerator for D basic types * added DWARF support * added x64 support
-rw-r--r--CHANGES11
-rw-r--r--INSTALL2
-rw-r--r--Makefile2
-rw-r--r--README11
-rw-r--r--TODO2
-rw-r--r--VERSION2
-rw-r--r--autoexp.expand21
-rw-r--r--autoexp.visualizer51
-rw-r--r--src/PEImage.cpp154
-rw-r--r--src/PEImage.h34
-rw-r--r--src/cv2pdb.cpp110
-rw-r--r--src/cv2pdb.h51
-rw-r--r--src/cv2pdb.sln41
-rw-r--r--src/cv2pdb.vcproj8
-rw-r--r--src/cvutil.cpp34
-rw-r--r--src/cvutil.h1
-rw-r--r--src/dviewhelper/dviewhelper.cpp53
-rw-r--r--src/dwarf.h1182
-rw-r--r--src/dwarf2pdb.cpp1690
-rw-r--r--src/main.cpp69
-rw-r--r--src/symutil.cpp23
-rw-r--r--src/symutil.h3
-rw-r--r--test/cvtest.d89
23 files changed, 3495 insertions, 149 deletions
diff --git a/CHANGES b/CHANGES
index 37af7af..4553fb6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,8 +1,8 @@
This is the CHANGES file for cv2pdb, a
-converter of DMD CodeView debug information to PDB files
+converter of DMD CodeView/DWARF debug information to PDB files
-Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
+Copyright (c) 2009-2012 by Rainer Schuetze, All Rights Reserved
Version history
---------------
@@ -155,3 +155,10 @@ unreleased Version 0.22
* added command line switch -s to specify the replacement character for '.' in symbols
* fixed another crash where compressed symbols expand to more than 4096 characters
+
+2012-02-12 Version 0.23
+
+ * disabled named enumerator for D basic types to avoid debugger troubles displaying arrays
+ * added command line switch -e to enable using named enumerator for D basic types
+ * added DWARF support
+ * added x64 support
diff --git a/INSTALL b/INSTALL
index 6cd551c..ec0713c 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,6 +1,6 @@
This is the INSTALL file for cv2pdb, a
-converter of DMD CodeView debug information to PDB files
+converter of DMD CodeView/DWARF debug information to PDB files
Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
diff --git a/Makefile b/Makefile
index c246003..8d5f278 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,8 @@ SRC = src\cv2pdb.cpp \
src\cv2pdb.h \
src\demangle.cpp \
src\demangle.h \
+ src\dwarf2pdb.cpp \
+ src\dwarf.h \
src\LastError.h \
src\main.cpp \
src\mscvpdb.h \
diff --git a/README b/README
index e17c560..7824875 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
This is the README file for cv2pdb, a
-converter of DMD CodeView debug information to PDB files
+converter of DMD CodeView/DWARF debug information to PDB files
Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
@@ -14,6 +14,7 @@ converted debug information, like WinDbg or DMC.
Features
--------
* conversion of DMD CodeView information to PDB file
+* conversion of DWARF information to PDB file
* converted line number info allows setting breakpoints
* display of variables, fields and objects in watch, local and auto window and in data tooltips
* generates generic debug info for dynamic arrays, associative arrays and delegates
@@ -37,6 +38,14 @@ version 2.1 of the License, or (at your option) any later version.
See the file header for more details and
http://www.gnu.org/licenses/lgpl.html for the full license.
+The file dwarf.h is taken from the libdwarf project
+(http://reality.sgiweb.org/davea/dwarf.html)
+and is distributed under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+See the file header for more details and
+http://www.gnu.org/licenses/lgpl.html for the full license.
+
Installation
------------
Sorry, there is no full featured installer available yet, you'll have
diff --git a/TODO b/TODO
index 776451d..82bbf60 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,6 @@
This is the TODO file for cv2pdb, a
-converter of DMD CodeView debug information to PDB files
+converter of DMD CodeView/DWARF debug information to PDB files
Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
diff --git a/VERSION b/VERSION
index 8ee1176..11300d1 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-VERSION = 0.22
+VERSION = 0.23
diff --git a/autoexp.expand b/autoexp.expand
index 25cc23b..cdaf324 100644
--- a/autoexp.expand
+++ b/autoexp.expand
@@ -9,9 +9,24 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
object_viewhelper=$ADDIN(dviewhelper.dll,_DObjectView@28)
-string_viewhelper=$ADDIN(dviewhelper.dll,_DStringView@28)
-wstring_viewhelper=$ADDIN(dviewhelper.dll,_DWStringView@28)
-dstring_viewhelper=$ADDIN(dviewhelper.dll,_DDStringView@28)
+string=$ADDIN(dviewhelper.dll,_DStringView@28)
+wstring=$ADDIN(dviewhelper.dll,_DWStringView@28)
+dstring=$ADDIN(dviewhelper.dll,_DDStringView@28)
+char[]=$ADDIN(dviewhelper.dll,_DStringView@28)
+wchar[]=$ADDIN(dviewhelper.dll,_DWStringView@28)
+dchar[]=$ADDIN(dviewhelper.dll,_DDStringView@28)
+const(char)[]=$ADDIN(dviewhelper.dll,_DStringView@28)
+const(wchar)[]=$ADDIN(dviewhelper.dll,_DWStringView@28)
+const(dchar)[]=$ADDIN(dviewhelper.dll,_DDStringView@28)
+const(char[])=$ADDIN(dviewhelper.dll,_DStringView@28)
+const(wchar[])=$ADDIN(dviewhelper.dll,_DWStringView@28)
+const(dchar[])=$ADDIN(dviewhelper.dll,_DDStringView@28)
+immutable(char)[]=$ADDIN(dviewhelper.dll,_DStringView@28)
+immutable(wchar)[]=$ADDIN(dviewhelper.dll,_DWStringView@28)
+immutable(dchar)[]=$ADDIN(dviewhelper.dll,_DDStringView@28)
+immutable(char[])=$ADDIN(dviewhelper.dll,_DStringView@28)
+immutable(wchar[])=$ADDIN(dviewhelper.dll,_DWStringView@28)
+immutable(dchar[])=$ADDIN(dviewhelper.dll,_DDStringView@28)
;; eo section AutoExpand for D variables ;;;;;;;;;;;;;;;;;;;;;;
;; eo added for cv2pdb - keep this line for uninstaller
diff --git a/autoexp.visualizer b/autoexp.visualizer
index 46b2d1c..d9afa2e 100644
--- a/autoexp.visualizer
+++ b/autoexp.visualizer
@@ -9,50 +9,17 @@
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; string, wstring and dstring use __viewhelper
-string|wstring|dstring {
-
- preview (
- #if ($e.ptr == 0) ( "null" )
- #else (
- #( "[", $e.length, "] ", [$e.__viewhelper] )
- )
- )
- stringview (
- #if ($e.ptr == 0) ( "null" )
- #else (
- #( [$e.ptr, s] )
- )
- )
- children (
- #(
- length: [$e.length, i],
- data: [$e.ptr]
- )
- )
+; strings not as dynamic arrays, use dviewhelper instead
+char[]|const(char)[]|immutable(char)[] {
+ preview ( [(string)$e] )
+}
+
+wchar[]|const(wchar)[]|immutable(wchar)[] {
+ preview ( [(wstring)$e] )
}
-; strings as dynamic arrays of char (no __viewhelper, check -D option for cv2pdb!)
-const char[]|char[]|const wchar[]|wchar[]|const dchar[]|dchar[] {
-
- preview (
- #if ($e.ptr == 0) ( "null" )
- #else (
- #( "[", $e.length, "] ", [$e.ptr] )
- )
- )
- stringview (
- #if ($e.ptr == 0) ( "null" )
- #else (
- #( [$e.ptr, s] )
- )
- )
- children (
- #(
- length: [$e.length, i],
- data: [$e.ptr]
- )
- )
+dchar[]|const(dchar)[]|immutable(dchar)[] {
+ preview ( [(dstring)$e] )
}
const void[]|void[] {
diff --git a/src/PEImage.cpp b/src/PEImage.cpp
index bc996a7..460f2bd 100644
--- a/src/PEImage.cpp
+++ b/src/PEImage.cpp
@@ -23,7 +23,20 @@ PEImage::PEImage(const char* iname)
: dump_base(0)
, dump_total_len(0)
, dirHeader(0)
+, hdr32(0)
+, hdr64(0)
, fd(-1)
+, debug_aranges(0)
+, debug_pubnames(0)
+, debug_pubtypes(0)
+, debug_info(0)
+, debug_abbrev(0)
+, debug_line(0)
+, debug_frame(0)
+, debug_str(0)
+, debug_loc(0)
+, debug_ranges(0)
+, codeSegment(0)
{
if(iname)
load(iname);
@@ -61,7 +74,7 @@ bool PEImage::load(const char* iname)
close(fd);
fd = -1;
- return initPtr(true);
+ return initCVPtr(true) || initDWARFPtr(true);
}
///////////////////////////////////////////////////////////////////////
@@ -86,20 +99,25 @@ bool PEImage::save(const char* oname)
}
///////////////////////////////////////////////////////////////////////
-bool PEImage::replaceDebugSection (const void* data, int datalen)
+bool PEImage::replaceDebugSection (const void* data, int datalen, bool initCV)
{
// append new debug directory to data
- IMAGE_DEBUG_DIRECTORY debugdir = *dbgDir;
+ IMAGE_DEBUG_DIRECTORY debugdir;
+ if(dbgDir)
+ debugdir = *dbgDir;
+ else
+ memset(&debugdir, 0, sizeof(debugdir));
int xdatalen = datalen + sizeof(debugdir);
// assume there is place for another section because of section alignment
int s;
DWORD lastVirtualAddress = 0;
- for(s = 0; s < hdr->FileHeader.NumberOfSections; s++)
+ int cntSections = countSections();
+ for(s = 0; s < cntSections; s++)
{
if (strcmp ((char*) sec [s].Name, ".debug") == 0)
{
- if (s == hdr->FileHeader.NumberOfSections - 1)
+ if (s == cntSections - 1)
{
dump_total_len = sec[s].PointerToRawData;
break;
@@ -110,7 +128,7 @@ bool PEImage::replaceDebugSection (const void* data, int datalen)
lastVirtualAddress = sec [s].VirtualAddress + sec[s].Misc.VirtualSize;
}
- int align = hdr->OptionalHeader.FileAlignment;
+ int align = IMGHDR(OptionalHeader.FileAlignment);
int align_len = xdatalen;
int fill = 0;
@@ -124,7 +142,7 @@ bool PEImage::replaceDebugSection (const void* data, int datalen)
return setError("cannot alloc new image");
int salign_len = xdatalen;
- align = hdr->OptionalHeader.SectionAlignment;
+ align = IMGHDR(OptionalHeader.SectionAlignment);
if (align > 0)
{
lastVirtualAddress = ((lastVirtualAddress + align - 1) / align) * align;
@@ -142,17 +160,22 @@ bool PEImage::replaceDebugSection (const void* data, int datalen)
sec[s].NumberOfLinenumbers = 0;
sec[s].Characteristics = IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA;
- hdr->FileHeader.NumberOfSections = s + 1;
+ IMGHDR(FileHeader.NumberOfSections) = s + 1;
// hdr->OptionalHeader.SizeOfImage += salign_len;
- hdr->OptionalHeader.SizeOfImage = sec[s].VirtualAddress + salign_len;
+ IMGHDR(OptionalHeader.SizeOfImage) = sec[s].VirtualAddress + salign_len;
- hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = lastVirtualAddress + datalen;
+ IMGHDR(OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) = lastVirtualAddress + datalen;
+ IMGHDR(OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size) = sizeof(IMAGE_DEBUG_DIRECTORY);
// append debug data chunk to existing file image
memcpy(newdata, dump_base, dump_total_len);
memset(newdata + dump_total_len, 0, fill);
memcpy(newdata + dump_total_len + fill, data, datalen);
+ if(!dbgDir)
+ {
+ debugdir.Type = 2;
+ }
dbgDir = (IMAGE_DEBUG_DIRECTORY*) (newdata + dump_total_len + fill + datalen);
memcpy(dbgDir, &debugdir, sizeof(debugdir));
@@ -169,11 +192,11 @@ bool PEImage::replaceDebugSection (const void* data, int datalen)
dump_base = newdata;
dump_total_len += fill + xdatalen;
- return initPtr(false);
+ return !initCV || initCVPtr(false);
}
///////////////////////////////////////////////////////////////////////
-bool PEImage::initPtr(bool initDbgDir)
+bool PEImage::initCVPtr(bool initDbgDir)
{
dos = DPV<IMAGE_DOS_HEADER> (0);
if(!dos)
@@ -181,24 +204,30 @@ bool PEImage::initPtr(bool initDbgDir)
if(dos->e_magic != IMAGE_DOS_SIGNATURE)
return setError("this is not a DOS executable");
- hdr = DPV<IMAGE_NT_HEADERS32> (dos->e_lfanew);
- if(!hdr)
+ hdr32 = DPV<IMAGE_NT_HEADERS32> (dos->e_lfanew);
+ hdr64 = DPV<IMAGE_NT_HEADERS64> (dos->e_lfanew);
+ if(!hdr32)
return setError("no optional header found");
+ if(hdr32->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ||
+ hdr32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64)
+ hdr32 = 0;
+ else
+ hdr64 = 0;
- if(hdr->Signature != IMAGE_NT_SIGNATURE)
- return setError("optional header does not have PE signature");
- if(hdr->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER32))
- return setError("optional header too small");
+ if(IMGHDR(Signature) != IMAGE_NT_SIGNATURE)
+ return setError("optional header does not have PE signature");
+ if(IMGHDR(FileHeader.SizeOfOptionalHeader) < sizeof(IMAGE_OPTIONAL_HEADER32))
+ return setError("optional header too small");
- sec = IMAGE_FIRST_SECTION(hdr);
+ sec = hdr32 ? IMAGE_FIRST_SECTION(hdr32) : IMAGE_FIRST_SECTION(hdr64);
- if(hdr->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_DEBUG)
- return setError("too few entries in data directory");
+ if(IMGHDR(OptionalHeader.NumberOfRvaAndSizes) <= IMAGE_DIRECTORY_ENTRY_DEBUG)
+ return setError("too few entries in data directory");
- if(hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0x1c)
- return setError("unexpected size of DEBUG data directory entry");
+ if(IMGHDR(OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size) != 0x1c)
+ return setError("unexpected size of DEBUG data directory entry");
- int off = hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ int off = IMGHDR(OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress);
dbgDir = RVA<IMAGE_DEBUG_DIRECTORY>(off, 0x1c);
if (!dbgDir)
return setError("debug directory not placed in image");
@@ -230,6 +259,83 @@ bool PEImage::initPtr(bool initDbgDir)
}
///////////////////////////////////////////////////////////////////////
+bool PEImage::initDWARFPtr(bool initDbgDir)
+{
+ dos = DPV<IMAGE_DOS_HEADER> (0);
+ if(!dos)
+ return setError("file too small for DOS header");
+ if(dos->e_magic != IMAGE_DOS_SIGNATURE)
+ return setError("this is not a DOS executable");
+
+ hdr32 = DPV<IMAGE_NT_HEADERS32> (dos->e_lfanew);
+ hdr64 = DPV<IMAGE_NT_HEADERS64> (dos->e_lfanew);
+ if(!hdr32)
+ return setError("no optional header found");
+ if(hdr32->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ||
+ hdr32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64)
+ hdr32 = 0;
+ else
+ hdr64 = 0;
+
+ if(IMGHDR(Signature) != IMAGE_NT_SIGNATURE)
+ return setError("optional header does not have PE signature");
+ if(IMGHDR(FileHeader.SizeOfOptionalHeader) < sizeof(IMAGE_OPTIONAL_HEADER32))
+ return setError("optional header too small");
+
+ 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));
+ for(int s = 0; s < nsec; s++)
+ {
+ const char* name = (const char*) sec[s].Name;
+ if(name[0] == '/')
+ {
+ int off = strtol(name + 1, 0, 10);
+ name = strtable + off;
+ }
+ if(strcmp(name, ".debug_aranges") == 0)
+ debug_aranges = DPV<char>(sec[s].PointerToRawData, sec[s].SizeOfRawData);
+ if(strcmp(name, ".debug_pubnames") == 0)
+ debug_pubnames = DPV<char>(sec[s].PointerToRawData, sec[s].SizeOfRawData);
+ if(strcmp(name, ".debug_pubtypes") == 0)
+ debug_pubtypes = DPV<char>(sec[s].PointerToRawData, sec[s].SizeOfRawData);
+ if(strcmp(name, ".debug_info") == 0)
+ debug_info = DPV<char>(sec[s].PointerToRawData, debug_info_length = sec[s].Misc.VirtualSize);
+ if(strcmp(name, ".debug_abbrev") == 0)
+ debug_abbrev = DPV<char>(sec[s].PointerToRawData, debug_abbrev_length = sec[s].Misc.VirtualSize);
+ if(strcmp(name, ".debug_line") == 0)
+ debug_line = DPV<char>(sec[s].PointerToRawData, debug_line_length = sec[s].Misc.VirtualSize);
+ if(strcmp(name, ".debug_frame") == 0)
+ debug_frame = DPV<char>(sec[s].PointerToRawData, sec[s].SizeOfRawData);
+ if(strcmp(name, ".debug_str") == 0)
+ debug_str = DPV<char>(sec[s].PointerToRawData, sec[s].SizeOfRawData);
+ if(strcmp(name, ".debug_loc") == 0)
+ debug_loc = DPV<char>(sec[s].PointerToRawData, sec[s].SizeOfRawData);
+ if(strcmp(name, ".debug_ranges") == 0)
+ debug_ranges = DPV<char>(sec[s].PointerToRawData, debug_ranges_length = sec[s].Misc.VirtualSize);
+ if(strcmp(name, ".reloc") == 0)
+ reloc = DPV<char>(sec[s].PointerToRawData, reloc_length = sec[s].Misc.VirtualSize);
+ if(strcmp(name, ".text") == 0)
+ codeSegment = s;
+ }
+
+ setError(0);
+
+ return true;
+}
+
+int PEImage::findSection(unsigned int off) const
+{
+ off -= IMGHDR(OptionalHeader.ImageBase);
+ int nsec = IMGHDR(FileHeader.NumberOfSections);
+ for(int s = 0; s < nsec; s++)
+ if(sec[s].VirtualAddress <= off && off < sec[s].VirtualAddress + sec[s].Misc.VirtualSize)
+ return s;
+ return -1;
+}
+
+///////////////////////////////////////////////////////////////////////
int PEImage::countCVEntries() const
{
return dirHeader ? dirHeader->cDir : 0;
diff --git a/src/PEImage.h b/src/PEImage.h
index a43d02b..4eac1dc 100644
--- a/src/PEImage.h
+++ b/src/PEImage.h
@@ -14,6 +14,8 @@
struct OMFDirHeader;
struct OMFDirEntry;
+#define IMGHDR(x) (hdr32 ? hdr32->x : hdr64->x)
+
class PEImage : public LastError
{
public:
@@ -57,8 +59,12 @@ public:
bool load(const char* iname);
bool save(const char* oname);
- bool replaceDebugSection (const void* data, int datalen);
- bool initPtr(bool initDbgDir);
+ bool replaceDebugSection (const void* data, int datalen, bool initCV);
+ bool initCVPtr(bool initDbgDir);
+ bool initDWARFPtr(bool initDbgDir);
+
+ bool hasDWARF() const { return debug_line != 0; }
+ bool isX64() const { return hdr64 != 0; }
int countCVEntries() const;
OMFDirEntry* getCVEntry(int i) const;
@@ -69,18 +75,40 @@ public:
static void* alloc_aligned(unsigned int size, unsigned int align, unsigned int alignoff = 0);
static void free_aligned(void* p);
+ int countSections() const { return IMGHDR(FileHeader.NumberOfSections); }
+ int findSection(unsigned int off) const;
+ const IMAGE_SECTION_HEADER& getSection(int s) const { return sec[s]; }
+ unsigned long long getImageBase() const { return IMGHDR(OptionalHeader.ImageBase); }
+
private:
int fd;
void* dump_base;
int dump_total_len;
+ // codeview
IMAGE_DOS_HEADER *dos;
- IMAGE_NT_HEADERS32* hdr;
+ IMAGE_NT_HEADERS32* hdr32;
+ IMAGE_NT_HEADERS64* hdr64;
IMAGE_SECTION_HEADER* sec;
IMAGE_DEBUG_DIRECTORY* dbgDir;
OMFDirHeader* dirHeader;
OMFDirEntry* dirEntry;
+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_frame;
+ char* debug_str;
+ char* debug_loc;
+ char* debug_ranges; unsigned long debug_ranges_length;
+ char* reloc; unsigned long reloc_length;
+
+ int codeSegment;
int cv_base;
};
diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp
index 72cb610..17a7b92 100644
--- a/src/cv2pdb.cpp
+++ b/src/cv2pdb.cpp
@@ -22,17 +22,23 @@ CV2PDB::CV2PDB(PEImage& image)
, userTypes(0), cbUserTypes(0), allocUserTypes(0)
, globalSymbols(0), cbGlobalSymbols(0), staticSymbols(0), cbStaticSymbols(0)
, udtSymbols(0), cbUdtSymbols(0), allocUdtSymbols(0)
+, dwarfTypes(0), cbDwarfTypes(0), allocDwarfTypes(0)
, srcLineStart(0), srcLineSections(0)
, pointerTypes(0)
, Dversion(2)
, classEnumType(0), ifaceEnumType(0), cppIfaceEnumType(0), structEnumType(0)
, classBaseType(0), ifaceBaseType(0), cppIfaceBaseType(0), structBaseType(0)
+, emptyFieldListType(0)
{
memset(typedefs, 0, sizeof(typedefs));
memset(translatedTypedefs, 0, sizeof(translatedTypedefs));
cntTypedefs = 0;
+ nextUserType = 0x1000;
+ nextDwarfType = 0x1000;
addClassTypeEnum = true;
+ addStringViewHelper = false;
+ useTypedefEnum = false;
useGlobalMod = true;
thisIsNotRef = true;
v3 = true;
@@ -74,6 +80,8 @@ bool CV2PDB::cleanup(bool commit)
free(userTypes);
if (udtSymbols)
free(udtSymbols);
+ if (dwarfTypes)
+ free(dwarfTypes);
delete [] pointerTypes;
for(int i = 0; i < srcLineSections; i++)
@@ -98,6 +106,8 @@ bool CV2PDB::cleanup(bool commit)
udtSymbols = 0;
cbUdtSymbols = 0;
allocUdtSymbols = 0;
+ cbDwarfTypes = 0;
+ allocDwarfTypes = 0;
modules = 0;
globmod = 0;
countEntries = 0;
@@ -786,7 +796,7 @@ void CV2PDB::checkUserTypeAlloc(int size, int add)
{
if (cbUserTypes + size >= allocUserTypes)
{
- allocUserTypes += add;
+ allocUserTypes += size + add;
userTypes = (BYTE*) realloc(userTypes, allocUserTypes);
}
}
@@ -1396,7 +1406,8 @@ const char* CV2PDB::appendDynamicArray(int indexType, int elemType)
int dataptrType = nextUserType++;
int dstringType = 0;
- if(strcmp(name, "string") == 0 || strcmp(name, "wstring") == 0 || strcmp(name, "dstring") == 0)
+ if(addStringViewHelper &&
+ (strcmp(name, "string") == 0 || strcmp(name, "wstring") == 0 || strcmp(name, "dstring") == 0))
{
// nextUserType + 1: field list (size, array)
rdtype = (codeview_reftype*) (userTypes + cbUserTypes);
@@ -1731,6 +1742,24 @@ int CV2PDB::appendPointerType(int pointedType, int attr)
return nextUserType - 1;
}
+int CV2PDB::appendModifierType(int type, int attr)
+{
+ checkUserTypeAlloc();
+
+ codeview_type* dtype = (codeview_type*) (userTypes + cbUserTypes);
+ dtype->modifier_v2.id = LF_MODIFIER_V2;
+ dtype->modifier_v2.type = translateType(type);
+ dtype->modifier_v2.attribute = attr;
+ int len = sizeof(dtype->modifier_v2);
+ //for (; len & 3; len++)
+ // userTypes[cbUserTypes + len] = 0xf4 - (len & 3);
+ dtype->modifier_v2.len = len - 2;
+ cbUserTypes += len;
+
+ nextUserType++;
+ return nextUserType - 1;
+}
+
int CV2PDB::appendComplex(int cplxtype, int basetype, int elemsize, const char* name)
{
basetype = translateType(basetype);
@@ -1902,36 +1931,56 @@ void CV2PDB::ensureUDT(int type, const codeview_type* cvtype)
addUdtSymbol(type + 0x1000, name);
}
-int CV2PDB::appendTypedef(int type, const char* name)
+int CV2PDB::createEmptyFieldListType()
{
- checkUserTypeAlloc();
-
- int basetype = type;
- if(type == 0x78)
- basetype = 0x75; // dchar type not understood by debugger, use uint instead
+ if(emptyFieldListType > 0)
+ return emptyFieldListType;
+ checkUserTypeAlloc();
codeview_reftype* rdtype = (codeview_reftype*) (userTypes + cbUserTypes);
rdtype->fieldlist.id = LF_FIELDLIST_V2;
rdtype->fieldlist.len = 2;
cbUserTypes += rdtype->fieldlist.len + 2;
- int fieldlistType = nextUserType++;
+ emptyFieldListType = nextUserType++;
- codeview_type* dtype = (codeview_type*) (userTypes + cbUserTypes);
- dtype->enumeration_v2.id = (v3 ? LF_ENUM_V3 : LF_ENUM_V2);
- dtype->enumeration_v2.type = basetype;
- dtype->enumeration_v2.fieldlist = fieldlistType;
- dtype->enumeration_v2.count = 0;
- dtype->enumeration_v2.property = kPropReserved2;
- int len = cstrcpy_v (v3, (BYTE*) &dtype->enumeration_v2.p_name, name);
- len += sizeof(dtype->enumeration_v2) - sizeof(dtype->enumeration_v2.p_name);
- writeUserTypeLen(dtype, len);
-
- typedefs[cntTypedefs] = type;
- translatedTypedefs[cntTypedefs] = nextUserType;
- cntTypedefs++;
+ return emptyFieldListType;
+}
- nextUserType++;
- return nextUserType - 1;
+int CV2PDB::appendTypedef(int type, const char* name, bool saveTranslation)
+{
+ int basetype = type;
+ if(type == 0x78)
+ basetype = 0x75; // dchar type not understood by debugger, use uint instead
+
+ int typedefType;
+ if(useTypedefEnum)
+ {
+ checkUserTypeAlloc();
+
+ int fieldlistType = createEmptyFieldListType();
+
+ codeview_type* dtype = (codeview_type*) (userTypes + cbUserTypes);
+ dtype->enumeration_v2.id = (v3 ? LF_ENUM_V3 : LF_ENUM_V2);
+ dtype->enumeration_v2.type = basetype;
+ dtype->enumeration_v2.fieldlist = fieldlistType;
+ dtype->enumeration_v2.count = 0;
+ dtype->enumeration_v2.property = kPropReserved2;
+ int len = cstrcpy_v (v3, (BYTE*) &dtype->enumeration_v2.p_name, name);
+ len += sizeof(dtype->enumeration_v2) - sizeof(dtype->enumeration_v2.p_name);
+ writeUserTypeLen(dtype, len);
+ typedefType = nextUserType++;
+ }
+ else
+ {
+ typedefType = appendModifierType(type, 0);
+ }
+ if(saveTranslation)
+ {
+ typedefs[cntTypedefs] = type;
+ translatedTypedefs[cntTypedefs] = typedefType;
+ cntTypedefs++;
+ }
+ return typedefType;
}
void CV2PDB::appendTypedefs()
@@ -2934,13 +2983,18 @@ codeview_symbol* CV2PDB::findUdtSymbol(const char* name)
return 0;
}
-bool CV2PDB::addUdtSymbol(int type, const char* name)
+void CV2PDB::checkUdtSymbolAlloc(int size, int add)
{
- if (cbUdtSymbols + 100 + kMaxNameLen > allocUdtSymbols)
+ if (cbUdtSymbols + size > allocUdtSymbols)
{
- allocUdtSymbols += kMaxNameLen + 5000;
+ allocUdtSymbols += size + add;
udtSymbols = (BYTE*) realloc(udtSymbols, allocUdtSymbols);
}
+}
+
+bool CV2PDB::addUdtSymbol(int type, const char* name)
+{
+ checkUdtSymbolAlloc(100 + kMaxNameLen);
// no need to convert to udt_v2/udt_v3, the debugger is fine with it.
codeview_symbol* sym = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
@@ -3045,7 +3099,7 @@ bool CV2PDB::addSymbols()
bool CV2PDB::writeImage(const char* opath)
{
int len = sizeof(*rsds) + strlen((char*)(rsds + 1)) + 1;
- if (!img.replaceDebugSection(rsds, len))
+ if (!img.replaceDebugSection(rsds, len, true))
return setError(img.getLastError());
if (!img.save(opath))
diff --git a/src/cv2pdb.h b/src/cv2pdb.h
index e352dcc..0dc6a44 100644
--- a/src/cv2pdb.h
+++ b/src/cv2pdb.h
@@ -11,12 +11,15 @@
#include "mspdb.h"
#include <windows.h>
+#include <map>
extern "C" {
#include "mscvpdb.h"
}
class PEImage;
+struct DWARF_InfoData;
+struct DWARF_CompilationUnit;
class CV2PDB : public LastError
{
@@ -67,6 +70,8 @@ public:
void checkUserTypeAlloc(int size = 1000, int add = 10000);
void checkGlobalTypeAlloc(int size, int add = 1000);
+ void checkUdtSymbolAlloc(int size, int add = 10000);
+ void checkDWARFTypeAlloc(int size, int add = 10000);
void writeUserTypeLen(codeview_type* type, int len);
const codeview_type* getTypeData(int type);
@@ -75,6 +80,7 @@ public:
const codeview_type* findCompleteClassType(const codeview_type* cvtype, int* ptype = 0);
int findMemberFunctionType(codeview_symbol* lastGProcSym, int thisPtrType);
+ int createEmptyFieldListType();
int fixProperty(int type, int prop, int fieldType);
bool derivesFromObject(const codeview_type* cvtype);
@@ -106,12 +112,19 @@ public:
const char* appendDelegate(int thisType, int funcType);
int appendObjectType (int object_derived_type, int enumType, const char* classSymbol);
int appendPointerType(int pointedType, int attr);
- int appendTypedef(int type, const char* name);
+ int appendModifierType(int type, int attr);
+ int appendTypedef(int type, const char* name, bool saveTranslation = true);
int appendComplex(int cplxtype, int basetype, int elemsize, const char* name);
void appendTypedefs();
int appendEnumerator(const char* typeName, const char* enumName, int enumValue, int prop);
int appendClassTypeEnum(const codeview_type* fieldlist, int type, const char* name);
- bool hasClassTypeEnum(const codeview_type* fieldlist);
+ void appendStackVar(const char* name, int type, int offset);
+ void appendGlobalVar(const char* name, int type, int seg, int offset);
+ bool appendEndArg();
+ void appendEnd();
+ void appendLexicalBlock(DWARF_InfoData& id, unsigned int proclo);
+
+ bool hasClassTypeEnum(const codeview_type* fieldlist);
bool insertClassTypeEnums();
int insertBaseClass(const codeview_type* fieldlist, int type);
@@ -143,6 +156,27 @@ public:
mspdb::Mod* globalMod();
+ // DWARF
+ bool createDWARFModules();
+ unsigned char* getDWARFAbbrev(int off, int n);
+ bool addDWARFTypes();
+ bool addDWARFLines();
+ bool addDWARFPublics();
+ bool relocateDebugLineInfo();
+ bool writeDWARFImage(const char* opath);
+
+ bool addDWARFSectionContrib(mspdb::Mod* mod, unsigned long pclo, unsigned long pchi);
+ bool addDWARFProc(DWARF_InfoData& id, DWARF_CompilationUnit* cu, unsigned char* &locals, unsigned char* end);
+ int addDWARFStructure(DWARF_InfoData& id, DWARF_CompilationUnit* cu, unsigned char* &locals, unsigned char* end);
+ int addDWARFArray(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, unsigned char* &locals, unsigned char* end);
+ int addDWARFBasicType(const char*name, int encoding, int byte_size);
+ bool iterateDWARFDebugInfo(int op);
+ int getTypeByDWARFOffset(DWARF_CompilationUnit* cu, int off);
+ int getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff);
+ int getDWARFArrayBounds(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu,
+ unsigned char* &locals, unsigned char* end, int& upperBound);
+ bool readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, unsigned char* &p, bool mergeInfo = false);
+
// private:
BYTE* libraries;
@@ -183,9 +217,15 @@ public:
int cbUdtSymbols;
int allocUdtSymbols;
+ unsigned char* dwarfTypes;
+ int cbDwarfTypes;
+ int allocDwarfTypes;
+
int nextUserType;
+ int nextDwarfType;
int objectType;
-
+
+ int emptyFieldListType;
int classEnumType;
int ifaceEnumType;
int cppIfaceEnumType;
@@ -202,6 +242,7 @@ public:
int cntTypedefs;
bool addClassTypeEnum;
+ bool addStringViewHelper;
bool useGlobalMod;
bool thisIsNotRef;
bool v3;
@@ -211,6 +252,10 @@ public:
char** srcLineStart; // array of bitmaps per segment, indicating whether src line start is available for corresponding address
double Dversion;
+
+ // DWARF
+ int codeSegOff;
+ std::map<int, int> mapOffsetToType;
};
diff --git a/src/cv2pdb.sln b/src/cv2pdb.sln
index ddb3df0..6252819 100644
--- a/src/cv2pdb.sln
+++ b/src/cv2pdb.sln
@@ -24,24 +24,65 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cvtest", "..\test\cvtest.vc
{5E2BD27D-446A-4C99-9829-135F7C000D90} = {5E2BD27D-446A-4C99-9829-135F7C000D90}
EndProjectSection
EndProject
+Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "test", "..\test\test.visualdproj", "{370E7494-D0CB-450F-B74A-4CEEDB19FBAE}"
+EndProject
+Project("{8BC9CEB9-8B4A-11D0-8D11-00A0C91BC942}") = "test64.exe", "..\bin\Debug GDCWin32\test64.exe", "{022545C9-DE2E-44F0-B87C-74CEAC3202F6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug GDC|Win32 = Debug GDC|Win32
+ Debug GDC|x64 = Debug GDC|x64
Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5E2BD27D-446A-4C99-9829-135F7C000D90}.Debug GDC|Win32.ActiveCfg = Debug|Win32
+ {5E2BD27D-446A-4C99-9829-135F7C000D90}.Debug GDC|Win32.Build.0 = Debug|Win32
+ {5E2BD27D-446A-4C99-9829-135F7C000D90}.Debug GDC|x64.ActiveCfg = Debug|Win32
{5E2BD27D-446A-4C99-9829-135F7C000D90}.Debug|Win32.ActiveCfg = Debug|Win32
{5E2BD27D-446A-4C99-9829-135F7C000D90}.Debug|Win32.Build.0 = Debug|Win32
+ {5E2BD27D-446A-4C99-9829-135F7C000D90}.Debug|x64.ActiveCfg = Debug|Win32
{5E2BD27D-446A-4C99-9829-135F7C000D90}.Release|Win32.ActiveCfg = Release|Win32
{5E2BD27D-446A-4C99-9829-135F7C000D90}.Release|Win32.Build.0 = Release|Win32
+ {5E2BD27D-446A-4C99-9829-135F7C000D90}.Release|x64.ActiveCfg = Release|Win32
+ {E4424774-A7A0-4502-8626-2723904D70EA}.Debug GDC|Win32.ActiveCfg = Debug|Win32
+ {E4424774-A7A0-4502-8626-2723904D70EA}.Debug GDC|Win32.Build.0 = Debug|Win32
+ {E4424774-A7A0-4502-8626-2723904D70EA}.Debug GDC|x64.ActiveCfg = Debug|Win32
{E4424774-A7A0-4502-8626-2723904D70EA}.Debug|Win32.ActiveCfg = Debug|Win32
{E4424774-A7A0-4502-8626-2723904D70EA}.Debug|Win32.Build.0 = Debug|Win32
+ {E4424774-A7A0-4502-8626-2723904D70EA}.Debug|x64.ActiveCfg = Debug|Win32
{E4424774-A7A0-4502-8626-2723904D70EA}.Release|Win32.ActiveCfg = Release|Win32
{E4424774-A7A0-4502-8626-2723904D70EA}.Release|Win32.Build.0 = Release|Win32
+ {E4424774-A7A0-4502-8626-2723904D70EA}.Release|x64.ActiveCfg = Release|Win32
+ {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Debug GDC|Win32.ActiveCfg = Debug|Win32
+ {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Debug GDC|Win32.Build.0 = Debug|Win32
+ {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Debug GDC|x64.ActiveCfg = Debug|Win32
{CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Debug|Win32.ActiveCfg = Debug|Win32
{CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Debug|Win32.Build.0 = Debug|Win32
+ {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Debug|x64.ActiveCfg = Debug|Win32
{CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Release|Win32.ActiveCfg = Release|Win32
{CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Release|Win32.Build.0 = Release|Win32
+ {CCC0643D-7D3F-4D5E-AE0E-C871776E86AF}.Release|x64.ActiveCfg = Release|Win32
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Debug GDC|Win32.ActiveCfg = Debug GDC|Win32
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Debug GDC|Win32.Build.0 = Debug GDC|Win32
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Debug GDC|x64.ActiveCfg = Debug GDC|x64
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Debug GDC|x64.Build.0 = Debug GDC|x64
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Debug|Win32.Build.0 = Debug|Win32
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Debug|x64.ActiveCfg = Debug|x64
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Debug|x64.Build.0 = Debug|x64
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Release|Win32.ActiveCfg = Release|Win32
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Release|Win32.Build.0 = Release|Win32
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Release|x64.ActiveCfg = Release|x64
+ {370E7494-D0CB-450F-B74A-4CEEDB19FBAE}.Release|x64.Build.0 = Release|x64
+ {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug GDC|Win32.ActiveCfg = Debug
+ {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug GDC|x64.ActiveCfg = Debug
+ {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug|Win32.ActiveCfg = Debug
+ {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Debug|x64.ActiveCfg = Debug
+ {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Release|Win32.ActiveCfg = Debug
+ {022545C9-DE2E-44F0-B87C-74CEAC3202F6}.Release|x64.ActiveCfg = Debug
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/cv2pdb.vcproj b/src/cv2pdb.vcproj
index fd3c973..bb7e6e7 100644
--- a/src/cv2pdb.vcproj
+++ b/src/cv2pdb.vcproj
@@ -184,6 +184,10 @@
>
</File>
<File
+ RelativePath=".\cv2pdb.h"
+ >
+ </File>
+ <File
RelativePath=".\cvutil.cpp"
>
</File>
@@ -200,6 +204,10 @@
>
</File>
<File
+ RelativePath=".\dwarf2pdb.cpp"
+ >
+ </File>
+ <File
RelativePath=".\LastError.h"
>
</File>
diff --git a/src/cvutil.cpp b/src/cvutil.cpp
index 64802f2..95e8ea3 100644
--- a/src/cvutil.cpp
+++ b/src/cvutil.cpp
@@ -110,7 +110,7 @@ bool isCompleteStruct(const codeview_type* type, const BYTE* name, bool cstr)
int numeric_leaf(int* value, const void* leaf)
{
unsigned short int type = *(const unsigned short int*) leaf;
- leaf = (const unsigned short int*) leaf + 2;
+ leaf = (const unsigned short int*) leaf + 1;
int length = 2;
*value = 0;
@@ -179,3 +179,35 @@ int numeric_leaf(int* value, const void* leaf)
return length;
}
+int write_numeric_leaf(int value, void* leaf)
+{
+ if(value >= 0 && value < LF_NUMERIC)
+ {
+ *(unsigned short int*) leaf = (unsigned short) value;
+ return 2;
+ }
+ unsigned short int* type = (unsigned short int*) leaf;
+ leaf = type + 1;
+ if (value >= -128 && value <= 127)
+ {
+ *type = LF_CHAR;
+ *(char*) leaf = (char)value;
+ return 3;
+ }
+ if (value >= -32768 && value <= 32767)
+ {
+ *type = LF_SHORT;
+ *(short*) leaf = (short)value;
+ return 4;
+ }
+ if (value >= 0 && value <= 65535)
+ {
+ *type = LF_USHORT;
+ *(unsigned short*) leaf = (unsigned short)value;
+ return 4;
+ }
+ *type = LF_LONG;
+ *(long*) leaf = (long)value;
+ return 6;
+}
+
diff --git a/src/cvutil.h b/src/cvutil.h
index d9817e5..5ab3f11 100644
--- a/src/cvutil.h
+++ b/src/cvutil.h
@@ -50,5 +50,6 @@ const BYTE* getStructName(const codeview_type* cvtype, bool &cstr);
bool cmpStructName(const codeview_type* cvtype, const BYTE* name, bool cstr);
int numeric_leaf(int* value, const void* leaf);
+int write_numeric_leaf(int value, void* leaf);
#endif // __CVUTIL_H__
diff --git a/src/dviewhelper/dviewhelper.cpp b/src/dviewhelper/dviewhelper.cpp
index 3cee363..c9d16af 100644
--- a/src/dviewhelper/dviewhelper.cpp
+++ b/src/dviewhelper/dviewhelper.cpp
@@ -25,13 +25,28 @@ extern "C" {
struct DEBUGHELPER
{
DWORD dwVersion;
- BOOL (WINAPI *ReadDebuggeeMemory)(DEBUGHELPER *pThis, DWORD dwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot);
+ HRESULT (WINAPI *ReadDebuggeeMemory)(DEBUGHELPER *pThis, DWORD dwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot);
// from here only when dwVersion >= 0x20000
DWORDLONG (WINAPI *GetRealAddress)(DEBUGHELPER *pThis);
- BOOL (WINAPI *ReadDebuggeeMemoryEx)(DEBUGHELPER *pThis, DWORDLONG qwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot);
+ HRESULT (WINAPI *ReadDebuggeeMemoryEx)(DEBUGHELPER *pThis, DWORDLONG qwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot);
int (WINAPI *GetProcessorType)(DEBUGHELPER *pThis);
};
+// possible processor types
+typedef enum _MPT {
+ mptix86 = 0, // Intel X86
+ mptia64 = 1, // Intel Merced
+ mptamd64 = 2, // AMD64
+ mptUnknown = 3 // Unknown
+} MPT;
+
+HRESULT readMem(DEBUGHELPER *pHelper, DWORDLONG qwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot)
+{
+ if(pHelper->dwVersion < 0x20000)
+ return pHelper->ReadDebuggeeMemory(pHelper, (DWORD)qwAddr, nWant, pWhere, nGot);
+ return pHelper->ReadDebuggeeMemoryEx(pHelper, qwAddr, nWant, pWhere, nGot);
+}
+
struct DString
{
DWORD length;
@@ -43,26 +58,46 @@ struct DString
HRESULT WINAPI StringView(DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings,
char *pResult, size_t max, DWORD sizePerChar)
{
+ DWORDLONG qwAddress = dwAddress;
+ if(pHelper->dwVersion >= 0x20000)
+ qwAddress = pHelper->GetRealAddress(pHelper);
+
+ int proc = 0;
+ if(pHelper->dwVersion >= 0x20000)
+ proc = pHelper->GetProcessorType(pHelper);
+ int sizeOfPtr = proc == 0 ? 4 : 8;
+
// Get the string struct
- DString dstr;
+ char strdata[16];
DWORD read;
- if (pHelper->ReadDebuggeeMemory(pHelper, dwAddress, sizeof(dstr), &dstr, &read) != S_OK)
+ if (readMem(pHelper, qwAddress, 2*sizeOfPtr, strdata, &read) != S_OK)
{
- strncpy(pResult,"Cannot access struct", max);
- return S_OK;
+ strncpy(pResult,"Cannot access struct", max);
+ return S_OK;
}
- if (dstr.length == 0)
+ DWORDLONG length, data;
+ if(sizeOfPtr > 4)
+ {
+ length = *(DWORDLONG*) strdata;
+ data = *(DWORDLONG*) (strdata + sizeOfPtr);
+ }
+ else
+ {
+ length = *(DWORD*) strdata;
+ data = *(DWORD*) (strdata + sizeOfPtr);
+ }
+ if (length == 0)
{
strncpy(pResult,"\"\"", max);
return S_OK;
}
char* pData = pResult + 1;
- DWORD cnt = (dstr.length < max - 3 ? dstr.length : max - 3);
+ DWORD cnt = (length < max - 3 ? (DWORD)length : max - 3);
if (sizePerChar * cnt > max)
pData = new char[sizePerChar * cnt];
- if (pHelper->ReadDebuggeeMemory(pHelper, dstr.data, sizePerChar * cnt, pData, &read) != S_OK)
+ if (readMem(pHelper, data, sizePerChar * cnt, pData, &read) != S_OK)
{
strncpy(pResult,"Cannot access data", max);
}
diff --git a/src/dwarf.h b/src/dwarf.h
new file mode 100644
index 0000000..92c36e9
--- /dev/null
+++ b/src/dwarf.h
@@ -0,0 +1,1182 @@
+/*
+ Copyright (C) 2000,2001,2003,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2007-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+#ifndef __DWARF_H
+#define __DWARF_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ dwarf.h DWARF debugging information values
+ $Revision: 1.41 $ $Date: 2006/04/17 00:09:56 $
+
+ The comment "DWARF3" appears where there are
+ new entries from DWARF3 as of 2004, "DWARF3f"
+ where there are new entries as of the November 2005
+ public review document and other comments apply
+ where extension entries appear.
+
+ Extensions part of DWARF4 are marked DWARF4.
+
+ A few extension names have omitted the 'vendor id'
+ (See chapter 7, "Vendor Extensibility"). Please
+ always use a 'vendor id' string in extension names.
+
+ Vendors should use a vendor string in names and
+ whereever possible avoid duplicating values used by
+ other vendor extensions
+*/
+
+
+#define DW_TAG_array_type 0x01
+#define DW_TAG_class_type 0x02
+#define DW_TAG_entry_point 0x03
+#define DW_TAG_enumeration_type 0x04
+#define DW_TAG_formal_parameter 0x05
+#define DW_TAG_imported_declaration 0x08
+#define DW_TAG_label 0x0a
+#define DW_TAG_lexical_block 0x0b
+#define DW_TAG_member 0x0d
+#define DW_TAG_pointer_type 0x0f
+#define DW_TAG_reference_type 0x10
+#define DW_TAG_compile_unit 0x11
+#define DW_TAG_string_type 0x12
+#define DW_TAG_structure_type 0x13
+#define DW_TAG_subroutine_type 0x15
+#define DW_TAG_typedef 0x16
+#define DW_TAG_union_type 0x17
+#define DW_TAG_unspecified_parameters 0x18
+#define DW_TAG_variant 0x19
+#define DW_TAG_common_block 0x1a
+#define DW_TAG_common_inclusion 0x1b
+#define DW_TAG_inheritance 0x1c
+#define DW_TAG_inlined_subroutine 0x1d
+#define DW_TAG_module 0x1e
+#define DW_TAG_ptr_to_member_type 0x1f
+#define DW_TAG_set_type 0x20
+#define DW_TAG_subrange_type 0x21
+#define DW_TAG_with_stmt 0x22
+#define DW_TAG_access_declaration 0x23
+#define DW_TAG_base_type 0x24
+#define DW_TAG_catch_block 0x25
+#define DW_TAG_const_type 0x26
+#define DW_TAG_constant 0x27
+#define DW_TAG_enumerator 0x28
+#define DW_TAG_file_type 0x29
+#define DW_TAG_friend 0x2a
+#define DW_TAG_namelist 0x2b
+ /* Early releases of this header had the following
+ misspelled with a trailing 's' */
+#define DW_TAG_namelist_item 0x2c /* DWARF3/2 spelling */
+#define DW_TAG_namelist_items 0x2c /* SGI misspelling/typo */
+#define DW_TAG_packed_type 0x2d
+#define DW_TAG_subprogram 0x2e
+ /* The DWARF2 document had two spellings of the following
+ two TAGs, DWARF3 specifies the longer spelling. */
+#define DW_TAG_template_type_parameter 0x2f /* DWARF3/2 spelling*/
+#define DW_TAG_template_type_param 0x2f /* DWARF2 spelling*/
+#define DW_TAG_template_value_parameter 0x30 /* DWARF3/2 spelling*/
+#define DW_TAG_template_value_param 0x30 /* DWARF2 spelling*/
+#define DW_TAG_thrown_type 0x31
+#define DW_TAG_try_block 0x32
+#define DW_TAG_variant_part 0x33
+#define DW_TAG_variable 0x34
+#define DW_TAG_volatile_type 0x35
+#define DW_TAG_dwarf_procedure 0x36 /* DWARF3 */
+#define DW_TAG_restrict_type 0x37 /* DWARF3 */
+#define DW_TAG_interface_type 0x38 /* DWARF3 */
+#define DW_TAG_namespace 0x39 /* DWARF3 */
+#define DW_TAG_imported_module 0x3a /* DWARF3 */
+#define DW_TAG_unspecified_type 0x3b /* DWARF3 */
+#define DW_TAG_partial_unit 0x3c /* DWARF3 */
+#define DW_TAG_imported_unit 0x3d /* DWARF3 */
+ /* Do not use DW_TAG_mutable_type */
+#define DW_TAG_mutable_type 0x3e /* Withdrawn from DWARF3 by DWARF3f. */
+#define DW_TAG_condition 0x3f /* DWARF3f */
+#define DW_TAG_shared_type 0x40 /* DWARF3f */
+#define DW_TAG_type_unit 0x41 /* DWARF4 */
+#define DW_TAG_rvalue_reference_type 0x42 /* DWARF4 */
+#define DW_TAG_template_alias 0x43 /* DWARF4 */
+#define DW_TAG_lo_user 0x4080
+
+#define DW_TAG_MIPS_loop 0x4081
+
+/* HP extensions: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz */
+#define DW_TAG_HP_array_descriptor 0x4090 /* HP */
+
+/* GNU extensions. The first 3 missing the GNU_. */
+#define DW_TAG_format_label 0x4101 /* GNU. Fortran. */
+#define DW_TAG_function_template 0x4102 /* GNU. For C++ */
+#define DW_TAG_class_template 0x4103 /* GNU. For C++ */
+#define DW_TAG_GNU_BINCL 0x4104 /* GNU */
+#define DW_TAG_GNU_EINCL 0x4105 /* GNU */
+
+/* GNU extension. http://gcc.gnu.org/wiki/TemplateParmsDwarf */
+#define DW_TAG_GNU_template_template_parameter 0x4106 /* GNU */
+#define DW_TAG_GNU_template_template_param 0x4106 /* GNU */
+#define DW_TAG_GNU_template_parameter_pack 0x4107 /* GNU */
+#define DW_TAG_GNU_formal_parameter_pack 0x4108 /* GNU */
+
+#define DW_TAG_GNU_call_site 0x4109 /* GNU */
+#define DW_TAG_GNU_call_site_parameter 0x410a /* GNU */
+
+/* ALTIUM extensions */
+ /* DSP-C/Starcore __circ qualifier */
+#define DW_TAG_ALTIUM_circ_type 0x5101 /* ALTIUM */
+ /* Starcore __mwa_circ qualifier */
+#define DW_TAG_ALTIUM_mwa_circ_type 0x5102 /* ALTIUM */
+ /* Starcore __rev_carry qualifier */
+#define DW_TAG_ALTIUM_rev_carry_type 0x5103 /* ALTIUM */
+ /* M16 __rom qualifier */
+#define DW_TAG_ALTIUM_rom 0x5111 /* ALTIUM */
+
+/* The following 3 are extensions to support UPC */
+#define DW_TAG_upc_shared_type 0x8765 /* UPC */
+#define DW_TAG_upc_strict_type 0x8766 /* UPC */
+#define DW_TAG_upc_relaxed_type 0x8767 /* UPC */
+
+/* PGI (STMicroelectronics) extensions. */
+#define DW_TAG_PGI_kanji_type 0xa000 /* PGI */
+#define DW_TAG_PGI_interface_block 0xa020 /* PGI */
+/* The following are SUN extensions */
+#define DW_TAG_SUN_function_template 0x4201 /* SUN */
+#define DW_TAG_SUN_class_template 0x4202 /* SUN */
+#define DW_TAG_SUN_struct_template 0x4203 /* SUN */
+#define DW_TAG_SUN_union_template 0x4204 /* SUN */
+#define DW_TAG_SUN_indirect_inheritance 0x4205 /* SUN */
+#define DW_TAG_SUN_codeflags 0x4206 /* SUN */
+#define DW_TAG_SUN_memop_info 0x4207 /* SUN */
+#define DW_TAG_SUN_omp_child_func 0x4208 /* SUN */
+#define DW_TAG_SUN_rtti_descriptor 0x4209 /* SUN */
+#define DW_TAG_SUN_dtor_info 0x420a /* SUN */
+#define DW_TAG_SUN_dtor 0x420b /* SUN */
+#define DW_TAG_SUN_f90_interface 0x420c /* SUN */
+#define DW_TAG_SUN_fortran_vax_structure 0x420d /* SUN */
+#define DW_TAG_SUN_hi 0x42ff /* SUN */
+
+
+#define DW_TAG_hi_user 0xffff
+
+#define DW_children_no 0
+#define DW_children_yes 1
+
+
+
+#define DW_FORM_addr 0x01
+#define DW_FORM_block2 0x03
+#define DW_FORM_block4 0x04
+#define DW_FORM_data2 0x05
+#define DW_FORM_data4 0x06
+#define DW_FORM_data8 0x07
+#define DW_FORM_string 0x08
+#define DW_FORM_block 0x09
+#define DW_FORM_block1 0x0a
+#define DW_FORM_data1 0x0b
+#define DW_FORM_flag 0x0c
+#define DW_FORM_sdata 0x0d
+#define DW_FORM_strp 0x0e
+#define DW_FORM_udata 0x0f
+#define DW_FORM_ref_addr 0x10
+#define DW_FORM_ref1 0x11
+#define DW_FORM_ref2 0x12
+#define DW_FORM_ref4 0x13
+#define DW_FORM_ref8 0x14
+#define DW_FORM_ref_udata 0x15
+#define DW_FORM_indirect 0x16
+#define DW_FORM_sec_offset 0x17 /* DWARF4 */
+#define DW_FORM_exprloc 0x18 /* DWARF4 */
+#define DW_FORM_flag_present 0x19 /* DWARF4 */
+/* 0x1a thru 0x1f were left unused accidentally. Reserved for future use. */
+#define DW_FORM_ref_sig8 0x20 /* DWARF4 */
+
+#define DW_AT_sibling 0x01
+#define DW_AT_location 0x02
+#define DW_AT_name 0x03
+#define DW_AT_ordering 0x09
+#define DW_AT_subscr_data 0x0a
+#define DW_AT_byte_size 0x0b
+#define DW_AT_bit_offset 0x0c
+#define DW_AT_bit_size 0x0d
+#define DW_AT_element_list 0x0f
+#define DW_AT_stmt_list 0x10
+#define DW_AT_low_pc 0x11
+#define DW_AT_high_pc 0x12
+#define DW_AT_language 0x13
+#define DW_AT_member 0x14
+#define DW_AT_discr 0x15
+#define DW_AT_discr_value 0x16
+#define DW_AT_visibility 0x17
+#define DW_AT_import 0x18
+#define DW_AT_string_length 0x19
+#define DW_AT_common_reference 0x1a
+#define DW_AT_comp_dir 0x1b
+#define DW_AT_const_value 0x1c
+#define DW_AT_containing_type 0x1d
+#define DW_AT_default_value 0x1e
+#define DW_AT_inline 0x20
+#define DW_AT_is_optional 0x21
+#define DW_AT_lower_bound 0x22
+#define DW_AT_producer 0x25
+#define DW_AT_prototyped 0x27
+#define DW_AT_return_addr 0x2a
+#define DW_AT_start_scope 0x2c
+#define DW_AT_bit_stride 0x2e /* DWARF3 name */
+#define DW_AT_stride_size 0x2e /* DWARF2 name */
+#define DW_AT_upper_bound 0x2f
+#define DW_AT_abstract_origin 0x31
+#define DW_AT_accessibility 0x32
+#define DW_AT_address_class 0x33
+#define DW_AT_artificial 0x34
+#define DW_AT_base_types 0x35
+#define DW_AT_calling_convention 0x36
+#define DW_AT_count 0x37
+#define DW_AT_data_member_location 0x38
+#define DW_AT_decl_column 0x39
+#define DW_AT_decl_file 0x3a
+#define DW_AT_decl_line 0x3b
+#define DW_AT_declaration 0x3c
+#define DW_AT_discr_list 0x3d
+#define DW_AT_encoding 0x3e
+#define DW_AT_external 0x3f
+#define DW_AT_frame_base 0x40
+#define DW_AT_friend 0x41
+#define DW_AT_identifier_case 0x42
+#define DW_AT_macro_info 0x43
+#define DW_AT_namelist_item 0x44
+#define DW_AT_priority 0x45
+#define DW_AT_segment 0x46
+#define DW_AT_specification 0x47
+#define DW_AT_static_link 0x48
+#define DW_AT_type 0x49
+#define DW_AT_use_location 0x4a
+#define DW_AT_variable_parameter 0x4b
+#define DW_AT_virtuality 0x4c
+#define DW_AT_vtable_elem_location 0x4d
+#define DW_AT_allocated 0x4e /* DWARF3 */
+#define DW_AT_associated 0x4f /* DWARF3 */
+#define DW_AT_data_location 0x50 /* DWARF3 */
+#define DW_AT_byte_stride 0x51 /* DWARF3f */
+#define DW_AT_stride 0x51 /* DWARF3 (do not use) */
+#define DW_AT_entry_pc 0x52 /* DWARF3 */
+#define DW_AT_use_UTF8 0x53 /* DWARF3 */
+#define DW_AT_extension 0x54 /* DWARF3 */
+#define DW_AT_ranges 0x55 /* DWARF3 */
+#define DW_AT_trampoline 0x56 /* DWARF3 */
+#define DW_AT_call_column 0x57 /* DWARF3 */
+#define DW_AT_call_file 0x58 /* DWARF3 */
+#define DW_AT_call_line 0x59 /* DWARF3 */
+#define DW_AT_description 0x5a /* DWARF3 */
+#define DW_AT_binary_scale 0x5b /* DWARF3f */
+#define DW_AT_decimal_scale 0x5c /* DWARF3f */
+#define DW_AT_small 0x5d /* DWARF3f */
+#define DW_AT_decimal_sign 0x5e /* DWARF3f */
+#define DW_AT_digit_count 0x5f /* DWARF3f */
+#define DW_AT_picture_string 0x60 /* DWARF3f */
+#define DW_AT_mutable 0x61 /* DWARF3f */
+#define DW_AT_threads_scaled 0x62 /* DWARF3f */
+#define DW_AT_explicit 0x63 /* DWARF3f */
+#define DW_AT_object_pointer 0x64 /* DWARF3f */
+#define DW_AT_endianity 0x65 /* DWARF3f */
+#define DW_AT_elemental 0x66 /* DWARF3f */
+#define DW_AT_pure 0x67 /* DWARF3f */
+#define DW_AT_recursive 0x68 /* DWARF3f */
+#define DW_AT_signature 0x69 /* DWARF4 */
+#define DW_AT_main_subprogram 0x6a /* DWARF4 */
+#define DW_AT_data_bit_offset 0x6b /* DWARF4 */
+#define DW_AT_const_expr 0x6c /* DWARF4 */
+#define DW_AT_enum_class 0x6d /* DWARF4 */
+#define DW_AT_linkage_name 0x6e /* DWARF4 */
+
+/* In extensions, we attempt to include the vendor extension
+ in the name even when the vendor leaves it out. */
+
+/* HP extensions. */
+#define DW_AT_HP_block_index 0x2000 /* HP */
+
+/* Follows extension so dwarfdump prints the most-likely-useful name. */
+#define DW_AT_lo_user 0x2000
+
+#define DW_AT_MIPS_fde 0x2001 /* MIPS/SGI */
+#define DW_AT_MIPS_loop_begin 0x2002 /* MIPS/SGI */
+#define DW_AT_MIPS_tail_loop_begin 0x2003 /* MIPS/SGI */
+#define DW_AT_MIPS_epilog_begin 0x2004 /* MIPS/SGI */
+#define DW_AT_MIPS_loop_unroll_factor 0x2005 /* MIPS/SGI */
+#define DW_AT_MIPS_software_pipeline_depth 0x2006 /* MIPS/SGI */
+#define DW_AT_MIPS_linkage_name 0x2007 /* MIPS/SGI, GNU, and others.*/
+#define DW_AT_MIPS_stride 0x2008 /* MIPS/SGI */
+#define DW_AT_MIPS_abstract_name 0x2009 /* MIPS/SGI */
+#define DW_AT_MIPS_clone_origin 0x200a /* MIPS/SGI */
+#define DW_AT_MIPS_has_inlines 0x200b /* MIPS/SGI */
+#define DW_AT_MIPS_stride_byte 0x200c /* MIPS/SGI */
+#define DW_AT_MIPS_stride_elem 0x200d /* MIPS/SGI */
+#define DW_AT_MIPS_ptr_dopetype 0x200e /* MIPS/SGI */
+#define DW_AT_MIPS_allocatable_dopetype 0x200f /* MIPS/SGI */
+#define DW_AT_MIPS_assumed_shape_dopetype 0x2010 /* MIPS/SGI */
+#define DW_AT_MIPS_assumed_size 0x2011 /* MIPS/SGI */
+
+/* HP extensions. */
+#define DW_AT_HP_unmodifiable 0x2001 /* conflict: MIPS */
+#define DW_AT_HP_actuals_stmt_list 0x2010 /* conflict: MIPS */
+#define DW_AT_HP_proc_per_section 0x2011 /* conflict: MIPS */
+#define DW_AT_HP_raw_data_ptr 0x2012 /* HP */
+#define DW_AT_HP_pass_by_reference 0x2013 /* HP */
+#define DW_AT_HP_opt_level 0x2014 /* HP */
+#define DW_AT_HP_prof_version_id 0x2015 /* HP */
+#define DW_AT_HP_opt_flags 0x2016 /* HP */
+#define DW_AT_HP_cold_region_low_pc 0x2017 /* HP */
+#define DW_AT_HP_cold_region_high_pc 0x2018 /* HP */
+#define DW_AT_HP_all_variables_modifiable 0x2019 /* HP */
+#define DW_AT_HP_linkage_name 0x201a /* HP */
+#define DW_AT_HP_prof_flags 0x201b /* HP */
+
+#define DW_AT_CPQ_discontig_ranges 0x2001 /* COMPAQ/HP */
+#define DW_AT_CPQ_semantic_events 0x2002 /* COMPAQ/HP */
+#define DW_AT_CPQ_split_lifetimes_var 0x2003 /* COMPAQ/HP */
+#define DW_AT_CPQ_split_lifetimes_rtn 0x2004 /* COMPAQ/HP */
+#define DW_AT_CPQ_prologue_length 0x2005 /* COMPAQ/HP */
+
+#define DW_AT_INTEL_other_endian 0x2026 /* Intel, 1 if byte swapped. */
+
+/* GNU extensions. */
+#define DW_AT_sf_names 0x2101 /* GNU */
+#define DW_AT_src_info 0x2102 /* GNU */
+#define DW_AT_mac_info 0x2103 /* GNU */
+#define DW_AT_src_coords 0x2104 /* GNU */
+#define DW_AT_body_begin 0x2105 /* GNU */
+#define DW_AT_body_end 0x2106 /* GNU */
+#define DW_AT_GNU_vector 0x2107 /* GNU */
+
+/* Thread safety, see http://gcc.gnu.org/wiki/ThreadSafetyAnnotation . */
+/* The values here are from gcc-4.6.2 include/dwarf2.h. The
+ values are not given on the web page at all, nor on web pages
+ it refers to. */
+#define DW_AT_GNU_guarded_by 0x2108 /* GNU */
+#define DW_AT_GNU_pt_guarded_by 0x2109 /* GNU */
+#define DW_AT_GNU_guarded 0x210a /* GNU */
+#define DW_AT_GNU_pt_guarded 0x210b /* GNU */
+#define DW_AT_GNU_locks_excluded 0x210c /* GNU */
+#define DW_AT_GNU_exclusive_locks_required 0x210d /* GNU */
+#define DW_AT_GNU_shared_locks_required 0x210e /* GNU */
+
+/* See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo */
+#define DW_AT_GNU_odr_signature 0x210f /* GNU */
+
+/* See See http://gcc.gnu.org/wiki/TemplateParmsDwarf */
+/* The value here is from gcc-4.6.2 include/dwarf2.h. The value is
+ not consistent with the web page as of December 2011. */
+#define DW_AT_GNU_template_name 0x2110 /* GNU */
+/* The GNU call site extension.
+ See http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open . */
+#define DW_AT_GNU_call_site_value 0x2111 /* GNU */
+#define DW_AT_GNU_call_site_data_value 0x2112 /* GNU */
+#define DW_AT_GNU_call_site_target 0x2113 /* GNU */
+#define DW_AT_GNU_call_site_target_clobbered 0x2114 /* GNU */
+#define DW_AT_GNU_tail_call 0x2115 /* GNU */
+#define DW_AT_GNU_all_tail_call_sites 0x2116 /* GNU */
+#define DW_AT_GNU_all_call_sites 0x2117 /* GNU */
+#define DW_AT_GNU_all_source_call_sites 0x2118 /* GNU */
+
+
+
+/* ALTIUM extension: ALTIUM Compliant location lists (flag) */
+#define DW_AT_ALTIUM_loclist 0x2300 /* ALTIUM */
+
+/* Sun extensions */
+#define DW_AT_SUN_template 0x2201 /* SUN */
+#define DW_AT_VMS_rtnbeg_pd_address 0x2201 /* VMS */
+#define DW_AT_SUN_alignment 0x2202 /* SUN */
+#define DW_AT_SUN_vtable 0x2203 /* SUN */
+#define DW_AT_SUN_count_guarantee 0x2204 /* SUN */
+#define DW_AT_SUN_command_line 0x2205 /* SUN */
+#define DW_AT_SUN_vbase 0x2206 /* SUN */
+#define DW_AT_SUN_compile_options 0x2207 /* SUN */
+#define DW_AT_SUN_language 0x2208 /* SUN */
+#define DW_AT_SUN_browser_file 0x2209 /* SUN */
+#define DW_AT_SUN_vtable_abi 0x2210 /* SUN */
+#define DW_AT_SUN_func_offsets 0x2211 /* SUN */
+#define DW_AT_SUN_cf_kind 0x2212 /* SUN */
+#define DW_AT_SUN_vtable_index 0x2213 /* SUN */
+#define DW_AT_SUN_omp_tpriv_addr 0x2214 /* SUN */
+#define DW_AT_SUN_omp_child_func 0x2215 /* SUN */
+#define DW_AT_SUN_func_offset 0x2216 /* SUN */
+#define DW_AT_SUN_memop_type_ref 0x2217 /* SUN */
+#define DW_AT_SUN_profile_id 0x2218 /* SUN */
+#define DW_AT_SUN_memop_signature 0x2219 /* SUN */
+#define DW_AT_SUN_obj_dir 0x2220 /* SUN */
+#define DW_AT_SUN_obj_file 0x2221 /* SUN */
+#define DW_AT_SUN_original_name 0x2222 /* SUN */
+#define DW_AT_SUN_hwcprof_signature 0x2223 /* SUN */
+#define DW_AT_SUN_amd64_parmdump 0x2224 /* SUN */
+#define DW_AT_SUN_part_link_name 0x2225 /* SUN */
+#define DW_AT_SUN_link_name 0x2226 /* SUN */
+#define DW_AT_SUN_pass_with_const 0x2227 /* SUN */
+#define DW_AT_SUN_return_with_const 0x2228 /* SUN */
+#define DW_AT_SUN_import_by_name 0x2229 /* SUN */
+#define DW_AT_SUN_f90_pointer 0x222a /* SUN */
+#define DW_AT_SUN_pass_by_ref 0x222b /* SUN */
+#define DW_AT_SUN_f90_allocatable 0x222c /* SUN */
+#define DW_AT_SUN_f90_assumed_shape_array 0x222d /* SUN */
+#define DW_AT_SUN_c_vla 0x222e /* SUN */
+#define DW_AT_SUN_return_value_ptr 0x2230 /* SUN */
+#define DW_AT_SUN_dtor_start 0x2231 /* SUN */
+#define DW_AT_SUN_dtor_length 0x2232 /* SUN */
+#define DW_AT_SUN_dtor_state_initial 0x2233 /* SUN */
+#define DW_AT_SUN_dtor_state_final 0x2234 /* SUN */
+#define DW_AT_SUN_dtor_state_deltas 0x2235 /* SUN */
+#define DW_AT_SUN_import_by_lname 0x2236 /* SUN */
+#define DW_AT_SUN_f90_use_only 0x2237 /* SUN */
+#define DW_AT_SUN_namelist_spec 0x2238 /* SUN */
+#define DW_AT_SUN_is_omp_child_func 0x2239 /* SUN */
+#define DW_AT_SUN_fortran_main_alias 0x223a /* SUN */
+#define DW_AT_SUN_fortran_based 0x223b /* SUN */
+
+/* See http://gcc.gnu.org/wiki/DW_AT_GNAT_descriptive_type . */
+#define DW_AT_use_GNAT_descriptive_type 0x2301 /* GNAT */
+#define DW_AT_GNAT_descriptive_type 0x2302 /* GNAT */
+
+/* UPC extension */
+#define DW_AT_upc_threads_scaled 0x3210 /* UPC */
+
+/* PGI (STMicroelectronics) extensions. */
+#define DW_AT_PGI_lbase 0x3a00 /* PGI. Block, constant, reference. This attribute is an ASTPLAB extension used to describe the array local base. */
+#define DW_AT_PGI_soffset 0x3a01 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the section offset, or the offset to the first element in the dimension. */
+#define DW_AT_PGI_lstride 0x3a02 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the linear stride or the distance between elements in the dimension. */
+
+/* There are two groups of Apple extensions here, it is
+ unclear what exactly is correct. */
+#define DW_AT_APPLE_optimized 0x3fe1 /* Apple */
+#define DW_AT_APPLE_flags 0x3fe2 /* Apple */
+#define DW_AT_APPLE_isa 0x3fe3 /* Apple */
+#define DW_AT_APPLE_block 0x3fe4 /* Apple */
+#define DW_AT_APPLE_major_runtime_vers 0x3fe5 /* Apple */
+#define DW_AT_APPLE_runtime_class 0x3fe6 /* Apple */
+#define DW_AT_APPLE_omit_frame_ptr 0x3fe7 /* Apple */
+
+/* Apple Extensions for closures */
+#define DW_AT_APPLE_closure 0x3fe4 /* Apple */
+/* Apple Extensions for Objective-C runtime info */
+#define DW_AT_APPLE_major_runtime_vers 0x3fe5 /* Apple */
+#define DW_AT_APPLE_runtime_class 0x3fe6 /* Apple */
+
+
+#define DW_AT_hi_user 0x3fff
+
+#define DW_OP_addr 0x03
+#define DW_OP_deref 0x06
+#define DW_OP_const1u 0x08
+#define DW_OP_const1s 0x09
+#define DW_OP_const2u 0x0a
+#define DW_OP_const2s 0x0b
+#define DW_OP_const4u 0x0c
+#define DW_OP_const4s 0x0d
+#define DW_OP_const8u 0x0e
+#define DW_OP_const8s 0x0f
+#define DW_OP_constu 0x10
+#define DW_OP_consts 0x11
+#define DW_OP_dup 0x12
+#define DW_OP_drop 0x13
+#define DW_OP_over 0x14
+#define DW_OP_pick 0x15
+#define DW_OP_swap 0x16
+#define DW_OP_rot 0x17
+#define DW_OP_xderef 0x18
+#define DW_OP_abs 0x19
+#define DW_OP_and 0x1a
+#define DW_OP_div 0x1b
+#define DW_OP_minus 0x1c
+#define DW_OP_mod 0x1d
+#define DW_OP_mul 0x1e
+#define DW_OP_neg 0x1f
+#define DW_OP_not 0x20
+#define DW_OP_or 0x21
+#define DW_OP_plus 0x22
+#define DW_OP_plus_uconst 0x23
+#define DW_OP_shl 0x24
+#define DW_OP_shr 0x25
+#define DW_OP_shra 0x26
+#define DW_OP_xor 0x27
+#define DW_OP_bra 0x28
+#define DW_OP_eq 0x29
+#define DW_OP_ge 0x2a
+#define DW_OP_gt 0x2b
+#define DW_OP_le 0x2c
+#define DW_OP_lt 0x2d
+#define DW_OP_ne 0x2e
+#define DW_OP_skip 0x2f
+#define DW_OP_lit0 0x30
+#define DW_OP_lit1 0x31
+#define DW_OP_lit2 0x32
+#define DW_OP_lit3 0x33
+#define DW_OP_lit4 0x34
+#define DW_OP_lit5 0x35
+#define DW_OP_lit6 0x36
+#define DW_OP_lit7 0x37
+#define DW_OP_lit8 0x38
+#define DW_OP_lit9 0x39
+#define DW_OP_lit10 0x3a
+#define DW_OP_lit11 0x3b
+#define DW_OP_lit12 0x3c
+#define DW_OP_lit13 0x3d
+#define DW_OP_lit14 0x3e
+#define DW_OP_lit15 0x3f
+#define DW_OP_lit16 0x40
+#define DW_OP_lit17 0x41
+#define DW_OP_lit18 0x42
+#define DW_OP_lit19 0x43
+#define DW_OP_lit20 0x44
+#define DW_OP_lit21 0x45
+#define DW_OP_lit22 0x46
+#define DW_OP_lit23 0x47
+#define DW_OP_lit24 0x48
+#define DW_OP_lit25 0x49
+#define DW_OP_lit26 0x4a
+#define DW_OP_lit27 0x4b
+#define DW_OP_lit28 0x4c
+#define DW_OP_lit29 0x4d
+#define DW_OP_lit30 0x4e
+#define DW_OP_lit31 0x4f
+#define DW_OP_reg0 0x50
+#define DW_OP_reg1 0x51
+#define DW_OP_reg2 0x52
+#define DW_OP_reg3 0x53
+#define DW_OP_reg4 0x54
+#define DW_OP_reg5 0x55
+#define DW_OP_reg6 0x56
+#define DW_OP_reg7 0x57
+#define DW_OP_reg8 0x58
+#define DW_OP_reg9 0x59
+#define DW_OP_reg10 0x5a
+#define DW_OP_reg11 0x5b
+#define DW_OP_reg12 0x5c
+#define DW_OP_reg13 0x5d
+#define DW_OP_reg14 0x5e
+#define DW_OP_reg15 0x5f
+#define DW_OP_reg16 0x60
+#define DW_OP_reg17 0x61
+#define DW_OP_reg18 0x62
+#define DW_OP_reg19 0x63
+#define DW_OP_reg20 0x64
+#define DW_OP_reg21 0x65
+#define DW_OP_reg22 0x66
+#define DW_OP_reg23 0x67
+#define DW_OP_reg24 0x68
+#define DW_OP_reg25 0x69
+#define DW_OP_reg26 0x6a
+#define DW_OP_reg27 0x6b
+#define DW_OP_reg28 0x6c
+#define DW_OP_reg29 0x6d
+#define DW_OP_reg30 0x6e
+#define DW_OP_reg31 0x6f
+#define DW_OP_breg0 0x70
+#define DW_OP_breg1 0x71
+#define DW_OP_breg2 0x72
+#define DW_OP_breg3 0x73
+#define DW_OP_breg4 0x74
+#define DW_OP_breg5 0x75
+#define DW_OP_breg6 0x76
+#define DW_OP_breg7 0x77
+#define DW_OP_breg8 0x78
+#define DW_OP_breg9 0x79
+#define DW_OP_breg10 0x7a
+#define DW_OP_breg11 0x7b
+#define DW_OP_breg12 0x7c
+#define DW_OP_breg13 0x7d
+#define DW_OP_breg14 0x7e
+#define DW_OP_breg15 0x7f
+#define DW_OP_breg16 0x80
+#define DW_OP_breg17 0x81
+#define DW_OP_breg18 0x82
+#define DW_OP_breg19 0x83
+#define DW_OP_breg20 0x84
+#define DW_OP_breg21 0x85
+#define DW_OP_breg22 0x86
+#define DW_OP_breg23 0x87
+#define DW_OP_breg24 0x88
+#define DW_OP_breg25 0x89
+#define DW_OP_breg26 0x8a
+#define DW_OP_breg27 0x8b
+#define DW_OP_breg28 0x8c
+#define DW_OP_breg29 0x8d
+#define DW_OP_breg30 0x8e
+#define DW_OP_breg31 0x8f
+#define DW_OP_regx 0x90
+#define DW_OP_fbreg 0x91
+#define DW_OP_bregx 0x92
+#define DW_OP_piece 0x93
+#define DW_OP_deref_size 0x94
+#define DW_OP_xderef_size 0x95
+#define DW_OP_nop 0x96
+#define DW_OP_push_object_address 0x97 /* DWARF3 */
+#define DW_OP_call2 0x98 /* DWARF3 */
+#define DW_OP_call4 0x99 /* DWARF3 */
+#define DW_OP_call_ref 0x9a /* DWARF3 */
+#define DW_OP_form_tls_address 0x9b /* DWARF3f */
+#define DW_OP_call_frame_cfa 0x9c /* DWARF3f */
+#define DW_OP_bit_piece 0x9d /* DWARF3f */
+#define DW_OP_implicit_value 0x9e /* DWARF4 */
+#define DW_OP_stack_value 0x9f /* DWARF4 */
+
+
+ /* GNU extensions. */
+#define DW_OP_GNU_push_tls_address 0xe0 /* GNU */
+
+/* Follows extension so dwarfdump prints the most-likely-useful name. */
+#define DW_OP_lo_user 0xe0
+
+
+#define DW_OP_GNU_uninit 0xf0 /* GNU */
+#define DW_OP_GNU_encoded_addr 0xf1 /* GNU */
+#define DW_OP_GNU_implicit_pointer 0xf2 /* GNU */
+#define DW_OP_GNU_entry_value 0xf3 /* GNU */
+
+ /* HP extensions. */
+#define DW_OP_HP_unknown 0xe0 /* HP conflict: GNU */
+#define DW_OP_HP_is_value 0xe1 /* HP */
+#define DW_OP_HP_fltconst4 0xe2 /* HP */
+#define DW_OP_HP_fltconst8 0xe3 /* HP */
+#define DW_OP_HP_mod_range 0xe4 /* HP */
+#define DW_OP_HP_unmod_range 0xe5 /* HP */
+#define DW_OP_HP_tls 0xe6 /* HP */
+
+#define DW_OP_INTEL_bit_piece 0xe8 /* Intel: made obsolete by DW_OP_bit_piece above. */
+
+ /* Apple extension. */
+#define DW_OP_APPLE_uninit 0xf0 /* Apple */
+#define DW_OP_PGI_omp_thread_num 0xf8 /* PGI (STMicroelectronics) */
+
+#define DW_OP_hi_user 0xff
+
+#define DW_ATE_address 0x1
+#define DW_ATE_boolean 0x2
+#define DW_ATE_complex_float 0x3
+#define DW_ATE_float 0x4
+#define DW_ATE_signed 0x5
+#define DW_ATE_signed_char 0x6
+#define DW_ATE_unsigned 0x7
+#define DW_ATE_unsigned_char 0x8
+#define DW_ATE_imaginary_float 0x9 /* DWARF3 */
+#define DW_ATE_packed_decimal 0xa /* DWARF3f */
+#define DW_ATE_numeric_string 0xb /* DWARF3f */
+#define DW_ATE_edited 0xc /* DWARF3f */
+#define DW_ATE_signed_fixed 0xd /* DWARF3f */
+#define DW_ATE_unsigned_fixed 0xe /* DWARF3f */
+#define DW_ATE_decimal_float 0xf /* DWARF3f */
+
+
+/* ALTIUM extensions. x80, x81 */
+#define DW_ATE_ALTIUM_fract 0x80 /* ALTIUM __fract type */
+
+/* Follows extension so dwarfdump prints the most-likely-useful name. */
+#define DW_ATE_lo_user 0x80
+
+/* Shown here to help dwarfdump build script. */
+#define DW_ATE_ALTIUM_accum 0x81 /* ALTIUM __accum type */
+
+/* HP Floating point extensions. */
+#define DW_ATE_HP_float80 0x80 /* (80 bit). HP */
+
+
+#define DW_ATE_HP_complex_float80 0x81 /* Complex (80 bit). HP */
+#define DW_ATE_HP_float128 0x82 /* (128 bit). HP */
+#define DW_ATE_HP_complex_float128 0x83 /* Complex (128 bit). HP */
+#define DW_ATE_HP_floathpintel 0x84 /* (82 bit IA64). HP */
+#define DW_ATE_HP_imaginary_float80 0x85 /* HP */
+#define DW_ATE_HP_imaginary_float128 0x86 /* HP */
+
+/* Sun extensions */
+#define DW_ATE_SUN_interval_float 0x91
+#define DW_ATE_SUN_imaginary_float 0x92 /* Obsolete: See DW_ATE_imaginary_float */
+
+#define DW_ATE_hi_user 0xff
+
+
+/* Decimal Sign codes. */
+#define DW_DS_unsigned 0x01 /* DWARF3f */
+#define DW_DS_leading_overpunch 0x02 /* DWARF3f */
+#define DW_DS_trailing_overpunch 0x03 /* DWARF3f */
+#define DW_DS_leading_separate 0x04 /* DWARF3f */
+
+#define DW_DS_trailing_separate 0x05 /* DWARF3f */
+
+/* Endian code name. */
+#define DW_END_default 0x00 /* DWARF3f */
+#define DW_END_big 0x01 /* DWARF3f */
+#define DW_END_little 0x02 /* DWARF3f */
+
+#define DW_END_lo_user 0x40 /* DWARF3f */
+#define DW_END_hi_user 0xff /* DWARF3f */
+
+/* For use with DW_TAG_SUN_codeflags
+ If DW_TAG_SUN_codeflags is accepted as a dwarf standard, then
+ standard dwarf ATCF entries start at 0x01 */
+#define DW_ATCF_lo_user 0x40 /* SUN */
+#define DW_ATCF_SUN_mop_bitfield 0x41 /* SUN */
+#define DW_ATCF_SUN_mop_spill 0x42 /* SUN */
+#define DW_ATCF_SUN_mop_scopy 0x43 /* SUN */
+#define DW_ATCF_SUN_func_start 0x44 /* SUN */
+#define DW_ATCF_SUN_end_ctors 0x45 /* SUN */
+#define DW_ATCF_SUN_branch_target 0x46 /* SUN */
+#define DW_ATCF_SUN_mop_stack_probe 0x47 /* SUN */
+#define DW_ATCF_SUN_func_epilog 0x48 /* SUN */
+#define DW_ATCF_hi_user 0xff /* SUN */
+
+/* Accessibility code name. */
+#define DW_ACCESS_public 0x01
+#define DW_ACCESS_protected 0x02
+#define DW_ACCESS_private 0x03
+
+/* Visibility code name. */
+#define DW_VIS_local 0x01
+#define DW_VIS_exported 0x02
+#define DW_VIS_qualified 0x03
+
+/* Virtuality code name. */
+#define DW_VIRTUALITY_none 0x00
+#define DW_VIRTUALITY_virtual 0x01
+#define DW_VIRTUALITY_pure_virtual 0x02
+
+#define DW_LANG_C89 0x0001
+#define DW_LANG_C 0x0002
+#define DW_LANG_Ada83 0x0003
+#define DW_LANG_C_plus_plus 0x0004
+#define DW_LANG_Cobol74 0x0005
+#define DW_LANG_Cobol85 0x0006
+#define DW_LANG_Fortran77 0x0007
+#define DW_LANG_Fortran90 0x0008
+#define DW_LANG_Pascal83 0x0009
+#define DW_LANG_Modula2 0x000a
+#define DW_LANG_Java 0x000b /* DWARF3 */
+#define DW_LANG_C99 0x000c /* DWARF3 */
+#define DW_LANG_Ada95 0x000d /* DWARF3 */
+#define DW_LANG_Fortran95 0x000e /* DWARF3 */
+#define DW_LANG_PLI 0x000f /* DWARF3 */
+#define DW_LANG_ObjC 0x0010 /* DWARF3f */
+#define DW_LANG_ObjC_plus_plus 0x0011 /* DWARF3f */
+#define DW_LANG_UPC 0x0012 /* DWARF3f */
+#define DW_LANG_D 0x0013 /* DWARF3f */
+#define DW_LANG_Python 0x0014 /* DWARF4 */
+/* The following 2 are not yet formally approved October 2010, but
+ it seems extremely likely they will be approved as the committee
+ chair agrees these should be ok and no one on the committee
+ has objected. */
+#define DW_LANG_OpenCL 0x0015 /* Provisionally DWARF5 */
+#define DW_LANG_Go 0x0016 /* Provisionally DWARF5 */
+#define DW_LANG_lo_user 0x8000
+#define DW_LANG_Mips_Assembler 0x8001 /* MIPS */
+#define DW_LANG_Upc 0x8765 /* UPC, use
+ DW_LANG_UPC instead. */
+/* ALTIUM extension */
+#define DW_LANG_ALTIUM_Assembler 0x9101 /* ALTIUM */
+
+/* Sun extensions */
+#define DW_LANG_SUN_Assembler 0x9001 /* SUN */
+
+#define DW_LANG_hi_user 0xffff
+
+/* Identifier case name. */
+#define DW_ID_case_sensitive 0x00
+#define DW_ID_up_case 0x01
+#define DW_ID_down_case 0x02
+#define DW_ID_case_insensitive 0x03
+
+/* Calling Convention Name. */
+#define DW_CC_normal 0x01
+#define DW_CC_program 0x02
+#define DW_CC_nocall 0x03
+#define DW_CC_lo_user 0x40
+
+#define DW_CC_GNU_renesas_sh 0x40 /* GNU */
+#define DW_CC_GNU_borland_fastcall_i386 0x41 /* GNU */
+
+
+
+/* ALTIUM extensions. */
+/* Function is an interrupt handler, return address on system stack. */
+#define DW_CC_ALTIUM_interrupt 0x65 /* ALTIUM*/
+
+/* Near function model, return address on system stack. */
+#define DW_CC_ALTIUM_near_system_stack 0x66 /*ALTIUM */
+
+/* Near function model, return address on user stack. */
+#define DW_CC_ALTIUM_near_user_stack 0x67 /* ALTIUM */
+
+/* Huge function model, return address on user stack. */
+#define DW_CC_ALTIUM_huge_user_stack 0x68 /* ALTIUM */
+
+
+#define DW_CC_hi_user 0xff
+
+/* Inline Code Name. */
+#define DW_INL_not_inlined 0x00
+#define DW_INL_inlined 0x01
+#define DW_INL_declared_not_inlined 0x02
+#define DW_INL_declared_inlined 0x03
+
+/* Ordering Name. */
+#define DW_ORD_row_major 0x00
+#define DW_ORD_col_major 0x01
+
+/* Discriminant Descriptor Name. */
+#define DW_DSC_label 0x00
+#define DW_DSC_range 0x01
+
+/* Line number standard opcode name. */
+#define DW_LNS_copy 0x01
+#define DW_LNS_advance_pc 0x02
+#define DW_LNS_advance_line 0x03
+#define DW_LNS_set_file 0x04
+#define DW_LNS_set_column 0x05
+#define DW_LNS_negate_stmt 0x06
+#define DW_LNS_set_basic_block 0x07
+#define DW_LNS_const_add_pc 0x08
+#define DW_LNS_fixed_advance_pc 0x09
+#define DW_LNS_set_prologue_end 0x0a /* DWARF3 */
+#define DW_LNS_set_epilogue_begin 0x0b /* DWARF3 */
+#define DW_LNS_set_isa 0x0c /* DWARF3 */
+
+/* Line number extended opcode name. */
+#define DW_LNE_end_sequence 0x01
+#define DW_LNE_set_address 0x02
+#define DW_LNE_define_file 0x03
+#define DW_LNE_set_discriminator 0x04 /* DWARF4 */
+
+/* HP extensions. */
+#define DW_LNE_HP_negate_is_UV_update 0x11 /* 17 HP */
+#define DW_LNE_HP_push_context 0x12 /* 18 HP */
+#define DW_LNE_HP_pop_context 0x13 /* 19 HP */
+#define DW_LNE_HP_set_file_line_column 0x14 /* 20 HP */
+#define DW_LNE_HP_set_routine_name 0x15 /* 21 HP */
+#define DW_LNE_HP_set_sequence 0x16 /* 22 HP */
+#define DW_LNE_HP_negate_post_semantics 0x17 /* 23 HP */
+#define DW_LNE_HP_negate_function_exit 0x18 /* 24 HP */
+#define DW_LNE_HP_negate_front_end_logical 0x19 /* 25 HP */
+#define DW_LNE_HP_define_proc 0x20 /* 32 HP */
+
+#define DW_LNE_HP_source_file_correlation 0x80 /* HP */
+#define DW_LNE_lo_user 0x80 /* DWARF3 */
+#define DW_LNE_hi_user 0xff /* DWARF3 */
+
+/* These are known values for DW_LNS_set_isa. */
+#define DW_ISA_UNKNOWN 0
+/* The following two are ARM specific. */
+#define DW_ISA_ARM_thumb 1 /* ARM ISA */
+#define DW_ISA_ARM_arm 2 /* ARM ISA */
+
+/* Macro information. */
+#define DW_MACINFO_define 0x01
+#define DW_MACINFO_undef 0x02
+#define DW_MACINFO_start_file 0x03
+#define DW_MACINFO_end_file 0x04
+#define DW_MACINFO_vendor_ext 0xff
+
+/* CFA operator compaction (a space saving measure, see
+ the DWARF standard) means DW_CFA_extended and DW_CFA_nop
+ have the same value here. */
+#define DW_CFA_advance_loc 0x40
+#define DW_CFA_offset 0x80
+#define DW_CFA_restore 0xc0
+#define DW_CFA_extended 0
+
+#define DW_CFA_nop 0x00
+#define DW_CFA_set_loc 0x01
+#define DW_CFA_advance_loc1 0x02
+#define DW_CFA_advance_loc2 0x03
+#define DW_CFA_advance_loc4 0x04
+#define DW_CFA_offset_extended 0x05
+#define DW_CFA_restore_extended 0x06
+#define DW_CFA_undefined 0x07
+#define DW_CFA_same_value 0x08
+#define DW_CFA_register 0x09
+#define DW_CFA_remember_state 0x0a
+#define DW_CFA_restore_state 0x0b
+#define DW_CFA_def_cfa 0x0c
+#define DW_CFA_def_cfa_register 0x0d
+#define DW_CFA_def_cfa_offset 0x0e
+#define DW_CFA_def_cfa_expression 0x0f /* DWARF3 */
+#define DW_CFA_expression 0x10 /* DWARF3 */
+#define DW_CFA_offset_extended_sf 0x11 /* DWARF3 */
+#define DW_CFA_def_cfa_sf 0x12 /* DWARF3 */
+#define DW_CFA_def_cfa_offset_sf 0x13 /* DWARF3 */
+#define DW_CFA_val_offset 0x14 /* DWARF3f */
+#define DW_CFA_val_offset_sf 0x15 /* DWARF3f */
+#define DW_CFA_val_expression 0x16 /* DWARF3f */
+
+#define DW_CFA_lo_user 0x1c
+#define DW_CFA_low_user 0x1c /* Incorrect spelling, do not use. */
+
+/* SGI/MIPS extension. */
+#define DW_CFA_MIPS_advance_loc8 0x1d /* MIPS */
+
+/* GNU extensions. */
+#define DW_CFA_GNU_window_save 0x2d /* GNU */
+#define DW_CFA_GNU_args_size 0x2e /* GNU */
+#define DW_CFA_GNU_negative_offset_extended 0x2f /* GNU */
+
+#define DW_CFA_high_user 0x3f
+
+/* GNU exception header encoding. See the Generic
+ Elf Specification of the Linux Standard Base (LSB).
+ http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
+ The upper 4 bits indicate how the value is to be applied.
+ The lower 4 bits indicate the format of the data.
+*/
+#define DW_EH_PE_absptr 0x00 /* GNU */
+#define DW_EH_PE_uleb128 0x01 /* GNU */
+#define DW_EH_PE_udata2 0x02 /* GNU */
+#define DW_EH_PE_udata4 0x03 /* GNU */
+#define DW_EH_PE_udata8 0x04 /* GNU */
+#define DW_EH_PE_sleb128 0x09 /* GNU */
+#define DW_EH_PE_sdata2 0x0A /* GNU */
+#define DW_EH_PE_sdata4 0x0B /* GNU */
+#define DW_EH_PE_sdata8 0x0C /* GNU */
+
+#define DW_EH_PE_pcrel 0x10 /* GNU */
+#define DW_EH_PE_textrel 0x20 /* GNU */
+#define DW_EH_PE_datarel 0x30 /* GNU */
+#define DW_EH_PE_funcrel 0x40 /* GNU */
+#define DW_EH_PE_aligned 0x50 /* GNU */
+
+#define DW_EH_PE_omit 0xff /* GNU. Means no value present. */
+
+
+/* Mapping from machine registers and pseudo-regs into the
+ .debug_frame table. DW_FRAME entries are machine specific.
+ These describe MIPS/SGI R3000, R4K, R4400 and all later
+ MIPS/SGI IRIX machines. They describe a mapping from
+ hardware register number to the number used in the table
+ to identify that register.
+
+ The CFA (Canonical Frame Address) described in DWARF is
+ called the Virtual Frame Pointer on MIPS/SGI machines.
+
+ The DW_FRAME* names here are MIPS/SGI specific.
+ Libdwarf interfaces defined in 2008 make the
+ frame definitions here (and the fixed table sizes
+ they imply) obsolete. They are left here for compatibility.
+*/
+/* Default column used for CFA in the libdwarf reader client.
+ Assumes reg 0 never appears as
+ a register in DWARF information. Usable for MIPS,
+ but never a good idea, really. */
+#define DW_FRAME_CFA_COL 0
+
+#define DW_FRAME_REG1 1 /* integer reg 1 */
+#define DW_FRAME_REG2 2 /* integer reg 2 */
+#define DW_FRAME_REG3 3 /* integer reg 3 */
+#define DW_FRAME_REG4 4 /* integer reg 4 */
+#define DW_FRAME_REG5 5 /* integer reg 5 */
+#define DW_FRAME_REG6 6 /* integer reg 6 */
+#define DW_FRAME_REG7 7 /* integer reg 7 */
+#define DW_FRAME_REG8 8 /* integer reg 8 */
+#define DW_FRAME_REG9 9 /* integer reg 9 */
+#define DW_FRAME_REG10 10 /* integer reg 10 */
+#define DW_FRAME_REG11 11 /* integer reg 11 */
+#define DW_FRAME_REG12 12 /* integer reg 12 */
+#define DW_FRAME_REG13 13 /* integer reg 13 */
+#define DW_FRAME_REG14 14 /* integer reg 14 */
+#define DW_FRAME_REG15 15 /* integer reg 15 */
+#define DW_FRAME_REG16 16 /* integer reg 16 */
+#define DW_FRAME_REG17 17 /* integer reg 17 */
+#define DW_FRAME_REG18 18 /* integer reg 18 */
+#define DW_FRAME_REG19 19 /* integer reg 19 */
+#define DW_FRAME_REG20 20 /* integer reg 20 */
+#define DW_FRAME_REG21 21 /* integer reg 21 */
+#define DW_FRAME_REG22 22 /* integer reg 22 */
+#define DW_FRAME_REG23 23 /* integer reg 23 */
+#define DW_FRAME_REG24 24 /* integer reg 24 */
+#define DW_FRAME_REG25 25 /* integer reg 25 */
+#define DW_FRAME_REG26 26 /* integer reg 26 */
+#define DW_FRAME_REG27 27 /* integer reg 27 */
+#define DW_FRAME_REG28 28 /* integer reg 28 */
+#define DW_FRAME_REG29 29 /* integer reg 29 */
+#define DW_FRAME_REG30 30 /* integer reg 30 */
+#define DW_FRAME_REG31 31 /* integer reg 31, aka ra */
+
+ /* MIPS1, 2 have only some of these 64-bit registers.
+ ** MIPS1 save/restore takes 2 instructions per 64-bit reg, and
+ ** in that case, the register is considered stored after the second
+ ** swc1.
+ */
+#define DW_FRAME_FREG0 32 /* 64-bit floating point reg 0 */
+#define DW_FRAME_FREG1 33 /* 64-bit floating point reg 1 */
+#define DW_FRAME_FREG2 34 /* 64-bit floating point reg 2 */
+#define DW_FRAME_FREG3 35 /* 64-bit floating point reg 3 */
+#define DW_FRAME_FREG4 36 /* 64-bit floating point reg 4 */
+#define DW_FRAME_FREG5 37 /* 64-bit floating point reg 5 */
+#define DW_FRAME_FREG6 38 /* 64-bit floating point reg 6 */
+#define DW_FRAME_FREG7 39 /* 64-bit floating point reg 7 */
+#define DW_FRAME_FREG8 40 /* 64-bit floating point reg 8 */
+#define DW_FRAME_FREG9 41 /* 64-bit floating point reg 9 */
+#define DW_FRAME_FREG10 42 /* 64-bit floating point reg 10 */
+#define DW_FRAME_FREG11 43 /* 64-bit floating point reg 11 */
+#define DW_FRAME_FREG12 44 /* 64-bit floating point reg 12 */
+#define DW_FRAME_FREG13 45 /* 64-bit floating point reg 13 */
+#define DW_FRAME_FREG14 46 /* 64-bit floating point reg 14 */
+#define DW_FRAME_FREG15 47 /* 64-bit floating point reg 15 */
+#define DW_FRAME_FREG16 48 /* 64-bit floating point reg 16 */
+#define DW_FRAME_FREG17 49 /* 64-bit floating point reg 17 */
+#define DW_FRAME_FREG18 50 /* 64-bit floating point reg 18 */
+#define DW_FRAME_FREG19 51 /* 64-bit floating point reg 19 */
+#define DW_FRAME_FREG20 52 /* 64-bit floating point reg 20 */
+#define DW_FRAME_FREG21 53 /* 64-bit floating point reg 21 */
+#define DW_FRAME_FREG22 54 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG23 55 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG24 56 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG25 57 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG26 58 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG27 59 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG28 60 /* 64-bit floating point reg 28 */
+#define DW_FRAME_FREG29 61 /* 64-bit floating point reg 29 */
+#define DW_FRAME_FREG30 62 /* 64-bit floating point reg 30 */
+#define DW_FRAME_FREG31 63 /* 64-bit floating point reg 31 */
+
+#define DW_FRAME_FREG32 64 /* 64-bit floating point reg 18 */
+#define DW_FRAME_FREG33 65 /* 64-bit floating point reg 19 */
+#define DW_FRAME_FREG34 66 /* 64-bit floating point reg 20 */
+#define DW_FRAME_FREG35 67 /* 64-bit floating point reg 21 */
+#define DW_FRAME_FREG36 68 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG37 69 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG38 70 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG39 71 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG40 72 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG41 73 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG42 74 /* 64-bit floating point reg 28 */
+#define DW_FRAME_FREG43 75 /* 64-bit floating point reg 29 */
+#define DW_FRAME_FREG44 76 /* 64-bit floating point reg 30 */
+#define DW_FRAME_FREG45 77 /* 64-bit floating point reg 31 */
+#define DW_FRAME_FREG46 78 /* 64-bit floating point reg 18 */
+#define DW_FRAME_FREG47 79 /* 64-bit floating point reg 19 */
+#define DW_FRAME_FREG48 80 /* 64-bit floating point reg 20 */
+#define DW_FRAME_FREG49 81 /* 64-bit floating point reg 21 */
+#define DW_FRAME_FREG50 82 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG51 83 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG52 84 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG53 85 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG54 86 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG55 87 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG56 88 /* 64-bit floating point reg 28 */
+#define DW_FRAME_FREG57 89 /* 64-bit floating point reg 29 */
+#define DW_FRAME_FREG58 90 /* 64-bit floating point reg 30 */
+#define DW_FRAME_FREG59 91 /* 64-bit floating point reg 31 */
+#define DW_FRAME_FREG60 92 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG61 93 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG62 94 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG63 95 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG64 96 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG65 97 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG66 98 /* 64-bit floating point reg 28 */
+#define DW_FRAME_FREG67 99 /* 64-bit floating point reg 29 */
+#define DW_FRAME_FREG68 100 /* 64-bit floating point reg 30 */
+#define DW_FRAME_FREG69 101 /* 64-bit floating point reg 31 */
+#define DW_FRAME_FREG70 102 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG71 103 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG72 104 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG73 105 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG74 106 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG75 107 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG76 108 /* 64-bit floating point reg 28 */
+
+
+/* ***IMPORTANT NOTE, TARGET DEPENDENCY ****
+ The following 4 #defines are dependent on
+ the target cpu(s) that you apply libdwarf to.
+ Ensure that DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL
+ do not conflict with the range [0-DW_FRAME_STATIC_LINK].
+ The value 63 works for MIPS cpus at least up to the R16000.
+
+ For a cpu with more than 63 real registers
+ DW_FRAME_HIGHEST_NORMAL_REGISTER
+ must be increased for things to work properly!
+ Also ensure that DW_FRAME_UNDEFINED_VAL DW_FRAME_SAME_VAL
+ are not in the range [0-DW_FRAME_STATIC_LINK]
+
+ Having DW_FRAME_HIGHEST_NORMAL_REGISTER be higher than
+ is strictly needed is safe.
+
+*/
+
+#ifndef DW_FRAME_HIGHEST_NORMAL_REGISTER
+#define DW_FRAME_HIGHEST_NORMAL_REGISTER 188
+#endif
+/* This is the number of columns in the Frame Table.
+ This constant should
+ be kept in sync with DW_REG_TABLE_SIZE defined in libdwarf.h
+ It must also be large enough to be beyond the highest
+ compiler-defined-register (meaning DW_FRAME_RA_COL DW_FRAME_STATIC_LINK
+ in the MIPS/IRIX case */
+#ifndef DW_FRAME_LAST_REG_NUM
+#define DW_FRAME_LAST_REG_NUM (DW_FRAME_HIGHEST_NORMAL_REGISTER + 3)
+#endif
+
+
+/* Column recording ra (return address from a function call).
+ This is common to many architectures, but as a 'simple register'
+ is not necessarily adequate for all architectures.
+ For MIPS/IRIX this register number is actually recorded on disk
+ in the .debug_frame section.
+ */
+#define DW_FRAME_RA_COL (DW_FRAME_HIGHEST_NORMAL_REGISTER + 1)
+
+/* Column recording static link applicable to up-level
+ addressing, as in IRIX mp code, pascal, etc.
+ This is common to many architectures but
+ is not necessarily adequate for all architectures.
+ For MIPS/IRIX this register number is actually recorded on disk
+ in the .debug_frame section.
+*/
+#define DW_FRAME_STATIC_LINK (DW_FRAME_HIGHEST_NORMAL_REGISTER + 2)
+
+
+
+/*
+ DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL are
+ never on disk, just generated by libdwarf. See libdwarf.h
+ for their values.
+*/
+
+
+
+#define DW_CHILDREN_no 0x00
+#define DW_CHILDREN_yes 0x01
+
+#define DW_ADDR_none 0
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __DWARF_H */
diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp
new file mode 100644
index 0000000..17afb65
--- /dev/null
+++ b/src/dwarf2pdb.cpp
@@ -0,0 +1,1690 @@
+// Convert DMD CodeView/DWARF debug information to PDB files
+// Copyright (c) 2009-2012 by Rainer Schuetze, All Rights Reserved
+//
+// License for redistribution is given by the Artistic License 2.0
+// see file LICENSE for further details
+//
+// todo:
+// tls vars
+// display associative array
+// 64 bit:
+// - arguments passed by register
+// - real
+
+#include "cv2pdb.h"
+#include "PEImage.h"
+#include "symutil.h"
+#include "cvutil.h"
+
+#include "dwarf.h"
+
+#include <assert.h>
+#include <string>
+#include <vector>
+
+///////////////////////////////////////////////////////////////////////////////
+
+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;
+}
+
+unsigned int LEB128(unsigned char* base, int& off)
+{
+ unsigned char* p = base + off;
+ unsigned int x = LEB128(p);
+ off = p - base;
+ return x;
+}
+
+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;
+}
+
+unsigned int RD2(unsigned char* p)
+{
+ unsigned int x = *p++;
+ x |= *p++ << 8;
+ return x;
+}
+
+unsigned int RD4(unsigned char* p)
+{
+ unsigned int x = *p++;
+ x |= *p++ << 8;
+ x |= *p++ << 16;
+ x |= *p++ << 24;
+ return x;
+}
+
+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;
+}
+
+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* 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 long location; // first 8 bytes
+ unsigned long long member_location; // first 8 bytes
+ unsigned long locationlist; // offset into debug_loc
+ long frame_base;
+ long upper_bound;
+ long lower_bound;
+};
+
+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, int &id, int& size)
+{
+ unsigned char* p = loc;
+ int stackDepth = 0;
+ long data = 0;
+ do
+ {
+ int op = *p++;
+ id = -1;
+ size = 0;
+
+ switch(op)
+ {
+ case DW_OP_addr: id = S_GDATA_V2; size = 4; data = RD4(p); break;
+ case DW_OP_fbreg: id = S_BPREL_V2; data = SLEB128(p); break;
+ case DW_OP_const1u: id = S_CONSTANT_V2; size = 1; data = *p; break;
+ case DW_OP_const2u: id = S_CONSTANT_V2; size = 2; data = RD2(p); break;
+ case DW_OP_const4u: id = S_CONSTANT_V2; size = 4; data = RD4(p); break;
+ case DW_OP_const1s: id = S_CONSTANT_V2; size = 1; data = (char)*p; break;
+ case DW_OP_const2s: id = S_CONSTANT_V2; size = 2; data = (short)RD2(p); break;
+ case DW_OP_const4s: id = S_CONSTANT_V2; size = 4; data = (int)RD4(p); break;
+ case DW_OP_constu: id = S_CONSTANT_V2; data = LEB128(p); break;
+ case DW_OP_consts: id = S_CONSTANT_V2; data = SLEB128(p); break;
+ case DW_OP_plus_uconst: id = S_CONSTANT_V2; data = LEB128(p); break;
+ case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3:
+ case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7:
+ case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11:
+ case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15:
+ case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19:
+ case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23:
+ case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27:
+ case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31:
+ id = S_CONSTANT_V2;
+ data = op - DW_OP_lit0;
+ break;
+ case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3:
+ case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7:
+ case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11:
+ case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15:
+ case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19:
+ case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23:
+ case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27:
+ case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31:
+ id = S_REGISTER_V2;
+ break;
+ case DW_OP_regx:
+ id = S_REGISTER_V2;
+ data = LEB128(p); // reg
+ break;
+ case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3:
+ case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7:
+ case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11:
+ case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15:
+ case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19:
+ case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23:
+ case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27:
+ case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31:
+ id = S_REGISTER_V2;
+ data = SLEB128(p);
+ break;
+ case DW_OP_bregx:
+ id = S_REGISTER_V2;
+ data = LEB128(p); // reg
+ data = SLEB128(p);
+ break;
+
+ case DW_OP_deref: break;
+ case DW_OP_deref_size: size = 1; break;
+ case DW_OP_dup: stackDepth++; break;
+ case DW_OP_drop: stackDepth--; break;
+ case DW_OP_over: stackDepth++; break;
+ case DW_OP_pick: size = 1; stackDepth++; break;
+ case DW_OP_swap: break;
+ case DW_OP_rot: break;
+ case DW_OP_xderef: stackDepth--; break;
+ case DW_OP_xderef_size: size = 1; stackDepth--; break;
+
+ case DW_OP_push_object_address: stackDepth++; break; /* DWARF3 */
+ case DW_OP_call2: size = 2; break;
+ case DW_OP_call4: size = 4; break;
+ case DW_OP_form_tls_address: break;
+ case DW_OP_call_frame_cfa: stackDepth++; break;
+ case DW_OP_call_ref:
+ case DW_OP_bit_piece:
+ case DW_OP_implicit_value: /* DWARF4 */
+ case DW_OP_stack_value:
+ assert(!"unsupported expression operations");
+
+ // unary operations pop and push
+ case DW_OP_abs:
+ case DW_OP_neg:
+ case DW_OP_not:
+ break;
+ // biary operations pop twice and push
+ case DW_OP_and:
+ case DW_OP_div:
+ case DW_OP_minus:
+ case DW_OP_mod:
+ case DW_OP_mul:
+ case DW_OP_or:
+ case DW_OP_plus:
+ case DW_OP_shl:
+ case DW_OP_shr:
+ case DW_OP_shra:
+ case DW_OP_xor:
+ case DW_OP_eq:
+ case DW_OP_ge:
+ case DW_OP_gt:
+ case DW_OP_le:
+ case DW_OP_lt:
+ case DW_OP_ne:
+ stackDepth--; break;
+ case DW_OP_bra:
+ case DW_OP_skip:
+ size = RD2(p) + 2;
+ break;
+ }
+ if(id >= 0)
+ stackDepth++;
+ p += size;
+ }
+ while(false); // stackDepth > 0);
+ size = p - loc;
+ return data;
+}
+
+
+long decodeLocation(unsigned long long loc, int &id)
+{
+ int size;
+ return decodeLocation((unsigned char*) &loc, id, size);
+}
+
+unsigned char* CV2PDB::getDWARFAbbrev(int off, int findcode)
+{
+ if(!img.debug_abbrev)
+ return 0;
+
+ unsigned char* p = (unsigned char*) img.debug_abbrev;
+ while(off < (int)img.debug_abbrev_length)
+ {
+ int code = LEB128(p, off);
+ if(code == findcode)
+ return p + off;
+ if(code == 0)
+ return 0;
+ int tag = LEB128(p, off);
+ int hasChild = p[off++];
+
+ // skip attributes
+ int attr, form;
+ do
+ {
+ attr = LEB128(p, off);
+ form = LEB128(p, off);
+ }
+ while(attr || form);
+ }
+ return 0;
+}
+
+bool CV2PDB::readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, unsigned char* &p, bool mergeInfo)
+{
+ int entryOff = p - (unsigned char*) cu;
+ int code = LEB128(p);
+ if(code == 0)
+ return false; // end of children list?
+
+ unsigned char* abbrev = getDWARFAbbrev(cu->debug_abbrev_offset, code);
+ assert(abbrev);
+ if(!abbrev)
+ return false;
+ int tag = LEB128(abbrev);
+ int hasChild = *abbrev++;
+
+ if(!mergeInfo)
+ {
+ id.entryOff = entryOff;
+ id.code = code;
+ id.tag = tag;
+ id.hasChild = hasChild;
+
+ id.name = 0;
+ id.dir = 0;
+ id.byte_size = 0;
+ id.sibling = 0;
+ id.encoding = 0;
+ id.pclo = 0;
+ id.pchi = 0;
+ id.ranges = 0;
+ id.type = 0;
+ id.containing_type = 0;
+ id.specification = 0;
+ id.inlined = 0;
+ id.member_location = 0;
+ id.location = 0;
+ id.locationlist = 0;
+ id.frame_base = -1;
+ id.upper_bound = 0;
+ id.lower_bound = 0;
+ }
+ int attr, form;
+ for( ; ; )
+ {
+ attr = LEB128(abbrev);
+ form = LEB128(abbrev);
+
+ if(attr == 0 && form == 0)
+ break;
+
+ const char* str = 0;
+ int size = 0;
+ unsigned long addr = 0;
+ unsigned long data = 0;
+ unsigned long long lldata = 0;
+ bool isRef = false;
+ switch(form)
+ {
+ case DW_FORM_addr: addr = *(unsigned long *)p; size = cu->address_size; break;
+ case DW_FORM_block2: size = RD2(p) + 2; break;
+ case DW_FORM_block4: size = RD4(p) + 4; break;
+ case DW_FORM_data2: size = 2; lldata = data = RD2(p); break;
+ case DW_FORM_data4: size = 4; lldata = data = RD4(p); break;
+ case DW_FORM_data8: size = 8; lldata = RD8(p); data = (unsigned long) lldata; break;
+ case DW_FORM_string: str = (const char*) p; size = strlen(str) + 1; break;
+ case DW_FORM_block: size = LEB128(p); lldata = RDsize(p, size); data = (unsigned long) lldata; break;
+ case DW_FORM_block1: size = *p++; lldata = RDsize(p, size); data = (unsigned long) lldata; break;
+ case DW_FORM_data1: size = 1; lldata = data = *p; break;
+ case DW_FORM_flag: size = 1; lldata = data = *p; break;
+ case DW_FORM_sdata: lldata = data = SLEB128(p); size = 0; break;
+ case DW_FORM_strp: size = cu->refSize(); str = (const char*) (img.debug_str + RDsize(p, size)); break;
+ case DW_FORM_udata: lldata = data = LEB128(p); size = 0; break;
+ case DW_FORM_ref_addr: size = cu->address_size; lldata = RDsize(p, size); data = (unsigned long) lldata; isRef = true; break;
+ case DW_FORM_ref1: size = 1; lldata = data = *p; isRef = true; break;
+ case DW_FORM_ref2: size = 2; lldata = data = RD2(p); isRef = true; break;
+ case DW_FORM_ref4: size = 4; lldata = data = RD4(p); isRef = true; break;
+ case DW_FORM_ref8: size = 8; lldata = RD8(p); data = (unsigned long) lldata; isRef = true; break;
+ case DW_FORM_ref_udata: lldata = data = LEB128(p); size = 0; isRef = true; break;
+ case DW_FORM_exprloc: size = LEB128(p); break;
+ case DW_FORM_flag_present: size = 1; break;
+ case DW_FORM_ref_sig8: size = 8; break;
+ case DW_FORM_indirect:
+ case DW_FORM_sec_offset:
+ default: return setError("unknown DWARF form entry");
+ }
+ switch(attr)
+ {
+ case DW_AT_byte_size: id.byte_size = data; break;
+ 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_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_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;
+ case DW_AT_specification: id.specification = data; break;
+ case DW_AT_data_member_location: id.member_location = lldata; break;
+ case DW_AT_location:
+ if(form == DW_FORM_block1)
+ id.location = lldata;
+ else
+ id.locationlist = data;
+ break;
+ case DW_AT_frame_base:
+ if(form != DW_FORM_block2 && form != DW_FORM_block4 && form != DW_FORM_block1 && form != DW_FORM_block)
+ id.frame_base = data;
+ break;
+ }
+ p += size;
+ }
+ return true;
+}
+
+void CV2PDB::checkDWARFTypeAlloc(int size, int add)
+{
+ if (cbDwarfTypes + size > allocDwarfTypes)
+ {
+ allocDwarfTypes += size + add;
+ dwarfTypes = (BYTE*) realloc(dwarfTypes, allocDwarfTypes);
+ }
+}
+
+void CV2PDB::appendStackVar(const char* name, int type, int offset)
+{
+ unsigned int len;
+ unsigned int align = 4;
+
+// if(type > 0x1020)
+// type = 0x74;
+
+ checkUdtSymbolAlloc(100 + kMaxNameLen);
+
+ codeview_symbol*cvs = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
+ cvs->stack_v2.offset = offset;
+ cvs->stack_v2.symtype = type;
+ if(img.isX64())
+ {
+ cvs->stack_xxxx_v3.id = S_BPREL_XXXX_V3;
+ // register as in "Microsoft Symbol and Type Information" 6.1, see also dia2dump/regs.cpp
+ cvs->stack_xxxx_v3.unknown = 0x14e; // 0x14f: esp relative, 0x14e: ebp relative
+ len = cstrcpy_v (true, (BYTE*) cvs->stack_xxxx_v3.name, name);
+ len += (BYTE*) &cvs->stack_xxxx_v3.name - (BYTE*) cvs;
+ }
+ else
+ {
+ cvs->stack_v2.id = v3 ? S_BPREL_V3 : S_BPREL_V2;
+ len = cstrcpy_v (v3, (BYTE*) &cvs->stack_v2.p_name, name);
+ len += (BYTE*) &cvs->stack_v2.p_name - (BYTE*) cvs;
+ }
+ for (; len & (align-1); len++)
+ udtSymbols[cbUdtSymbols + len] = 0xf4 - (len & 3);
+ cvs->stack_v2.len = len - 2;
+ cbUdtSymbols += len;
+}
+
+void CV2PDB::appendGlobalVar(const char* name, int type, int seg, int offset)
+{
+ unsigned int len;
+ unsigned int align = 4;
+
+ for(char* cname = (char*) name; *cname; cname++)
+ if (*cname == '.')
+ *cname = dotReplacementChar;
+
+ checkUdtSymbolAlloc(100 + kMaxNameLen);
+
+ codeview_symbol*cvs = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
+ cvs->data_v2.id = v3 ? S_GDATA_V3 : S_GDATA_V2;
+ cvs->data_v2.offset = offset;
+ cvs->data_v2.symtype = type;
+ cvs->data_v2.segment = seg;
+ len = cstrcpy_v (v3, (BYTE*) &cvs->data_v2.p_name, name);
+ len += (BYTE*) &cvs->data_v2.p_name - (BYTE*) cvs;
+ for (; len & (align-1); len++)
+ udtSymbols[cbUdtSymbols + len] = 0xf4 - (len & 3);
+ cvs->data_v2.len = len - 2;
+ cbUdtSymbols += len;
+}
+
+bool CV2PDB::appendEndArg()
+{
+ checkUdtSymbolAlloc(8);
+
+ codeview_symbol*cvs = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
+ cvs->common.id = S_ENDARG_V1;
+ cvs->common.len = 2;
+ cbUdtSymbols += 4;
+ return true;
+}
+
+void CV2PDB::appendEnd()
+{
+ checkUdtSymbolAlloc(8);
+
+ codeview_symbol*cvs = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
+ cvs->common.id = S_END_V1;
+ cvs->common.len = 2;
+ cbUdtSymbols += 4;
+}
+
+void CV2PDB::appendLexicalBlock(DWARF_InfoData& id, unsigned int proclo)
+{
+ checkUdtSymbolAlloc(32);
+
+ codeview_symbol*dsym = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
+ dsym->block_v3.id = S_BLOCK_V3;
+ dsym->block_v3.parent = 0;
+ dsym->block_v3.end = 0; // destSize + sizeof(dsym->block_v3) + 12;
+ dsym->block_v3.length = id.pchi - id.pclo;
+ dsym->block_v3.offset = id.pclo - codeSegOff;
+ dsym->block_v3.segment = img.codeSegment + 1;
+ dsym->block_v3.name[0] = 0;
+ int len = sizeof(dsym->block_v3);
+ for (; len & 3; len++)
+ udtSymbols[cbUdtSymbols + len] = 0xf4 - (len & 3);
+ dsym->block_v3.len = len - 2;
+ cbUdtSymbols += len;
+}
+
+bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu,
+ unsigned char* &locals, unsigned char* end)
+{
+ unsigned int pclo = procid.pclo - codeSegOff;
+ unsigned int pchi = procid.pchi - codeSegOff;
+
+ int length = procid.hasChild ? end - locals : 0;
+ unsigned int len;
+ unsigned int align = 4;
+
+ checkUdtSymbolAlloc(100 + kMaxNameLen);
+
+ // GLOBALPROC
+ codeview_symbol*cvs = (codeview_symbol*) (udtSymbols + cbUdtSymbols);
+ cvs->proc_v2.id = v3 ? S_GPROC_V3 : S_GPROC_V2;
+ cvs->proc_v2.pparent = 0;
+ cvs->proc_v2.pend = 0;
+ cvs->proc_v2.next = 0;
+ cvs->proc_v2.proc_len = pchi - pclo;
+ cvs->proc_v2.debug_start = pclo - pclo;
+ cvs->proc_v2.debug_end = pchi - pclo;
+ cvs->proc_v2.offset = pclo;
+ cvs->proc_v2.segment = img.codeSegment + 1;
+ cvs->proc_v2.proctype = 0; // translateType(sym->proc_v1.proctype);
+ cvs->proc_v2.flags = 0;
+
+// printf("GlobalPROC %s\n", procid.name);
+
+ len = cstrcpy_v (v3, (BYTE*) &cvs->proc_v2.p_name, procid.name);
+ len += (BYTE*) &cvs->proc_v2.p_name - (BYTE*) cvs;
+ for (; len & (align-1); len++)
+ udtSymbols[cbUdtSymbols + len] = 0xf4 - (len & 3);
+ cvs->proc_v2.len = len - 2;
+ cbUdtSymbols += len;
+
+#if 0
+ addStackVar("local_var", 0x1001, 8);
+#endif
+
+ int frameOff = 8; // assume ebp+8 in fb
+ if(img.debug_loc && procid.frame_base >= 0)
+ {
+ unsigned char* loc = (unsigned char*) (img.debug_loc + procid.frame_base);
+ int frame_breg = cu->address_size == 8 ? DW_OP_breg6 : DW_OP_breg5;
+#if 1
+ while(RDsize(loc, cu->address_size) != 0 || RDsize(loc + cu->address_size, cu->address_size) != 0)
+ {
+ loc += 2*cu->address_size;
+ int opsize = RD2(loc);
+ loc += 2;
+ if(*loc == frame_breg)
+ {
+ unsigned char* p = loc + 1;
+ frameOff = SLEB128(p);
+ break;
+ }
+ loc += opsize;
+ }
+#endif
+ }
+ if(cu && locals && length)
+ {
+ bool endarg = false;
+ unsigned char* p = locals;
+ unsigned char* end = locals + length;
+ DWARF_InfoData id;
+ int off = 8;
+ int cvid;
+
+ std::vector<unsigned char*> lexicalBlockEnd;
+ lexicalBlockEnd.push_back(end);
+ while(lexicalBlockEnd.size() > 0)
+ {
+ if(p >= lexicalBlockEnd.back())
+ {
+ if (!endarg)
+ endarg = appendEndArg();
+ appendEnd();
+ lexicalBlockEnd.pop_back();
+ continue;
+ }
+ if(!readDWARFInfoData(id, cu, p))
+ continue;
+
+ if (id.tag == DW_TAG_formal_parameter)
+ {
+ if(id.name)
+ {
+ off = decodeLocation(id.location, cvid);
+ if(cvid == S_BPREL_V2)
+ appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff);
+ }
+ }
+ else
+ {
+ if(!endarg)
+ endarg = appendEndArg();
+ switch(id.tag)
+ {
+ case DW_TAG_variable:
+ if(id.name)
+ {
+ off = decodeLocation(id.location, cvid);
+ if(cvid == S_BPREL_V2)
+ appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff);
+ }
+ break;
+ case DW_TAG_subprogram:
+ if(id.hasChild && !id.inlined)
+ p = (id.sibling ? (unsigned char*) cu + id.sibling : end);
+ break;
+ case DW_TAG_lexical_block:
+ if(id.hasChild && id.pchi != id.pclo)
+ {
+ appendLexicalBlock(id, pclo + codeSegOff);
+ if(id.sibling)
+ lexicalBlockEnd.push_back((unsigned char*) cu + id.sibling);
+ else
+ lexicalBlockEnd.push_back(lexicalBlockEnd.back());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ appendEndArg();
+ appendEnd();
+ }
+ return true;
+}
+
+int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* cu,
+ unsigned char* &locals, unsigned char* end)
+{
+ bool isunion = structid.tag == DW_TAG_union_type;
+ int length = structid.hasChild ? end - locals : 0;
+
+ int fieldlistType = 0;
+ int nfields = 0;
+ if(cu && locals && length)
+ {
+ checkDWARFTypeAlloc(100);
+ codeview_reftype* fl = (codeview_reftype*) (dwarfTypes + cbDwarfTypes);
+ int flbegin = cbDwarfTypes;
+ fl->fieldlist.id = LF_FIELDLIST_V2;
+ cbDwarfTypes += 4;
+
+#if 0
+ if(structid.containing_type && structid.containing_type != structid.entryOff)
+ {
+ codeview_fieldtype* bc = (codeview_fieldtype*) (dwarfTypes + cbDwarfTypes);
+ bc->bclass_v2.id = LF_BCLASS_V2;
+ bc->bclass_v2.offset = 0;
+ bc->bclass_v2.type = getTypeByDWARFOffset(cu, structid.containing_type);
+ bc->bclass_v2.attribute = 3; // public
+ cbDwarfTypes += sizeof(bc->bclass_v2);
+ for (; cbDwarfTypes & 3; cbDwarfTypes++)
+ dwarfTypes[cbDwarfTypes] = 0xf4 - (cbDwarfTypes & 3);
+ nfields++;
+ }
+#endif
+ unsigned char* p = locals;
+ unsigned char* end = locals + length;
+ DWARF_InfoData id;
+ int len = 0;
+ while(p < end)
+ {
+ if(!readDWARFInfoData(id, cu, p))
+ continue;
+
+ int cvid = -1;
+ if (id.tag == DW_TAG_member && id.name)
+ {
+ int off = isunion ? 0 : decodeLocation(id.member_location, cvid);
+ if(isunion || cvid == S_CONSTANT_V2)
+ {
+ checkDWARFTypeAlloc(kMaxNameLen + 100);
+ codeview_fieldtype* dfieldtype = (codeview_fieldtype*) (dwarfTypes + cbDwarfTypes);
+ cbDwarfTypes += addFieldMember(dfieldtype, 0, off, getTypeByDWARFOffset(cu, id.type), id.name);
+ nfields++;
+ }
+ }
+ else if(id.tag == DW_TAG_inheritance)
+ {
+ int off = decodeLocation(id.member_location, cvid);
+ if(cvid == S_CONSTANT_V2)
+ {
+ codeview_fieldtype* bc = (codeview_fieldtype*) (dwarfTypes + cbDwarfTypes);
+ bc->bclass_v2.id = LF_BCLASS_V2;
+ bc->bclass_v2.offset = off;
+ bc->bclass_v2.type = getTypeByDWARFOffset(cu, id.type);
+ bc->bclass_v2.attribute = 3; // public
+ cbDwarfTypes += sizeof(bc->bclass_v2);
+ for (; cbDwarfTypes & 3; cbDwarfTypes++)
+ dwarfTypes[cbDwarfTypes] = 0xf4 - (cbDwarfTypes & 3);
+ nfields++;
+ }
+ }
+ if(id.sibling)
+ p = (unsigned char*) cu + id.sibling;
+ }
+ fl = (codeview_reftype*) (dwarfTypes + flbegin);
+ fl->fieldlist.len = cbDwarfTypes - flbegin - 2;
+ fieldlistType = nextDwarfType++;
+ }
+
+ checkUserTypeAlloc(kMaxNameLen + 100);
+ codeview_type* cvt = (codeview_type*) (userTypes + cbUserTypes);
+
+ const char* name = (structid.name ? structid.name : "__noname");
+ int attr = fieldlistType ? 0 : kPropIncomplete;
+ int len = addAggregate(cvt, false, nfields, fieldlistType, attr, 0, 0, structid.byte_size, name);
+ cbUserTypes += len;
+
+ //ensureUDT()?
+ int cvtype = nextUserType++;
+ addUdtSymbol(cvtype, name);
+ return cvtype;
+}
+
+int CV2PDB::getDWARFArrayBounds(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu,
+ unsigned char* &locals, unsigned char* end, int& upperBound)
+{
+ int length = arrayid.hasChild ? end - locals : 0;
+ int lowerBound = 0;
+
+ if(cu && locals && length)
+ {
+ unsigned char* p = locals;
+ unsigned char* end = locals + length;
+ DWARF_InfoData id;
+ int len = 0;
+ while(p < end)
+ {
+ if(!readDWARFInfoData(id, cu, p))
+ continue;
+
+ int cvid = -1;
+ if (id.tag == DW_TAG_subrange_type)
+ {
+ lowerBound = id.lower_bound;
+ upperBound = id.upper_bound;
+ }
+ if(id.sibling)
+ p = (unsigned char*) cu + id.sibling;
+ }
+ }
+ return lowerBound;
+}
+
+int CV2PDB::addDWARFArray(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu,
+ unsigned char* &locals, unsigned char* end)
+{
+ int upperBound, lowerBound = getDWARFArrayBounds(arrayid, cu, locals, end, upperBound);
+
+ checkUserTypeAlloc(kMaxNameLen + 100);
+ codeview_type* cvt = (codeview_type*) (userTypes + cbUserTypes);
+
+ cvt->array_v2.id = v3 ? LF_ARRAY_V3 : LF_ARRAY_V2;
+ cvt->array_v2.elemtype = getTypeByDWARFOffset(cu, arrayid.type);
+ cvt->array_v2.idxtype = 0x74;
+ int len = (BYTE*)&cvt->array_v2.arrlen - (BYTE*)cvt;
+ int size = (upperBound - lowerBound + 1) * getDWARFTypeSize(cu, arrayid.type);
+ len += write_numeric_leaf(size, &cvt->array_v2.arrlen);
+ ((BYTE*)cvt)[len++] = 0; // empty name
+ for (; len & 3; len++)
+ userTypes[cbUserTypes + len] = 0xf4 - (len & 3);
+ cvt->array_v2.len = len - 2;
+
+ cbUserTypes += len;
+
+ int cvtype = nextUserType++;
+ return cvtype;
+}
+
+bool CV2PDB::addDWARFTypes()
+{
+ checkUdtSymbolAlloc(100);
+
+ int prefix = 4;
+ DWORD* ddata = new DWORD [img.debug_info_length/4]; // large enough
+ unsigned char *data = (unsigned char*) (ddata + prefix);
+ unsigned int off = 0;
+ unsigned int len;
+ unsigned int align = 4;
+
+ // SSEARCH
+ codeview_symbol* cvs = (codeview_symbol*) (data + off);
+ cvs->ssearch_v1.id = S_SSEARCH_V1;
+ cvs->ssearch_v1.segment = img.codeSegment + 1;
+ cvs->ssearch_v1.offset = 0;
+ len = sizeof(cvs->ssearch_v1);
+ for (; len & (align-1); len++)
+ data[off + len] = 0xf4 - (len & 3);
+ cvs->ssearch_v1.len = len - 2;
+ off += len;
+
+ // COMPILAND
+ cvs = (codeview_symbol*) (data + off);
+ cvs->compiland_v1.id = S_COMPILAND_V1;
+ cvs->compiland_v1.unknown = 0x800100; // ?, 0x100: C++,
+ cvs->compiland_v1.unknown |= img.isX64() ? 0xd0 : 6; //0x06: Pentium Pro/II, 0xd0: x64
+ len = sizeof(cvs->compiland_v1) - sizeof(cvs->compiland_v1.p_name);
+ len += c2p("cv2pdb", cvs->compiland_v1.p_name);
+ for (; len & (align-1); len++)
+ data[off + len] = 0xf4 - (len & 3);
+ cvs->compiland_v1.len = len - 2;
+ off += len;
+
+#if 0
+ // define one proc over everything
+ int s = codeSegment;
+ int pclo = 0; // img.getImageBase() + img.getSection(s).VirtualAddress;
+ int pchi = pclo + img.getSection(s).Misc.VirtualSize;
+ addDWARFProc("procall", pclo, pchi, 0, 0, 0);
+#endif
+
+ //////////////////////////
+ mspdb::Mod* mod = globalMod();
+ //return writeSymbols (mod, ddata, off, prefix, true);
+ return addSymbols (mod, data, off, true);
+}
+
+bool CV2PDB::addDWARFSectionContrib(mspdb::Mod* mod, unsigned long pclo, unsigned long pchi)
+{
+ int segIndex = img.findSection(pclo);
+ if(segIndex >= 0)
+ {
+ int segFlags = 0x60101020; // 0x40401040, 0x60500020; // TODO
+ int rc = mod->AddSecContrib(segIndex, pclo, pchi - pclo, segFlags);
+ if (rc <= 0)
+ return setError("cannot add section contribution to module");
+ }
+ return true;
+}
+
+int CV2PDB::addDWARFBasicType(const char*name, int encoding, int byte_size)
+{
+ int type = 0, mode = 0, size = 0;
+ switch(encoding)
+ {
+ case DW_ATE_boolean: type = 3; break;
+ case DW_ATE_complex_float: type = 5; byte_size /= 2; break;
+ case DW_ATE_float: type = 4; break;
+ case DW_ATE_signed: type = 1; break;
+ case DW_ATE_signed_char: type = 7; break;
+ case DW_ATE_unsigned: type = 2; break;
+ case DW_ATE_unsigned_char: type = 7; break;
+ case DW_ATE_imaginary_float:type = 4; break;
+ default:
+ setError("unknown basic type encoding");
+ }
+ switch(type)
+ {
+ case 1: // signed
+ case 2: // unsigned
+ case 3: // boolean
+ switch(byte_size)
+ {
+ case 1: size = 0; break;
+ case 2: size = 1; break;
+ case 4: size = 2; break;
+ case 8: size = 3; break;
+ default:
+ setError("unsupported integer type size");
+ }
+ break;
+ case 4:
+ case 5:
+ switch(byte_size)
+ {
+ case 4: size = 0; break;
+ case 8: size = 1; break;
+ case 10: size = 2; break;
+ case 12: size = 2; break; // with padding bytes
+ case 16: size = 3; break;
+ case 6: size = 4; break;
+ default:
+ setError("unsupported real type size");
+ }
+ break;
+ case 7:
+ switch(byte_size)
+ {
+ case 1: size = 0; break;
+ case 2: size = encoding == DW_ATE_signed_char ? 2 : 3; break;
+ case 4: size = encoding == DW_ATE_signed_char ? 4 : 5; break;
+ case 8: size = encoding == DW_ATE_signed_char ? 6 : 7; break;
+ default:
+ setError("unsupported real int type size");
+ }
+ }
+ int t = size | (type << 4);
+ t = translateType(t);
+ int cvtype = appendTypedef(t, name, false);
+ if(useTypedefEnum)
+ addUdtSymbol(cvtype, name);
+ return cvtype;
+}
+
+int CV2PDB::getTypeByDWARFOffset(DWARF_CompilationUnit* cu, int off)
+{
+ int cuoff = (char*) cu - img.debug_info;
+ std::map<int,int>::iterator it = mapOffsetToType.find(cuoff + off);
+ if(it == mapOffsetToType.end())
+ return 0x03; // void
+ return it->second;
+}
+
+int CV2PDB::getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff)
+{
+ DWARF_InfoData id;
+ unsigned char* p = (unsigned char*) cu + typeOff;
+ if(!readDWARFInfoData(id, cu, p))
+ return 0;
+ if(id.byte_size > 0)
+ return id.byte_size;
+
+ switch(id.tag)
+ {
+ case DW_TAG_ptr_to_member_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_pointer_type:
+ return cu->address_size;
+ case DW_TAG_array_type:
+ {
+ int upperBound, lowerBound = getDWARFArrayBounds(id, cu, p, p + 1, upperBound);
+ return (upperBound + lowerBound + 1) * getDWARFTypeSize(cu, id.type);
+ }
+ default:
+ if(id.type)
+ return getDWARFTypeSize(cu, id.type);
+ break;
+ }
+ return 0;
+}
+
+enum iterateOp { kOpMapTypes, kOpCreateTypes };
+
+bool CV2PDB::iterateDWARFDebugInfo(int op)
+{
+ mspdb::Mod* mod = globalMod();
+ int typeID = nextUserType;
+
+ int pointerAttr = img.isX64() ? 0x1000C : 0x800A;
+ for(unsigned long off = 0; off < img.debug_info_length; )
+ {
+ DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*) (img.debug_info + off);
+ int length = cu->unit_length;
+ if(length < 0)
+ break;
+
+ length += sizeof(length);
+ unsigned char* end = (unsigned char*) cu + length;
+ std::vector<unsigned char*> endStack;
+ endStack.push_back(end);
+
+ for(unsigned char* p = (unsigned char*) (cu + 1); endStack.size() > 0; )
+ {
+ if(p >= endStack.back())
+ {
+ endStack.pop_back();
+ continue;
+ }
+ DWARF_InfoData id;
+ if(!readDWARFInfoData(id, cu, p))
+ continue;
+ if(id.specification)
+ {
+ unsigned char* q = (unsigned char*) cu + id.specification;
+ readDWARFInfoData(id, cu, q, true);
+ }
+ if(id.hasChild)
+ if(id.sibling)
+ endStack.push_back((unsigned char*) cu + id.sibling);
+ else
+ endStack.push_back(endStack.back());
+
+ if(op == kOpMapTypes)
+ {
+ switch(id.tag)
+ {
+ case DW_TAG_base_type:
+ case DW_TAG_typedef:
+ case DW_TAG_pointer_type:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_array_type:
+ case DW_TAG_const_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_reference_type:
+
+ case DW_TAG_class_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_string_type:
+ case DW_TAG_union_type:
+ case DW_TAG_ptr_to_member_type:
+ case DW_TAG_set_type:
+ case DW_TAG_subrange_type:
+ case DW_TAG_file_type:
+ case DW_TAG_packed_type:
+ case DW_TAG_thrown_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_restrict_type: // DWARF3
+ case DW_TAG_interface_type:
+ case DW_TAG_unspecified_type:
+ case DW_TAG_mutable_type: // withdrawn
+ case DW_TAG_shared_type:
+ case DW_TAG_rvalue_reference_type:
+ mapOffsetToType.insert(std::pair<int,int>(off + id.entryOff, typeID));
+ typeID++;
+ }
+ }
+ else
+ {
+ int cvtype = -1;
+ switch(id.tag)
+ {
+ case DW_TAG_base_type:
+ cvtype = addDWARFBasicType(id.name, id.encoding, id.byte_size);
+ break;
+ case DW_TAG_typedef:
+ cvtype = appendModifierType(getTypeByDWARFOffset(cu, id.type), 0);
+ addUdtSymbol(cvtype, id.name);
+ break;
+ case DW_TAG_pointer_type:
+ cvtype = appendPointerType(getTypeByDWARFOffset(cu, id.type), pointerAttr);
+ break;
+ case DW_TAG_const_type:
+ cvtype = appendModifierType(getTypeByDWARFOffset(cu, id.type), 1);
+ break;
+ case DW_TAG_reference_type:
+ cvtype = appendPointerType(getTypeByDWARFOffset(cu, id.type), pointerAttr | 0x20);
+ break;
+
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ cvtype = addDWARFStructure(id, cu, p, endStack.back());
+ break;
+ case DW_TAG_array_type:
+ cvtype = addDWARFArray(id, cu, p, endStack.back());
+ break;
+ case DW_TAG_subroutine_type:
+ case DW_TAG_subrange_type:
+
+ case DW_TAG_enumeration_type:
+ case DW_TAG_string_type:
+ case DW_TAG_ptr_to_member_type:
+ case DW_TAG_set_type:
+ case DW_TAG_file_type:
+ case DW_TAG_packed_type:
+ case DW_TAG_thrown_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_restrict_type: // DWARF3
+ case DW_TAG_interface_type:
+ case DW_TAG_unspecified_type:
+ case DW_TAG_mutable_type: // withdrawn
+ case DW_TAG_shared_type:
+ case DW_TAG_rvalue_reference_type:
+ cvtype = appendPointerType(0x74, pointerAttr);
+ break;
+
+ case DW_TAG_subprogram:
+ if(id.name && id.pclo && id.pchi)
+ {
+ addDWARFProc(id, cu, p, endStack.back());
+ int rc = mod->AddPublic2(id.name, img.codeSegment + 1, id.pclo - codeSegOff, 0);
+ }
+ break;
+
+ case DW_TAG_compile_unit:
+ #if !FULL_CONTRIB
+ if(id.dir && id.name)
+ {
+ if(id.ranges > 0 && id.ranges < img.debug_ranges_length)
+ {
+ unsigned char* r = (unsigned char*)img.debug_ranges + id.ranges;
+ unsigned char* rend = (unsigned char*)img.debug_ranges + img.debug_ranges_length;
+ while(r < rend)
+ {
+ unsigned long pclo = RD4(r); r += 4;
+ unsigned long pchi = RD4(r); r += 4;
+ if(pclo == 0 && pchi == 0)
+ break;
+ //printf("%s %s %x - %x\n", dir, name, pclo, pchi);
+ if(!addDWARFSectionContrib(mod, pclo, pchi))
+ return false;
+ }
+ }
+ else
+ {
+ //printf("%s %s %x - %x\n", dir, name, pclo, pchi);
+ if(!addDWARFSectionContrib(mod, id.pclo, id.pchi))
+ return false;
+ }
+ }
+ #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 = img.findSection(off);
+ 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);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if(cvtype >= 0)
+ {
+ assert(cvtype == typeID); typeID++;
+ assert(mapOffsetToType[off + id.entryOff] == cvtype);
+ }
+ }
+ }
+ off += length;
+ }
+
+ if(op == kOpMapTypes)
+ nextDwarfType = typeID;
+
+ return true;
+}
+
+bool CV2PDB::createDWARFModules()
+{
+ if(!img.debug_info)
+ return setError("no .debug_info section found");
+
+ codeSegOff = img.getImageBase() + img.getSection(img.codeSegment).VirtualAddress;
+
+ mspdb::Mod* mod = globalMod();
+ for (int s = 0; s < img.countSections(); s++)
+ {
+ const IMAGE_SECTION_HEADER& sec = img.getSection(s);
+ int rc = dbi->AddSec(s + 1, 0x10d, 0, sec.SizeOfRawData);
+ if (rc <= 0)
+ return setError("cannot add section");
+ }
+
+#define FULL_CONTRIB 1
+#if FULL_CONTRIB
+ // we use a single global module, so we can simply add the whole text segment
+ int segFlags = 0x60101020; // 0x40401040, 0x60500020; // TODO
+ int s = img.codeSegment;
+ int pclo = 0; // img.getImageBase() + img.getSection(s).VirtualAddress;
+ int pchi = pclo + img.getSection(s).Misc.VirtualSize;
+ int rc = mod->AddSecContrib(s + 1, pclo, pchi - pclo, segFlags);
+ if (rc <= 0)
+ return setError("cannot add section contribution to module");
+#endif
+
+ checkUserTypeAlloc();
+ *(DWORD*) userTypes = 4;
+ cbUserTypes = 4;
+
+ createEmptyFieldListType();
+ if(Dversion > 0)
+ {
+ appendComplex(0x50, 0x40, 4, "cfloat");
+ appendComplex(0x51, 0x41, 8, "cdouble");
+ appendComplex(0x52, 0x42, 12, "creal");
+ }
+
+ countEntries = 0;
+ if(!iterateDWARFDebugInfo(kOpMapTypes))
+ return false;
+ if(!iterateDWARFDebugInfo(kOpCreateTypes))
+ return false;
+
+#if 0
+ modules = new mspdb::Mod* [countEntries];
+ memset (modules, 0, countEntries * sizeof(*modules));
+
+ for (int m = 0; m < countEntries; m++)
+ {
+ mspdb::Mod* mod = globalMod();
+ }
+#endif
+
+ if(cbUserTypes > 0 || cbDwarfTypes)
+ {
+ if(dwarfTypes)
+ {
+ checkUserTypeAlloc(cbDwarfTypes);
+ memcpy(userTypes + cbUserTypes, dwarfTypes, cbDwarfTypes);
+ cbUserTypes += cbDwarfTypes;
+ cbDwarfTypes = 0;
+ }
+ int rc = mod->AddTypes(userTypes, cbUserTypes);
+ if (rc <= 0)
+ return setError("cannot add type info to module");
+ }
+ return true;
+}
+
+bool isRelativePath(const std::string& s)
+{
+ if(s.length() < 1)
+ return true;
+ if(s[0] == '/' || s[0] == '\\')
+ return false;
+ if(s.length() < 2)
+ return true;
+ if(s[1] == ':')
+ return false;
+ return true;
+}
+
+static int cmpAdr(const void* s1, const void* s2)
+{
+ const mspdb::LineInfoEntry* e1 = (const mspdb::LineInfoEntry*) s1;
+ const mspdb::LineInfoEntry* e2 = (const mspdb::LineInfoEntry*) s2;
+ return e1->offset - e2->offset;
+}
+
+bool _flushDWARFLines(CV2PDB* cv2pdb, DWARF_LineState& state)
+{
+ if(state.lineInfo.size() == 0)
+ return true;
+
+ unsigned int saddr = state.lineInfo[0].offset;
+ unsigned int eaddr = state.lineInfo.back().offset;
+ int segIndex = cv2pdb->img.findSection(saddr + state.seg_offset);
+ if(segIndex < 0)
+ {
+ // throw away invalid lines (mostly due to "set address to 0")
+ state.lineInfo.resize(0);
+ return true;
+ //return false;
+ }
+
+// if(saddr >= 0x4000)
+// return true;
+
+ const DWARF_FileName* dfn;
+ if(state.file == 0)
+ dfn = state.file_ptr;
+ else if(state.file > 0 && state.file <= state.files.size())
+ dfn = &state.files[state.file - 1];
+ else
+ return false;
+ std::string fname = dfn->file_name;
+
+ if(isRelativePath(fname) &&
+ dfn->dir_index > 0 && dfn->dir_index <= state.include_dirs.size())
+ {
+ std::string dir = state.include_dirs[dfn->dir_index - 1];
+ if(dir.length() > 0 && dir[dir.length() - 1] != '/' && dir[dir.length() - 1] != '\\')
+ dir.append("\\");
+ fname = dir + fname;
+ }
+ for(size_t i = 0; i < fname.length(); i++)
+ if(fname[i] == '/')
+ fname[i] = '\\';
+
+ mspdb::Mod* mod = cv2pdb->globalMod();
+#if 1
+ bool dump = false; // (fname == "cvtest.d");
+ //qsort(&state.lineInfo[0], state.lineInfo.size(), sizeof(state.lineInfo[0]), cmpAdr);
+#if 0
+ printf("%s:\n", fname.c_str());
+ for(size_t ln = 0; ln < state.lineInfo.size(); ln++)
+ printf(" %08x: %4d\n", state.lineInfo[ln].offset + 0x401000, state.lineInfo[ln].line);
+#endif
+
+ unsigned int firstLine = state.lineInfo[0].line;
+ unsigned int firstAddr = state.lineInfo[0].offset;
+ unsigned int firstEntry = 0;
+ unsigned int entry = 0;
+ for(size_t ln = firstEntry; ln < state.lineInfo.size(); ln++)
+ {
+ if(state.lineInfo[ln].line < firstLine || state.lineInfo[ln].offset < firstAddr)
+ {
+ if(ln > firstEntry)
+ {
+ unsigned int length = state.lineInfo[entry-1].offset + 1; // firstAddr has been subtracted before
+ if(dump)
+ printf("AddLines(%08x+%04x, Line=%4d+%3d, %s)\n", firstAddr, length, firstLine, entry - firstEntry, fname.c_str());
+ int rc = mod->AddLines(fname.c_str(), segIndex + 1, firstAddr, length, firstAddr, firstLine,
+ (unsigned char*) &state.lineInfo[firstEntry],
+ (ln - firstEntry) * sizeof(state.lineInfo[0]));
+ firstLine = state.lineInfo[ln].line;
+ firstAddr = state.lineInfo[ln].offset;
+ firstEntry = entry;
+ }
+ }
+ else if(ln > firstEntry && state.lineInfo[ln].offset == state.lineInfo[ln-1].offset)
+ continue; // skip entries without offset change
+ state.lineInfo[entry].line = state.lineInfo[ln].line - firstLine;
+ state.lineInfo[entry].offset = state.lineInfo[ln].offset - firstAddr;
+ entry++;
+ }
+ unsigned int length = eaddr - firstAddr;
+ if(dump)
+ printf("AddLines(%08x+%04x, Line=%4d+%3d, %s)\n", firstAddr, length, firstLine, entry - firstEntry, fname.c_str());
+ int rc = mod->AddLines(fname.c_str(), segIndex + 1, firstAddr, length, firstAddr, firstLine,
+ (unsigned char*) &state.lineInfo[firstEntry],
+ (entry - firstEntry) * sizeof(state.lineInfo[0]));
+#else
+ unsigned int firstLine = 0;
+ unsigned int firstAddr = 0;
+ int rc = mod->AddLines(fname.c_str(), segIndex + 1, saddr, eaddr - saddr, firstAddr, firstLine,
+ (unsigned char*) &state.lineInfo[0], state.lineInfo.size() * sizeof(state.lineInfo[0]));
+#endif
+
+ state.lineInfo.resize(0);
+ return rc > 0;
+}
+
+bool CV2PDB::addDWARFLines()
+{
+ if(!img.debug_line)
+ return setError("no .debug_line section found");
+
+ mspdb::Mod* mod = globalMod();
+ for(unsigned long off = 0; off < img.debug_line_length; )
+ {
+ DWARF_LineNumberProgramHeader* hdr = (DWARF_LineNumberProgramHeader*) (img.debug_line + off);
+ int length = hdr->unit_length;
+ if(length < 0)
+ break;
+ length += sizeof(length);
+
+ unsigned char* p = (unsigned char*) (hdr + 1);
+ unsigned char* end = (unsigned char*) hdr + length;
+
+ std::vector<unsigned int> opcode_lengths;
+ opcode_lengths.resize(hdr->opcode_base);
+ opcode_lengths[0] = 0;
+ for(int o = 1; o < hdr->opcode_base && p < end; o++)
+ opcode_lengths[o] = LEB128(p);
+
+ DWARF_LineState state;
+ state.seg_offset = img.getImageBase() + img.getSection(img.codeSegment).VirtualAddress;
+
+ // dirs
+ while(p < end)
+ {
+ if(*p == 0)
+ break;
+ state.include_dirs.push_back((const char*) p);
+ p += strlen((const char*) p) + 1;
+ }
+ p++;
+
+ // files
+ DWARF_FileName fname;
+ while(p < end && *p)
+ {
+ fname.read(p);
+ state.files.push_back(fname);
+ }
+ p++;
+
+ std::vector<mspdb::LineInfoEntry> lineInfo;
+
+ state.init(hdr);
+ while(p < end)
+ {
+ int opcode = *p++;
+ if(opcode >= hdr->opcode_base)
+ {
+ // special opcode
+ int adjusted_opcode = opcode - hdr->opcode_base;
+ int operation_advance = adjusted_opcode / hdr->line_range;
+ state.advance_addr(hdr, operation_advance);
+ int line_advance = hdr->line_base + (adjusted_opcode % hdr->line_range);
+ state.line += line_advance;
+
+ state.addLineInfo();
+
+ state.basic_block = false;
+ state.prologue_end = false;
+ state.epilogue_end = false;
+ state.discriminator = 0;
+ }
+ else
+ {
+ switch(opcode)
+ {
+ case 0: // extended
+ {
+ int exlength = LEB128(p);
+ unsigned char* q = p + exlength;
+ int excode = *p++;
+ switch(excode)
+ {
+ case DW_LNE_end_sequence:
+ if((char*)p - img.debug_line >= 0xe4e0)
+ p = p;
+ state.end_sequence = true;
+ state.last_addr = state.address;
+ state.addLineInfo();
+ if(!_flushDWARFLines(this, state))
+ return setError("cannot add line number info to module");
+ state.init(hdr);
+ break;
+ case DW_LNE_set_address:
+ if(unsigned long adr = RD4(p))
+ state.address = adr;
+ else
+ state.address = state.last_addr; // strange adr 0 for templates?
+ state.op_index = 0;
+ break;
+ case DW_LNE_define_file:
+ fname.read(p);
+ state.file_ptr = &fname;
+ state.file = 0;
+ break;
+ case DW_LNE_set_discriminator:
+ state.discriminator = LEB128(p);
+ break;
+ }
+ p = q;
+ }
+ break;
+ case DW_LNS_copy:
+ state.addLineInfo();
+ state.basic_block = false;
+ state.prologue_end = false;
+ state.epilogue_end = false;
+ state.discriminator = 0;
+ break;
+ case DW_LNS_advance_pc:
+ state.advance_addr(hdr, LEB128(p));
+ break;
+ case DW_LNS_advance_line:
+ state.line += SLEB128(p);
+ break;
+ case DW_LNS_set_file:
+ if(!_flushDWARFLines(this, state))
+ return setError("cannot add line number info to module");
+ state.file = LEB128(p);
+ break;
+ case DW_LNS_set_column:
+ state.column = LEB128(p);
+ break;
+ case DW_LNS_negate_stmt:
+ state.is_stmt = !state.is_stmt;
+ break;
+ case DW_LNS_set_basic_block:
+ state.basic_block = true;
+ break;
+ case DW_LNS_const_add_pc:
+ state.advance_addr(hdr, (255 - hdr->opcode_base) / hdr->line_range);
+ break;
+ case DW_LNS_fixed_advance_pc:
+ state.address += RD2(p);
+ state.op_index = 0;
+ break;
+ case DW_LNS_set_prologue_end:
+ state.prologue_end = true;
+ break;
+ case DW_LNS_set_epilogue_begin:
+ state.epilogue_end = true;
+ break;
+ case DW_LNS_set_isa:
+ state.isa = LEB128(p);
+ break;
+ default:
+ // unknown standard opcode
+ for(unsigned int arg = 0; arg < opcode_lengths[opcode]; arg++)
+ LEB128(p);
+ break;
+ }
+ }
+ }
+ if(!_flushDWARFLines(this, state))
+ return setError("cannot add line number info to module");
+
+ off += length;
+ }
+
+ return true;
+}
+
+bool CV2PDB::relocateDebugLineInfo()
+{
+ if(!img.reloc || !img.reloc_length)
+ return true;
+
+ unsigned int img_base = 0x400000;
+ char* relocbase = img.reloc;
+ char* relocend = img.reloc + img.reloc_length;
+ while(relocbase < relocend)
+ {
+ unsigned int virtadr = *(unsigned int *) relocbase;
+ unsigned int chksize = *(unsigned int *) (relocbase + 4);
+
+ char* p = img.RVA<char> (virtadr, 1);
+ if(p >= img.debug_line && p < img.debug_line + img.debug_line_length)
+ {
+ for (unsigned int p = 8; p < chksize; p += 2)
+ {
+ unsigned short entry = *(unsigned short*)(relocbase + p);
+ unsigned short type = (entry >> 12) & 0xf;
+ unsigned short off = entry & 0xfff;
+
+ if(type == 3) // HIGHLOW
+ {
+ *(long*) (p + off) += img_base;
+ }
+ }
+ }
+ if(chksize == 0 || chksize >= img.reloc_length)
+ break;
+ relocbase += chksize;
+ }
+ return true;
+}
+
+bool CV2PDB::addDWARFPublics()
+{
+ mspdb::Mod* mod = globalMod();
+
+ int type = 0;
+ int rc = mod->AddPublic2("public_all", img.codeSegment + 1, 0, 0x1000);
+ if (rc <= 0)
+ return setError("cannot add public");
+ return true;
+}
+
+bool CV2PDB::writeDWARFImage(const char* opath)
+{
+ int len = sizeof(*rsds) + strlen((char*)(rsds + 1)) + 1;
+ if (!img.replaceDebugSection(rsds, len, false))
+ return setError(img.getLastError());
+
+ if (!img.save(opath))
+ return setError(img.getLastError());
+
+ return true;
+}
diff --git a/src/main.cpp b/src/main.cpp
index 18c1631..69807aa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -81,8 +81,8 @@ int main(int argc, char** argv)
{
if (argc < 2)
{
- printf("Convert DMD CodeView debug information to PDB files, Version %g\n", VERSION);
- printf("Copyright (c) 2009-2011 by Rainer Schuetze, All Rights Reserved\n");
+ printf("Convert DMD CodeView/DWARF debug information to PDB files, Version %g\n", VERSION);
+ printf("Copyright (c) 2009-2012 by Rainer Schuetze, All Rights Reserved\n");
printf("\n");
printf("License for redistribution is given by the Artistic License 2.0\n");
printf("see file LICENSE for further details\n");
@@ -106,6 +106,8 @@ int main(int argc, char** argv)
Dversion = 0;
else if (argv[0][1] == 'n')
demangleSymbols = false;
+ else if (argv[0][1] == 'e')
+ useTypedefEnum = true;
else if (argv[0][1] == 's' && argv[0][2])
dotReplacementChar = argv[0][2];
else
@@ -114,12 +116,12 @@ int main(int argc, char** argv)
if (!img.load(argv[1]))
fatal("%s: %s", argv[1], img.getLastError());
- if (img.countCVEntries() == 0)
+ if (img.countCVEntries() == 0 && !img.hasDWARF())
fatal("%s: no codeview debug entries found", argv[1]);
CV2PDB cv2pdb(img);
- cv2pdb.initLibraries();
cv2pdb.Dversion = Dversion;
+ cv2pdb.initLibraries();
char* outname = argv[1];
if (argc > 2 && argv[2][0])
@@ -144,32 +146,55 @@ int main(int argc, char** argv)
if(!cv2pdb.openPDB(pdbname))
fatal("%s: %s", pdbname, cv2pdb.getLastError());
- if (!cv2pdb.initSegMap())
- fatal("%s: %s", argv[1], cv2pdb.getLastError());
+ if(img.hasDWARF())
+ {
+ if(!cv2pdb.relocateDebugLineInfo())
+ fatal("%s: %s", argv[1], cv2pdb.getLastError());
- if (!cv2pdb.initGlobalSymbols())
- fatal("%s: %s", argv[1], cv2pdb.getLastError());
+ if(!cv2pdb.createDWARFModules())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
- if (!cv2pdb.initGlobalTypes())
- fatal("%s: %s", argv[1], cv2pdb.getLastError());
+ if(!cv2pdb.addDWARFTypes())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
- if (!cv2pdb.createModules())
- fatal("%s: %s", pdbname, cv2pdb.getLastError());
+ if(!cv2pdb.addDWARFLines())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
- if (!cv2pdb.addTypes())
- fatal("%s: %s", pdbname, cv2pdb.getLastError());
+ if (!cv2pdb.addDWARFPublics())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
- if (!cv2pdb.addSymbols())
- fatal("%s: %s", pdbname, cv2pdb.getLastError());
+ if (!cv2pdb.writeDWARFImage(outname))
+ fatal("%s: %s", outname, cv2pdb.getLastError());
+ }
+ else
+ {
+ if (!cv2pdb.initSegMap())
+ fatal("%s: %s", argv[1], cv2pdb.getLastError());
- if (!cv2pdb.addSrcLines())
- fatal("%s: %s", pdbname, cv2pdb.getLastError());
+ if (!cv2pdb.initGlobalSymbols())
+ fatal("%s: %s", argv[1], cv2pdb.getLastError());
- if (!cv2pdb.addPublics())
- fatal("%s: %s", pdbname, cv2pdb.getLastError());
+ if (!cv2pdb.initGlobalTypes())
+ fatal("%s: %s", argv[1], cv2pdb.getLastError());
+
+ if (!cv2pdb.createModules())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
+
+ if (!cv2pdb.addTypes())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
+
+ if (!cv2pdb.addSymbols())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
+
+ if (!cv2pdb.addSrcLines())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
+
+ if (!cv2pdb.addPublics())
+ fatal("%s: %s", pdbname, cv2pdb.getLastError());
- if (!cv2pdb.writeImage(outname))
- fatal("%s: %s", outname, cv2pdb.getLastError());
+ if (!cv2pdb.writeImage(outname))
+ fatal("%s: %s", outname, cv2pdb.getLastError());
+ }
return 0;
}
diff --git a/src/symutil.cpp b/src/symutil.cpp
index 61a4fa0..91e086e 100644
--- a/src/symutil.cpp
+++ b/src/symutil.cpp
@@ -15,6 +15,7 @@ extern "C" {
char dotReplacementChar = '@';
bool demangleSymbols = true;
+bool useTypedefEnum = false;
int dsym2c(const BYTE* p, int len, char* cname, int maxclen)
{
@@ -143,6 +144,28 @@ char* p2c(const p_string& p, int idx)
return p2c(&p.namelen, idx);
}
+int c2p(const char* c, BYTE* p)
+{
+ BYTE* q = p;
+ int len = strlen(c);
+ if(len > 255)
+ {
+ *p++ = 0xff;
+ *p++ = 0;
+ *p++ = len & 0xff;
+ *p++ = len >> 8;
+ }
+ else
+ *p++ = len;
+ memcpy(p, c, len);
+ return p + len - q;
+}
+
+int c2p(const char* c, p_string& p)
+{
+ return c2p(c, &p.namelen);
+}
+
int p2ccpy(char* p, const BYTE* s)
{
int len = pstrlen(s);
diff --git a/src/symutil.h b/src/symutil.h
index dfc8b76..1384029 100644
--- a/src/symutil.h
+++ b/src/symutil.h
@@ -19,6 +19,8 @@ int pstrmemlen(const BYTE* p);
int pstrlen(const BYTE* &p);
char* p2c(const BYTE* p, int idx = 0);
char* p2c(const p_string& p, int idx = 0);
+int c2p(const char* c, BYTE* p); // return byte len
+int c2p(const char* c, p_string& p);
int p2ccpy(char* p, const BYTE* s);
int pstrcpy(BYTE* p, const BYTE* s);
int pstrcpy(p_string& p, const p_string& s);
@@ -31,5 +33,6 @@ bool dstrcmp(const BYTE* s1, bool cstr1, const BYTE* s2, bool cstr2);
extern char dotReplacementChar;
extern bool demangleSymbols;
+extern bool useTypedefEnum;
#endif //__SYMUTIL_H__
diff --git a/test/cvtest.d b/test/cvtest.d
index 4d64873..e425354 100644
--- a/test/cvtest.d
+++ b/test/cvtest.d
@@ -87,6 +87,8 @@ class class_outer
// LF_ARRAY_V1
long[4] global_fixed_array;
+__gshared long[4] gshared_fixed_array = [ 1, 2, 3, 4 ];
+__gshared string gshared_bss_string;
// OEM types;
long[] global_oem_long_dynarray;
@@ -218,7 +220,7 @@ void voidpointers(ubyte* p)
const(int*) const_ip2 = cast(const(int*)) p;
}
-int arrays()
+size_t arrays()
{
int[] iarr;
iarr ~= 4;
@@ -228,9 +230,30 @@ int arrays()
const void[] cvarr;
+ int[7] xarr = [ 1, 2, 3, 4, 5, 6, 7 ];
+ string[7] sarr = [ "a", "b", "c", "d", "e", "f", "g" ];
+ wstring[7] wsarr = [ "a", "b", "c", "d", "e", "f", "g" ];
+ dstring[7] dsarr = [ "a", "b", "c", "d", "e", "f", "g" ];
+
return iarr.length;
}
+size_t lexical_scope()
+{
+ int[10] arr1;
+ for(int i = 0; i < 10; i++)
+ arr1[i] = i;
+
+ for(int i = 0; i < 10; i++)
+ arr1[i] += i;
+
+ foreach(i; "hello")
+ if(i == 'e')
+ break;
+
+ return arr1.length;
+}
+
enum { Forward, Accept, Reject }
alias int Action;
@@ -250,7 +273,7 @@ int main2(char[][]argv)
class_method inst_method = new class_method;
class_staticmember inst_staticmember = new class_staticmember;
class_outer inst_outer = new class_outer;
- class_outer.class_inner inst_inner = inst_outer.inner; // = new class_outer.class_inner(inst_outer);
+ class_outer.class_inner inst_inner = /*inst_outer.inner; // =*/ inst_outer.new class_inner;
struct_name inst_struct;
struct_name* pinst_struct;
pinst_struct = &inst_struct;
@@ -266,7 +289,7 @@ int main2(char[][]argv)
CUnknown unkn = new CUnknown;
IUnknown iunkn = unkn;
- CUnknown nunkn = cast(CUnknown) iunkn;
+// CUnknown nunkn = cast(CUnknown) iunkn;
FILE stdfile;
inst_member.member1 = 2;
@@ -309,9 +332,15 @@ int main(char[][]argv)
voidpointers(null);
arrays();
+ lexical_scope();
+
outer_func(3);
A.outer_func(3);
+ global_fixed_array[1] = 3;
+ gshared_fixed_array[0] = 3;
+ gshared_bss_string = "bss";
+
main2(argv);
writefln("Hello world");
@@ -351,7 +380,7 @@ int main(char[][]argv)
(new Test).test();
- dmd_quirks();
+ basictypes();
strings();
int[] dynint_arr;
@@ -365,7 +394,7 @@ int main(char[][]argv)
class Test
{
- int test()
+ size_t test()
{
class_outer clss = new class_outer;
@@ -384,16 +413,60 @@ class Test
int strings()
{
- string cs = "char string";
+ string empty;
+ string cs = "char string";
wstring ws = "wchar string"w;
dstring ds = "dchar string"d;
+ immutable(char)[] ics = cs;
+ immutable(wchar)[] iws = ws;
+ immutable(dchar)[] ids = ds;
+
+ char[] mcs = cs.dup;
+ wchar[] mws = ws.dup;
+ dchar[] mds = ds.dup;
+
+ const(char)[] ccs = cs;
+ const(wchar)[] cws = ws;
+ const(dchar)[] cds = ds;
+
+ immutable char[] i2cs = cs;
+ immutable wchar[] i2ws = ws;
+ immutable dchar[] i2ds = ds;
+
+ const char[] c2cs = cs;
+ const wchar[] c2ws = ws;
+ const dchar[] c2ds = ds;
+
return 0;
}
-void dmd_quirks()
-{
+double basictypes()
+{
+ // basic types
+ char c;
+ wchar wc;
+ dchar dc;
+ byte b;
+ ubyte ub;
+ short s;
+ ushort us;
+ int i;
+ uint ui;
long quirk_long; // written as delegate<void*,int>
ulong quirk_ulong; // written as int[]
+
+ float f;
+ double d;
+ real r;
+
+ ifloat iflt;
+ idouble id;
+ ireal ir;
+ cfloat cf;
+ cdouble cd;
+ creal cr;
+
+ return f + d + r + cf.im;
}