diff options
Diffstat (limited to 'src/Native/ObjWriter')
23 files changed, 3273 insertions, 452 deletions
diff --git a/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec deleted file mode 100644 index f3421bb32..000000000 --- a/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<package > - <metadata> - <id>Microsoft.DotNet.ObjectWriter</id> - <version>1.0.19-prerelease-00001</version> - <title>Microsoft .NET Object File Generator</title> - <authors>Microsoft</authors> - <owners>Microsoft</owners> - <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl> - <projectUrl>https://github.com/dotnet/corert</projectUrl> - <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl> - <requireLicenseAcceptance>true</requireLicenseAcceptance> - <description>Provides object writer to the managed to native code-generator.</description> - <releaseNotes>Initial release</releaseNotes> - <copyright>Copyright © Microsoft Corporation</copyright> - </metadata> - <files> - <file src="runtime.json" /> - </files> -</package> diff --git a/src/Native/ObjWriter/.nuget/runtime.json b/src/Native/ObjWriter/.nuget/runtime.json deleted file mode 100644 index c9c5b8e6b..000000000 --- a/src/Native/ObjWriter/.nuget/runtime.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "runtimes": { - "win7-x64": { - "Microsoft.DotNet.ObjectWriter": { - "toolchain.win7-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001" - } - }, - "ubuntu.14.04-x64": { - "Microsoft.DotNet.ObjectWriter": { - "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001" - } - }, - "osx.10.10-x64": { - "Microsoft.DotNet.ObjectWriter": { - "toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001" - } - } - } -} diff --git a/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec deleted file mode 100644 index 7a571beaf..000000000 --- a/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<package > - <metadata> - <id>toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter</id> - <version>1.0.19-prerelease-00001</version> - <title>Microsoft .NET Object File Generator</title> - <authors>Microsoft</authors> - <owners>Microsoft</owners> - <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl> - <projectUrl>https://github.com/dotnet/corert</projectUrl> - <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl> - <requireLicenseAcceptance>true</requireLicenseAcceptance> - <description>Provides object writer to the managed to native code-generator.</description> - <releaseNotes>Initial release</releaseNotes> - <copyright>Copyright © Microsoft Corporation</copyright> - </metadata> - <files> - <file src="../libobjwriter.dylib" target="runtimes/osx.10.10-x64/native/libobjwriter.dylib" /> - </files> -</package> diff --git a/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec deleted file mode 100644 index fd9c514c6..000000000 --- a/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<package > - <metadata> - <id>toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter</id> - <version>1.0.19-prerelease-00001</version> - <title>Microsoft .NET Object File Generator</title> - <authors>Microsoft</authors> - <owners>Microsoft</owners> - <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl> - <projectUrl>https://github.com/dotnet/corert</projectUrl> - <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl> - <requireLicenseAcceptance>true</requireLicenseAcceptance> - <description>Provides object writer to the managed to native code-generator.</description> - <releaseNotes>Initial release</releaseNotes> - <copyright>Copyright © Microsoft Corporation</copyright> - </metadata> - <files> - <file src="../libobjwriter.so" target="runtimes/ubuntu.14.04-x64/native/libobjwriter.so" /> - </files> -</package> diff --git a/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec deleted file mode 100644 index a54cdc230..000000000 --- a/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<package > - <metadata> - <id>toolchain.win7-x64.Microsoft.DotNet.ObjectWriter</id> - <version>1.0.19-prerelease-00001</version> - <title>Microsoft .NET Object File Generator</title> - <authors>Microsoft</authors> - <owners>Microsoft</owners> - <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl> - <projectUrl>https://github.com/dotnet/corert</projectUrl> - <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl> - <requireLicenseAcceptance>true</requireLicenseAcceptance> - <description>Provides object writer to the managed to native code-generator.</description> - <releaseNotes>Initial release</releaseNotes> - <copyright>Copyright © Microsoft Corporation</copyright> - </metadata> - <files> - <file src="..\objwriter.dll" target="runtimes\win7-x64\native\objwriter.dll" /> - </files> -</package> diff --git a/src/Native/ObjWriter/CMakeLists.txt b/src/Native/ObjWriter/CMakeLists.txt index fae4ddb12..490a36701 100644 --- a/src/Native/ObjWriter/CMakeLists.txt +++ b/src/Native/ObjWriter/CMakeLists.txt @@ -2,7 +2,15 @@ project(objwriter) set(CMAKE_BUILD_TYPE "${OBJWRITER_BUILD_TYPE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OBJWRITER_C_FLAGS}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OBJWRITER_CXX_FLAGS} -std=c++11 -fno-rtti") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OBJWRITER_CXX_FLAGS}") + +if(WIN32) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") +endif() + +if(NOT WIN32) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti") +endif() message(STATUS "ObjWriter configuring with (${CMAKE_BUILD_TYPE}) build type and (${LLVM_DEFAULT_TARGET_TRIPLE}) default target triple") @@ -29,9 +37,16 @@ endif() add_library(objwriter SHARED objwriter.cpp - typeBuilder.cpp + debugInfo/codeView/codeViewTypeBuilder.cpp + debugInfo/codeView/codeViewTypeBuilder.h + debugInfo/dwarf/dwarfTypeBuilder.cpp + debugInfo/dwarf/dwarfTypeBuilder.h + debugInfo/dwarf/dwarfGen.cpp + debugInfo/dwarf/dwarfGen.h + debugInfo/dwarf/dwarfAbbrev.cpp + debugInfo/dwarf/dwarfAbbrev.h + debugInfo/typeBuilder.h objwriter.h # Visual Studio generator doesn't include necessary header files into the project automatically - typeBuilder.h ${OBJWRITER_EXPORTS_DEF} ) diff --git a/src/Native/ObjWriter/cordebuginfo.h b/src/Native/ObjWriter/cordebuginfo.h index 1ed430a11..46d74c2e1 100644 --- a/src/Native/ObjWriter/cordebuginfo.h +++ b/src/Native/ObjWriter/cordebuginfo.h @@ -195,104 +195,114 @@ public: VLT_INVALID, }; + // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc) + // eg. EAX + // VLT_REG_BYREF -- the specified register contains the address of the variable + // eg. [EAX] + + struct vlReg + { + RegNum vlrReg; + }; + + // VLT_STK -- Any 32 bit value which is on the stack + // eg. [ESP+0x20], or [EBP-0x28] + // VLT_STK_BYREF -- the specified stack location contains the address of the variable + // eg. mov EAX, [ESP+0x20]; [EAX] + + struct vlStk + { + RegNum vlsBaseReg; + signed vlsOffset; + }; + + // VLT_REG_REG -- TYP_LONG with both DWords enregistred + // eg. RBM_EAXEDX + + struct vlRegReg + { + RegNum vlrrReg1; + RegNum vlrrReg2; + }; + + // VLT_REG_STK -- Partly enregistered TYP_LONG + // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] } + + struct vlRegStk + { + RegNum vlrsReg; + struct + { + RegNum vlrssBaseReg; + signed vlrssOffset; + } vlrsStk; + }; + + // VLT_STK_REG -- Partly enregistered TYP_LONG + // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX } + + struct vlStkReg + { + struct + { + RegNum vlsrsBaseReg; + signed vlsrsOffset; + } vlsrStk; + RegNum vlsrReg; + }; + + // VLT_STK2 -- Any 64 bit value which is on the stack, + // in 2 successsive DWords. + // eg 2 DWords at [ESP+0x10] + + struct vlStk2 + { + RegNum vls2BaseReg; + signed vls2Offset; + }; + + // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack) + // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk") + + struct vlFPstk + { + unsigned vlfReg; + }; + + // VLT_FIXED_VA -- fixed argument of a varargs function. + // The argument location depends on the size of the variable + // arguments (...). Inspecting the VARARGS_HANDLE indicates the + // location of the first arg. This argument can then be accessed + // relative to the position of the first arg + + struct vlFixedVarArg + { + unsigned vlfvOffset; + }; + + // VLT_MEMORY + + struct vlMemory + { + void *rpValue; // pointer to the in-process + // location of the value. + }; + struct VarLoc { VarLocType vlType; union { - // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc) - // eg. EAX - // VLT_REG_BYREF -- the specified register contains the address of the variable - // eg. [EAX] - - struct - { - RegNum vlrReg; - } vlReg; - - // VLT_STK -- Any 32 bit value which is on the stack - // eg. [ESP+0x20], or [EBP-0x28] - // VLT_STK_BYREF -- the specified stack location contains the address of the variable - // eg. mov EAX, [ESP+0x20]; [EAX] - - struct - { - RegNum vlsBaseReg; - signed vlsOffset; - } vlStk; - - // VLT_REG_REG -- TYP_LONG with both DWords enregistred - // eg. RBM_EAXEDX - - struct - { - RegNum vlrrReg1; - RegNum vlrrReg2; - } vlRegReg; - - // VLT_REG_STK -- Partly enregistered TYP_LONG - // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] } - - struct - { - RegNum vlrsReg; - struct - { - RegNum vlrssBaseReg; - signed vlrssOffset; - } vlrsStk; - } vlRegStk; - - // VLT_STK_REG -- Partly enregistered TYP_LONG - // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX } - - struct - { - struct - { - RegNum vlsrsBaseReg; - signed vlsrsOffset; - } vlsrStk; - RegNum vlsrReg; - } vlStkReg; - - // VLT_STK2 -- Any 64 bit value which is on the stack, - // in 2 successsive DWords. - // eg 2 DWords at [ESP+0x10] - - struct - { - RegNum vls2BaseReg; - signed vls2Offset; - } vlStk2; - - // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack) - // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk") - - struct - { - unsigned vlfReg; - } vlFPstk; - - // VLT_FIXED_VA -- fixed argument of a varargs function. - // The argument location depends on the size of the variable - // arguments (...). Inspecting the VARARGS_HANDLE indicates the - // location of the first arg. This argument can then be accessed - // relative to the position of the first arg - - struct - { - unsigned vlfvOffset; - } vlFixedVarArg; - - // VLT_MEMORY - - struct - { - void *rpValue; // pointer to the in-process - // location of the value. - } vlMemory; + ICorDebugInfo::vlReg vlReg; + ICorDebugInfo::vlStk vlStk; + ICorDebugInfo::vlRegReg vlRegReg; + ICorDebugInfo::vlRegStk vlRegStk; + ICorDebugInfo::vlStkReg vlStkReg; + ICorDebugInfo::vlStk2 vlStk2; + ICorDebugInfo::vlFPstk vlFPstk; + ICorDebugInfo::vlFixedVarArg vlFixedVarArg; + ICorDebugInfo::vlMemory vlMemory; }; }; diff --git a/src/Native/ObjWriter/cvconst.h b/src/Native/ObjWriter/cvconst.h index 5c4f2569e..92c5bb4e7 100644 --- a/src/Native/ObjWriter/cvconst.h +++ b/src/Native/ObjWriter/cvconst.h @@ -1,18 +1,6 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -/////////////////////////////////////////////////////////////////////////////// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. // cvconst.h - codeview constant definitions //----------------------------------------------------------------- diff --git a/src/Native/ObjWriter/typeBuilder.cpp b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.cpp index 2b6edacc5..d3af316ca 100644 --- a/src/Native/ObjWriter/typeBuilder.cpp +++ b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.cpp @@ -1,55 +1,43 @@ -//===---- typeBuilder.cpp --------------------------------*- C++ -*-===// +//===---- codeViewTypeBuilder.cpp -------------------------------*- C++ -*-===// // // type builder implementation using codeview::TypeTableBuilder // -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. -// See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. // //===----------------------------------------------------------------------===// -#include "typeBuilder.h" +#include "codeViewTypeBuilder.h" #include "llvm/BinaryFormat/COFF.h" #include <sstream> #include <vector> -UserDefinedTypesBuilder::UserDefinedTypesBuilder() - : Allocator(), TypeTable(Allocator), Streamer(nullptr), - TargetPointerSize(0) +UserDefinedCodeViewTypesBuilder::UserDefinedCodeViewTypesBuilder() + : Allocator(), TypeTable(Allocator) { VFTableShapeRecord vfTableShape(TypeRecordKind::VFTableShape); ClassVTableTypeIndex = TypeTable.writeKnownType(vfTableShape); } -void UserDefinedTypesBuilder::SetStreamer(MCObjectStreamer *Streamer) { - assert(this->Streamer == nullptr); - assert(Streamer != nullptr); - this->Streamer = Streamer; -} - -void UserDefinedTypesBuilder::SetTargetPointerSize(unsigned TargetPointerSize) { - assert(this->TargetPointerSize == 0); - assert(TargetPointerSize != 0); - this->TargetPointerSize = TargetPointerSize; -} - -void UserDefinedTypesBuilder::EmitCodeViewMagicVersion() { +void UserDefinedCodeViewTypesBuilder::EmitCodeViewMagicVersion() { Streamer->EmitValueToAlignment(4); Streamer->AddComment("Debug section magic"); Streamer->EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4); } -ClassOptions UserDefinedTypesBuilder::GetCommonClassOptions() { +ClassOptions UserDefinedCodeViewTypesBuilder::GetCommonClassOptions() { return ClassOptions(); } -void UserDefinedTypesBuilder::EmitTypeInformation( - MCSection *COFFDebugTypesSection) { +void UserDefinedCodeViewTypesBuilder::EmitTypeInformation( + MCSection *TypeSection, + MCSection *StrSection) { if (TypeTable.empty()) return; - Streamer->SwitchSection(COFFDebugTypesSection); + Streamer->SwitchSection(TypeSection); EmitCodeViewMagicVersion(); TypeTable.ForEachRecord([&](TypeIndex FieldTypeIndex, @@ -59,7 +47,7 @@ void UserDefinedTypesBuilder::EmitTypeInformation( }); } -unsigned UserDefinedTypesBuilder::GetEnumFieldListType( +unsigned UserDefinedCodeViewTypesBuilder::GetEnumFieldListType( uint64 Count, const EnumRecordTypeDescriptor *TypeRecords) { FieldListRecordBuilder FLRB(TypeTable); FLRB.begin(); @@ -77,7 +65,7 @@ unsigned UserDefinedTypesBuilder::GetEnumFieldListType( return Type.getIndex(); } -unsigned UserDefinedTypesBuilder::GetEnumTypeIndex( +unsigned UserDefinedCodeViewTypesBuilder::GetEnumTypeIndex( const EnumTypeDescriptor &TypeDescriptor, const EnumRecordTypeDescriptor *TypeRecords) { @@ -92,11 +80,11 @@ unsigned UserDefinedTypesBuilder::GetEnumTypeIndex( ElementTypeIndex); TypeIndex Type = TypeTable.writeKnownType(EnumRecord); - UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, Type)); + UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, Type.getIndex())); return Type.getIndex(); } -unsigned UserDefinedTypesBuilder::GetClassTypeIndex( +unsigned UserDefinedCodeViewTypesBuilder::GetClassTypeIndex( const ClassTypeDescriptor &ClassDescriptor) { TypeRecordKind Kind = ClassDescriptor.IsStruct ? TypeRecordKind::Struct : TypeRecordKind::Class; @@ -119,10 +107,11 @@ unsigned UserDefinedTypesBuilder::GetClassTypeIndex( return FwdDeclTI.getIndex(); } -unsigned UserDefinedTypesBuilder::GetCompleteClassTypeIndex( +unsigned UserDefinedCodeViewTypesBuilder::GetCompleteClassTypeIndex( const ClassTypeDescriptor &ClassDescriptor, const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, - const DataFieldDescriptor *FieldsDescriptors) { + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors) { FieldListRecordBuilder FLBR(TypeTable); FLBR.begin(); @@ -165,12 +154,12 @@ unsigned UserDefinedTypesBuilder::GetCompleteClassTypeIndex( ClassDescriptor.Name, StringRef()); TypeIndex ClassIndex = TypeTable.writeKnownType(CR); - UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex)); + UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex.getIndex())); return ClassIndex.getIndex(); } -unsigned UserDefinedTypesBuilder::GetArrayTypeIndex( +unsigned UserDefinedCodeViewTypesBuilder::GetArrayTypeIndex( const ClassTypeDescriptor &ClassDescriptor, const ArrayTypeDescriptor &ArrayDescriptor) { FieldListRecordBuilder FLBR(TypeTable); @@ -229,12 +218,12 @@ unsigned UserDefinedTypesBuilder::GetArrayTypeIndex( StringRef()); TypeIndex ClassIndex = TypeTable.writeKnownType(CR); - UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex)); + UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex.getIndex())); return ClassIndex.getIndex(); } -unsigned UserDefinedTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) +unsigned UserDefinedCodeViewTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) { uint32_t elementType = PointerDescriptor.ElementType; PointerKind pointerKind = PointerDescriptor.Is64Bit ? PointerKind::Near64 : PointerKind::Near32; @@ -246,7 +235,7 @@ unsigned UserDefinedTypesBuilder::GetPointerTypeIndex(const PointerTypeDescripto return PointerIndex.getIndex(); } -unsigned UserDefinedTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, +unsigned UserDefinedCodeViewTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, uint32_t const *const ArgumentTypes) { std::vector<TypeIndex> argumentTypes; @@ -271,14 +260,52 @@ unsigned UserDefinedTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctio return MemberFunctionIndex.getIndex(); } -unsigned UserDefinedTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) +unsigned UserDefinedCodeViewTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) { MemberFuncIdRecord MemberFuncId(TypeIndex(MemberIdDescriptor.MemberFunction), TypeIndex(MemberIdDescriptor.ParentClass), MemberIdDescriptor.Name); TypeIndex MemberFuncIdIndex = TypeTable.writeKnownType(MemberFuncId); return MemberFuncIdIndex.getIndex(); } -void UserDefinedTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR, +unsigned UserDefinedCodeViewTypesBuilder::GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) { + switch (Type) { + case PrimitiveTypeFlags::Void: + return TypeIndex::Void().getIndex(); + case PrimitiveTypeFlags::Boolean: + return TypeIndex(SimpleTypeKind::Boolean8).getIndex(); + case PrimitiveTypeFlags::Char: + return TypeIndex::WideCharacter().getIndex(); + case PrimitiveTypeFlags::SByte: + return TypeIndex(SimpleTypeKind::SByte).getIndex(); + case PrimitiveTypeFlags::Byte: + return TypeIndex(SimpleTypeKind::Byte).getIndex(); + case PrimitiveTypeFlags::Int16: + return TypeIndex(SimpleTypeKind::Int16).getIndex(); + case PrimitiveTypeFlags::UInt16: + return TypeIndex(SimpleTypeKind::UInt16).getIndex(); + case PrimitiveTypeFlags::Int32: + return TypeIndex::Int32().getIndex(); + case PrimitiveTypeFlags::UInt32: + return TypeIndex::UInt32().getIndex(); + case PrimitiveTypeFlags::Int64: + return TypeIndex::Int64().getIndex(); + case PrimitiveTypeFlags::UInt64: + return TypeIndex::UInt64().getIndex(); + case PrimitiveTypeFlags::Single: + return TypeIndex::Float32().getIndex(); + case PrimitiveTypeFlags::Double: + return TypeIndex::Float64().getIndex(); + case PrimitiveTypeFlags::IntPtr: + case PrimitiveTypeFlags::UIntPtr: + return TargetPointerSize == 4 ? TypeIndex::VoidPointer32().getIndex() : + TypeIndex::VoidPointer64().getIndex(); + default: + assert(false && "Unexpected type"); + return 0; + } +} + +void UserDefinedCodeViewTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR, unsigned BaseClassId) { MemberAttributes def; TypeIndex BaseTypeIndex(BaseClassId); @@ -286,7 +313,7 @@ void UserDefinedTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR, FLBR.writeMemberType(BCR); } -void UserDefinedTypesBuilder::AddClassVTShape(FieldListRecordBuilder &FLBR) { +void UserDefinedCodeViewTypesBuilder::AddClassVTShape(FieldListRecordBuilder &FLBR) { VFPtrRecord VfPtr(ClassVTableTypeIndex); FLBR.writeMemberType(VfPtr); } diff --git a/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h new file mode 100644 index 000000000..5534cc7d3 --- /dev/null +++ b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h @@ -0,0 +1,73 @@ +//===---- codeViewTypeBuilder.h ---------------------------------*- C++ -*-===// +// +// type builder is used to convert .Net types into CodeView descriptors. +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "debugInfo/typeBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" + +#include <vector> + +using namespace llvm::codeview; + +class ArrayDimensionsDescriptor { +public: + const char *GetLengthName(unsigned index); + const char *GetBoundsName(unsigned index); + +private: + void Resize(unsigned NewSize); + + std::vector<std::string> Lengths; + std::vector<std::string> Bounds; +}; + +class UserDefinedCodeViewTypesBuilder : public UserDefinedTypesBuilder { +public: + UserDefinedCodeViewTypesBuilder(); + void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) override; + + unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords) override; + unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) override; + unsigned GetCompleteClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors) override; + + unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, + const ArrayTypeDescriptor &ArrayDescriptor) override; + + unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) override; + + unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes) override; + + unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) override; + + unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) override; + +private: + void EmitCodeViewMagicVersion(); + ClassOptions GetCommonClassOptions(); + + unsigned GetEnumFieldListType(uint64 Count, + const EnumRecordTypeDescriptor *TypeRecords); + + void AddBaseClass(FieldListRecordBuilder &FLBR, unsigned BaseClassId); + void AddClassVTShape(FieldListRecordBuilder &FLBR); + + BumpPtrAllocator Allocator; + TypeTableBuilder TypeTable; + + ArrayDimensionsDescriptor ArrayDimentions; + TypeIndex ClassVTableTypeIndex; +};
\ No newline at end of file diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp new file mode 100644 index 000000000..23ee3fa30 --- /dev/null +++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp @@ -0,0 +1,284 @@ +//===---- dwarfAbbrev.cpp ---------------------------------------*- C++ -*-===// +// +// dwarf abbreviations implementation +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +//===----------------------------------------------------------------------===// + +#include "dwarfAbbrev.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectFileInfo.h" + +namespace DwarfAbbrev { + +void Dump(MCObjectStreamer *Streamer, uint16_t DwarfVersion, unsigned TargetPointerSize) { + uint16_t DW_FORM_size; + switch (TargetPointerSize) { + case 1: + DW_FORM_size = dwarf::DW_FORM_data1; + break; + case 2: + DW_FORM_size = dwarf::DW_FORM_data2; + break; + case 4: + DW_FORM_size = dwarf::DW_FORM_data4; + break; + case 8: + DW_FORM_size = dwarf::DW_FORM_data8; + break; + default: + assert(false && "Unexpected TargerPointerSize"); + return; + } + + const uint16_t AbbrevTable[] = { + CompileUnit, + dwarf::DW_TAG_compile_unit, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_producer, dwarf::DW_FORM_string, + dwarf::DW_AT_language, dwarf::DW_FORM_data2, + dwarf::DW_AT_stmt_list, (DwarfVersion >= 4 ? dwarf::DW_FORM_sec_offset : dwarf::DW_FORM_data4), + 0, 0, + + BaseType, + dwarf::DW_TAG_base_type, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, + 0, 0, + + EnumerationType, + dwarf::DW_TAG_enumeration_type, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, + 0, 0, + + Enumerator1, + dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_const_value, dwarf::DW_FORM_data1, + 0, 0, + + Enumerator2, + dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_const_value, dwarf::DW_FORM_data2, + 0, 0, + + Enumerator4, + dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_const_value, dwarf::DW_FORM_data4, + 0, 0, + + Enumerator8, + dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_const_value, dwarf::DW_FORM_data8, + 0, 0, + + TypeDef, + dwarf::DW_TAG_typedef, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + 0, 0, + + Subprogram, + dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + dwarf::DW_AT_high_pc, DW_FORM_size, + dwarf::DW_AT_frame_base, dwarf::DW_FORM_exprloc, + dwarf::DW_AT_object_pointer, dwarf::DW_FORM_ref4, + 0, 0, + + SubprogramStatic, + dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + dwarf::DW_AT_high_pc, DW_FORM_size, + dwarf::DW_AT_frame_base, dwarf::DW_FORM_exprloc, + 0, 0, + + SubprogramSpec, + dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, + dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, + dwarf::DW_AT_object_pointer, dwarf::DW_FORM_ref4, + 0, 0, + + SubprogramStaticSpec, + dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, + dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, + 0, 0, + + Variable, + dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_location, dwarf::DW_FORM_exprloc, + 0, 0, + + VariableLoc, + dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset, + 0, 0, + + VariableStatic, + dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + dwarf::DW_AT_location, dwarf::DW_FORM_exprloc, + 0, 0, + + FormalParameter, + dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_location, dwarf::DW_FORM_exprloc, + 0, 0, + + FormalParameterThis, + dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_location, dwarf::DW_FORM_exprloc, + dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present, + 0, 0, + + FormalParameterLoc, + dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset, + 0, 0, + + FormalParameterThisLoc, + dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, + dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset, + dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present, + 0, 0, + + FormalParameterSpec, + dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + 0, 0, + + FormalParameterThisSpec, + dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present, + 0, 0, + + ClassType, + dwarf::DW_TAG_class_type, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_byte_size, dwarf::DW_FORM_data4, + 0, 0, + + ClassTypeDecl, + dwarf::DW_TAG_class_type, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, + 0, 0, + + ClassMember, + dwarf::DW_TAG_member, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data4, + 0, 0, + + ClassMemberStatic, + dwarf::DW_TAG_member, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_name, dwarf::DW_FORM_strp, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, + dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, + 0, 0, + + PointerType, + dwarf::DW_TAG_pointer_type, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, + 0, 0, + + ReferenceType, + dwarf::DW_TAG_reference_type, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, + 0, 0, + + ArrayType, + dwarf::DW_TAG_array_type, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + 0, 0, + + SubrangeType, + dwarf::DW_TAG_subrange_type, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_upper_bound, dwarf::DW_FORM_udata, + 0, 0, + + ClassInheritance, + dwarf::DW_TAG_inheritance, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_type, dwarf::DW_FORM_ref4, + dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, + 0, 0, + + LexicalBlock, + dwarf::DW_TAG_lexical_block, dwarf::DW_CHILDREN_yes, + dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + dwarf::DW_AT_high_pc, DW_FORM_size, + 0, 0, + + TryBlock, + dwarf::DW_TAG_try_block, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + dwarf::DW_AT_high_pc, DW_FORM_size, + 0, 0, + + CatchBlock, + dwarf::DW_TAG_catch_block, dwarf::DW_CHILDREN_no, + dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + dwarf::DW_AT_high_pc, DW_FORM_size, + 0, 0 + }; + + MCContext &context = Streamer->getContext(); + Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); + + for (uint16_t e : AbbrevTable) { + Streamer->EmitULEB128IntValue(e); + } +} + +}
\ No newline at end of file diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h new file mode 100644 index 000000000..82589c027 --- /dev/null +++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h @@ -0,0 +1,59 @@ +//===---- dwarfAbbrev.h -----------------------------------------*- C++ -*-===// +// +// dwarf abbreviations +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/MC/MCObjectStreamer.h" + +using namespace llvm; + +namespace DwarfAbbrev { + +enum DwarfAbbrev : uint16_t +{ + CompileUnit = 0x1, + BaseType, + EnumerationType, + Enumerator1, + Enumerator2, + Enumerator4, + Enumerator8, + TypeDef, + Subprogram, + SubprogramStatic, + SubprogramSpec, + SubprogramStaticSpec, + Variable, + VariableLoc, + VariableStatic, + FormalParameter, + FormalParameterThis, + FormalParameterLoc, + FormalParameterThisLoc, + FormalParameterSpec, + FormalParameterThisSpec, + ClassType, + ClassTypeDecl, + ClassMember, + ClassMemberStatic, + PointerType, + ReferenceType, + ArrayType, + SubrangeType, + ClassInheritance, + LexicalBlock, + TryBlock, + CatchBlock +}; + +void Dump(MCObjectStreamer *Streamer, uint16_t DwarfVersion, unsigned TargetPointerSize); + +} diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp new file mode 100644 index 000000000..518608673 --- /dev/null +++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp @@ -0,0 +1,1066 @@ +//===---- dwarfGen.cpp ------------------------------------------*- C++ -*-===// +// +// dwarf generator implementation +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +//===----------------------------------------------------------------------===// + +#include "dwarfGen.h" +#include "dwarfAbbrev.h" + +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/Support/LEB128.h" + +#ifdef FEATURE_LANGID_CS +#define DW_LANG_MICROSOFT_CSHARP 0x9e57 +#endif + +// Keep sync with ICorDebugInfo::RegNum (cordebuginfo.h) + +enum class RegNumX86 +{ + REGNUM_EAX, + REGNUM_ECX, + REGNUM_EDX, + REGNUM_EBX, + REGNUM_ESP, + REGNUM_EBP, + REGNUM_ESI, + REGNUM_EDI, + REGNUM_COUNT, + REGNUM_FP = REGNUM_EBP, + REGNUM_SP = REGNUM_ESP +}; + +enum class RegNumArm +{ + REGNUM_R0, + REGNUM_R1, + REGNUM_R2, + REGNUM_R3, + REGNUM_R4, + REGNUM_R5, + REGNUM_R6, + REGNUM_R7, + REGNUM_R8, + REGNUM_R9, + REGNUM_R10, + REGNUM_R11, + REGNUM_R12, + REGNUM_SP, + REGNUM_LR, + REGNUM_PC, + REGNUM_COUNT, + REGNUM_FP = REGNUM_R7 +}; + +enum class RegNumArm64 +{ + REGNUM_X0, + REGNUM_X1, + REGNUM_X2, + REGNUM_X3, + REGNUM_X4, + REGNUM_X5, + REGNUM_X6, + REGNUM_X7, + REGNUM_X8, + REGNUM_X9, + REGNUM_X10, + REGNUM_X11, + REGNUM_X12, + REGNUM_X13, + REGNUM_X14, + REGNUM_X15, + REGNUM_X16, + REGNUM_X17, + REGNUM_X18, + REGNUM_X19, + REGNUM_X20, + REGNUM_X21, + REGNUM_X22, + REGNUM_X23, + REGNUM_X24, + REGNUM_X25, + REGNUM_X26, + REGNUM_X27, + REGNUM_X28, + REGNUM_FP, + REGNUM_LR, + REGNUM_SP, + REGNUM_PC, + REGNUM_COUNT +}; + +enum class RegNumAmd64 +{ + REGNUM_RAX, + REGNUM_RCX, + REGNUM_RDX, + REGNUM_RBX, + REGNUM_RSP, + REGNUM_RBP, + REGNUM_RSI, + REGNUM_RDI, + REGNUM_R8, + REGNUM_R9, + REGNUM_R10, + REGNUM_R11, + REGNUM_R12, + REGNUM_R13, + REGNUM_R14, + REGNUM_R15, + REGNUM_COUNT, + REGNUM_SP = REGNUM_RSP, + REGNUM_FP = REGNUM_RBP +}; + +// Helper routines from lib/MC/MCDwarf.cpp +static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) { + MCContext &Context = OS.getContext(); + assert(!isa<MCSymbolRefExpr>(Expr)); + if (Context.getAsmInfo()->hasAggressiveSymbolFolding()) + return Expr; + + MCSymbol *ABS = Context.createTempSymbol(); + OS.EmitAssignment(ABS, Expr); + return MCSymbolRefExpr::create(ABS, Context); +} + +static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) { + const MCExpr *ABS = forceExpAbs(OS, Value); + OS.EmitValue(ABS, Size); +} + +static const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, + const MCSymbol &Start, + const MCSymbol &End, + int IntVal) { + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *Res = + MCSymbolRefExpr::create(&End, Variant, MCOS.getContext()); + const MCExpr *RHS = + MCSymbolRefExpr::create(&Start, Variant, MCOS.getContext()); + const MCExpr *Res1 = + MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext()); + const MCExpr *Res2 = + MCConstantExpr::create(IntVal, MCOS.getContext()); + const MCExpr *Res3 = + MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext()); + return Res3; +} + +static int GetDwarfRegNum(Triple::ArchType ArchType, int RegNum) { + switch (ArchType) { + case Triple::x86: + switch (static_cast<RegNumX86>(RegNum)) { + case RegNumX86::REGNUM_EAX: return 0; + case RegNumX86::REGNUM_ECX: return 1; + case RegNumX86::REGNUM_EDX: return 2; + case RegNumX86::REGNUM_EBX: return 3; + case RegNumX86::REGNUM_ESP: return 4; + case RegNumX86::REGNUM_EBP: return 5; + case RegNumX86::REGNUM_ESI: return 6; + case RegNumX86::REGNUM_EDI: return 7; + // fp registers + default: + return RegNum - static_cast<int>(RegNumX86::REGNUM_COUNT) + 32; + } + case Triple::arm: // fall through + case Triple::armeb: // fall through + case Triple::thumb: // fall through + case Triple::thumbeb: + switch (static_cast<RegNumArm>(RegNum)) { + case RegNumArm::REGNUM_R0: return 0; + case RegNumArm::REGNUM_R1: return 1; + case RegNumArm::REGNUM_R2: return 2; + case RegNumArm::REGNUM_R3: return 3; + case RegNumArm::REGNUM_R4: return 4; + case RegNumArm::REGNUM_R5: return 5; + case RegNumArm::REGNUM_R6: return 6; + case RegNumArm::REGNUM_R7: return 7; + case RegNumArm::REGNUM_R8: return 8; + case RegNumArm::REGNUM_R9: return 9; + case RegNumArm::REGNUM_R10: return 10; + case RegNumArm::REGNUM_R11: return 11; + case RegNumArm::REGNUM_R12: return 12; + case RegNumArm::REGNUM_SP: return 13; + case RegNumArm::REGNUM_LR: return 14; + case RegNumArm::REGNUM_PC: return 15; + // fp registers + default: + return RegNum - static_cast<int>(RegNumArm::REGNUM_COUNT) + 64; + } + case Triple::aarch64: // fall through + case Triple::aarch64_be: + switch (static_cast<RegNumArm64>(RegNum)) { + case RegNumArm64::REGNUM_X0: return 0; + case RegNumArm64::REGNUM_X1: return 1; + case RegNumArm64::REGNUM_X2: return 2; + case RegNumArm64::REGNUM_X3: return 3; + case RegNumArm64::REGNUM_X4: return 4; + case RegNumArm64::REGNUM_X5: return 5; + case RegNumArm64::REGNUM_X6: return 6; + case RegNumArm64::REGNUM_X7: return 7; + case RegNumArm64::REGNUM_X8: return 8; + case RegNumArm64::REGNUM_X9: return 9; + case RegNumArm64::REGNUM_X10: return 10; + case RegNumArm64::REGNUM_X11: return 11; + case RegNumArm64::REGNUM_X12: return 12; + case RegNumArm64::REGNUM_X13: return 13; + case RegNumArm64::REGNUM_X14: return 14; + case RegNumArm64::REGNUM_X15: return 15; + case RegNumArm64::REGNUM_X16: return 16; + case RegNumArm64::REGNUM_X17: return 17; + case RegNumArm64::REGNUM_X18: return 18; + case RegNumArm64::REGNUM_X19: return 19; + case RegNumArm64::REGNUM_X20: return 20; + case RegNumArm64::REGNUM_X21: return 21; + case RegNumArm64::REGNUM_X22: return 22; + case RegNumArm64::REGNUM_X23: return 23; + case RegNumArm64::REGNUM_X24: return 24; + case RegNumArm64::REGNUM_X25: return 25; + case RegNumArm64::REGNUM_X26: return 26; + case RegNumArm64::REGNUM_X27: return 27; + case RegNumArm64::REGNUM_X28: return 28; + case RegNumArm64::REGNUM_FP: return 29; + case RegNumArm64::REGNUM_LR: return 30; + case RegNumArm64::REGNUM_SP: return 31; + case RegNumArm64::REGNUM_PC: return 32; + // fp registers + default: + return RegNum - static_cast<int>(RegNumArm64::REGNUM_COUNT) + 64; + } + case Triple::x86_64: + switch (static_cast<RegNumAmd64>(RegNum)) { + case RegNumAmd64::REGNUM_RAX: return 0; + case RegNumAmd64::REGNUM_RDX: return 1; + case RegNumAmd64::REGNUM_RCX: return 2; + case RegNumAmd64::REGNUM_RBX: return 3; + case RegNumAmd64::REGNUM_RSI: return 4; + case RegNumAmd64::REGNUM_RDI: return 5; + case RegNumAmd64::REGNUM_RBP: return 6; + case RegNumAmd64::REGNUM_RSP: return 7; + case RegNumAmd64::REGNUM_R8: return 8; + case RegNumAmd64::REGNUM_R9: return 9; + case RegNumAmd64::REGNUM_R10: return 10; + case RegNumAmd64::REGNUM_R11: return 11; + case RegNumAmd64::REGNUM_R12: return 12; + case RegNumAmd64::REGNUM_R13: return 13; + case RegNumAmd64::REGNUM_R14: return 14; + case RegNumAmd64::REGNUM_R15: return 15; + // fp registers + default: + return RegNum - static_cast<int>(RegNumAmd64::REGNUM_COUNT) + 17; + } + default: + assert(false && "Unexpected architecture"); + return 0; + } +} + +static int GetDwarfFpRegNum(Triple::ArchType ArchType) +{ + switch (ArchType) { + case Triple::x86: + return GetDwarfRegNum(ArchType, static_cast<int>(RegNumX86::REGNUM_FP)); + case Triple::arm: // fall through + case Triple::armeb: // fall through + case Triple::thumb: // fall through + case Triple::thumbeb: + return GetDwarfRegNum(ArchType, static_cast<int>(RegNumArm::REGNUM_FP)); + case Triple::aarch64: // fall through + case Triple::aarch64_be: + return GetDwarfRegNum(ArchType, static_cast<int>(RegNumArm64::REGNUM_FP)); + case Triple::x86_64: + return GetDwarfRegNum(ArchType, static_cast<int>(RegNumAmd64::REGNUM_FP)); + default: + assert(false && "Unexpected architecture"); + return 0; + } +} + +static void EmitVarLocation(MCObjectStreamer *Streamer, + const ICorDebugInfo::NativeVarInfo &VarInfo, + bool IsLocList = false) { + MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + Triple::ArchType ArchType = context.getObjectFileInfo()->getTargetTriple().getArch(); + + int DwarfRegNum; + int DwarfRegNum2; + int DwarfBaseRegNum; + unsigned Len; + + bool IsByRef = false; + bool IsStk2 = false; + bool IsRegStk = false; + + switch (VarInfo.loc.vlType) { + case ICorDebugInfo::VLT_REG_BYREF: // fall through + IsByRef = true; + case ICorDebugInfo::VLT_REG_FP: // fall through + case ICorDebugInfo::VLT_REG: { + DwarfRegNum = GetDwarfRegNum(ArchType, VarInfo.loc.vlReg.vlrReg); + if (IsByRef) { + Len = 2; + if (IsLocList) { + Streamer->EmitIntValue(Len, 2); + } else { + Streamer->EmitULEB128IntValue(Len); + } + Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_breg0, 1); + Streamer->EmitSLEB128IntValue(0); + } else { + Len = 1; + if (IsLocList) { + Streamer->EmitIntValue(Len, 2); + } else { + Streamer->EmitULEB128IntValue(Len); + } + Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); + } + + break; + } + case ICorDebugInfo::VLT_STK_BYREF: // fall through + IsByRef = true; + case ICorDebugInfo::VLT_STK2: + IsStk2 = true; + case ICorDebugInfo::VLT_STK: { + DwarfBaseRegNum = GetDwarfRegNum(ArchType, IsStk2 ? VarInfo.loc.vlStk2.vls2BaseReg : + VarInfo.loc.vlStk.vlsBaseReg); + + SmallString<128> Tmp; + raw_svector_ostream OSE(Tmp); + encodeSLEB128(IsStk2 ? VarInfo.loc.vlStk2.vls2Offset : + VarInfo.loc.vlStk.vlsOffset, OSE); + StringRef OffsetRepr = OSE.str(); + + if (IsByRef) { + Len = OffsetRepr.size() + 2; + if (IsLocList) { + Streamer->EmitIntValue(Len, 2); + } else { + Streamer->EmitULEB128IntValue(Len); + } + Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1); + Streamer->EmitBytes(OffsetRepr); + Streamer->EmitIntValue(dwarf::DW_OP_deref, 1); + } else { + Len = OffsetRepr.size() + 1; + if (IsLocList) { + Streamer->EmitIntValue(Len, 2); + } else { + Streamer->EmitULEB128IntValue(Len); + } + Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1); + Streamer->EmitBytes(OffsetRepr); + } + + break; + } + case ICorDebugInfo::VLT_REG_REG: { + DwarfRegNum = GetDwarfRegNum(ArchType, VarInfo.loc.vlRegReg.vlrrReg1); + DwarfRegNum2 = GetDwarfRegNum(ArchType, VarInfo.loc.vlRegReg.vlrrReg2); + + Len = (1 /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) * 2 + 1; + if (IsLocList) { + Streamer->EmitIntValue(Len, 2); + } else { + Streamer->EmitULEB128IntValue(Len + 1); + } + + Streamer->EmitIntValue(DwarfRegNum2 + dwarf::DW_OP_reg0, 1); + Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); + Streamer->EmitULEB128IntValue(TargetPointerSize); + + Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); + Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); + Streamer->EmitULEB128IntValue(TargetPointerSize); + + break; + } + case ICorDebugInfo::VLT_REG_STK: // fall through + IsRegStk = true; + case ICorDebugInfo::VLT_STK_REG: { + DwarfRegNum = GetDwarfRegNum(ArchType, IsRegStk ? VarInfo.loc.vlRegStk.vlrsReg : + VarInfo.loc.vlStkReg.vlsrReg); + DwarfBaseRegNum = GetDwarfRegNum(ArchType, IsRegStk ? VarInfo.loc.vlRegStk.vlrsStk.vlrssBaseReg : + VarInfo.loc.vlStkReg.vlsrStk.vlsrsBaseReg); + + SmallString<128> Tmp; + raw_svector_ostream OSE(Tmp); + encodeSLEB128(IsRegStk ? VarInfo.loc.vlRegStk.vlrsStk.vlrssOffset : + VarInfo.loc.vlStkReg.vlsrStk.vlsrsOffset, OSE); + StringRef OffsetRepr = OSE.str(); + + Len = (1 /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) + + (1 /*DW_OP_breg */ + OffsetRepr.size() + 1 /* DW_OP_piece */ + 1 /* Reg size */) + 1; + + if (IsLocList) { + Streamer->EmitIntValue(Len, 2); + } else { + Streamer->EmitULEB128IntValue(Len + 1); + } + + if (IsRegStk) { + Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); + Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); + Streamer->EmitULEB128IntValue(TargetPointerSize); + + Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1); + Streamer->EmitBytes(OffsetRepr); + Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); + Streamer->EmitULEB128IntValue(TargetPointerSize); + } else { + Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1); + Streamer->EmitBytes(OffsetRepr); + Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); + Streamer->EmitULEB128IntValue(TargetPointerSize); + + Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); + Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); + Streamer->EmitULEB128IntValue(TargetPointerSize); + } + + break; + } + case ICorDebugInfo::VLT_FPSTK: + case ICorDebugInfo::VLT_FIXED_VA: + assert(false && "Unsupported varloc type!"); + default: + assert(false && "Unknown varloc type!"); + if (IsLocList) { + Streamer->EmitIntValue(0, 2); + } else { + Streamer->EmitULEB128IntValue(0); + } + } +} + +// Lexical scope + +class LexicalScope +{ +public: + LexicalScope(uint64_t Start, uint64_t End, bool IsFuncScope = false) : + Start(Start), + End(End), + IsFuncScope(IsFuncScope) {} + + LexicalScope(VarInfo *Info) : + Start(Info->GetStartOffset()), + End(Info->GetEndOffset()), + IsFuncScope(false) { Vars.push_back(Info); } + + bool IsContains(const VarInfo *Info) const { + return Start <= Info->GetStartOffset() && End >= Info->GetEndOffset(); + } + + void AddVar(VarInfo *Info); + + void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection, const MCExpr *SymExpr); + +private: + uint64_t Start; + uint64_t End; + bool IsFuncScope; + std::vector<VarInfo*> Vars; + std::vector<LexicalScope> InnerScopes; +}; + +void LexicalScope::AddVar(VarInfo *Info) { + if (Info->IsParam() && IsFuncScope) { + Vars.push_back(Info); + return; + } + + if (!IsContains(Info)) + return; + + uint64_t VarStart = Info->GetStartOffset(); + uint64_t VarEnd = Info->GetEndOffset(); + + // Var belongs to inner scope + if (VarStart != Start || VarEnd != End) { + // Try to add variable to one the inner scopes + for (auto &Scope : InnerScopes) { + if (Scope.IsContains(Info)) { + Scope.AddVar(Info); + return; + } + } + // We need to create new inner scope for this var + InnerScopes.emplace_back(Info); + } else { + Vars.push_back(Info); + } +} + +void LexicalScope::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection, const MCExpr *SymExpr) { + Streamer->SwitchSection(TypeSection); + + if (!IsFuncScope) + { + // Dump lexical block DIE + MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::LexicalBlock); + + // DW_AT_low_pc + const MCExpr *StartExpr = MCConstantExpr::create(Start, context); + const MCExpr *LowPcExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr, + StartExpr, context); + Streamer->EmitValue(LowPcExpr, TargetPointerSize); + + // DW_AT_high_pc + Streamer->EmitIntValue(End - Start, TargetPointerSize); + } + + for (auto *Var : Vars) { + Var->Dump(TypeBuilder, Streamer, TypeSection, StrSection); + } + + for (auto &Scope : InnerScopes) { + Scope.Dump(TypeBuilder, Streamer, TypeSection, StrSection, SymExpr); + } + + if (!IsFuncScope) { + // Terminate block + Streamer->EmitIntValue(0, 1); + } +} + +// StaticVarInfo + +class StaticVarInfo : public DwarfInfo +{ +public: + StaticVarInfo(const DwarfStaticDataField *StaticField) : StaticField(StaticField) {} + + void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override {}; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + const DwarfStaticDataField *StaticField; + + void EmitLocation(MCObjectStreamer *Streamer); +}; + +void StaticVarInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + MCContext &context = Streamer->getContext(); + MCSymbol *Sym = context.getOrCreateSymbol(Twine(StaticField->GetStaticDataName())); + if (Sym->isUndefined()) + return; + + DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection); +} + +void StaticVarInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::VariableStatic); + + // DW_AT_specification + EmitInfoOffset(Streamer, StaticField, 4); + + // DW_AT_location + EmitLocation(Streamer); +} + +void StaticVarInfo::EmitLocation(MCObjectStreamer *Streamer) { + MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + + MCSymbol *Sym = context.getOrCreateSymbol(Twine(StaticField->GetStaticDataName())); + + SmallString<128> Tmp; + raw_svector_ostream OSE(Tmp); + encodeULEB128(StaticField->GetStaticOffset(), OSE); + StringRef OffsetRepr = OSE.str(); + + unsigned Len = 1 /* DW_OP_addr */ + TargetPointerSize; + + // Need double deref + if (StaticField->IsStaticDataInObject()) { + Len += (1 /* DW_OP_deref */) * 2; + } + + if (StaticField->GetStaticOffset() != 0) { + Len += 1 /* DW_OP_plus_uconst */ + OffsetRepr.size(); + } + + Streamer->EmitULEB128IntValue(Len); + Streamer->EmitIntValue(dwarf::DW_OP_addr, 1); + Streamer->EmitSymbolValue(Sym, TargetPointerSize); + + if (StaticField->IsStaticDataInObject()) { + Streamer->EmitIntValue(dwarf::DW_OP_deref, 1); + Streamer->EmitIntValue(dwarf::DW_OP_deref, 1); + } + + if (StaticField->GetStaticOffset() != 0) { + Streamer->EmitIntValue(dwarf::DW_OP_plus_uconst, 1); + Streamer->EmitBytes(OffsetRepr); + } +} + +// VarInfo + +VarInfo::VarInfo(const DebugVarInfo &Info, bool IsThis) : + DebugInfo(Info), + LocSymbol(nullptr), + IsThis(IsThis) { + if (!Info.IsParam) { + assert(!Info.Ranges.empty()); + StartOffset = Info.Ranges.front().startOffset; + EndOffset = Info.Ranges.back().endOffset; + } else { + // Params belong to func scope + StartOffset = 0xFFFFFFFF; + EndOffset = 0xFFFFFFFF; + } +} + +void VarInfo::DumpLocsIfNeeded(MCObjectStreamer *Streamer, + MCSection *LocSection, + const MCExpr *SymExpr) { + if (!IsDebugLocNeeded()) + return; + + Streamer->SwitchSection(LocSection); + + MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + + LocSymbol = context.createTempSymbol(); + Streamer->EmitLabel(LocSymbol); + + for (const auto &NativeInfo : DebugInfo.Ranges) { + const MCExpr *StartOffsetExpr = MCConstantExpr::create(NativeInfo.startOffset, context); + const MCExpr *EndOffsetExpr = MCConstantExpr::create(NativeInfo.endOffset, context); + + // Begin address + const MCExpr *BeginAddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr, + StartOffsetExpr, context); + Streamer->EmitValue(BeginAddrExpr, TargetPointerSize); + + // End address + const MCExpr *EndAddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr, + EndOffsetExpr, context); + Streamer->EmitValue(EndAddrExpr, TargetPointerSize); + + // Expression + EmitVarLocation(Streamer, NativeInfo, true); + } + + // Terminate list entry + Streamer->EmitIntValue(0, TargetPointerSize); + Streamer->EmitIntValue(0, TargetPointerSize); +} + +void VarInfo::DumpStrings(MCObjectStreamer *Streamer) { + if (IsThis) { + Streamer->EmitBytes(StringRef("this")); + } else { + Streamer->EmitBytes(StringRef(DebugInfo.Name)); + } + Streamer->EmitIntValue(0, 1); +} + +void VarInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + bool IsDebugLocUsed = IsDebugLocNeeded(); + + // Abbrev Number + if (DebugInfo.IsParam) { + if (IsThis) { + Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::FormalParameterThisLoc : + DwarfAbbrev::FormalParameterThis); + } else { + Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::FormalParameterLoc : + DwarfAbbrev::FormalParameter); + } + } else { + Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::VariableLoc : + DwarfAbbrev::Variable); + } + + // DW_AT_name + EmitSectionOffset(Streamer, StrSymbol, 4); + + // DW_AT_decl_file + Streamer->EmitIntValue(1, 1); + + // DW_AT_decl_line + Streamer->EmitIntValue(1, 1); + + // DW_AT_type + DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(DebugInfo.TypeIndex); + assert(Info != nullptr); + + EmitInfoOffset(Streamer, Info, 4); + + // DW_AT_location + if (IsDebugLocUsed) { + EmitSectionOffset(Streamer, LocSymbol, 4); + } else { + assert(DebugInfo.Ranges.size() == 1); + EmitVarLocation(Streamer, DebugInfo.Ranges[0]); + } +} + +// SubprogramInfo + +SubprogramInfo::SubprogramInfo(const char *Name, + int Size, + DwarfMemberFunctionIdTypeInfo *MethodTypeInfo, + const std::vector<DebugVarInfo> &DebugVarInfos, + const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos) : + Name(Name), + Size(Size), + MethodTypeInfo(MethodTypeInfo), + DebugEHClauseInfos(DebugEHClauseInfos) { + bool IsStatic = MethodTypeInfo->IsStatic(); + for (unsigned i = 0; i < DebugVarInfos.size(); i++) { + VarInfos.emplace_back(DebugVarInfos[i], i == 0 && !IsStatic); + } +} + +void SubprogramInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection, MCSection *LocSection) { + DumpDebugLoc(Streamer, LocSection); + + DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection); + + // Dump vars + DumpVars(TypeBuilder, Streamer, TypeSection, StrSection); + + // Dump try-catch blocks + Streamer->SwitchSection(TypeSection); + DumpEHClauses(Streamer, TypeSection); + + // Terminate subprogram DIE + Streamer->EmitIntValue(0, 1); +} + +void SubprogramInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + MCContext &context = Streamer->getContext(); + bool IsStatic = MethodTypeInfo->IsStatic(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + Triple::ArchType ArchType = context.getObjectFileInfo()->getTargetTriple().getArch(); + + // Subprogram DIE + + // Abbrev Number + Streamer->EmitULEB128IntValue(IsStatic ? DwarfAbbrev::SubprogramStatic : + DwarfAbbrev::Subprogram); + + // DW_AT_specification + EmitInfoOffset(Streamer, MethodTypeInfo, 4); + + // DW_AT_low_pc + MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name)); + const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context); + Streamer->EmitValue(SymExpr, TargetPointerSize); + + // DW_AT_high_pc + Streamer->EmitIntValue(Size, TargetPointerSize); + + // DW_AT_frame_base + Streamer->EmitULEB128IntValue(1); + Streamer->EmitIntValue(GetDwarfFpRegNum(ArchType) + dwarf::DW_OP_reg0, 1); + + if (!IsStatic) { + // DW_AT_object_pointer + uint32_t Offset = Streamer->getOrCreateDataFragment()->getContents().size(); + + Streamer->EmitIntValue(Offset + 4, 4); + } +} + +void SubprogramInfo::DumpDebugLoc(MCObjectStreamer *Streamer, MCSection *LocSection) { + MCContext &context = Streamer->getContext(); + MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name)); + const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context); + + for (auto &VarInfo : VarInfos) { + VarInfo.DumpLocsIfNeeded(Streamer, LocSection, SymExpr); + } +} + +void SubprogramInfo::DumpVars(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + MCContext &context = Streamer->getContext(); + MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name)); + const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context); + + LexicalScope FuncScope(0, Size, true); + + for (unsigned i = 0; i < VarInfos.size(); i++) { + FuncScope.AddVar(&VarInfos[i]); + } + + FuncScope.Dump(TypeBuilder, Streamer, TypeSection, StrSection, SymExpr); +} + +static void DumpEHClause(MCObjectStreamer *Streamer, MCSection *TypeSection, int Abbrev, + const MCExpr *SymExpr, unsigned Offset, unsigned Length) { + MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + + // Abbrev Number + Streamer->EmitULEB128IntValue(Abbrev); + + // DW_AT_low_pc + const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, context); + const MCExpr *AddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr, + OffsetExpr, context); + + Streamer->EmitValue(AddrExpr, TargetPointerSize); + + // DW_AT_high_pc + Streamer->EmitIntValue(Length, TargetPointerSize); +} + +void SubprogramInfo::DumpEHClauses(MCObjectStreamer *Streamer, MCSection *TypeSection) { + MCContext &context = Streamer->getContext(); + + MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name)); + const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context); + + for (const auto &EHClause: DebugEHClauseInfos) { + // Try block DIE + DumpEHClause(Streamer, TypeSection, DwarfAbbrev::TryBlock, + SymExpr, EHClause.TryOffset, EHClause.TryLength); + + // Catch block DIE + DumpEHClause(Streamer, TypeSection, DwarfAbbrev::CatchBlock, + SymExpr, EHClause.HandlerOffset, EHClause.HandlerLength); + } +} + +// DwarfGen + +void DwarfGen::SetTypeBuilder(UserDefinedDwarfTypesBuilder *TypeBuilder) { + assert(this->TypeBuilder == nullptr); + assert(TypeBuilder != nullptr); + this->TypeBuilder = TypeBuilder; + this->Streamer = TypeBuilder->GetStreamer(); +} + +void DwarfGen::EmitCompileUnit() { + MCContext &context = Streamer->getContext(); + + MCSymbol *LineSectionSymbol = nullptr; + MCSymbol *AbbrevSectionSymbol = nullptr; + if (context.getAsmInfo()->doesDwarfUseRelocationsAcrossSections()) { + LineSectionSymbol = Streamer->getDwarfLineTableSymbol(0); + + Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); + AbbrevSectionSymbol = context.createTempSymbol(); + Streamer->EmitLabel(AbbrevSectionSymbol); + } + + MCSection *debugSection = context.getObjectFileInfo()->getDwarfInfoSection(); + Streamer->SwitchSection(debugSection); + + InfoStart = debugSection->getBeginSymbol(); + InfoEnd = context.createTempSymbol(); + + // Length + const MCExpr *Length = MakeStartMinusEndExpr(*Streamer, *InfoStart, *InfoEnd, 4); + emitAbsValue(*Streamer, Length, 4); + + // Version + Streamer->EmitIntValue(context.getDwarfVersion(), 2); + + // Unit type, Addr Size and Abbrev offset - DWARF >= 5 + // Abbrev offset, Addr Size - DWARF <= 4 + unsigned addrSize = context.getAsmInfo()->getCodePointerSize(); + if (context.getDwarfVersion() >= 5) { + Streamer->EmitIntValue(dwarf::DW_UT_compile, 1); + Streamer->EmitIntValue(addrSize, 1); + } + + // Abbrev Offset + if (AbbrevSectionSymbol == nullptr) { + Streamer->EmitIntValue(0, 4); + } else { + Streamer->EmitSymbolValue(AbbrevSectionSymbol, 4, + context.getAsmInfo()->needsDwarfSectionOffsetDirective()); + } + + if (context.getDwarfVersion() <= 4) + Streamer->EmitIntValue(addrSize, 1); + + // CompileUnit DIE + + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::CompileUnit); + + // DW_AT_producer: CoreRT + Streamer->EmitBytes(StringRef("CoreRT")); + Streamer->EmitIntValue(0, 1); + + // DW_AT_language +#ifdef FEATURE_LANGID_CS + Streamer->EmitIntValue(DW_LANG_MICROSOFT_CSHARP, 2); +#else + Streamer->EmitIntValue(dwarf::DW_LANG_C_plus_plus, 2); +#endif + + // DW_AT_stmt_list + if (LineSectionSymbol == nullptr) { + Streamer->EmitIntValue(0, 4); + } else { + Streamer->EmitSymbolValue(LineSectionSymbol, 4, + context.getAsmInfo()->needsDwarfSectionOffsetDirective()); + } +} + +void DwarfGen::EmitSubprogramInfo(const char *FunctionName, + int FunctionSize, + unsigned MethodTypeIndex, + const std::vector<DebugVarInfo> &VarInfos, + const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos) { + // return if CU isn't emitted + if (InfoStart == nullptr) + return; + + if (MethodTypeIndex == 0) + return; + + DwarfMemberFunctionIdTypeInfo *MethodTypeInfo = static_cast<DwarfMemberFunctionIdTypeInfo*>( + TypeBuilder->GetTypeInfoByIndex(MethodTypeIndex)); + assert(MethodTypeInfo != nullptr); + + MethodTypeInfo->SetLinkageName(FunctionName); + + Subprograms.emplace_back(FunctionName, FunctionSize, MethodTypeInfo, VarInfos, DebugEHClauseInfos); +} + +void DwarfGen::EmitAbbrev() { + // return if CU isn't emitted + if (InfoStart == nullptr) + return; + + MCContext &context = Streamer->getContext(); + + DwarfAbbrev::Dump(Streamer, context.getDwarfVersion(), + context.getAsmInfo()->getCodePointerSize()); +} + +void DwarfGen::EmitAranges() { + // return if CU isn't emitted + if (InfoStart == nullptr) + return; + + MCContext &context = Streamer->getContext(); + Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); + + auto &Sections = context.getGenDwarfSectionSyms(); + + int Length = 4 + 2 + 4 + 1 + 1; + int AddrSize = context.getAsmInfo()->getCodePointerSize(); + int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1)); + if (Pad == 2 * AddrSize) + Pad = 0; + Length += Pad; + + Length += 2 * AddrSize * Sections.size(); + Length += 2 * AddrSize; + + // Emit the header for this section. + // The 4 byte length not including the 4 byte value for the length. + Streamer->EmitIntValue(Length - 4, 4); + + // The 2 byte version, which is 2. + Streamer->EmitIntValue(2, 2); + + // The 4 byte offset to the compile unit in the .debug_info from the start + // of the .debug_info. + Streamer->EmitSymbolValue(InfoStart, 4, + context.getAsmInfo()->needsDwarfSectionOffsetDirective()); + + Streamer->EmitIntValue(AddrSize, 1); + + Streamer->EmitIntValue(0, 1); + + for(int i = 0; i < Pad; i++) + Streamer->EmitIntValue(0, 1); + + for (MCSection *Sec : Sections) { + const MCSymbol *StartSymbol = Sec->getBeginSymbol(); + MCSymbol *EndSymbol = Sec->getEndSymbol(context); + assert(StartSymbol && "StartSymbol must not be NULL"); + assert(EndSymbol && "EndSymbol must not be NULL"); + + const MCExpr *Addr = MCSymbolRefExpr::create( + StartSymbol, MCSymbolRefExpr::VK_None, context); + const MCExpr *Size = MakeStartMinusEndExpr(*Streamer, + *StartSymbol, *EndSymbol, 0); + Streamer->EmitValue(Addr, AddrSize); + emitAbsValue(*Streamer, Size, AddrSize); + } + + // Terminating zeros. + Streamer->EmitIntValue(0, AddrSize); + Streamer->EmitIntValue(0, AddrSize); +} + +void DwarfGen::Finish() { + // return if CU isn't emitted + if (InfoStart == nullptr) + return; + + MCContext &context = Streamer->getContext(); + + // Dump type info + + MCSection *InfoSection = context.getObjectFileInfo()->getDwarfInfoSection(); + MCSection *StrSection = context.getObjectFileInfo()->getDwarfStrSection(); + MCSection *LocSection = context.getObjectFileInfo()->getDwarfLocSection(); + + TypeBuilder->EmitTypeInformation(InfoSection, StrSection); + + // Dump subprograms + + for (auto &Subprogram : Subprograms) { + Subprogram.Dump(TypeBuilder, Streamer, InfoSection, StrSection, LocSection); + } + + // Dump static vars + + for (const auto *ClassTypeInfo : TypeBuilder->GetClassesWithStaticFields()) { + for (const auto &StaticField : ClassTypeInfo->GetStaticFields()) { + StaticVarInfo Info(&StaticField); + Info.Dump(TypeBuilder, Streamer, InfoSection, StrSection); + } + } + + // Add the NULL terminating the Compile Unit DIE's. + Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); + + Streamer->EmitIntValue(0, 1); + + Streamer->EmitLabel(InfoEnd); + + Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); + + // Terminate the abbreviations for this compilation unit + Streamer->EmitIntValue(0, 1); +}
\ No newline at end of file diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h new file mode 100644 index 000000000..2fd78a5c6 --- /dev/null +++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h @@ -0,0 +1,106 @@ +//===---- dwarfGen.h --------------------------------------------*- C++ -*-===// +// +// dwarf generator is used to generate dwarf debuginfo. +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "llvm/MC/MCObjectStreamer.h" + +#include "dwarfTypeBuilder.h" +#include "jitDebugInfo.h" + +#include <vector> + +class VarInfo : public DwarfInfo +{ +public: + VarInfo(const DebugVarInfo &Info, bool IsThis); + + bool IsDebugLocNeeded() const { return DebugInfo.Ranges.size() > 1; } + + void DumpLocsIfNeeded(MCObjectStreamer *Streamer, MCSection *LocSection, const MCExpr *SymExpr); + + uint64_t GetStartOffset() const { return StartOffset; } + + uint64_t GetEndOffset() const { return EndOffset; } + + bool IsParam() const { return DebugInfo.IsParam; } + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + DebugVarInfo DebugInfo; + MCSymbol *LocSymbol; + bool IsThis; + uint64_t StartOffset; + uint64_t EndOffset; +}; + +class SubprogramInfo : public DwarfInfo +{ +public: + using DwarfInfo::Dump; + + SubprogramInfo(const char *Name, + int Size, + DwarfMemberFunctionIdTypeInfo *MethodTypeInfo, + const std::vector<DebugVarInfo> &DebugVarInfos, + const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos); + + void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection, MCSection *LocSection); + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override {} + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + void DumpDebugLoc(MCObjectStreamer *Streamer, MCSection *LocSection); + void DumpVars(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection); + void DumpEHClauses(MCObjectStreamer *Streamer, MCSection *TypeSection); + + std::string Name; + int Size; + DwarfMemberFunctionIdTypeInfo *MethodTypeInfo; + std::vector<DebugEHClauseInfo> DebugEHClauseInfos; + std::vector<VarInfo> VarInfos; +}; + +class DwarfGen +{ +public: + DwarfGen() : Streamer(nullptr), + TypeBuilder(nullptr), + InfoStart(nullptr), + InfoEnd(nullptr) {} + + void SetTypeBuilder(UserDefinedDwarfTypesBuilder *TypeBuilder); + void EmitCompileUnit(); + void EmitSubprogramInfo(const char *FunctionName, + int FunctionSize, + unsigned MethodTypeIndex, + const std::vector<DebugVarInfo> &VarsInfo, + const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos); + + void EmitAbbrev(); + void EmitAranges(); + void Finish(); + +private: + MCObjectStreamer *Streamer; + UserDefinedDwarfTypesBuilder *TypeBuilder; + + MCSymbol *InfoStart; + MCSymbol *InfoEnd; + + std::vector<SubprogramInfo> Subprograms; +};
\ No newline at end of file diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp new file mode 100644 index 000000000..da5448bf1 --- /dev/null +++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp @@ -0,0 +1,780 @@ +//===---- dwarfTypeBuilder.cpp ----------------------------------*- C++ -*-===// +// +// dwarf type builder implementation +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +//===----------------------------------------------------------------------===// + +#include "dwarfTypeBuilder.h" +#include "dwarfAbbrev.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" + +#include <sstream> +#include <vector> + +// DwarfInfo + +void DwarfInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumped) + return; + + IsDumped = true; + + MCContext &context = Streamer->getContext(); + + InfoSymbol = context.createTempSymbol(); + InfoExpr = CreateOffsetExpr(context, TypeSection->getBeginSymbol(), InfoSymbol); + + DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + + Streamer->SwitchSection(StrSection); + StrSymbol = context.createTempSymbol(); + Streamer->EmitLabel(StrSymbol); + DumpStrings(Streamer); + + Streamer->SwitchSection(TypeSection); + Streamer->EmitLabel(InfoSymbol); + DumpTypeInfo(Streamer, TypeBuilder); +} + +void DwarfInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumpedTypes) + return; + + IsDumpedTypes = true; +} + +void DwarfInfo::EmitSectionOffset(MCObjectStreamer *Streamer, + MCSymbol *Symbol, + unsigned Size, + uint32_t Offset) { + MCContext &context = Streamer->getContext(); + + if (context.getAsmInfo()->doesDwarfUseRelocationsAcrossSections()) { + if (Offset == 0) { + Streamer->EmitSymbolValue(Symbol, Size); + } else { + const MCSymbolRefExpr *SymbolExpr = MCSymbolRefExpr::create(Symbol, + MCSymbolRefExpr::VK_None, context); + const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, context); + const MCExpr *Expr = MCBinaryExpr::createAdd(SymbolExpr, OffsetExpr, context); + Streamer->EmitValue(Expr, Size); + } + } else { + Streamer->EmitIntValue(Symbol->getOffset() + Offset, Size); + } +} + +const MCExpr *DwarfInfo::CreateOffsetExpr(MCContext &Context, + MCSymbol *BeginSymbol, + MCSymbol *Symbol) { + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *StartExpr = + MCSymbolRefExpr::create(BeginSymbol, Variant, Context); + const MCExpr *EndExpr = + MCSymbolRefExpr::create(Symbol, Variant, Context); + return MCBinaryExpr::createSub(EndExpr, StartExpr, Context); +} + +void DwarfInfo::EmitOffset(MCObjectStreamer *Streamer, + const MCExpr *OffsetExpr, + unsigned Size) { + MCContext &context = Streamer->getContext(); + + if (!context.getAsmInfo()->hasAggressiveSymbolFolding()) { + MCSymbol *Temp = context.createTempSymbol(); + Streamer->EmitAssignment(Temp, OffsetExpr); + OffsetExpr = MCSymbolRefExpr::create(Temp, context); + } + + Streamer->EmitValue(OffsetExpr, Size); +} + +void DwarfInfo::EmitInfoOffset(MCObjectStreamer *Streamer, const DwarfInfo *Info, unsigned Size) { + uint64_t Offset = Info->InfoSymbol->getOffset(); + if (Offset != 0) { + Streamer->EmitIntValue(Offset, Size); + } else { + EmitOffset(Streamer, Info->InfoExpr, Size); + } +} + +// DwarfPrimitiveTypeInfo + +struct PrimitiveTypeDesc { + const char *Name; + int Encoding; + unsigned ByteSize; +}; + +static PrimitiveTypeDesc GetPrimitiveTypeDesc(PrimitiveTypeFlags Type, unsigned TargetPointerSize) { + switch (Type) { + case PrimitiveTypeFlags::Void: return {"void", dwarf::DW_ATE_address, 0}; + case PrimitiveTypeFlags::Boolean: return {"bool", dwarf::DW_ATE_boolean, 1}; + case PrimitiveTypeFlags::Char: return {"char16_t", dwarf::DW_ATE_UTF, 2}; + case PrimitiveTypeFlags::SByte: return {"sbyte", dwarf::DW_ATE_signed, 1}; + case PrimitiveTypeFlags::Byte: return {"byte", dwarf::DW_ATE_unsigned, 1}; + case PrimitiveTypeFlags::Int16: return {"short", dwarf::DW_ATE_signed, 2}; + case PrimitiveTypeFlags::UInt16: return {"ushort", dwarf::DW_ATE_unsigned, 2}; + case PrimitiveTypeFlags::Int32: return {"int", dwarf::DW_ATE_signed, 4}; + case PrimitiveTypeFlags::UInt32: return {"uint", dwarf::DW_ATE_unsigned, 4}; + case PrimitiveTypeFlags::Int64: return {"long", dwarf::DW_ATE_signed, 8}; + case PrimitiveTypeFlags::UInt64: return {"ulong", dwarf::DW_ATE_unsigned, 8}; + case PrimitiveTypeFlags::IntPtr: return {"System.IntPtr", dwarf::DW_ATE_signed, TargetPointerSize}; + case PrimitiveTypeFlags::UIntPtr: return {"System.UIntPtr", dwarf::DW_ATE_unsigned, TargetPointerSize}; + case PrimitiveTypeFlags::Single: return {"float", dwarf::DW_ATE_float, 4}; + case PrimitiveTypeFlags::Double: return {"double", dwarf::DW_ATE_float, 8}; + default: + assert(false && "Unexpected type"); + return {nullptr, 0, 0}; + } +} + +void DwarfPrimitiveTypeInfo::DumpStrings(MCObjectStreamer *Streamer) { + MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + + PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(Type, TargetPointerSize); + if (TD.Name == nullptr) + return; + + Streamer->EmitBytes(StringRef(TD.Name)); + Streamer->EmitIntValue(0, 1); +} + +void DwarfPrimitiveTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + + PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(Type, TargetPointerSize); + if (TD.Name == nullptr) + return; + + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::BaseType); + + // DW_AT_name + EmitSectionOffset(Streamer, StrSymbol, 4); + + // DW_AT_encoding + Streamer->EmitIntValue(TD.Encoding, 1); + + // DW_AT_byte_size + Streamer->EmitIntValue(TD.ByteSize, 1); +} + +// DwarfEnumerator + +void DwarfEnumerator::DumpStrings(MCObjectStreamer *Streamer) { + Streamer->EmitBytes(Name); + Streamer->EmitIntValue(0, 1); +} + +void DwarfEnumerator::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + uint8_t Size = EnumTypeInfo->GetByteSize(); + + // Abbrev Number + switch (Size) { + case 1: + Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator1); + break; + case 2: + Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator2); + break; + case 4: + Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator4); + break; + case 8: + Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator8); + break; + default: + assert(false && "Unexpected byte size value"); + } + + // DW_AT_name + EmitSectionOffset(Streamer, StrSymbol, 4); + + // DW_AT_const_value + Streamer->EmitIntValue(Value, Size); +} + +// DwarfEnumTypeInfo + +DwarfEnumTypeInfo::DwarfEnumTypeInfo(const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords) : + Name(TypeDescriptor.Name), + ElementType(TypeDescriptor.ElementType) { + for (uint64 i = 0; i < TypeDescriptor.ElementCount; i++) { + Records.emplace_back(TypeRecords[i], this); + } +} + +void DwarfEnumTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumpedTypes) + return; + + DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + + DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType); + assert(Info != nullptr); + + Info->Dump(TypeBuilder, Streamer, TypeSection, StrSection); +} + +void DwarfEnumTypeInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumped) + return; + + MCContext &context = Streamer->getContext(); + unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize(); + + DwarfPrimitiveTypeInfo *ElementTypeInfo = static_cast<DwarfPrimitiveTypeInfo*>( + TypeBuilder->GetTypeInfoByIndex(ElementType)); + assert(ElementTypeInfo != nullptr); + + PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(ElementTypeInfo->GetType(), TargetPointerSize); + ByteSize = TD.ByteSize; + + DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection); + + for (auto &Enumerator : Records) { + Enumerator.Dump(TypeBuilder, Streamer, TypeSection, StrSection); + } + + // Terminate DIE + Streamer->SwitchSection(TypeSection); + Streamer->EmitIntValue(0, 1); +} + +void DwarfEnumTypeInfo::DumpStrings(MCObjectStreamer *Streamer) { + Streamer->EmitBytes(Name); + Streamer->EmitIntValue(0, 1); +} + +void DwarfEnumTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::EnumerationType); + + // DW_AT_name + EmitSectionOffset(Streamer, StrSymbol, 4); + + // DW_AT_type + DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType); + assert(Info != nullptr); + + EmitInfoOffset(Streamer, Info, 4); + + // DW_AT_byte_size + Streamer->EmitIntValue(ByteSize, 1); +} + +// DwarfDataField + +void DwarfDataField::DumpStrings(MCObjectStreamer *Streamer) { + Streamer->EmitBytes(StringRef(Name)); + Streamer->EmitIntValue(0, 1); +} + +void DwarfDataField::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumpedTypes) + return; + + DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + + DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex); + assert(MemberTypeInfo != nullptr); + + MemberTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection); +} + +void DwarfDataField::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassMember); + + // DW_AT_name + EmitSectionOffset(Streamer, StrSymbol, 4); + + // DW_AT_type + DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex); + assert(MemberTypeInfo != nullptr); + EmitInfoOffset(Streamer, MemberTypeInfo, 4); + + // DW_AT_data_member_location + Streamer->EmitIntValue(Offset, 4); +} + +// DwarfStaticDataField + +void DwarfStaticDataField::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassMemberStatic); + + // DW_AT_name + EmitSectionOffset(Streamer, StrSymbol, 4); + + // DW_AT_type + DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex); + assert(MemberTypeInfo != nullptr); + EmitInfoOffset(Streamer, MemberTypeInfo, 4); +} + +// DwarfClassTypeInfo + +DwarfClassTypeInfo::DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors) : + Name(ClassDescriptor.Name), + IsStruct(ClassDescriptor.IsStruct), + BaseClassId(ClassDescriptor.BaseClassId), + Size(ClassDescriptor.InstanceSize), + IsForwardDecl(false) { + int32_t staticIdx = 0; + for (int32_t i = 0; i < ClassFieldsDescriptor.FieldsCount; i++) { + if (FieldsDescriptors[i].Offset == 0xFFFFFFFF) { + StaticFields.emplace_back(FieldsDescriptors[i], StaticsDescriptors[staticIdx++]); + } else { + Fields.emplace_back(FieldsDescriptors[i]); + } + } +} + +void DwarfClassTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumpedTypes) + return; + + DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + + if (BaseClassId != 0) { + DwarfInfo *BaseClassInfo = TypeBuilder->GetTypeInfoByIndex(BaseClassId); + assert(BaseClassInfo != nullptr); + + BaseClassInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection); + } + + for (auto &Field : Fields) { + Field.DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + } + + for (auto &StaticField : StaticFields) { + StaticField.DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + } + + for (auto *Function : MemberFunctions) { + Function->DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + } +} + +void DwarfClassTypeInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumped) + return; + + DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection); + + if (IsForwardDecl) + return; + + for (auto &Field : Fields) { + Field.Dump(TypeBuilder, Streamer, TypeSection, StrSection); + } + + for (auto &StaticField : StaticFields) { + StaticField.Dump(TypeBuilder, Streamer, TypeSection, StrSection); + } + + for (auto *Function : MemberFunctions) { + Function->Dump(TypeBuilder, Streamer, TypeSection, StrSection); + } + + // Terminate DIE + Streamer->SwitchSection(TypeSection); + Streamer->EmitIntValue(0, 1); +} + +void DwarfClassTypeInfo::DumpStrings(MCObjectStreamer *Streamer) { + Streamer->EmitBytes(StringRef(Name)); + Streamer->EmitIntValue(0, 1); +} + +void DwarfClassTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // Abbrev Number + Streamer->EmitULEB128IntValue(IsForwardDecl ? DwarfAbbrev::ClassTypeDecl : DwarfAbbrev::ClassType); + + // DW_AT_name + EmitSectionOffset(Streamer, StrSymbol, 4); + + if (!IsForwardDecl) { + // DW_AT_byte_size + Streamer->EmitIntValue(Size, 4); + } + + if (BaseClassId != 0) { + DwarfInfo *BaseClassInfo = TypeBuilder->GetTypeInfoByIndex(BaseClassId); + assert(BaseClassInfo != nullptr); + + // DW_TAG_inheritance DIE + + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassInheritance); + + // DW_AT_type + EmitInfoOffset(Streamer, BaseClassInfo, 4); + + // DW_AT_data_member_location = 0 + Streamer->EmitIntValue(0, 1); + } +} + +// DwarfSimpleArrayTypeInfo + +void DwarfSimpleArrayTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumpedTypes) + return; + + DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + + DwarfInfo *ElementInfo = TypeBuilder->GetTypeInfoByIndex(ElementType); + assert(ElementInfo != nullptr); + + ElementInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection); +} + +void DwarfSimpleArrayTypeInfo::DumpStrings(MCObjectStreamer *Streamer) { + // nothing to dump +} + +void DwarfSimpleArrayTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::ArrayType); + + DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType); + assert(Info != nullptr); + + // DW_AT_type + EmitInfoOffset(Streamer, Info, 4); + + // DW_TAG_subrange_type DIE + + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::SubrangeType); + + // DW_AT_upper_bound + Streamer->EmitULEB128IntValue(Size - 1); + + // Terminate DIE + Streamer->EmitIntValue(0, 1); +} + +// DwarfPointerTypeInfo + +void DwarfPointerTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumpedTypes) + return; + + DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + + DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(TypeDesc.ElementType); + assert(Info != nullptr); + + Info->Dump(TypeBuilder, Streamer, TypeSection, StrSection); +} + +void DwarfPointerTypeInfo::DumpStrings(MCObjectStreamer *Streamer) { + // nothing to dump +} + +void DwarfPointerTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // Abbrev Number + Streamer->EmitULEB128IntValue(TypeDesc.IsReference ? DwarfAbbrev::ReferenceType : DwarfAbbrev::PointerType); + + DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(TypeDesc.ElementType); + assert(Info != nullptr); + + // DW_AT_type + EmitInfoOffset(Streamer, Info, 4); + + // DW_AT_byte_size + Streamer->EmitIntValue(TypeDesc.Is64Bit ? 8 : 4, 1); +} + +// DwarfMemberFunctionTypeInfo + +DwarfMemberFunctionTypeInfo::DwarfMemberFunctionTypeInfo( + const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes, + bool IsStaticMethod) : + TypeDesc(MemberDescriptor), + IsStaticMethod(IsStaticMethod) { + for (uint16_t i = 0; i < MemberDescriptor.NumberOfArguments; i++) { + this->ArgumentTypes.push_back(ArgumentTypes[i]); + } +} + +void DwarfMemberFunctionTypeInfo::DumpStrings(MCObjectStreamer *Streamer) { + // nothing to dump +} + +void DwarfMemberFunctionTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // nothing to dump +} + +// DwarfMemberFunctionIdTypeInfo + +void DwarfMemberFunctionIdTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) { + if (IsDumpedTypes) + return; + + DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection); + + // Dump return type + DwarfInfo *ReturnTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetReturnTypeIndex()); + assert(ReturnTypeInfo != nullptr); + + ReturnTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection); + + // Dump this pointer type + if (!MemberFunctionTypeInfo->IsStatic()) { + DwarfInfo *ThisPtrTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetThisPtrTypeIndex()); + assert(ThisPtrTypeInfo != nullptr); + + ThisPtrTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection); + } + + // Dump argument types + for (uint32_t ArgTypeIndex : MemberFunctionTypeInfo->GetArgTypes()) { + DwarfInfo *ArgTypeInfo = TypeBuilder->GetTypeInfoByIndex(ArgTypeIndex); + assert(ArgTypeInfo != nullptr); + ArgTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection); + } +} + +void DwarfMemberFunctionIdTypeInfo::DumpStrings(MCObjectStreamer *Streamer) { + Streamer->EmitBytes(StringRef(Name)); + Streamer->EmitIntValue(0, 1); + + MCContext &context = Streamer->getContext(); + LinkageNameSymbol = context.createTempSymbol(); + Streamer->EmitLabel(LinkageNameSymbol); + Streamer->EmitBytes(StringRef(LinkageName)); + Streamer->EmitIntValue(0, 1); +} + +void DwarfMemberFunctionIdTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) { + // Abbrev Number + bool IsStatic = MemberFunctionTypeInfo->IsStatic(); + + Streamer->EmitULEB128IntValue(IsStatic ? DwarfAbbrev::SubprogramStaticSpec : DwarfAbbrev::SubprogramSpec); + + // DW_AT_name + EmitSectionOffset(Streamer, StrSymbol, 4); + + // DW_AT_linkage_name + EmitSectionOffset(Streamer, LinkageNameSymbol, 4); + + // DW_AT_decl_file + Streamer->EmitIntValue(1, 1); + + // DW_AT_decl_line + Streamer->EmitIntValue(1, 1); + + // DW_AT_type + DwarfInfo *ReturnTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetReturnTypeIndex()); + assert(ReturnTypeInfo != nullptr); + + EmitInfoOffset(Streamer, ReturnTypeInfo, 4); + + if (!IsStatic) { + // DW_AT_object_pointer + uint32_t Offset = Streamer->getOrCreateDataFragment()->getContents().size(); + + Streamer->EmitIntValue(Offset + 4, 4); + + // This formal parameter DIE + DwarfInfo *ThisTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetThisPtrTypeIndex()); + assert(ThisTypeInfo != nullptr); + + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::FormalParameterThisSpec); + + // DW_AT_type + EmitInfoOffset(Streamer, ThisTypeInfo, 4); + } + + for (uint32_t ArgTypeIndex : MemberFunctionTypeInfo->GetArgTypes()) { + DwarfInfo *ArgTypeInfo = TypeBuilder->GetTypeInfoByIndex(ArgTypeIndex); + assert(ArgTypeInfo != nullptr); + + // Formal parameter DIE + + // Abbrev Number + Streamer->EmitULEB128IntValue(DwarfAbbrev::FormalParameterSpec); + + // DW_AT_type + EmitInfoOffset(Streamer, ArgTypeInfo, 4); + } + + // Ternimate DIE + Streamer->EmitIntValue(0, 1); +} + +// DwarfTypesBuilder + +void UserDefinedDwarfTypesBuilder::EmitTypeInformation( + MCSection *TypeSection, + MCSection *StrSection) { + for (auto &Info : DwarfTypes) { + Info->Dump(this, Streamer, TypeSection, StrSection); + } +} + +unsigned UserDefinedDwarfTypesBuilder::GetEnumTypeIndex( + const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords) { + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, TypeIndex)); + DwarfTypes.push_back(make_unique<DwarfEnumTypeInfo>(TypeDescriptor, TypeRecords)); + return TypeIndex; +} + +unsigned UserDefinedDwarfTypesBuilder::GetClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor) { + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + DwarfTypes.push_back(make_unique<DwarfClassTypeInfo>(ClassDescriptor)); + return TypeIndex; +} + +unsigned UserDefinedDwarfTypesBuilder::GetCompleteClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors) { + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, TypeIndex)); + + DwarfClassTypeInfo *ClassTypeInfo = new DwarfClassTypeInfo(ClassDescriptor, ClassFieldsDescriptor, + FieldsDescriptors, StaticsDescriptors); + + DwarfTypes.push_back(std::unique_ptr<DwarfClassTypeInfo>(ClassTypeInfo)); + + if (ClassTypeInfo->GetStaticFields().size() > 0) { + ClassesWithStaticFields.push_back(ClassTypeInfo); + } + + return TypeIndex; +} + +unsigned UserDefinedDwarfTypesBuilder::GetArrayTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ArrayTypeDescriptor &ArrayDescriptor) { + // Create corresponding class info + ClassTypeDescriptor ArrayClassDescriptor = ClassDescriptor; + + std::vector<DataFieldDescriptor> FieldDescs; + unsigned FieldOffset = TargetPointerSize; + + FieldDescs.push_back({GetPrimitiveTypeIndex(PrimitiveTypeFlags::Int32), FieldOffset, "m_NumComponents"}); + FieldOffset += TargetPointerSize; + + if (ArrayDescriptor.IsMultiDimensional == 1) { + unsigned BoundsTypeIndex = GetSimpleArrayTypeIndex(GetPrimitiveTypeIndex(PrimitiveTypeFlags::Int32), ArrayDescriptor.Rank); + FieldDescs.push_back({BoundsTypeIndex, FieldOffset, "m_Bounds"}); + FieldOffset += 2 * 4 * ArrayDescriptor.Rank; + } + + unsigned DataTypeIndex = GetSimpleArrayTypeIndex(ArrayDescriptor.ElementType, 0); + FieldDescs.push_back({DataTypeIndex, FieldOffset, "m_Data"}); + + ClassFieldsTypeDescriptior FieldsTypeDesc = + {TargetPointerSize, ArrayDescriptor.IsMultiDimensional ? 3 : 2}; + + ArrayClassDescriptor.InstanceSize = FieldOffset; + + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + UserDefinedTypes.push_back(std::make_pair(ArrayClassDescriptor.Name, TypeIndex)); + DwarfTypes.push_back(make_unique<DwarfClassTypeInfo>(ArrayClassDescriptor, FieldsTypeDesc, FieldDescs.data(), nullptr)); + + return TypeIndex; +} + +unsigned UserDefinedDwarfTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) +{ + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + DwarfTypes.push_back(make_unique<DwarfPointerTypeInfo>(PointerDescriptor)); + return TypeIndex; +} + +unsigned UserDefinedDwarfTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes) +{ + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + bool IsStatic = MemberDescriptor.TypeIndexOfThisPointer == GetPrimitiveTypeIndex(PrimitiveTypeFlags::Void); + DwarfTypes.push_back(make_unique<DwarfMemberFunctionTypeInfo>(MemberDescriptor, ArgumentTypes, IsStatic)); + return TypeIndex; +} + +unsigned UserDefinedDwarfTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) +{ + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + + DwarfMemberFunctionTypeInfo *MemberFunctionTypeInfo = static_cast<DwarfMemberFunctionTypeInfo*>( + GetTypeInfoByIndex(MemberIdDescriptor.MemberFunction)); + assert(MemberFunctionTypeInfo != nullptr); + + DwarfMemberFunctionIdTypeInfo *MemberFunctionIdTypeInfo = + new DwarfMemberFunctionIdTypeInfo(MemberIdDescriptor, MemberFunctionTypeInfo); + + DwarfTypes.push_back(std::unique_ptr<DwarfMemberFunctionIdTypeInfo>(MemberFunctionIdTypeInfo)); + + DwarfClassTypeInfo *ParentClassInfo = static_cast<DwarfClassTypeInfo*>( + GetTypeInfoByIndex(MemberIdDescriptor.ParentClass)); + assert(ParentClassInfo != nullptr); + + ParentClassInfo->AddMemberFunction(MemberFunctionIdTypeInfo); + + return TypeIndex; +} + +unsigned UserDefinedDwarfTypesBuilder::GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) { + auto Iter = PrimitiveDwarfTypes.find(Type); + if (Iter != PrimitiveDwarfTypes.end()) + return Iter->second; + + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + DwarfTypes.push_back(make_unique<DwarfPrimitiveTypeInfo>(Type)); + + PrimitiveDwarfTypes.insert(std::make_pair(Type, TypeIndex)); + + return TypeIndex; +} + +unsigned UserDefinedDwarfTypesBuilder::GetSimpleArrayTypeIndex(unsigned ElemIndex, unsigned Size) { + auto Iter = SimpleArrayDwarfTypes.find(ElemIndex); + if (Iter != SimpleArrayDwarfTypes.end()) { + auto CountMap = Iter->second; + auto CountIter = CountMap.find(Size); + if (CountIter != CountMap.end()) + return CountIter->second; + } + + unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size()); + DwarfTypes.push_back(make_unique<DwarfSimpleArrayTypeInfo>(ElemIndex, Size)); + + SimpleArrayDwarfTypes[ElemIndex][Size] = TypeIndex; + + return TypeIndex; +}
\ No newline at end of file diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h new file mode 100644 index 000000000..0ea43a451 --- /dev/null +++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h @@ -0,0 +1,366 @@ +//===---- dwarfTypeBuilder.h ------------------------------------*- C++ -*-===// +// +// type builder is used to convert .Net types into Dwarf debuginfo. +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "debugInfo/typeBuilder.h" + +#include <vector> +#include <unordered_map> + +class UserDefinedDwarfTypesBuilder; + +class DwarfInfo +{ +public: + DwarfInfo() : + StrSymbol(nullptr), + InfoSymbol(nullptr), + IsDumped(false), + IsDumpedTypes(false) {} + + virtual ~DwarfInfo() {} + + virtual void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection); + + virtual void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection); + + MCSymbol *GetInfoSymbol() { return InfoSymbol; } + + const MCExpr *GetInfoExpr() { return InfoExpr; } + +protected: + virtual void DumpStrings(MCObjectStreamer *Streamer) = 0; + virtual void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) = 0; + + static void EmitSectionOffset(MCObjectStreamer *Streamer, + MCSymbol *Symbol, + unsigned Size, + uint32_t Offset = 0); + + static const MCExpr *CreateOffsetExpr(MCContext &Context, + MCSymbol *BeginSymbol, + MCSymbol *Symbol); + + static void EmitOffset(MCObjectStreamer *Streamer, + const MCExpr *OffsetExpr, + unsigned Size); + + static void EmitInfoOffset(MCObjectStreamer *Streamer, const DwarfInfo *Info, unsigned Size); + + MCSymbol *StrSymbol; + MCSymbol *InfoSymbol; + const MCExpr *InfoExpr; + + bool IsDumped; + bool IsDumpedTypes; +}; + +class DwarfPrimitiveTypeInfo : public DwarfInfo +{ +public: + DwarfPrimitiveTypeInfo(PrimitiveTypeFlags PrimitiveType) : Type(PrimitiveType) {} + + PrimitiveTypeFlags GetType() { return Type; } + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + PrimitiveTypeFlags Type; +}; + +class DwarfEnumTypeInfo; + +class DwarfEnumerator : public DwarfInfo +{ +public: + DwarfEnumerator(const EnumRecordTypeDescriptor &Descriptor, DwarfEnumTypeInfo *TypeInfo) : + Name(Descriptor.Name), Value(Descriptor.Value), EnumTypeInfo(TypeInfo) {} + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + std::string Name; + uint64 Value; + DwarfEnumTypeInfo *EnumTypeInfo; +}; + +class DwarfEnumTypeInfo : public DwarfInfo +{ +public: + DwarfEnumTypeInfo(const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords); + + void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + + void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + + uint8_t GetByteSize() const { return ByteSize; } + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + std::string Name; + uint32_t ElementType; + std::vector<DwarfEnumerator> Records; + uint8_t ByteSize; +}; + +class DwarfDataField : public DwarfInfo +{ +public: + DwarfDataField(const DataFieldDescriptor &Descriptor) : + Name(Descriptor.Name), + TypeIndex(Descriptor.FieldTypeIndex), + Offset(Descriptor.Offset) {} + + void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + + uint32_t GetTypeIndex() const { return TypeIndex; } + + const std::string &GetName() const { return Name; } + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + + std::string Name; + uint32_t TypeIndex; + uint64 Offset; +}; + +class DwarfStaticDataField : public DwarfDataField +{ +public: + DwarfStaticDataField(const DataFieldDescriptor &Descriptor, + const StaticDataFieldDescriptor &StaticDescriptor) : + DwarfDataField(Descriptor), + StaticDataName(StaticDescriptor.StaticDataName), + StaticOffset(StaticDescriptor.StaticOffset), + StaticDataInObject(StaticDescriptor.IsStaticDataInObject) {} + + const std::string &GetStaticDataName() const { return StaticDataName; } + uint64 GetStaticOffset() const { return StaticOffset; } + bool IsStaticDataInObject() const { return StaticDataInObject; } + +protected: + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + std::string StaticDataName; + uint64 StaticOffset; + bool StaticDataInObject; +}; + +class DwarfMemberFunctionIdTypeInfo; + +class DwarfClassTypeInfo : public DwarfInfo +{ +public: + DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor) : + Name(ClassDescriptor.Name), + IsStruct(ClassDescriptor.IsStruct), + BaseClassId(ClassDescriptor.BaseClassId), + Size(ClassDescriptor.InstanceSize), + IsForwardDecl(true) {} + + DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors); + + void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + + void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + + void AddMemberFunction(DwarfMemberFunctionIdTypeInfo* TypeInfo) { + MemberFunctions.push_back(TypeInfo); + } + + const std::vector<DwarfStaticDataField> &GetStaticFields() const { return StaticFields; } + + const std::string &GetName() const { return Name; } + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + std::string Name; + bool IsStruct; + uint32_t BaseClassId; + uint64 Size; + bool IsForwardDecl; + std::vector<DwarfDataField> Fields; + std::vector<DwarfStaticDataField> StaticFields; + std::vector<DwarfMemberFunctionIdTypeInfo*> MemberFunctions; +}; + +class DwarfSimpleArrayTypeInfo : public DwarfInfo +{ +public: + DwarfSimpleArrayTypeInfo(uint32_t ArrayElementType, uint64_t Size) : + ElementType(ArrayElementType), + Size(Size) {} + + void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + uint32_t ElementType; + uint64_t Size; +}; + +class DwarfPointerTypeInfo : public DwarfInfo +{ +public: + DwarfPointerTypeInfo(const PointerTypeDescriptor& PointerDescriptor) : + TypeDesc(PointerDescriptor) {} + + void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + PointerTypeDescriptor TypeDesc; +}; + +class DwarfMemberFunctionTypeInfo : public DwarfInfo +{ +public: + DwarfMemberFunctionTypeInfo(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes, + bool IsStaticMethod); + + const std::vector<uint32_t> &GetArgTypes() const { return ArgumentTypes; } + + bool IsStatic() const { return IsStaticMethod; } + + uint32_t GetReturnTypeIndex() const { return TypeDesc.ReturnType; } + + uint32_t GetThisPtrTypeIndex() const { return TypeDesc.TypeIndexOfThisPointer; } + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + MemberFunctionTypeDescriptor TypeDesc; + std::vector<uint32_t> ArgumentTypes; + bool IsStaticMethod; +}; + +class DwarfMemberFunctionIdTypeInfo : public DwarfInfo +{ +public: + DwarfMemberFunctionIdTypeInfo(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor, + DwarfMemberFunctionTypeInfo *TypeInfo) : + LinkageName(MemberIdDescriptor.Name), + Name(MemberIdDescriptor.Name), + ParentClass(MemberIdDescriptor.ParentClass), + MemberFunctionTypeInfo(TypeInfo), + LinkageNameSymbol(nullptr) {} + + const std::vector<uint32_t> &GetArgTypes() const { return MemberFunctionTypeInfo->GetArgTypes(); } + + void SetLinkageName(const char *Name) { LinkageName = Name; } + + void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer, + MCSection *TypeSection, MCSection *StrSection) override; + + bool IsStatic() const { return MemberFunctionTypeInfo->IsStatic(); } + +protected: + void DumpStrings(MCObjectStreamer *Streamer) override; + void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override; + +private: + std::string LinkageName; + std::string Name; + uint32_t ParentClass; + DwarfMemberFunctionTypeInfo *MemberFunctionTypeInfo; + MCSymbol *LinkageNameSymbol; +}; + +template<class T> +class EnumHash +{ + typedef typename std::underlying_type<T>::type enumType; +public: + size_t operator()(const T& elem) const { + return std::hash<enumType>()(static_cast<enumType>(elem)); + } +}; + +class UserDefinedDwarfTypesBuilder : public UserDefinedTypesBuilder +{ +public: + UserDefinedDwarfTypesBuilder() {} + void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) override; + + unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords) override; + unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) override; + unsigned GetCompleteClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors) override; + + unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, + const ArrayTypeDescriptor &ArrayDescriptor) override; + + unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) override; + + unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes) override; + + unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) override; + + unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) override; + + DwarfInfo *GetTypeInfoByIndex(unsigned Index) const { return DwarfTypes[TypeIndexToArrayIndex(Index)].get(); } + + unsigned GetSimpleArrayTypeIndex(unsigned ElemIndex, unsigned Size); + + const std::vector<DwarfClassTypeInfo*> &GetClassesWithStaticFields() const { return ClassesWithStaticFields; } + +private: + static const unsigned StartTypeIndex = 1; // Make TypeIndex 0 - Invalid + static unsigned TypeIndexToArrayIndex(unsigned TypeIndex) { return TypeIndex - StartTypeIndex; } + static unsigned ArrayIndexToTypeIndex(unsigned ArrayIndex) { return ArrayIndex + StartTypeIndex; } + + std::vector<std::unique_ptr<DwarfInfo>> DwarfTypes; + std::unordered_map<PrimitiveTypeFlags, uint32_t, EnumHash<PrimitiveTypeFlags>> PrimitiveDwarfTypes; + // map[ElemTypeIndex][Size] -> ArrTypeIndex + std::unordered_map<uint32_t, std::unordered_map<uint32_t, uint32_t>> SimpleArrayDwarfTypes; + + std::vector<DwarfClassTypeInfo*> ClassesWithStaticFields; +};
\ No newline at end of file diff --git a/src/Native/ObjWriter/debugInfo/typeBuilder.h b/src/Native/ObjWriter/debugInfo/typeBuilder.h new file mode 100644 index 000000000..f3e3046e5 --- /dev/null +++ b/src/Native/ObjWriter/debugInfo/typeBuilder.h @@ -0,0 +1,158 @@ +//===---- typeBuilder.h -----------------------------------------*- C++ -*-===// +// +// type builder is used to convert .Net types into debuginfo. +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "llvm/MC/MCObjectStreamer.h" + +#include <string> +#include <vector> + +using namespace llvm; + +// Keep in sync with Internal.TypeSystem.TypeFlags (Common/src/TypeSystem/Common/TypeFlags.cs) +enum class PrimitiveTypeFlags { + Unknown = 0x00, + Void = 0x01, + Boolean = 0x02, + Char = 0x03, + SByte = 0x04, + Byte = 0x05, + Int16 = 0x06, + UInt16 = 0x07, + Int32 = 0x08, + UInt32 = 0x09, + Int64 = 0x0A, + UInt64 = 0x0B, + IntPtr = 0x0C, + UIntPtr = 0x0D, + Single = 0x0E, + Double = 0x0F +}; + +typedef unsigned long long uint64; + +#pragma pack(push, 8) + +extern "C" struct EnumRecordTypeDescriptor { + uint64 Value; + const char *Name; +}; + +extern "C" struct EnumTypeDescriptor { + uint32_t ElementType; + uint64 ElementCount; + const char *Name; +}; + +extern "C" struct ClassTypeDescriptor { + int32_t IsStruct; + const char *Name; + uint32_t BaseClassId; + uint64 InstanceSize; +}; + +extern "C" struct DataFieldDescriptor { + uint32_t FieldTypeIndex; + uint64 Offset; + const char *Name; +}; + +extern "C" struct StaticDataFieldDescriptor { + const char *StaticDataName; + uint64 StaticOffset; + int IsStaticDataInObject; +}; + +extern "C" struct ClassFieldsTypeDescriptior { + uint64 Size; + int32_t FieldsCount; +}; + +extern "C" struct ArrayTypeDescriptor { + uint32_t Rank; + uint32_t ElementType; + uint32_t Size; // ElementSize + int32_t IsMultiDimensional; +}; + +extern "C" struct PointerTypeDescriptor { + uint32_t ElementType; + int32_t IsReference; + int32_t IsConst; + int32_t Is64Bit; +}; + +extern "C" struct MemberFunctionTypeDescriptor { + uint32_t ReturnType; + uint32_t ContainingClass; + uint32_t TypeIndexOfThisPointer; + int32_t ThisAdjust; + uint32_t CallingConvention; + uint16_t NumberOfArguments; +}; + +extern "C" struct MemberFunctionIdTypeDescriptor { + uint32_t MemberFunction; + uint32_t ParentClass; + const char *Name; +}; + +#pragma pack(pop) +class UserDefinedTypesBuilder { +public: + UserDefinedTypesBuilder() : Streamer(nullptr), TargetPointerSize(0) {} + virtual ~UserDefinedTypesBuilder() {} + void SetStreamer(MCObjectStreamer *Streamer) { + assert(this->Streamer == nullptr); + assert(Streamer != nullptr); + this->Streamer = Streamer; + } + MCObjectStreamer *GetStreamer() const { + return Streamer; + } + void SetTargetPointerSize(unsigned TargetPointerSize) { + assert(this->TargetPointerSize == 0); + assert(TargetPointerSize != 0); + this->TargetPointerSize = TargetPointerSize; + } + virtual void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) = 0; + + virtual unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor, + const EnumRecordTypeDescriptor *TypeRecords) = 0; + virtual unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) = 0; + virtual unsigned GetCompleteClassTypeIndex( + const ClassTypeDescriptor &ClassDescriptor, + const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors) = 0; + + virtual unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, + const ArrayTypeDescriptor &ArrayDescriptor) = 0; + + virtual unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) = 0; + + virtual unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, + uint32_t const *const ArgumentTypes) = 0; + + virtual unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) = 0; + + virtual unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) = 0; + + virtual const std::vector<std::pair<std::string, uint32_t>> &GetUDTs() { + return UserDefinedTypes; + } + +protected: + MCObjectStreamer *Streamer; + unsigned TargetPointerSize; + + std::vector<std::pair<std::string, uint32_t>> UserDefinedTypes; +};
\ No newline at end of file diff --git a/src/Native/ObjWriter/jitDebugInfo.h b/src/Native/ObjWriter/jitDebugInfo.h index 103dff8ad..ec63c3dfb 100644 --- a/src/Native/ObjWriter/jitDebugInfo.h +++ b/src/Native/ObjWriter/jitDebugInfo.h @@ -26,6 +26,18 @@ struct DebugVarInfo { : Name(ArgName), TypeIndex(ArgTypeIndex), IsParam(ArgIsParam) {} }; +struct DebugEHClauseInfo { + unsigned TryOffset; + unsigned TryLength; + unsigned HandlerOffset; + unsigned HandlerLength; + + DebugEHClauseInfo(unsigned TryOffset, unsigned TryLength, + unsigned HandlerOffset, unsigned HandlerLength) : + TryOffset(TryOffset), TryLength(TryLength), + HandlerOffset(HandlerOffset), HandlerLength(HandlerLength) {} +}; + typedef unsigned short CVRegMapping; #define CVREGDAT(p2, cv) cv diff --git a/src/Native/ObjWriter/llvm.patch b/src/Native/ObjWriter/llvm.patch index fd8420125..67ae23ec9 100644 --- a/src/Native/ObjWriter/llvm.patch +++ b/src/Native/ObjWriter/llvm.patch @@ -15,7 +15,7 @@ index 7c1189e..d1d77c9 100644 /// can change its size during relaxation. virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &); diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h -index 5390e79..e28a3cc 100644 +index 5390e79..5b258e7 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -115,6 +115,7 @@ public: @@ -26,6 +26,16 @@ index 5390e79..e28a3cc 100644 virtual void emitUnwindRaw(int64_t StackOffset, const SmallVectorImpl<uint8_t> &Opcodes); +@@ -548,6 +549,9 @@ public: + /// etc. + virtual void EmitBytes(StringRef Data); + ++ /// \brief Emit the given \p Instruction data into the current section. ++ virtual void EmitInstructionBytes(StringRef Data); ++ + /// Functionally identical to EmitBytes. When emitting textual assembly, this + /// method uses .byte directives instead of .ascii or .asciz for readability. + virtual void EmitBinaryData(StringRef Data); diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 174397e..ef7161f 100644 --- a/lib/MC/MCObjectStreamer.cpp @@ -57,6 +67,18 @@ index 174397e..ef7161f 100644 void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { // We need to create a local symbol to avoid relocations. Frame.Begin = getContext().createTempSymbol(); +diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp +index 2bfb9a6..a710098 100644 +--- a/lib/MC/MCStreamer.cpp ++++ b/lib/MC/MCStreamer.cpp +@@ -830,6 +830,7 @@ void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, + void MCStreamer::ChangeSection(MCSection *, const MCExpr *) {} + void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} + void MCStreamer::EmitBytes(StringRef Data) {} ++void MCStreamer::EmitInstructionBytes(StringRef Data) { EmitBytes(Data); } + void MCStreamer::EmitBinaryData(StringRef Data) { EmitBytes(Data); } + void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) { + visitUsedExpr(*Value); diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index a77df7a..e1aa752 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -122,7 +144,7 @@ index 59f31be..9b95598 100644 case ARM::fixup_arm_uncondbl: switch (Modifier) { diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp -index 93f4006..67ae439 100644 +index 93f4006..81e4caa 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -396,6 +396,7 @@ private: @@ -141,7 +163,26 @@ index 93f4006..67ae439 100644 void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes); void ChangeSection(MCSection *Section, const MCExpr *Subsection) override { -@@ -698,6 +700,7 @@ private: +@@ -533,6 +535,18 @@ public: + MCELFStreamer::EmitBytes(Data); + } + ++ /// This function is the one used to emit instruction data into the ELF ++ /// streamer. We override it to add the appropriate mapping symbol if ++ /// necessary. ++ void EmitInstructionBytes(StringRef Data) override { ++ if (IsThumb) ++ EmitThumbMappingSymbol(); ++ else ++ EmitARMMappingSymbol(); ++ ++ MCELFStreamer::EmitBytes(Data); ++ } ++ + void FlushPendingMappingSymbol() { + if (!LastEMSInfo->hasInfo()) + return; +@@ -698,6 +712,7 @@ private: bool CantUnwind; SmallVector<uint8_t, 64> Opcodes; UnwindOpcodeAssembler UnwindOpAsm; @@ -149,7 +190,7 @@ index 93f4006..67ae439 100644 }; } // end anonymous namespace -@@ -740,6 +743,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, +@@ -740,6 +755,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, getStreamer().emitRegSave(RegList, isVector); } @@ -160,7 +201,7 @@ index 93f4006..67ae439 100644 void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes) { getStreamer().emitUnwindRaw(Offset, Opcodes); -@@ -1233,6 +1240,7 @@ void ARMELFStreamer::EHReset() { +@@ -1233,6 +1252,7 @@ void ARMELFStreamer::EHReset() { PendingOffset = 0; UsedFP = false; CantUnwind = false; @@ -168,7 +209,7 @@ index 93f4006..67ae439 100644 Opcodes.clear(); UnwindOpAsm.Reset(); -@@ -1330,6 +1338,8 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { +@@ -1330,6 +1350,8 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { } // Finalize the unwind opcode sequence @@ -177,7 +218,7 @@ index 93f4006..67ae439 100644 UnwindOpAsm.Finalize(PersonalityIndex, Opcodes); // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx -@@ -1374,7 +1384,13 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { +@@ -1374,7 +1396,13 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { // // In case that the .handlerdata directive is not specified by the // programmer, we should emit zero to terminate the handler data. @@ -192,7 +233,7 @@ index 93f4006..67ae439 100644 EmitIntValue(0, 4); } -@@ -1457,6 +1473,10 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, +@@ -1457,6 +1485,10 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, UnwindOpAsm.EmitRegSave(Mask); } diff --git a/src/Native/ObjWriter/llvmCap/CMakeLists.txt b/src/Native/ObjWriter/llvmCap/CMakeLists.txt index a749ea878..07dca10e9 100644 --- a/src/Native/ObjWriter/llvmCap/CMakeLists.txt +++ b/src/Native/ObjWriter/llvmCap/CMakeLists.txt @@ -116,14 +116,32 @@ ExternalProject_Add(LLVM ExternalProject_Get_Property(LLVM source_dir) set(LLVM_SOURCE_DIR ${source_dir}) ExternalProject_Add_Step(LLVM PatchingLLVM - COMMAND git apply --3way ${OBJWRITER_ROOT}/llvm.patch COMMENT "Applying LLVM patch with ObjWriter fixes" + COMMAND git checkout -- . + COMMAND git apply ${OBJWRITER_ROOT}/llvm.patch COMMENT "Applying LLVM patch with ObjWriter fixes" WORKING_DIRECTORY ${LLVM_SOURCE_DIR} DEPENDEES patch USES_TERMINAL 1 ) + +if(CMAKE_HOST_WIN32) +ExternalProject_Add_Step(LLVM ObjWriterInjection + COMMAND ${CMAKE_COMMAND} -E copy_directory ${OBJWRITER_ROOT} ${OBJWRITER_LLVM_POINT} COMMENT "copy ${OBJWRITER_ROOT} -> ${OBJWRITER_LLVM_POINT}" + WORKING_DIRECTORY ${LLVM_SOURCE_DIR} + DEPENDEES patch + USES_TERMINAL 1 + ) +else() ExternalProject_Add_Step(LLVM ObjWriterInjection COMMAND ${CMAKE_COMMAND} -E create_symlink ${OBJWRITER_ROOT} ${OBJWRITER_LLVM_POINT} COMMENT "mklink ${OBJWRITER_ROOT} -> ${OBJWRITER_LLVM_POINT}" WORKING_DIRECTORY ${LLVM_SOURCE_DIR} DEPENDEES patch USES_TERMINAL 1 ) +endif() + +ExternalProject_Add_Step(LLVM forceconfigure + COMMAND ${CMAKE_COMMAND} -E echo "Force configure of LLVM" + DEPENDEES update + DEPENDERS configure + ALWAYS 1 + ) diff --git a/src/Native/ObjWriter/objwriter.cpp b/src/Native/ObjWriter/objwriter.cpp index 55f79aa47..bdf1016dc 100644 --- a/src/Native/ObjWriter/objwriter.cpp +++ b/src/Native/ObjWriter/objwriter.cpp @@ -1,10 +1,10 @@ -//===---- objwriter.cpp --------------------------------*- C++ -*-===// +//===---- objwriter.cpp -----------------------------------------*- C++ -*-===// // // object writer // -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. -// See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. // //===----------------------------------------------------------------------===// /// @@ -14,6 +14,8 @@ //===----------------------------------------------------------------------===// #include "objwriter.h" +#include "debugInfo/dwarf/dwarfTypeBuilder.h" +#include "debugInfo/codeView/codeViewTypeBuilder.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" @@ -162,9 +164,18 @@ bool ObjectWriter::Init(llvm::StringRef ObjectFilePath) { SetCodeSectionAttribute("text", CustomSectionAttributes_Executable, nullptr); if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { - TypeBuilder.SetStreamer(Streamer); - unsigned TargetPointerSize = AssemblerPrinter->getPointerSize(); - TypeBuilder.SetTargetPointerSize(TargetPointerSize); + TypeBuilder.reset(new UserDefinedCodeViewTypesBuilder()); + } else { + TypeBuilder.reset(new UserDefinedDwarfTypesBuilder()); + } + + TypeBuilder->SetStreamer(Streamer); + unsigned TargetPointerSize = AssemblerPrinter->getPointerSize(); + TypeBuilder->SetTargetPointerSize(TargetPointerSize); + + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) { + DwarfGenerator.reset(new DwarfGen()); + DwarfGenerator->SetTypeBuilder(static_cast<UserDefinedDwarfTypesBuilder*>(TypeBuilder.get())); } return true; @@ -294,7 +305,11 @@ void ObjectWriter::EmitAlignment(int ByteAlignment) { } void ObjectWriter::EmitBlob(int BlobSize, const char *Blob) { - Streamer->EmitBytes(StringRef(Blob, BlobSize)); + if (Streamer->getCurrentSectionOnly()->getKind().isText()) { + Streamer->EmitInstructionBytes(StringRef(Blob, BlobSize)); + } else { + Streamer->EmitBytes(StringRef(Blob, BlobSize)); + } } void ObjectWriter::EmitIntValue(uint64_t Value, unsigned Size) { @@ -690,6 +705,22 @@ void ObjectWriter::EmitCVDebugFunctionInfo(const char *FunctionName, Streamer->EmitCVLinetableDirective(FuncId++, Fn, FnEnd); } +void ObjectWriter::EmitDwarfFunctionInfo(const char *FunctionName, + int FunctionSize, + unsigned MethodTypeIndex) { + if (FuncId == 1) { + DwarfGenerator->EmitCompileUnit(); + } + + DwarfGenerator->EmitSubprogramInfo(FunctionName, FunctionSize, + MethodTypeIndex, DebugVarInfos, DebugEHClauseInfos); + + DebugVarInfos.clear(); + DebugEHClauseInfos.clear(); + + FuncId++; +} + void ObjectWriter::EmitDebugFileInfo(int FileId, const char *FileName) { assert(FileId > 0 && "FileId should be greater than 0."); if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { @@ -700,7 +731,8 @@ void ObjectWriter::EmitDebugFileInfo(int FileId, const char *FileName) { } void ObjectWriter::EmitDebugFunctionInfo(const char *FunctionName, - int FunctionSize) { + int FunctionSize, + unsigned MethodTypeIndex) { if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { Streamer->EmitCVFuncIdDirective(FuncId); EmitCVDebugFunctionInfo(FunctionName, FunctionSize); @@ -710,6 +742,7 @@ void ObjectWriter::EmitDebugFunctionInfo(const char *FunctionName, Streamer->EmitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); Streamer->emitELFSize(Sym, MCConstantExpr::create(FunctionSize, *OutContext)); + EmitDwarfFunctionInfo(FunctionName, FunctionSize, MethodTypeIndex); } // TODO: Should test it for Macho. } @@ -729,6 +762,13 @@ void ObjectWriter::EmitDebugVar(char *Name, int TypeIndex, bool IsParm, DebugVarInfos.push_back(NewVar); } +void ObjectWriter::EmitDebugEHClause(unsigned TryOffset, unsigned TryLength, + unsigned HandlerOffset, unsigned HandlerLength) { + if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) { + DebugEHClauseInfos.emplace_back(TryOffset, TryLength, HandlerOffset, HandlerLength); + } +} + void ObjectWriter::EmitDebugLoc(int NativeOffset, int FileId, int LineNumber, int ColNumber) { assert(FileId > 0 && "FileId should be greater than 0."); @@ -742,7 +782,7 @@ void ObjectWriter::EmitDebugLoc(int NativeOffset, int FileId, int LineNumber, } void ObjectWriter::EmitCVUserDefinedTypesSymbols() { - const auto &UDTs = TypeBuilder.GetUDTs(); + const auto &UDTs = TypeBuilder->GetUDTs(); if (UDTs.empty()) { return; } @@ -755,12 +795,12 @@ void ObjectWriter::EmitCVUserDefinedTypesSymbols() { EmitLabelDiff(SymbolsBegin, SymbolsEnd); Streamer->EmitLabel(SymbolsBegin); - for (const std::pair<std::string, codeview::TypeIndex> &UDT : UDTs) { + for (const std::pair<std::string, uint32_t> &UDT : UDTs) { unsigned NameLength = UDT.first.length() + 1; unsigned RecordLength = 2 + 4 + NameLength; Streamer->EmitIntValue(RecordLength, 2); Streamer->EmitIntValue(unsigned(SymbolKind::S_UDT), 2); - Streamer->EmitIntValue(UDT.second.getIndex(), 4); + Streamer->EmitIntValue(UDT.second, 4); Streamer->EmitBytes(StringRef(UDT.first.c_str(), NameLength)); } Streamer->EmitLabel(SymbolsEnd); @@ -769,7 +809,7 @@ void ObjectWriter::EmitCVUserDefinedTypesSymbols() { void ObjectWriter::EmitDebugModuleInfo() { if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) { - TypeBuilder.EmitTypeInformation(ObjFileInfo->getCOFFDebugTypesSection()); + TypeBuilder->EmitTypeInformation(ObjFileInfo->getCOFFDebugTypesSection()); EmitCVUserDefinedTypesSymbols(); } @@ -783,6 +823,10 @@ void ObjectWriter::EmitDebugModuleInfo() { Streamer->SwitchSection(Section); Streamer->EmitCVFileChecksumsDirective(); Streamer->EmitCVStringTableDirective(); + } else if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) { + DwarfGenerator->EmitAbbrev(); + DwarfGenerator->EmitAranges(); + DwarfGenerator->Finish(); } else { OutContext->setGenDwarfForAssembly(true); } @@ -791,56 +835,50 @@ void ObjectWriter::EmitDebugModuleInfo() { unsigned ObjectWriter::GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor, const EnumRecordTypeDescriptor *TypeRecords) { - assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && - "only COFF is supported now"); - return TypeBuilder.GetEnumTypeIndex(TypeDescriptor, TypeRecords); + return TypeBuilder->GetEnumTypeIndex(TypeDescriptor, TypeRecords); } unsigned ObjectWriter::GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) { - assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && - "only COFF is supported now"); - return TypeBuilder.GetClassTypeIndex(ClassDescriptor); + unsigned res = TypeBuilder->GetClassTypeIndex(ClassDescriptor); + return res; } unsigned ObjectWriter::GetCompleteClassTypeIndex( const ClassTypeDescriptor &ClassDescriptor, const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, - const DataFieldDescriptor *FieldsDescriptors) { - assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && - "only COFF is supported now"); - return TypeBuilder.GetCompleteClassTypeIndex( - ClassDescriptor, ClassFieldsDescriptor, FieldsDescriptors); + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors) { + unsigned res = TypeBuilder->GetCompleteClassTypeIndex(ClassDescriptor, + ClassFieldsDescriptor, FieldsDescriptors, StaticsDescriptors); + return res; } unsigned ObjectWriter::GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, const ArrayTypeDescriptor &ArrayDescriptor) { - assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && - "only COFF is supported now"); - return TypeBuilder.GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor); + return TypeBuilder->GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor); } unsigned ObjectWriter::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) { - assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && - "only COFF is supported now"); - return TypeBuilder.GetPointerTypeIndex(PointerDescriptor); + return TypeBuilder->GetPointerTypeIndex(PointerDescriptor); } unsigned ObjectWriter::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, uint32_t const *const ArgumentTypes) { - assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && - "only COFF is supported now"); - return TypeBuilder.GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes); + return TypeBuilder->GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes); } unsigned ObjectWriter::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) { - assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF && - "only COFF is supported now"); - return TypeBuilder.GetMemberFunctionId(MemberIdDescriptor); + return TypeBuilder->GetMemberFunctionId(MemberIdDescriptor); +} + +unsigned +ObjectWriter::GetPrimitiveTypeIndex(int Type) { + return TypeBuilder->GetPrimitiveTypeIndex(static_cast<PrimitiveTypeFlags>(Type)); } void @@ -883,13 +921,13 @@ void ObjectWriter::EmitARMExIdxCode(int Offset, const char *Blob) ATS.emitPad(CfiCode->Offset); break; case CFI_REL_OFFSET: - RegList.push_back(CfiCode->DwarfReg); + RegList.push_back(CfiCode->DwarfReg + 14); // See ARMRegEncodingTable in ARMGenRegisterInfo.inc by getEncodingValue ATS.emitRegSave(RegList, false); break; case CFI_DEF_CFA_REGISTER: assert(CfiCode->Offset == 0 && "Unexpected Offset Value for OpDefCfaRegister"); - ATS.emitMovSP(CfiCode->DwarfReg, 0); + ATS.emitMovSP(CfiCode->DwarfReg + 14, 0); // See ARMRegEncodingTable in ARMGenRegisterInfo.inc by getEncodingValue break; default: assert(false && "Unrecognized CFI"); diff --git a/src/Native/ObjWriter/objwriter.h b/src/Native/ObjWriter/objwriter.h index 21327b3be..6c1ba8645 100644 --- a/src/Native/ObjWriter/objwriter.h +++ b/src/Native/ObjWriter/objwriter.h @@ -1,10 +1,10 @@ -//===---- objwriter.h --------------------------------*- C++ -*-===// +//===---- objwriter.h ------------------------------------------*- C++ -*-===// // // object writer // -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. -// See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. // //===----------------------------------------------------------------------===// @@ -19,7 +19,8 @@ #include "jitDebugInfo.h" #include <string> #include <set> -#include "typeBuilder.h" +#include "debugInfo/typeBuilder.h" +#include "debugInfo/dwarf/dwarfGen.h" using namespace llvm; using namespace llvm::codeview; @@ -68,11 +69,13 @@ public: int EmitSymbolRef(const char *SymbolName, RelocType RelocType, int Delta); void EmitDebugFileInfo(int FileId, const char *FileName); - void EmitDebugFunctionInfo(const char *FunctionName, int FunctionSize); + void EmitDebugFunctionInfo(const char *FunctionName, int FunctionSize, unsigned MethodTypeIndex); void EmitDebugVar(char *Name, int TypeIndex, bool IsParm, int RangeCount, const ICorDebugInfo::NativeVarInfo *Ranges); void EmitDebugLoc(int NativeOffset, int FileId, int LineNumber, int ColNumber); + void EmitDebugEHClause(unsigned TryOffset, unsigned TryLength, + unsigned HandlerOffset, unsigned HandlerLength); void EmitDebugModuleInfo(); void EmitCFIStart(int Offset); @@ -86,7 +89,8 @@ public: unsigned GetCompleteClassTypeIndex( const ClassTypeDescriptor &ClassDescriptor, const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, - const DataFieldDescriptor *FieldsDescriptors); + const DataFieldDescriptor *FieldsDescriptors, + const StaticDataFieldDescriptor *StaticsDescriptors); unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, const ArrayTypeDescriptor &ArrayDescriptor); @@ -98,6 +102,8 @@ public: unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor); + unsigned GetPrimitiveTypeIndex(int Type); + void EmitARMFnStart(); void EmitARMFnEnd(); void EmitARMExIdxCode(int Offset, const char *Blob); @@ -114,6 +120,8 @@ private: int NumVarInfos); void EmitCVDebugFunctionInfo(const char *FunctionName, int FunctionSize); + void EmitDwarfFunctionInfo(const char *FunctionName, int FunctionSize, unsigned MethodTypeIndex); + const MCSymbolRefExpr *GetSymbolRefExpr( const char *SymbolName, MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None); @@ -149,16 +157,18 @@ private: std::unique_ptr<TargetMachine> TMachine; std::unique_ptr<AsmPrinter> AssemblerPrinter; MCAssembler *Assembler; // Owned by MCStreamer + std::unique_ptr<DwarfGen> DwarfGenerator; std::unique_ptr<raw_fd_ostream> OS; MCTargetOptions TargetMOptions; bool FrameOpened; std::vector<DebugVarInfo> DebugVarInfos; + std::vector<DebugEHClauseInfo> DebugEHClauseInfos; std::set<MCSection *> Sections; int FuncId; - UserDefinedTypesBuilder TypeBuilder; + std::unique_ptr<UserDefinedTypesBuilder> TypeBuilder; std::string TripleName; @@ -258,9 +268,10 @@ DLL_EXPORT void EmitDebugFileInfo(ObjectWriter *OW, int FileId, DLL_EXPORT void EmitDebugFunctionInfo(ObjectWriter *OW, const char *FunctionName, - int FunctionSize) { + int FunctionSize, + unsigned MethodTypeIndex) { assert(OW && "ObjWriter is null"); - OW->EmitDebugFunctionInfo(FunctionName, FunctionSize); + OW->EmitDebugFunctionInfo(FunctionName, FunctionSize, MethodTypeIndex); } DLL_EXPORT void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex, @@ -270,6 +281,13 @@ DLL_EXPORT void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex, OW->EmitDebugVar(Name, TypeIndex, IsParam, RangeCount, Ranges); } +DLL_EXPORT void EmitDebugEHClause(ObjectWriter *OW, unsigned TryOffset, + unsigned TryLength, unsigned HandlerOffset, + unsigned HandlerLength) { + assert(OW && "ObjWriter is null"); + OW->EmitDebugEHClause(TryOffset, TryLength, HandlerOffset, HandlerLength); +} + DLL_EXPORT void EmitDebugLoc(ObjectWriter *OW, int NativeOffset, int FileId, int LineNumber, int ColNumber) { assert(OW && "ObjWriter is null"); @@ -299,10 +317,11 @@ DLL_EXPORT unsigned GetClassTypeIndex(ObjectWriter *OW, DLL_EXPORT unsigned GetCompleteClassTypeIndex(ObjectWriter *OW, ClassTypeDescriptor ClassDescriptor, ClassFieldsTypeDescriptior ClassFieldsDescriptor, - DataFieldDescriptor *FieldsDescriptors) { + DataFieldDescriptor *FieldsDescriptors, + StaticDataFieldDescriptor *StaticsDescriptors) { assert(OW && "ObjWriter is null"); return OW->GetCompleteClassTypeIndex(ClassDescriptor, ClassFieldsDescriptor, - FieldsDescriptors); + FieldsDescriptors, StaticsDescriptors); } DLL_EXPORT unsigned GetArrayTypeIndex(ObjectWriter *OW, @@ -331,6 +350,11 @@ DLL_EXPORT unsigned GetMemberFunctionIdTypeIndex(ObjectWriter *OW, return OW->GetMemberFunctionId(MemberIdDescriptor); } +DLL_EXPORT unsigned GetPrimitiveTypeIndex(ObjectWriter *OW, int Type) { + assert(OW && "ObjWriter is null"); + return OW->GetPrimitiveTypeIndex(Type); +} + DLL_EXPORT void EmitARMFnStart(ObjectWriter *OW) { assert(OW && "ObjWriter is null"); return OW->EmitARMFnStart(); diff --git a/src/Native/ObjWriter/typeBuilder.h b/src/Native/ObjWriter/typeBuilder.h deleted file mode 100644 index a5037b769..000000000 --- a/src/Native/ObjWriter/typeBuilder.h +++ /dev/null @@ -1,145 +0,0 @@ -//===---- typeBuilder.h --------------------------------*- C++ -*-===// -// -// type builder is used to convert .Net types into CodeView descriptors. -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. -// See LICENSE file in the project root for full license information. -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" -#include "llvm/MC/MCObjectStreamer.h" - -#include <string> -#include <vector> - -using namespace llvm; -using namespace llvm::codeview; - -typedef unsigned long long uint64; - -#pragma pack(push, 8) - -extern "C" struct EnumRecordTypeDescriptor { - uint64 Value; - char *Name; -}; - -extern "C" struct EnumTypeDescriptor { - uint32_t ElementType; - uint64 ElementCount; - char *Name; -}; - -extern "C" struct ClassTypeDescriptor { - int32_t IsStruct; - char *Name; - uint32_t BaseClassId; -}; - -extern "C" struct DataFieldDescriptor { - uint32_t FieldTypeIndex; - uint64 Offset; - char *Name; -}; - -extern "C" struct ClassFieldsTypeDescriptior { - uint64 Size; - int32_t FieldsCount; -}; - -extern "C" struct ArrayTypeDescriptor { - uint32_t Rank; - uint32_t ElementType; - uint32_t Size; - int32_t IsMultiDimensional; -}; - -extern "C" struct PointerTypeDescriptor { - uint32_t ElementType; - int32_t IsReference; - int32_t IsConst; - int32_t Is64Bit; -}; - -extern "C" struct MemberFunctionTypeDescriptor { - uint32_t ReturnType; - uint32_t ContainingClass; - uint32_t TypeIndexOfThisPointer; - int32_t ThisAdjust; - uint32_t CallingConvention; - uint16_t NumberOfArguments; -}; - -extern "C" struct MemberFunctionIdTypeDescriptor { - uint32_t MemberFunction; - uint32_t ParentClass; - char *Name; -}; - -class ArrayDimensionsDescriptor { -public: - const char *GetLengthName(unsigned index); - const char *GetBoundsName(unsigned index); - -private: - void Resize(unsigned NewSize); - - std::vector<std::string> Lengths; - std::vector<std::string> Bounds; -}; - -#pragma pack(pop) -class UserDefinedTypesBuilder { -public: - UserDefinedTypesBuilder(); - void SetStreamer(MCObjectStreamer *Streamer); - void SetTargetPointerSize(unsigned TargetPointerSize); - void EmitTypeInformation(MCSection *COFFDebugTypesSection); - - unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor, - const EnumRecordTypeDescriptor *TypeRecords); - unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor); - unsigned GetCompleteClassTypeIndex( - const ClassTypeDescriptor &ClassDescriptor, - const ClassFieldsTypeDescriptior &ClassFieldsDescriptor, - const DataFieldDescriptor *FieldsDescriptors); - - unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor, - const ArrayTypeDescriptor &ArrayDescriptor); - - unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor); - - unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor, - uint32_t const *const ArgumentTypes); - - unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor); - - const std::vector<std::pair<std::string, codeview::TypeIndex>> &GetUDTs() { - return UserDefinedTypes; - } - -private: - void EmitCodeViewMagicVersion(); - ClassOptions GetCommonClassOptions(); - - unsigned GetEnumFieldListType(uint64 Count, - const EnumRecordTypeDescriptor *TypeRecords); - - void AddBaseClass(FieldListRecordBuilder &FLBR, unsigned BaseClassId); - void AddClassVTShape(FieldListRecordBuilder &FLBR); - - BumpPtrAllocator Allocator; - TypeTableBuilder TypeTable; - - MCObjectStreamer *Streamer; - unsigned TargetPointerSize; - - ArrayDimensionsDescriptor ArrayDimentions; - TypeIndex ClassVTableTypeIndex; - - std::vector<std::pair<std::string, codeview::TypeIndex>> UserDefinedTypes; -}; |