From 96e6e9fa7388b010f55cf8d122ef03a2a8ab87e4 Mon Sep 17 00:00:00 2001 From: sagitario Date: Sun, 12 Feb 2012 16:05:27 +0000 Subject: * 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 --- CHANGES | 11 +- INSTALL | 2 +- Makefile | 2 + README | 11 +- TODO | 2 +- VERSION | 2 +- autoexp.expand | 21 +- autoexp.visualizer | 51 +- src/PEImage.cpp | 154 +++- src/PEImage.h | 34 +- src/cv2pdb.cpp | 110 ++- src/cv2pdb.h | 51 +- src/cv2pdb.sln | 41 + src/cv2pdb.vcproj | 8 + src/cvutil.cpp | 34 +- src/cvutil.h | 1 + src/dviewhelper/dviewhelper.cpp | 53 +- src/dwarf.h | 1182 +++++++++++++++++++++++++++ src/dwarf2pdb.cpp | 1690 +++++++++++++++++++++++++++++++++++++++ src/main.cpp | 69 +- src/symutil.cpp | 23 + src/symutil.h | 3 + test/cvtest.d | 89 ++- 23 files changed, 3495 insertions(+), 149 deletions(-) create mode 100644 src/dwarf.h create mode 100644 src/dwarf2pdb.cpp 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 (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 (dos->e_lfanew); - if(!hdr) + hdr32 = DPV (dos->e_lfanew); + hdr64 = DPV (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(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 (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 (dos->e_lfanew); + hdr64 = DPV (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(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(sec[s].PointerToRawData, sec[s].SizeOfRawData); + if(strcmp(name, ".debug_pubnames") == 0) + debug_pubnames = DPV(sec[s].PointerToRawData, sec[s].SizeOfRawData); + if(strcmp(name, ".debug_pubtypes") == 0) + debug_pubtypes = DPV(sec[s].PointerToRawData, sec[s].SizeOfRawData); + if(strcmp(name, ".debug_info") == 0) + debug_info = DPV(sec[s].PointerToRawData, debug_info_length = sec[s].Misc.VirtualSize); + if(strcmp(name, ".debug_abbrev") == 0) + debug_abbrev = DPV(sec[s].PointerToRawData, debug_abbrev_length = sec[s].Misc.VirtualSize); + if(strcmp(name, ".debug_line") == 0) + debug_line = DPV(sec[s].PointerToRawData, debug_line_length = sec[s].Misc.VirtualSize); + if(strcmp(name, ".debug_frame") == 0) + debug_frame = DPV(sec[s].PointerToRawData, sec[s].SizeOfRawData); + if(strcmp(name, ".debug_str") == 0) + debug_str = DPV(sec[s].PointerToRawData, sec[s].SizeOfRawData); + if(strcmp(name, ".debug_loc") == 0) + debug_loc = DPV(sec[s].PointerToRawData, sec[s].SizeOfRawData); + if(strcmp(name, ".debug_ranges") == 0) + debug_ranges = DPV(sec[s].PointerToRawData, debug_ranges_length = sec[s].Misc.VirtualSize); + if(strcmp(name, ".reloc") == 0) + reloc = DPV(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 +#include 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 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 @@ > + + @@ -200,6 +204,10 @@ > + + 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 +#include +#include + +/////////////////////////////////////////////////////////////////////////////// + +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 include_dirs; + std::vector 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 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 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::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 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(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 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 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 (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 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; } -- cgit v0.12