summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVadim Chugunov <vadimcn@gmail.com>2014-10-17 16:42:53 (GMT)
committerVadim Chugunov <vadimcn@gmail.com>2014-12-05 21:31:34 (GMT)
commitb5bb7f4c024cdedab46a4967433cdbc1e2af31a9 (patch)
tree7d1529e1d9540cfbcade5dd2c5714015d996dbf5 /src
parentbd5029b0462023e27021c23ae1b7c50d00876d97 (diff)
downloadcv2pdb-b5bb7f4c024cdedab46a4967433cdbc1e2af31a9.zip
cv2pdb-b5bb7f4c024cdedab46a4967433cdbc1e2af31a9.tar.gz
cv2pdb-b5bb7f4c024cdedab46a4967433cdbc1e2af31a9.tar.bz2
Fixed O^n abbrev search.
DIE tree navigation without requiring DW_AT_sibling attributes, moved navigation logic into DIECursor class.
Diffstat (limited to 'src')
-rw-r--r--src/cv2pdb.h19
-rw-r--r--src/cv2pdb.vcxproj245
-rw-r--r--src/cv2pdb.vcxproj.filters129
-rw-r--r--src/dwarf2pdb.cpp998
-rw-r--r--src/readDwarf.cpp392
-rw-r--r--src/readDwarf.h308
6 files changed, 1125 insertions, 966 deletions
diff --git a/src/cv2pdb.h b/src/cv2pdb.h
index 0153169..f5b2938 100644
--- a/src/cv2pdb.h
+++ b/src/cv2pdb.h
@@ -9,9 +9,11 @@
#include "LastError.h"
#include "mspdb.h"
+#include "readDwarf.h"
#include <windows.h>
#include <map>
+#include <unordered_map>
extern "C" {
#include "mscvpdb.h"
@@ -158,7 +160,6 @@ public:
// DWARF
bool createDWARFModules();
- unsigned char* getDWARFAbbrev(int off, int n);
bool addDWARFTypes();
bool addDWARFLines();
bool addDWARFPublics();
@@ -166,16 +167,16 @@ public:
bool writeDWARFImage(const TCHAR* 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);
+ bool addDWARFProc(DWARF_InfoData& id, DWARF_CompilationUnit* cu, DIECursor cursor);
+ int addDWARFStructure(DWARF_InfoData& id, DWARF_CompilationUnit* cu, DIECursor cursor);
+ int addDWARFArray(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, DIECursor cursor);
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);
+ int getDWARFArrayBounds(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, DIECursor cursor, int& upperBound);
+
+ bool mapTypes();
+ bool createTypes();
// private:
BYTE* libraries;
@@ -255,7 +256,7 @@ public:
// DWARF
int codeSegOff;
- std::map<int, int> mapOffsetToType;
+ std::unordered_map<int, int> mapOffsetToType;
};
diff --git a/src/cv2pdb.vcxproj b/src/cv2pdb.vcxproj
index 3694a5b..00e669e 100644
--- a/src/cv2pdb.vcxproj
+++ b/src/cv2pdb.vcxproj
@@ -1,122 +1,125 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{5E2BD27D-446A-4C99-9829-135F7C000D90}</ProjectGuid>
- <RootNamespace>cv2pdb</RootNamespace>
- <Keyword>Win32Proj</Keyword>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <PlatformToolset>v120_xp</PlatformToolset>
- <CharacterSet>Unicode</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <PlatformToolset>v120_xp</PlatformToolset>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <OutDir>..\bin\$(Configuration)\</OutDir>
- <IntDir>..\bin\$(Configuration)\$(ProjectName)\</IntDir>
- <LinkIncremental>true</LinkIncremental>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <OutDir>..\bin\$(Configuration)\</OutDir>
- <IntDir>..\bin\$(Configuration)\$(ProjectName)\</IntDir>
- <LinkIncremental>false</LinkIncremental>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <AdditionalOptions>/wd4996 %(AdditionalOptions)</AdditionalOptions>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
- <PrecompiledHeader />
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- </ClCompile>
- <Link>
- <AdditionalDependencies>dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Console</SubSystem>
- <TargetMachine>MachineX86</TargetMachine>
- <MinimumRequiredVersion>5.1</MinimumRequiredVersion>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <AdditionalOptions>/wd4996 %(AdditionalOptions)</AdditionalOptions>
- <Optimization>MaxSpeed</Optimization>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
- <PrecompiledHeader />
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Console</SubSystem>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <TargetMachine>MachineX86</TargetMachine>
- <Profile>true</Profile>
- <MinimumRequiredVersion>5.1</MinimumRequiredVersion>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="cv2pdb.cpp" />
- <ClCompile Include="cvutil.cpp" />
- <ClCompile Include="demangle.cpp" />
- <ClCompile Include="dwarf2pdb.cpp" />
- <ClCompile Include="main.cpp" />
- <ClCompile Include="mspdb.cpp" />
- <ClCompile Include="PEImage.cpp" />
- <ClCompile Include="symutil.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="cv2pdb.h" />
- <ClInclude Include="cvutil.h" />
- <ClInclude Include="demangle.h" />
- <ClInclude Include="LastError.h" />
- <ClInclude Include="mscvpdb.h" />
- <ClInclude Include="mspdb.h" />
- <ClInclude Include="PEImage.h" />
- <ClInclude Include="symutil.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5E2BD27D-446A-4C99-9829-135F7C000D90}</ProjectGuid>
+ <RootNamespace>cv2pdb</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>..\bin\$(Configuration)\</OutDir>
+ <IntDir>..\bin\$(Configuration)\$(ProjectName)\</IntDir>
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>..\bin\$(Configuration)\</OutDir>
+ <IntDir>..\bin\$(Configuration)\$(ProjectName)\</IntDir>
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalOptions>/wd4996 %(AdditionalOptions)</AdditionalOptions>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
+ <PrecompiledHeader />
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <MinimumRequiredVersion>5.1</MinimumRequiredVersion>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions>/wd4996 %(AdditionalOptions)</AdditionalOptions>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
+ <PrecompiledHeader />
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <Profile>true</Profile>
+ <MinimumRequiredVersion>5.1</MinimumRequiredVersion>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="cv2pdb.cpp" />
+ <ClCompile Include="cvutil.cpp" />
+ <ClCompile Include="demangle.cpp" />
+ <ClCompile Include="dwarf2pdb.cpp" />
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="mspdb.cpp" />
+ <ClCompile Include="PEImage.cpp" />
+ <ClCompile Include="readDwarf.cpp" />
+ <ClCompile Include="symutil.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="cv2pdb.h" />
+ <ClInclude Include="cvutil.h" />
+ <ClInclude Include="demangle.h" />
+ <ClInclude Include="dwarf.h" />
+ <ClInclude Include="LastError.h" />
+ <ClInclude Include="mscvpdb.h" />
+ <ClInclude Include="mspdb.h" />
+ <ClInclude Include="PEImage.h" />
+ <ClInclude Include="readDwarf.h" />
+ <ClInclude Include="symutil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
</Project> \ No newline at end of file
diff --git a/src/cv2pdb.vcxproj.filters b/src/cv2pdb.vcxproj.filters
index 9807733..3bf032c 100644
--- a/src/cv2pdb.vcxproj.filters
+++ b/src/cv2pdb.vcxproj.filters
@@ -1,61 +1,70 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="cv2pdb.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="cvutil.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="demangle.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="dwarf2pdb.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="main.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="mspdb.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="PEImage.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="symutil.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="cv2pdb.h">
- <Filter>Source Files</Filter>
- </ClInclude>
- <ClInclude Include="cvutil.h">
- <Filter>Source Files</Filter>
- </ClInclude>
- <ClInclude Include="demangle.h">
- <Filter>Source Files</Filter>
- </ClInclude>
- <ClInclude Include="LastError.h">
- <Filter>Source Files</Filter>
- </ClInclude>
- <ClInclude Include="mscvpdb.h">
- <Filter>Source Files</Filter>
- </ClInclude>
- <ClInclude Include="mspdb.h">
- <Filter>Source Files</Filter>
- </ClInclude>
- <ClInclude Include="PEImage.h">
- <Filter>Source Files</Filter>
- </ClInclude>
- <ClInclude Include="symutil.h">
- <Filter>Source Files</Filter>
- </ClInclude>
- </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="cv2pdb.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="cvutil.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="demangle.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dwarf2pdb.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mspdb.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="PEImage.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="symutil.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="readDwarf.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="cv2pdb.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="cvutil.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="demangle.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="LastError.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mscvpdb.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mspdb.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="PEImage.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="symutil.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="readDwarf.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="dwarf.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp
index 13bb426..58228ab 100644
--- a/src/dwarf2pdb.cpp
+++ b/src/dwarf2pdb.cpp
@@ -21,546 +21,16 @@
#include <string>
#include <vector>
-///////////////////////////////////////////////////////////////////////////////
-
-unsigned int LEB128(unsigned char* &p)
-{
- unsigned int x = 0;
- int shift = 0;
- while(*p & 0x80)
- {
- x |= (*p & 0x7f) << shift;
- shift += 7;
- p++;
- }
- x |= *p << shift;
- p++;
- return x;
-}
-
-unsigned int LEB128(unsigned char* base, int& off)
-{
- unsigned char* p = base + off;
- unsigned int x = LEB128(p);
- off = p - base;
- return x;
-}
-
-int SLEB128(unsigned char* &p)
-{
- unsigned int x = 0;
- int shift = 0;
- while(*p & 0x80)
- {
- x |= (*p & 0x7f) << shift;
- shift += 7;
- p++;
- }
- x |= *p << shift;
- if(*p & 0x40)
- x |= -(1 << (shift + 7)); // sign extend
- p++;
- return x;
-}
-
-unsigned int RD2(unsigned char* p)
-{
- unsigned int x = *p++;
- x |= *p++ << 8;
- return x;
-}
-
-unsigned int RD4(unsigned char* p)
-{
- unsigned int x = *p++;
- x |= *p++ << 8;
- x |= *p++ << 16;
- x |= *p++ << 24;
- return x;
-}
-
-unsigned long long RD8(unsigned char* p)
-{
- unsigned long long x = *p++;
- for(int shift = 8; shift < 64; shift += 8)
- x |= (unsigned long long) *p++ << shift;
- return x;
-}
-
-unsigned long long RDsize(unsigned char* p, int size)
-{
- if(size > 8)
- size = 8;
- unsigned long long x = *p++;
- for(int shift = 8; shift < size * 8; shift += 8)
- x |= (unsigned long long) *p++ << shift;
- return x;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include "pshpack1.h"
-
-struct DWARF_CompilationUnit
-{
- unsigned int unit_length; // 12 byte in DWARF-64
- unsigned short version;
- unsigned int debug_abbrev_offset; // 8 byte in DWARF-64
- unsigned char address_size;
-
- bool isDWARF64() const { return unit_length == ~0; }
- int refSize() const { return unit_length == ~0 ? 8 : 4; }
-};
-
-struct DWARF_FileName
-{
- const char* file_name;
- unsigned int dir_index;
- unsigned long lastModification;
- unsigned long fileLength;
-
- void read(unsigned char* &p)
- {
- file_name = (const char*) p;
- p += strlen((const char*) p) + 1;
- dir_index = LEB128(p);
- lastModification = LEB128(p);
- fileLength = LEB128(p);
- }
-};
-
-struct DWARF_InfoData
-{
- int entryOff;
- int code;
- int tag;
- int hasChild;
-
- const char* name;
- const char* linkage_name;
- const char* dir;
- unsigned long byte_size;
- unsigned long sibling;
- unsigned long encoding;
- unsigned long pclo;
- unsigned long pchi;
- unsigned long ranges;
- unsigned long type;
- unsigned long containing_type;
- unsigned long specification;
- unsigned long inlined;
- unsigned long external;
- unsigned char*location_ptr;
- unsigned long location_len;
- unsigned char*member_location_ptr;
- unsigned long member_location_len;
- unsigned long member_location_data;
- unsigned long locationlist; // offset into debug_loc
- long frame_base;
- long upper_bound;
- long lower_bound;
-};
-
-static const int maximum_operations_per_instruction = 1;
-
-struct DWARF_LineNumberProgramHeader
-{
- unsigned int unit_length; // 12 byte in DWARF-64
- unsigned short version;
- unsigned int header_length; // 8 byte in DWARF-64
- unsigned char minimum_instruction_length;
- //unsigned char maximum_operations_per_instruction; (// not in DWARF 2
- unsigned char default_is_stmt;
- signed char line_base;
- unsigned char line_range;
- unsigned char opcode_base;
- //LEB128 standard_opcode_lengths[opcode_base];
- // string include_directories[] // zero byte terminated
- // DWARF_FileNames file_names[] // zero byte terminated
-};
-
-struct DWARF_LineState
-{
- // hdr info
- std::vector<const char*> include_dirs;
- std::vector<DWARF_FileName> files;
-
- unsigned long address;
- unsigned int op_index;
- unsigned int file;
- unsigned int line;
- unsigned int column;
- bool is_stmt;
- bool basic_block;
- bool end_sequence;
- bool prologue_end;
- bool epilogue_end;
- unsigned int isa;
- unsigned int discriminator;
-
- // not part of the "documented" state
- DWARF_FileName* file_ptr;
- unsigned long seg_offset;
- unsigned long last_addr;
- std::vector<mspdb::LineInfoEntry> lineInfo;
-
- DWARF_LineState()
- {
- seg_offset = 0x400000;
- init(0);
- }
-
- void init(DWARF_LineNumberProgramHeader* hdr)
- {
- address = 0;
- op_index = 0;
- file = 1;
- line = 1;
- column = 0;
- is_stmt = hdr && hdr->default_is_stmt != 0;
- basic_block = false;
- end_sequence = false;
- prologue_end = false;
- epilogue_end = false;
- isa = 0;
- discriminator = 0;
- }
-
- void advance_addr(DWARF_LineNumberProgramHeader* hdr, int operation_advance)
- {
- int address_advance = hdr->minimum_instruction_length * ((op_index + operation_advance) / maximum_operations_per_instruction);
- address += address_advance;
- op_index = (op_index + operation_advance) % maximum_operations_per_instruction;
- }
-
- void addLineInfo()
- {
-#if 0
- const char* fname = (file == 0 ? file_ptr->file_name : files[file - 1].file_name);
- printf("Adr:%08x Line: %5d File: %s\n", address, line, fname);
-#endif
- if(address < seg_offset)
- return;
- mspdb::LineInfoEntry entry;
- entry.offset = address - seg_offset;
- entry.line = line;
- lineInfo.push_back(entry);
- }
-};
-
-#include "poppack.h"
-
-///////////////////////////////////////////////////////////////////////////////
-
-long decodeLocation(unsigned char* loc, long len, bool push0, int &id, int& size)
-{
- unsigned char* p = loc;
- long stack[8] = {0};
- int stackDepth = push0 ? 1 : 0;
- long data = 0;
- id = push0 ? S_CONSTANT_V2 : -1;
- do
- {
- if(p - loc >= len)
- break;
-
- int op = *p++;
- if(op == 0)
- break;
- size = 0;
-
- switch(op)
- {
- case DW_OP_addr: id = S_GDATA_V2; size = 4; stack[stackDepth++] = RD4(p); break;
- case DW_OP_fbreg: id = S_BPREL_V2; stack[stackDepth++] = SLEB128(p); break;
- case DW_OP_const1u: id = S_CONSTANT_V2; size = 1; stack[stackDepth++] = *p; break;
- case DW_OP_const2u: id = S_CONSTANT_V2; size = 2; stack[stackDepth++] = RD2(p); break;
- case DW_OP_const4u: id = S_CONSTANT_V2; size = 4; stack[stackDepth++] = RD4(p); break;
- case DW_OP_const1s: id = S_CONSTANT_V2; size = 1; stack[stackDepth++] = (char)*p; break;
- case DW_OP_const2s: id = S_CONSTANT_V2; size = 2; stack[stackDepth++] = (short)RD2(p); break;
- case DW_OP_const4s: id = S_CONSTANT_V2; size = 4; stack[stackDepth++] = (int)RD4(p); break;
- case DW_OP_constu: id = S_CONSTANT_V2; stack[stackDepth++] = LEB128(p); break;
- case DW_OP_consts: id = S_CONSTANT_V2; stack[stackDepth++] = SLEB128(p); break;
- case DW_OP_plus_uconst: stack[stackDepth-1] += 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;
- stack[stackDepth++] = 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 = ( op == DW_OP_breg4 ? S_BPREL_XXXX_V3 : op == DW_OP_breg5 ? S_BPREL_V2 : S_REGISTER_V2 );
- stack[stackDepth++] = SLEB128(p);
- break;
- case DW_OP_bregx:
- data = LEB128(p); // reg
- id = ( data == DW_OP_breg4 ? S_BPREL_XXXX_V3 : data == DW_OP_breg5 ? S_BPREL_V2 : S_REGISTER_V2 );
- stack[stackDepth++] = SLEB128(p);
- break;
-
- case DW_OP_deref: break;
- case DW_OP_deref_size: size = 1; break;
- case DW_OP_dup: stack[stackDepth] = stack[stackDepth-1]; stackDepth++; break;
- case DW_OP_drop: stackDepth--; break;
- case DW_OP_over: stack[stackDepth] = stack[stackDepth-2]; stackDepth++; break;
- case DW_OP_pick: size = 1; stack[stackDepth++] = stack[*p]; break;
- case DW_OP_swap: data = stack[stackDepth-1]; stack[stackDepth-1] = stack[stackDepth-2]; stack[stackDepth-2] = data; break;
- case DW_OP_rot: data = stack[stackDepth-1]; stack[stackDepth-1] = stack[stackDepth-2]; stack[stackDepth-2] = stack[stackDepth-3]; stack[stackDepth-3] = data; 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: stack[stackDepth++] = -1; break; // default stack offset?
- 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");
- id = -1;
- return 0;
-
- // unary operations pop and push
- case DW_OP_abs: stack[stackDepth-1] = abs(stack[stackDepth-1]); break;
- case DW_OP_neg: stack[stackDepth-1] = -stack[stackDepth-1]; break;
- case DW_OP_not: stack[stackDepth-1] = ~stack[stackDepth-1]; break;
- break;
- // binary operations pop twice and push
- case DW_OP_and: stack[stackDepth-2] = stack[stackDepth-2] & stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_div: stack[stackDepth-2] = stack[stackDepth-2] / stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_minus: stack[stackDepth-2] = stack[stackDepth-2] - stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_mod: stack[stackDepth-2] = stack[stackDepth-2] % stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_mul: stack[stackDepth-2] = stack[stackDepth-2] * stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_or: stack[stackDepth-2] = stack[stackDepth-2] | stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_plus: stack[stackDepth-2] = stack[stackDepth-2] + stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_shl: stack[stackDepth-2] = stack[stackDepth-2] << stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_shr: stack[stackDepth-2] = stack[stackDepth-2] >> stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_shra: stack[stackDepth-2] = stack[stackDepth-2] >> stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_xor: stack[stackDepth-2] = stack[stackDepth-2] ^ stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_eq: stack[stackDepth-2] = stack[stackDepth-2] == stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_ge: stack[stackDepth-2] = stack[stackDepth-2] >= stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_gt: stack[stackDepth-2] = stack[stackDepth-2] > stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_le: stack[stackDepth-2] = stack[stackDepth-2] <= stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_lt: stack[stackDepth-2] = stack[stackDepth-2] < stack[stackDepth-1]; stackDepth--; break;
- case DW_OP_ne: stack[stackDepth-2] = stack[stackDepth-2] != stack[stackDepth-1]; stackDepth--; break;
-
- case DW_OP_bra:
- case DW_OP_skip:
- size = RD2(p) + 2;
- break;
- }
- p += size;
- }
- while(stackDepth > 0);
- size = p - loc;
- return stack[0];
-}
-
-
-long decodeLocation(unsigned char*loc, long len, bool push0, int &id)
-{
- int size;
- return decodeLocation(loc, len, push0, 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.linkage_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.external = 0;
- id.member_location_ptr = 0;
- id.member_location_len = 0;
- id.member_location_data = 0;
- id.location_ptr = 0;
- id.location_len = 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;
- int locid;
- 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); lldata = decodeLocation(p, size, false, locid); data = (unsigned long) lldata; isRef = true; break;
- case DW_FORM_flag_present: size = 0; lldata = data = 1; break;
- case DW_FORM_ref_sig8: size = 8; break;
- case DW_FORM_sec_offset: size = img.isX64() ? 8 : 4; lldata = RDsize(p, size); data = (unsigned long) lldata; isRef = true; break;
- case DW_FORM_indirect:
- 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_MIPS_linkage_name: id.linkage_name = str; break;
- case DW_AT_comp_dir: id.dir = str; break;
- case DW_AT_low_pc: id.pclo = addr; break;
- case DW_AT_high_pc:
- if(form == DW_FORM_addr)
- id.pchi = addr;
- else
- id.pchi = id.pclo + data;
- break;
- case DW_AT_ranges: id.ranges = data; break;
- case DW_AT_type: id.type = data; break;
- case DW_AT_inline: id.inlined = data; break;
- case DW_AT_external: id.external = data; break;
- case DW_AT_upper_bound: id.upper_bound = data; break;
- case DW_AT_lower_bound: id.lower_bound = data; break;
- case DW_AT_containing_type: id.containing_type = data; break;
- case DW_AT_specification: id.specification = data; break;
- case DW_AT_data_member_location:
- if(form == DW_FORM_block1 || form == DW_FORM_exprloc)
- id.member_location_ptr = p, id.member_location_len = size;
- else
- id.member_location_data = data;
- break;
- case DW_AT_location:
- if(form == DW_FORM_block1 || form == DW_FORM_exprloc)
- id.location_ptr = p, id.location_len = size;
- 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;
+ //allocDwarfTypes += size + add;
+ allocDwarfTypes += allocDwarfTypes/2 + size + add;
dwarfTypes = (BYTE*) realloc(dwarfTypes, allocDwarfTypes);
+ if (dwarfTypes == nullptr)
+ __debugbreak();
}
}
@@ -664,13 +134,11 @@ void CV2PDB::appendLexicalBlock(DWARF_InfoData& id, unsigned int proclo)
cbUdtSymbols += len;
}
-bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu,
- unsigned char* &locals, unsigned char* end)
+bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, DIECursor cursor)
{
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;
@@ -739,75 +207,64 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu,
}
#endif
}
- if(cu && locals && length)
+
+ if (cu)
{
bool endarg = false;
- unsigned char* p = locals;
- unsigned char* end = locals + length;
DWARF_InfoData id;
int off = 8;
int cvid;
- std::vector<unsigned char*> lexicalBlockEnd;
- lexicalBlockEnd.push_back(end);
- while(lexicalBlockEnd.size() > 0)
+ DIECursor prev = cursor;
+ while (cursor.readSibling(id) && id.tag == DW_TAG_formal_parameter)
{
- 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)
+ if (id.name)
{
off = decodeLocation(id.location_ptr, id.location_len, false, cvid);
- if(cvid == S_BPREL_V2)
+ if (cvid == S_BPREL_V2)
appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff, false);
- else if(cvid == S_BPREL_XXXX_V3)
+ else if (cvid == S_BPREL_XXXX_V3)
appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off, true);
}
}
- else
+ prev = cursor;
+ }
+ appendEndArg();
+
+ std::vector<DIECursor> lexicalBlocks;
+ lexicalBlocks.push_back(prev);
+
+ while (!lexicalBlocks.empty())
+ {
+ cursor = lexicalBlocks.back();
+ lexicalBlocks.pop_back();
+
+ while (cursor.readSibling(id))
{
- if(!endarg)
- endarg = appendEndArg();
- switch(id.tag)
+ if (id.tag == DW_TAG_variable)
{
- case DW_TAG_variable:
- if(id.name)
- {
- off = decodeLocation(id.location_ptr, id.location_len, false, cvid);
- if(cvid == S_BPREL_V2)
- appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff, false);
- else if(cvid == S_BPREL_XXXX_V3)
- appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off, true);
- }
- 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;
+ if (id.name)
+ {
+ off = decodeLocation(id.location_ptr, id.location_len, false, cvid);
+ if (cvid == S_BPREL_V2)
+ appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff, false);
+ else if (cvid == S_BPREL_XXXX_V3)
+ appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off, true);
+ }
+ }
+ else if (id.tag == DW_TAG_lexical_block)
+ {
+ if (id.hasChild && id.pchi != id.pclo)
+ {
+ appendLexicalBlock(id, pclo + codeSegOff);
+ lexicalBlocks.push_back(cursor);
+ cursor = cursor.getSubtreeCursor();
+ }
}
}
+ appendEnd();
}
}
else
@@ -818,15 +275,15 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu,
return true;
}
-int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* cu,
- unsigned char* &locals, unsigned char* end)
+int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* cu, DIECursor cursor)
{
+ printf("Adding struct %s, entryoff %d, abbrev %d\n", structid.name, structid.entryOff, structid.abbrev);
+
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)
+ if (cu)
{
checkDWARFTypeAlloc(100);
codeview_reftype* fl = (codeview_reftype*) (dwarfTypes + cbDwarfTypes);
@@ -848,19 +305,15 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c
nfields++;
}
#endif
- unsigned char* p = locals;
- unsigned char* end = locals + length;
DWARF_InfoData id;
int len = 0;
- while(p < end)
+ while (cursor.readSibling(id))
{
- if(!readDWARFInfoData(id, cu, p))
- continue;
-
int cvid = -1;
if (id.tag == DW_TAG_member && id.name)
{
- int off = 0;
+ printf(" Adding field %s\n", id.name);
+ int off = 0;
if(!isunion)
{
if(id.member_location_ptr)
@@ -881,7 +334,7 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c
}
else if(id.tag == DW_TAG_inheritance)
{
- int off = decodeLocation(id.member_location_ptr, id.member_location_len, true, cvid);
+ int off = decodeLocation(id.member_location_ptr, id.member_location_len, true, cvid);
if(cvid == S_CONSTANT_V2)
{
codeview_fieldtype* bc = (codeview_fieldtype*) (dwarfTypes + cbDwarfTypes);
@@ -895,8 +348,6 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c
nfields++;
}
}
- if(id.sibling)
- p = (unsigned char*) cu + id.sibling;
}
fl = (codeview_reftype*) (dwarfTypes + flbegin);
fl->fieldlist.len = cbDwarfTypes - flbegin - 2;
@@ -918,39 +369,30 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c
}
int CV2PDB::getDWARFArrayBounds(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu,
- unsigned char* &locals, unsigned char* end, int& upperBound)
+ DIECursor cursor, int& upperBound)
{
- int length = arrayid.hasChild ? end - locals : 0;
int lowerBound = 0;
- if(cu && locals && length)
+ if (cu)
{
- unsigned char* p = locals;
- unsigned char* end = locals + length;
DWARF_InfoData id;
- int len = 0;
- while(p < end)
+ while (cursor.readSibling(id))
{
- 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)
+ DIECursor cursor)
{
- int upperBound, lowerBound = getDWARFArrayBounds(arrayid, cu, locals, end, upperBound);
+ int upperBound, lowerBound = getDWARFArrayBounds(arrayid, cu, cursor, upperBound);
checkUserTypeAlloc(kMaxNameLen + 100);
codeview_type* cvt = (codeview_type*) (userTypes + cbUserTypes);
@@ -1100,7 +542,7 @@ int CV2PDB::addDWARFBasicType(const char*name, int encoding, int byte_size)
int CV2PDB::getTypeByDWARFOffset(DWARF_CompilationUnit* cu, int off)
{
int cuoff = (char*) cu - img.debug_info;
- std::map<int,int>::iterator it = mapOffsetToType.find(cuoff + off);
+ std::unordered_map<int,int>::iterator it = mapOffsetToType.find(cuoff + off);
if(it == mapOffsetToType.end())
return 0x03; // void
return it->second;
@@ -1109,8 +551,9 @@ int CV2PDB::getTypeByDWARFOffset(DWARF_CompilationUnit* cu, int off)
int CV2PDB::getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff)
{
DWARF_InfoData id;
- unsigned char* p = (unsigned char*) cu + typeOff;
- if(!readDWARFInfoData(id, cu, p))
+ DIECursor cursor(cu, typeOff);
+
+ if (!cursor.readNext(id))
return 0;
if(id.byte_size > 0)
return id.byte_size;
@@ -1123,7 +566,7 @@ int CV2PDB::getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff)
return cu->address_size;
case DW_TAG_array_type:
{
- int upperBound, lowerBound = getDWARFArrayBounds(id, cu, p, p + 1, upperBound);
+ int upperBound, lowerBound = getDWARFArrayBounds(id, cu, cursor, upperBound);
return (upperBound + lowerBound + 1) * getDWARFTypeSize(cu, id.type);
}
default:
@@ -1134,51 +577,22 @@ int CV2PDB::getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff)
return 0;
}
-enum iterateOp { kOpMapTypes, kOpCreateTypes };
-
-bool CV2PDB::iterateDWARFDebugInfo(int op)
+bool CV2PDB::mapTypes()
{
- mspdb::Mod* mod = globalMod();
int typeID = nextUserType;
-
- int pointerAttr = img.isX64() ? 0x1000C : 0x800A;
- for(unsigned long off = 0; off < img.debug_info_length; )
+ unsigned long off = 0;
+ while (off < img.debug_info_length)
{
- DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*) (img.debug_info + off);
- int length = cu->unit_length;
- if(length < 0)
- break;
+ DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*)(img.debug_info + off);
- length += sizeof(length);
- unsigned char* end = (unsigned char*) cu + length;
- std::vector<unsigned char*> endStack;
- endStack.push_back(end);
-
- for(unsigned char* p = (unsigned char*) (cu + 1); endStack.size() > 0; )
+ DIECursor cursor(cu, sizeof(DWARF_CompilationUnit));
+ DWARF_InfoData id;
+ while (cursor.readNext(id))
{
- if(p >= endStack.back())
- {
- endStack.pop_back();
- continue;
- }
- DWARF_InfoData id;
- if(!readDWARFInfoData(id, cu, p))
- continue;
- if(id.specification)
+ //printf("0x%08x, level = %d, id.code = %d, id.tag = %d\n",
+ // (unsigned char*)cu + id.entryOff - (unsigned char*)img.debug_info, cursor.level, id.code, id.tag);
+ switch (id.tag)
{
- 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:
@@ -1205,144 +619,167 @@ bool CV2PDB::iterateDWARFDebugInfo(int op)
case DW_TAG_mutable_type: // withdrawn
case DW_TAG_shared_type:
case DW_TAG_rvalue_reference_type:
- mapOffsetToType.insert(std::pair<int,int>(off + id.entryOff, typeID));
+ mapOffsetToType.insert(std::pair<int, int>(off + id.entryOff, typeID));
typeID++;
- }
}
- else
- {
- int cvtype = -1;
- switch(id.tag)
- {
- case DW_TAG_base_type:
- cvtype = addDWARFBasicType(id.name, id.encoding, id.byte_size);
- break;
- case DW_TAG_typedef:
- cvtype = appendModifierType(getTypeByDWARFOffset(cu, id.type), 0);
- addUdtSymbol(cvtype, id.name);
- break;
- case DW_TAG_pointer_type:
- cvtype = appendPointerType(getTypeByDWARFOffset(cu, id.type), pointerAttr);
- break;
- case DW_TAG_const_type:
- cvtype = appendModifierType(getTypeByDWARFOffset(cu, id.type), 1);
- break;
- case DW_TAG_reference_type:
- cvtype = appendPointerType(getTypeByDWARFOffset(cu, id.type), pointerAttr | 0x20);
- break;
+ }
- case DW_TAG_class_type:
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- cvtype = addDWARFStructure(id, cu, p, endStack.back());
- break;
- case DW_TAG_array_type:
- cvtype = addDWARFArray(id, cu, p, endStack.back());
- break;
- case DW_TAG_subroutine_type:
- case DW_TAG_subrange_type:
+ off += sizeof(cu->unit_length) + cu->unit_length;
+ }
- 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;
+ nextDwarfType = typeID;
+ return true;
+}
- 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;
+bool CV2PDB::createTypes()
+{
+ mspdb::Mod* mod = globalMod();
+ int typeID = nextUserType;
+ int pointerAttr = img.isX64() ? 0x1000C : 0x800A;
- case DW_TAG_compile_unit:
- #if !FULL_CONTRIB
- if(id.dir && id.name)
+ unsigned long off = 0;
+ while (off < img.debug_info_length)
+ {
+ DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*)(img.debug_info + off);
+
+ DIECursor cursor(cu, sizeof(DWARF_CompilationUnit));
+ DWARF_InfoData id;
+ while (cursor.readNext(id))
+ {
+ //printf("0x%08x, level = %d, id.code = %d, id.tag = %d\n",
+ // (unsigned char*)cu + id.entryOff - (unsigned char*)img.debug_info, cursor.level, id.code, id.tag);
+
+ 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, cursor.getSubtreeCursor());
+ break;
+ case DW_TAG_array_type:
+ cvtype = addDWARFArray(id, cu, cursor.getSubtreeCursor());
+ 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, cursor.getSubtreeCursor());
+ 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)
{
- 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
+ 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, id.pclo, id.pchi))
+ if (!addDWARFSectionContrib(mod, pclo, pchi))
return false;
}
}
- #endif
- break;
-
- case DW_TAG_variable:
- if(id.name)
+ else
{
- int seg = -1;
- unsigned long segOff;
- if(id.location_ptr == 0 && id.external && id.linkage_name)
- {
- seg = img.findSymbol(id.linkage_name, segOff);
- }
- else
- {
- int cvid;
- segOff = decodeLocation(id.location_ptr, id.location_len, false, cvid);
- if(cvid == S_GDATA_V2)
- seg = img.findSection(segOff);
- if(seg >= 0)
- segOff -= img.getImageBase() + img.getSection(seg).VirtualAddress;
- }
- if(seg >= 0)
- {
- int type = getTypeByDWARFOffset(cu, id.type);
- appendGlobalVar(id.name, type, seg + 1, segOff);
- int rc = mod->AddPublic2(id.name, seg + 1, segOff, type);
- }
+ //printf("%s %s %x - %x\n", dir, name, pclo, pchi);
+ if (!addDWARFSectionContrib(mod, id.pclo, id.pchi))
+ return false;
}
- break;
- case DW_TAG_formal_parameter:
- case DW_TAG_unspecified_parameters:
- case DW_TAG_inheritance:
- case DW_TAG_member:
- case DW_TAG_inlined_subroutine:
- case DW_TAG_lexical_block:
- default:
- break;
}
- if(cvtype >= 0)
+#endif
+ break;
+
+ case DW_TAG_variable:
+ if (id.name)
{
- assert(cvtype == typeID); typeID++;
- assert(mapOffsetToType[off + id.entryOff] == cvtype);
+ int seg = -1;
+ unsigned long segOff;
+ if (id.location_ptr == 0 && id.external && id.linkage_name)
+ {
+ seg = img.findSymbol(id.linkage_name, segOff);
+ }
+ else
+ {
+ int cvid;
+ segOff = decodeLocation(id.location_ptr, id.location_len, false, cvid);
+ if (cvid == S_GDATA_V2)
+ seg = img.findSection(segOff);
+ if (seg >= 0)
+ segOff -= img.getImageBase() + img.getSection(seg).VirtualAddress;
+ }
+ if (seg >= 0)
+ {
+ int type = getTypeByDWARFOffset(cu, id.type);
+ appendGlobalVar(id.name, type, seg + 1, segOff);
+ int rc = mod->AddPublic2(id.name, seg + 1, segOff, type);
+ }
}
+ break;
+ case DW_TAG_formal_parameter:
+ case DW_TAG_unspecified_parameters:
+ case DW_TAG_inheritance:
+ case DW_TAG_member:
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_lexical_block:
+ default:
+ break;
+ }
+
+ if (cvtype >= 0)
+ {
+ assert(cvtype == typeID); typeID++;
+ int x = mapOffsetToType[off + id.entryOff];
+ assert(mapOffsetToType[off + id.entryOff] == cvtype);
}
}
- off += length;
+
+ off += sizeof(cu->unit_length) + cu->unit_length;
}
-
- if(op == kOpMapTypes)
- nextDwarfType = typeID;
return true;
}
@@ -1387,11 +824,20 @@ bool CV2PDB::createDWARFModules()
appendComplex(0x52, 0x42, 12, "creal");
}
+ DIECursor::setContext(&img);
+
countEntries = 0;
+ if (!mapTypes())
+ return false;
+ if (!createTypes())
+ return false;
+
+ /*
if(!iterateDWARFDebugInfo(kOpMapTypes))
return false;
if(!iterateDWARFDebugInfo(kOpCreateTypes))
return false;
+ */
#if 0
modules = new mspdb::Mod* [countEntries];
diff --git a/src/readDwarf.cpp b/src/readDwarf.cpp
new file mode 100644
index 0000000..0d298bb
--- /dev/null
+++ b/src/readDwarf.cpp
@@ -0,0 +1,392 @@
+#include "readDwarf.h"
+#include <assert.h>
+#include <unordered_map>
+#include <array>
+#include <windows.h>
+
+#include "PEImage.h"
+#include "dwarf.h"
+#include "mspdb.h"
+extern "C" {
+ #include "mscvpdb.h"
+}
+
+long decodeLocation(unsigned char* loc, long len, bool push0, int &id, int& size)
+{
+ unsigned char* p = loc;
+ long stack[8] = { 0 };
+ int stackDepth = push0 ? 1 : 0;
+ long data = 0;
+ id = push0 ? S_CONSTANT_V2 : -1;
+ do
+ {
+ if (p - loc >= len)
+ break;
+
+ int op = *p++;
+ if (op == 0)
+ break;
+ size = 0;
+
+ switch (op)
+ {
+ case DW_OP_addr: id = S_GDATA_V2; size = 4; stack[stackDepth++] = RD4(p); break;
+ case DW_OP_fbreg: id = S_BPREL_V2; stack[stackDepth++] = SLEB128(p); break;
+ case DW_OP_const1u: id = S_CONSTANT_V2; size = 1; stack[stackDepth++] = *p; break;
+ case DW_OP_const2u: id = S_CONSTANT_V2; size = 2; stack[stackDepth++] = RD2(p); break;
+ case DW_OP_const4u: id = S_CONSTANT_V2; size = 4; stack[stackDepth++] = RD4(p); break;
+ case DW_OP_const1s: id = S_CONSTANT_V2; size = 1; stack[stackDepth++] = (char)*p; break;
+ case DW_OP_const2s: id = S_CONSTANT_V2; size = 2; stack[stackDepth++] = (short)RD2(p); break;
+ case DW_OP_const4s: id = S_CONSTANT_V2; size = 4; stack[stackDepth++] = (int)RD4(p); break;
+ case DW_OP_constu: id = S_CONSTANT_V2; stack[stackDepth++] = LEB128(p); break;
+ case DW_OP_consts: id = S_CONSTANT_V2; stack[stackDepth++] = SLEB128(p); break;
+ case DW_OP_plus_uconst: stack[stackDepth - 1] += 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;
+ stack[stackDepth++] = 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 = (op == DW_OP_breg4 ? S_BPREL_XXXX_V3 : op == DW_OP_breg5 ? S_BPREL_V2 : S_REGISTER_V2);
+ stack[stackDepth++] = SLEB128(p);
+ break;
+ case DW_OP_bregx:
+ data = LEB128(p); // reg
+ id = (data == DW_OP_breg4 ? S_BPREL_XXXX_V3 : data == DW_OP_breg5 ? S_BPREL_V2 : S_REGISTER_V2);
+ stack[stackDepth++] = SLEB128(p);
+ break;
+
+ case DW_OP_deref: break;
+ case DW_OP_deref_size: size = 1; break;
+ case DW_OP_dup: stack[stackDepth] = stack[stackDepth - 1]; stackDepth++; break;
+ case DW_OP_drop: stackDepth--; break;
+ case DW_OP_over: stack[stackDepth] = stack[stackDepth - 2]; stackDepth++; break;
+ case DW_OP_pick: size = 1; stack[stackDepth++] = stack[*p]; break;
+ case DW_OP_swap: data = stack[stackDepth - 1]; stack[stackDepth - 1] = stack[stackDepth - 2]; stack[stackDepth - 2] = data; break;
+ case DW_OP_rot: data = stack[stackDepth - 1]; stack[stackDepth - 1] = stack[stackDepth - 2]; stack[stackDepth - 2] = stack[stackDepth - 3]; stack[stackDepth - 3] = data; 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: stack[stackDepth++] = -1; break; // default stack offset?
+ 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");
+ id = -1;
+ return 0;
+
+ // unary operations pop and push
+ case DW_OP_abs: stack[stackDepth - 1] = abs(stack[stackDepth - 1]); break;
+ case DW_OP_neg: stack[stackDepth - 1] = -stack[stackDepth - 1]; break;
+ case DW_OP_not: stack[stackDepth - 1] = ~stack[stackDepth - 1]; break;
+ break;
+ // binary operations pop twice and push
+ case DW_OP_and: stack[stackDepth - 2] = stack[stackDepth - 2] & stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_div: stack[stackDepth - 2] = stack[stackDepth - 2] / stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_minus: stack[stackDepth - 2] = stack[stackDepth - 2] - stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_mod: stack[stackDepth - 2] = stack[stackDepth - 2] % stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_mul: stack[stackDepth - 2] = stack[stackDepth - 2] * stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_or: stack[stackDepth - 2] = stack[stackDepth - 2] | stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_plus: stack[stackDepth - 2] = stack[stackDepth - 2] + stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_shl: stack[stackDepth - 2] = stack[stackDepth - 2] << stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_shr: stack[stackDepth - 2] = stack[stackDepth - 2] >> stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_shra: stack[stackDepth - 2] = stack[stackDepth - 2] >> stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_xor: stack[stackDepth - 2] = stack[stackDepth - 2] ^ stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_eq: stack[stackDepth - 2] = stack[stackDepth - 2] == stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_ge: stack[stackDepth - 2] = stack[stackDepth - 2] >= stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_gt: stack[stackDepth - 2] = stack[stackDepth - 2] > stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_le: stack[stackDepth - 2] = stack[stackDepth - 2] <= stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_lt: stack[stackDepth - 2] = stack[stackDepth - 2] < stack[stackDepth - 1]; stackDepth--; break;
+ case DW_OP_ne: stack[stackDepth - 2] = stack[stackDepth - 2] != stack[stackDepth - 1]; stackDepth--; break;
+
+ case DW_OP_bra:
+ case DW_OP_skip:
+ size = RD2(p) + 2;
+ break;
+ }
+ p += size;
+ } while (stackDepth > 0);
+ size = p - loc;
+ return stack[0];
+}
+
+
+// declare hasher for pair<T1,T2>
+namespace std
+{
+ template<typename T1, typename T2>
+ struct hash<std::pair<T1, T2>>
+ {
+ size_t operator()(const std::pair<T1, T2>& t)
+ {
+ return std::hash<T1>()(t.first) ^ std::hash<T2>()(t.second);
+ }
+ };
+}
+
+typedef std::unordered_map<std::pair<unsigned, unsigned>, unsigned char*> abbrevMap_t;
+
+static PEImage* img;
+static abbrevMap_t abbrevMap;
+
+void DIECursor::setContext(PEImage* img_)
+{
+ img = img_;
+ abbrevMap.clear();
+}
+
+
+DIECursor::DIECursor(DWARF_CompilationUnit* cu_, unsigned long offset)
+{
+ cu = cu_;
+ ptr = (unsigned char*)cu + offset;
+ level = 0;
+ hasChild = false;
+ sibling = 0;
+}
+
+
+bool DIECursor::readSibling(DWARF_InfoData& id)
+{
+ if (sibling)
+ {
+ // use sibling pointer, if available
+ ptr = (unsigned char*)cu + sibling;
+ hasChild = false;
+ }
+ else if (hasChild)
+ {
+ int currLevel = level;
+ level = currLevel + 1;
+ hasChild = false;
+
+ DWARF_InfoData dummy;
+ // read untill we pop back to the level we were at
+ while (level > currLevel)
+ readNext(dummy);
+ }
+
+ return readNext(id, true);
+}
+
+DIECursor DIECursor::getSubtreeCursor()
+{
+ if (hasChild)
+ {
+ DIECursor subtree = *this;
+ subtree.level = 0;
+ subtree.hasChild = false;
+ return subtree;
+ }
+ else // Return invalid cursor
+ {
+ DIECursor subtree = *this;
+ subtree.level = -1;
+ return subtree;
+ }
+}
+
+bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull)
+{
+ id.clear();
+
+ if (hasChild)
+ ++level;
+
+ for (;;)
+ {
+ if (level == -1)
+ return false; // we were already at the end of the subtree
+
+ if (ptr >= ((unsigned char*)cu + sizeof(cu->unit_length) + cu->unit_length))
+ return false; // root of the tree does not have a null terminator, but we know the length
+
+ id.entryOff = ptr - (unsigned char*)cu;
+ id.code = LEB128(ptr);
+ if (id.code == 0)
+ {
+ --level; // pop up one level
+ if (stopAtNull)
+ {
+ hasChild = false;
+ return false;
+ }
+ continue; // read the next DIE
+ }
+
+ break;
+ }
+
+ unsigned char* abbrev = getDWARFAbbrev(cu->debug_abbrev_offset, id.code);
+ assert(abbrev);
+ if (!abbrev)
+ return false;
+
+ id.abbrev = abbrev;
+ id.tag = LEB128(abbrev);
+ id.hasChild = *abbrev++;
+
+ 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;
+ int locid;
+ bool isRef = false;
+ switch (form)
+ {
+ case DW_FORM_addr: addr = *(unsigned long *)ptr; size = cu->address_size; break;
+ case DW_FORM_block2: size = RD2(ptr) + 2; break;
+ case DW_FORM_block4: size = RD4(ptr) + 4; break;
+ case DW_FORM_data2: size = 2; lldata = data = RD2(ptr); break;
+ case DW_FORM_data4: size = 4; lldata = data = RD4(ptr); break;
+ case DW_FORM_data8: size = 8; lldata = RD8(ptr); data = (unsigned long)lldata; break;
+ case DW_FORM_string: str = (const char*)ptr; size = strlen(str) + 1; break;
+ case DW_FORM_block: size = LEB128(ptr); lldata = RDsize(ptr, size); data = (unsigned long)lldata; break;
+ case DW_FORM_block1: size = *ptr++; lldata = RDsize(ptr, size); data = (unsigned long)lldata; break;
+ case DW_FORM_data1: size = 1; lldata = data = *ptr; break;
+ case DW_FORM_flag: size = 1; lldata = data = *ptr; break;
+ case DW_FORM_sdata: lldata = data = SLEB128(ptr); size = 0; break;
+ case DW_FORM_strp: size = cu->refSize(); str = (const char*)(img->debug_str + RDsize(ptr, size)); break;
+ case DW_FORM_udata: lldata = data = LEB128(ptr); size = 0; break;
+ case DW_FORM_ref_addr: size = cu->address_size; lldata = RDsize(ptr, size); data = (unsigned long)lldata; isRef = true; break;
+ case DW_FORM_ref1: size = 1; lldata = data = *ptr; isRef = true; break;
+ case DW_FORM_ref2: size = 2; lldata = data = RD2(ptr); isRef = true; break;
+ case DW_FORM_ref4: size = 4; lldata = data = RD4(ptr); isRef = true; break;
+ case DW_FORM_ref8: size = 8; lldata = RD8(ptr); data = (unsigned long)lldata; isRef = true; break;
+ case DW_FORM_ref_udata: lldata = data = LEB128(ptr); size = 0; isRef = true; break;
+ case DW_FORM_exprloc: size = LEB128(ptr); lldata = decodeLocation(ptr, size, false, locid); data = (unsigned long)lldata; isRef = true; break;
+ case DW_FORM_flag_present: size = 0; lldata = data = 1; break;
+ case DW_FORM_ref_sig8: size = 8; break;
+ case DW_FORM_sec_offset: size = img->isX64() ? 8 : 4; lldata = RDsize(ptr, size); data = (unsigned long)lldata; isRef = true; break;
+ case DW_FORM_indirect:
+ default: assert(false && "Unsupported DWARF attribute form"); return false;
+ }
+ 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_MIPS_linkage_name: id.linkage_name = str; break;
+ case DW_AT_comp_dir: id.dir = str; break;
+ case DW_AT_low_pc: id.pclo = addr; break;
+ case DW_AT_high_pc:
+ if (form == DW_FORM_addr)
+ id.pchi = addr;
+ else
+ id.pchi = id.pclo + data;
+ break;
+ case DW_AT_ranges: id.ranges = data; break;
+ case DW_AT_type: id.type = data; break;
+ case DW_AT_inline: id.inlined = data; break;
+ case DW_AT_external: id.external = data; break;
+ case DW_AT_upper_bound: id.upper_bound = data; break;
+ case DW_AT_lower_bound: id.lower_bound = data; break;
+ case DW_AT_containing_type: id.containing_type = data; break;
+ case DW_AT_specification: id.specification = data; break;
+ case DW_AT_data_member_location:
+ if (form == DW_FORM_block1 || form == DW_FORM_exprloc)
+ id.member_location_ptr = ptr, id.member_location_len = size;
+ else
+ id.member_location_data = data;
+ break;
+ case DW_AT_location:
+ if (form == DW_FORM_block1 || form == DW_FORM_exprloc)
+ id.location_ptr = ptr, id.location_len = size;
+ 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;
+ }
+ ptr += size;
+ }
+
+ hasChild = id.hasChild != 0;
+ sibling = id.sibling;
+
+ return true;
+}
+
+unsigned char* DIECursor::getDWARFAbbrev(unsigned off, unsigned findcode)
+{
+ if (!img->debug_abbrev)
+ return 0;
+
+ std::pair<unsigned, unsigned> key = std::make_pair(off, findcode);
+ abbrevMap_t::iterator it = abbrevMap.find(key);
+ if (it != abbrevMap.end())
+ {
+ return it->second;
+ }
+
+ unsigned char* p = (unsigned char*)img->debug_abbrev + off;
+ unsigned char* end = (unsigned char*)img->debug_abbrev + img->debug_abbrev_length;
+ while (p < end)
+ {
+ int code = LEB128(p);
+ if (code == findcode)
+ {
+ abbrevMap.insert(std::make_pair(key, p));
+ return p;
+ }
+ if (code == 0)
+ return 0;
+
+ int tag = LEB128(p);
+ int hasChild = *p++;
+
+ // skip attributes
+ int attr, form;
+ do
+ {
+ attr = LEB128(p);
+ form = LEB128(p);
+ } while (attr || form);
+ }
+ return 0;
+}
diff --git a/src/readDwarf.h b/src/readDwarf.h
new file mode 100644
index 0000000..c0587b4
--- /dev/null
+++ b/src/readDwarf.h
@@ -0,0 +1,308 @@
+#ifndef __READDWARF_H__
+#define __READDWARF_H__
+
+#include <string>
+#include <vector>
+#include "mspdb.h"
+
+inline unsigned int LEB128(unsigned char* &p)
+{
+ unsigned int x = 0;
+ int shift = 0;
+ while (*p & 0x80)
+ {
+ x |= (*p & 0x7f) << shift;
+ shift += 7;
+ p++;
+ }
+ x |= *p << shift;
+ p++;
+ return x;
+}
+
+inline int SLEB128(unsigned char* &p)
+{
+ unsigned int x = 0;
+ int shift = 0;
+ while (*p & 0x80)
+ {
+ x |= (*p & 0x7f) << shift;
+ shift += 7;
+ p++;
+ }
+ x |= *p << shift;
+ if (*p & 0x40)
+ x |= -(1 << (shift + 7)); // sign extend
+ p++;
+ return x;
+}
+
+inline unsigned int RD2(unsigned char* p)
+{
+ unsigned int x = *p++;
+ x |= *p++ << 8;
+ return x;
+}
+
+inline unsigned int RD4(unsigned char* p)
+{
+ unsigned int x = *p++;
+ x |= *p++ << 8;
+ x |= *p++ << 16;
+ x |= *p++ << 24;
+ return x;
+}
+
+inline unsigned long long RD8(unsigned char* p)
+{
+ unsigned long long x = *p++;
+ for (int shift = 8; shift < 64; shift += 8)
+ x |= (unsigned long long) *p++ << shift;
+ return x;
+}
+
+inline unsigned long long RDsize(unsigned char* p, int size)
+{
+ if (size > 8)
+ size = 8;
+ unsigned long long x = *p++;
+ for (int shift = 8; shift < size * 8; shift += 8)
+ x |= (unsigned long long) *p++ << shift;
+ return x;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "pshpack1.h"
+
+struct DWARF_CompilationUnit
+{
+ unsigned int unit_length; // 12 byte in DWARF-64
+ unsigned short version;
+ unsigned int debug_abbrev_offset; // 8 byte in DWARF-64
+ unsigned char address_size;
+
+ bool isDWARF64() const { return unit_length == ~0; }
+ int refSize() const { return unit_length == ~0 ? 8 : 4; }
+};
+
+struct DWARF_FileName
+{
+ const char* file_name;
+ unsigned int dir_index;
+ unsigned long lastModification;
+ unsigned long fileLength;
+
+ void read(unsigned char* &p)
+ {
+ file_name = (const char*)p;
+ p += strlen((const char*)p) + 1;
+ dir_index = LEB128(p);
+ lastModification = LEB128(p);
+ fileLength = LEB128(p);
+ }
+};
+
+struct DWARF_InfoData
+{
+ int entryOff;
+ int code;
+ int tag;
+ int hasChild;
+
+ const char* name;
+ const char* linkage_name;
+ const char* dir;
+ unsigned long byte_size;
+ unsigned long sibling;
+ unsigned long encoding;
+ unsigned long pclo;
+ unsigned long pchi;
+ unsigned long ranges;
+ unsigned long type;
+ unsigned long containing_type;
+ unsigned long specification;
+ unsigned long inlined;
+ unsigned long external;
+ unsigned char*location_ptr;
+ unsigned long location_len;
+ unsigned char*member_location_ptr;
+ unsigned long member_location_len;
+ unsigned long member_location_data;
+ unsigned long locationlist; // offset into debug_loc
+ long frame_base;
+ long upper_bound;
+ long lower_bound;
+ unsigned char* abbrev;
+
+ void clear()
+ {
+ entryOff = 0;
+ code = 0;
+ tag = 0;
+ hasChild = 0;
+
+ name = 0;
+ linkage_name = 0;
+ dir = 0;
+ byte_size = 0;
+ sibling = 0;
+ encoding = 0;
+ pclo = 0;
+ pchi = 0;
+ ranges = 0;
+ type = 0;
+ containing_type = 0;
+ specification = 0;
+ inlined = 0;
+ external = 0;
+ member_location_ptr = 0;
+ member_location_len = 0;
+ member_location_data = 0;
+ location_ptr = 0;
+ location_len = 0;
+ locationlist = 0;
+ frame_base = -1;
+ upper_bound = 0;
+ lower_bound = 0;
+ abbrev = 0;
+ }
+};
+
+static const int maximum_operations_per_instruction = 1;
+
+struct DWARF_LineNumberProgramHeader
+{
+ unsigned int unit_length; // 12 byte in DWARF-64
+ unsigned short version;
+ unsigned int header_length; // 8 byte in DWARF-64
+ unsigned char minimum_instruction_length;
+ //unsigned char maximum_operations_per_instruction; (// not in DWARF 2
+ unsigned char default_is_stmt;
+ signed char line_base;
+ unsigned char line_range;
+ unsigned char opcode_base;
+ //LEB128 standard_opcode_lengths[opcode_base];
+ // string include_directories[] // zero byte terminated
+ // DWARF_FileNames file_names[] // zero byte terminated
+};
+
+struct DWARF_LineState
+{
+ // hdr info
+ std::vector<const char*> include_dirs;
+ std::vector<DWARF_FileName> files;
+
+ unsigned long address;
+ unsigned int op_index;
+ unsigned int file;
+ unsigned int line;
+ unsigned int column;
+ bool is_stmt;
+ bool basic_block;
+ bool end_sequence;
+ bool prologue_end;
+ bool epilogue_end;
+ unsigned int isa;
+ unsigned int discriminator;
+
+ // not part of the "documented" state
+ DWARF_FileName* file_ptr;
+ unsigned long seg_offset;
+ unsigned long last_addr;
+ std::vector<mspdb::LineInfoEntry> lineInfo;
+
+ DWARF_LineState()
+ {
+ seg_offset = 0x400000;
+ init(0);
+ }
+
+ void init(DWARF_LineNumberProgramHeader* hdr)
+ {
+ address = 0;
+ op_index = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = hdr && hdr->default_is_stmt != 0;
+ basic_block = false;
+ end_sequence = false;
+ prologue_end = false;
+ epilogue_end = false;
+ isa = 0;
+ discriminator = 0;
+ }
+
+ void advance_addr(DWARF_LineNumberProgramHeader* hdr, int operation_advance)
+ {
+ int address_advance = hdr->minimum_instruction_length * ((op_index + operation_advance) / maximum_operations_per_instruction);
+ address += address_advance;
+ op_index = (op_index + operation_advance) % maximum_operations_per_instruction;
+ }
+
+ void addLineInfo()
+ {
+#if 0
+ const char* fname = (file == 0 ? file_ptr->file_name : files[file - 1].file_name);
+ printf("Adr:%08x Line: %5d File: %s\n", address, line, fname);
+#endif
+ if (address < seg_offset)
+ return;
+ mspdb::LineInfoEntry entry;
+ entry.offset = address - seg_offset;
+ entry.line = line;
+ lineInfo.push_back(entry);
+ }
+};
+
+#include "poppack.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+long decodeLocation(unsigned char* loc, long len, bool push0, int &id, int& size);
+
+inline long decodeLocation(unsigned char*loc, long len, bool push0, int &id)
+{
+ int size;
+ return decodeLocation(loc, len, push0, id, size);
+}
+
+
+class PEImage;
+
+// Debug Information Entry Cursor
+class DIECursor
+{
+public:
+ DWARF_CompilationUnit* cu;
+ unsigned char* ptr;
+ int level;
+ bool hasChild; // indicates whether the last read DIE has children
+ unsigned int sibling;
+
+ unsigned char* getDWARFAbbrev(unsigned off, unsigned findcode);
+
+public:
+
+ static void setContext(PEImage* img_);
+
+ // Create a new DIECursor from compilation unit with offset relative to the CU.
+ DIECursor(DWARF_CompilationUnit* cu_, unsigned long offset);
+
+ // Reads next sibling DIE. If the last read DIE had any children, they will be skipped over.
+ // Returns 'false' upon reaching the last sibling on the current level.
+ bool readSibling(DWARF_InfoData& id);
+
+ // Returns cursor that will enumerate children of the last read DIE.
+ DIECursor getSubtreeCursor();
+
+ // Reads the next DIE in physical order, returns 'true' if succeeds.
+ // If stopAtNull is true, readNext() will stop upon reaching a null DIE (end of the current tree level).
+ // Otherwise, it will skip null DIEs and stop only at the end of the subtree for which this DIECursor was created.
+ bool readNext(DWARF_InfoData& id, bool stopAtNull = false);
+};
+
+#endif \ No newline at end of file