diff options
author | Aleksandr Urakov <aleksandr.urakov@jetbrains.com> | 2019-02-01 10:01:18 +0000 |
---|---|---|
committer | Aleksandr Urakov <aleksandr.urakov@jetbrains.com> | 2019-02-01 10:01:18 +0000 |
commit | 758657e56550c0681260bb61b0a2bddb4a5c2e6d (patch) | |
tree | cd529a2f27ed73e5871fc04afa541f0a97959ade | |
parent | bac11518cd44f85cea38e5be116388cd254de9eb (diff) | |
download | bcm5719-llvm-758657e56550c0681260bb61b0a2bddb4a5c2e6d.tar.gz bcm5719-llvm-758657e56550c0681260bb61b0a2bddb4a5c2e6d.zip |
[PDB] Fix location retrieval for function local variables and arguments that are
stored relative to VFRAME
Summary:
This patch makes LLDB able to retrieve proper values for function arguments and
local variables stored in PDB relative to VFRAME register.
Patch contains retrieval of corresponding FPO table entries from PDB and a
generic translator from FPO programs to DWARF expressions to get correct VFRAME
value.
Patch also improves variables-locations.test and makes this test passable on
x86.
Patch By: leonid.mashinsky
Reviewers: zturner, asmith, stella.stamenova, aleksandr.urakov
Reviewed By: zturner
Subscribers: arphaman, labath, mgorny, aprantl, JDevlieghere, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D55122
llvm-svn: 352845
22 files changed, 1514 insertions, 929 deletions
diff --git a/lldb/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp b/lldb/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp index 54d54c0d56a..7b7180a3ec4 100644 --- a/lldb/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp +++ b/lldb/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp @@ -5,11 +5,22 @@ void __fastcall foo(short arg_0, float arg_1) { double loc_1 = 0.5678; } +__declspec(align(128)) struct S { + int a = 1234; +}; + +void bar(int arg_0) { + S loc_0; + int loc_1 = 5678; +} + + int main(int argc, char *argv[]) { bool loc_0 = true; int loc_1 = 3333; foo(1111, 0.1234); + bar(22); return 0; } diff --git a/lldb/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script b/lldb/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script index 7058f29ae1c..7dd90352cce 100644 --- a/lldb/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script +++ b/lldb/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script @@ -1,4 +1,5 @@ breakpoint set --file VariablesLocationsTest.cpp --line 6 +breakpoint set --file VariablesLocationsTest.cpp --line 15 run @@ -14,3 +15,11 @@ frame select 1 frame variable loc_0 frame variable loc_1 + +continue + +frame variable arg_0 + +frame variable loc_0 +frame variable loc_1 + diff --git a/lldb/lit/SymbolFile/PDB/variables-locations.test b/lldb/lit/SymbolFile/PDB/variables-locations.test index 7696dc92cee..b5bfc6fe81a 100644 --- a/lldb/lit/SymbolFile/PDB/variables-locations.test +++ b/lldb/lit/SymbolFile/PDB/variables-locations.test @@ -1,5 +1,6 @@ REQUIRES: system-windows, lld RUN: %build --compiler=clang-cl --output=%t.exe %S/Inputs/VariablesLocationsTest.cpp +RUN: env LLDB_USE_NATIVE_PDB_READER=0 %lldb -b -s %S/Inputs/VariablesLocationsTest.script -- %t.exe | FileCheck %s RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -b -s %S/Inputs/VariablesLocationsTest.script -- %t.exe | FileCheck %s CHECK: g_var = 2222 @@ -12,3 +13,8 @@ CHECK: loc_1 = 0.567 CHECK: loc_0 = true CHECK: loc_1 = 3333 + +CHECK: arg_0 = 22 + +CHECK: loc_0 = (a = 1234) +CHECK: loc_1 = 5678 diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 4d002a4f452..8c7db6f78f2 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -3203,7 +3203,7 @@ static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data, break; default: s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); - return true; + return false; } switch (size) { @@ -3249,7 +3249,7 @@ static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data, break; } - return false; + return true; } bool DWARFExpression::PrintDWARFExpression(Stream &s, const DataExtractor &data, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt index da2d7fe8108..52b431db517 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt @@ -1,7 +1,9 @@ add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN + CodeViewRegisterMapping.cpp CompileUnitIndex.cpp DWARFLocationExpression.cpp PdbAstBuilder.cpp + PdbFPOProgramToDWARFExpression.cpp PdbIndex.cpp PdbSymUid.cpp PdbUtil.cpp @@ -13,7 +15,7 @@ add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN clangLex lldbCore lldbSymbol - lldbUtility + lldbUtility LINK_COMPONENTS DebugInfoCodeView DebugInfoPDB diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp new file mode 100644 index 00000000000..30bcdc70051 --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp @@ -0,0 +1,458 @@ +//===-- CodeViewRegisterMapping.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CodeViewRegisterMapping.h" + +#include "lldb/lldb-defines.h" + +#include "Plugins/Process/Utility/lldb-x86-register-enums.h" + +using namespace lldb_private; + +static const uint32_t g_code_view_to_lldb_registers_x86[] = { + LLDB_INVALID_REGNUM, // NONE + lldb_al_i386, // AL + lldb_cl_i386, // CL + lldb_dl_i386, // DL + lldb_bl_i386, // BL + lldb_ah_i386, // AH + lldb_ch_i386, // CH + lldb_dh_i386, // DH + lldb_bh_i386, // BH + lldb_ax_i386, // AX + lldb_cx_i386, // CX + lldb_dx_i386, // DX + lldb_bx_i386, // BX + lldb_sp_i386, // SP + lldb_bp_i386, // BP + lldb_si_i386, // SI + lldb_di_i386, // DI + lldb_eax_i386, // EAX + lldb_ecx_i386, // ECX + lldb_edx_i386, // EDX + lldb_ebx_i386, // EBX + lldb_esp_i386, // ESP + lldb_ebp_i386, // EBP + lldb_esi_i386, // ESI + lldb_edi_i386, // EDI + lldb_es_i386, // ES + lldb_cs_i386, // CS + lldb_ss_i386, // SS + lldb_ds_i386, // DS + lldb_fs_i386, // FS + lldb_gs_i386, // GS + LLDB_INVALID_REGNUM, // IP + LLDB_INVALID_REGNUM, // FLAGS + lldb_eip_i386, // EIP + lldb_eflags_i386, // EFLAGS + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // TEMP + LLDB_INVALID_REGNUM, // TEMPH + LLDB_INVALID_REGNUM, // QUOTE + LLDB_INVALID_REGNUM, // PCDR3 + LLDB_INVALID_REGNUM, // PCDR4 + LLDB_INVALID_REGNUM, // PCDR5 + LLDB_INVALID_REGNUM, // PCDR6 + LLDB_INVALID_REGNUM, // PCDR7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // CR0 + LLDB_INVALID_REGNUM, // CR1 + LLDB_INVALID_REGNUM, // CR2 + LLDB_INVALID_REGNUM, // CR3 + LLDB_INVALID_REGNUM, // CR4 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_dr0_i386, // DR0 + lldb_dr1_i386, // DR1 + lldb_dr2_i386, // DR2 + lldb_dr3_i386, // DR3 + lldb_dr4_i386, // DR4 + lldb_dr5_i386, // DR5 + lldb_dr6_i386, // DR6 + lldb_dr7_i386, // DR7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // GDTR + LLDB_INVALID_REGNUM, // GDTL + LLDB_INVALID_REGNUM, // IDTR + LLDB_INVALID_REGNUM, // IDTL + LLDB_INVALID_REGNUM, // LDTR + LLDB_INVALID_REGNUM, // TR + LLDB_INVALID_REGNUM, // PSEUDO1 + LLDB_INVALID_REGNUM, // PSEUDO2 + LLDB_INVALID_REGNUM, // PSEUDO3 + LLDB_INVALID_REGNUM, // PSEUDO4 + LLDB_INVALID_REGNUM, // PSEUDO5 + LLDB_INVALID_REGNUM, // PSEUDO6 + LLDB_INVALID_REGNUM, // PSEUDO7 + LLDB_INVALID_REGNUM, // PSEUDO8 + LLDB_INVALID_REGNUM, // PSEUDO9 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_st0_i386, // ST0 + lldb_st1_i386, // ST1 + lldb_st2_i386, // ST2 + lldb_st3_i386, // ST3 + lldb_st4_i386, // ST4 + lldb_st5_i386, // ST5 + lldb_st6_i386, // ST6 + lldb_st7_i386, // ST7 + LLDB_INVALID_REGNUM, // CTRL + LLDB_INVALID_REGNUM, // STAT + LLDB_INVALID_REGNUM, // TAG + LLDB_INVALID_REGNUM, // FPIP + LLDB_INVALID_REGNUM, // FPCS + LLDB_INVALID_REGNUM, // FPDO + LLDB_INVALID_REGNUM, // FPDS + LLDB_INVALID_REGNUM, // ISEM + LLDB_INVALID_REGNUM, // FPEIP + LLDB_INVALID_REGNUM, // FPEDO + lldb_mm0_i386, // MM0 + lldb_mm1_i386, // MM1 + lldb_mm2_i386, // MM2 + lldb_mm3_i386, // MM3 + lldb_mm4_i386, // MM4 + lldb_mm5_i386, // MM5 + lldb_mm6_i386, // MM6 + lldb_mm7_i386, // MM7 + lldb_xmm0_i386, // XMM0 + lldb_xmm1_i386, // XMM1 + lldb_xmm2_i386, // XMM2 + lldb_xmm3_i386, // XMM3 + lldb_xmm4_i386, // XMM4 + lldb_xmm5_i386, // XMM5 + lldb_xmm6_i386, // XMM6 + lldb_xmm7_i386 // XMM7 +}; + +static const uint32_t g_code_view_to_lldb_registers_x86_64[] = { + LLDB_INVALID_REGNUM, // NONE + lldb_al_x86_64, // AL + lldb_cl_x86_64, // CL + lldb_dl_x86_64, // DL + lldb_bl_x86_64, // BL + lldb_ah_x86_64, // AH + lldb_ch_x86_64, // CH + lldb_dh_x86_64, // DH + lldb_bh_x86_64, // BH + lldb_ax_x86_64, // AX + lldb_cx_x86_64, // CX + lldb_dx_x86_64, // DX + lldb_bx_x86_64, // BX + lldb_sp_x86_64, // SP + lldb_bp_x86_64, // BP + lldb_si_x86_64, // SI + lldb_di_x86_64, // DI + lldb_eax_x86_64, // EAX + lldb_ecx_x86_64, // ECX + lldb_edx_x86_64, // EDX + lldb_ebx_x86_64, // EBX + lldb_esp_x86_64, // ESP + lldb_ebp_x86_64, // EBP + lldb_esi_x86_64, // ESI + lldb_edi_x86_64, // EDI + lldb_es_x86_64, // ES + lldb_cs_x86_64, // CS + lldb_ss_x86_64, // SS + lldb_ds_x86_64, // DS + lldb_fs_x86_64, // FS + lldb_gs_x86_64, // GS + LLDB_INVALID_REGNUM, // IP + LLDB_INVALID_REGNUM, // FLAGS + LLDB_INVALID_REGNUM, // EIP + LLDB_INVALID_REGNUM, // EFLAGS + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // TEMP + LLDB_INVALID_REGNUM, // TEMPH + LLDB_INVALID_REGNUM, // QUOTE + LLDB_INVALID_REGNUM, // PCDR3 + LLDB_INVALID_REGNUM, // PCDR4 + LLDB_INVALID_REGNUM, // PCDR5 + LLDB_INVALID_REGNUM, // PCDR6 + LLDB_INVALID_REGNUM, // PCDR7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // CR0 + LLDB_INVALID_REGNUM, // CR1 + LLDB_INVALID_REGNUM, // CR2 + LLDB_INVALID_REGNUM, // CR3 + LLDB_INVALID_REGNUM, // CR4 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_dr0_x86_64, // DR0 + lldb_dr1_x86_64, // DR1 + lldb_dr2_x86_64, // DR2 + lldb_dr3_x86_64, // DR3 + lldb_dr4_x86_64, // DR4 + lldb_dr5_x86_64, // DR5 + lldb_dr6_x86_64, // DR6 + lldb_dr7_x86_64, // DR7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // GDTR + LLDB_INVALID_REGNUM, // GDTL + LLDB_INVALID_REGNUM, // IDTR + LLDB_INVALID_REGNUM, // IDTL + LLDB_INVALID_REGNUM, // LDTR + LLDB_INVALID_REGNUM, // TR + LLDB_INVALID_REGNUM, // PSEUDO1 + LLDB_INVALID_REGNUM, // PSEUDO2 + LLDB_INVALID_REGNUM, // PSEUDO3 + LLDB_INVALID_REGNUM, // PSEUDO4 + LLDB_INVALID_REGNUM, // PSEUDO5 + LLDB_INVALID_REGNUM, // PSEUDO6 + LLDB_INVALID_REGNUM, // PSEUDO7 + LLDB_INVALID_REGNUM, // PSEUDO8 + LLDB_INVALID_REGNUM, // PSEUDO9 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_st0_x86_64, // ST0 + lldb_st1_x86_64, // ST1 + lldb_st2_x86_64, // ST2 + lldb_st3_x86_64, // ST3 + lldb_st4_x86_64, // ST4 + lldb_st5_x86_64, // ST5 + lldb_st6_x86_64, // ST6 + lldb_st7_x86_64, // ST7 + LLDB_INVALID_REGNUM, // CTRL + LLDB_INVALID_REGNUM, // STAT + LLDB_INVALID_REGNUM, // TAG + LLDB_INVALID_REGNUM, // FPIP + LLDB_INVALID_REGNUM, // FPCS + LLDB_INVALID_REGNUM, // FPDO + LLDB_INVALID_REGNUM, // FPDS + LLDB_INVALID_REGNUM, // ISEM + LLDB_INVALID_REGNUM, // FPEIP + LLDB_INVALID_REGNUM, // FPEDO + lldb_mm0_x86_64, // MM0 + lldb_mm1_x86_64, // MM1 + lldb_mm2_x86_64, // MM2 + lldb_mm3_x86_64, // MM3 + lldb_mm4_x86_64, // MM4 + lldb_mm5_x86_64, // MM5 + lldb_mm6_x86_64, // MM6 + lldb_mm7_x86_64, // MM7 + lldb_xmm0_x86_64, // XMM0 + lldb_xmm1_x86_64, // XMM1 + lldb_xmm2_x86_64, // XMM2 + lldb_xmm3_x86_64, // XMM3 + lldb_xmm4_x86_64, // XMM4 + lldb_xmm5_x86_64, // XMM5 + lldb_xmm6_x86_64, // XMM6 + lldb_xmm7_x86_64, // XMM7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, + lldb_mxcsr_x86_64, // MXCSR + LLDB_INVALID_REGNUM, // EDXEAX + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // EMM0L + LLDB_INVALID_REGNUM, // EMM1L + LLDB_INVALID_REGNUM, // EMM2L + LLDB_INVALID_REGNUM, // EMM3L + LLDB_INVALID_REGNUM, // EMM4L + LLDB_INVALID_REGNUM, // EMM5L + LLDB_INVALID_REGNUM, // EMM6L + LLDB_INVALID_REGNUM, // EMM7L + LLDB_INVALID_REGNUM, // EMM0H + LLDB_INVALID_REGNUM, // EMM1H + LLDB_INVALID_REGNUM, // EMM2H + LLDB_INVALID_REGNUM, // EMM3H + LLDB_INVALID_REGNUM, // EMM4H + LLDB_INVALID_REGNUM, // EMM5H + LLDB_INVALID_REGNUM, // EMM6H + LLDB_INVALID_REGNUM, // EMM7H + LLDB_INVALID_REGNUM, // MM00 + LLDB_INVALID_REGNUM, // MM01 + LLDB_INVALID_REGNUM, // MM10 + LLDB_INVALID_REGNUM, // MM11 + LLDB_INVALID_REGNUM, // MM20 + LLDB_INVALID_REGNUM, // MM21 + LLDB_INVALID_REGNUM, // MM30 + LLDB_INVALID_REGNUM, // MM31 + LLDB_INVALID_REGNUM, // MM40 + LLDB_INVALID_REGNUM, // MM41 + LLDB_INVALID_REGNUM, // MM50 + LLDB_INVALID_REGNUM, // MM51 + LLDB_INVALID_REGNUM, // MM60 + LLDB_INVALID_REGNUM, // MM61 + LLDB_INVALID_REGNUM, // MM70 + LLDB_INVALID_REGNUM, // MM71 + lldb_xmm8_x86_64, // XMM8 + lldb_xmm9_x86_64, // XMM9 + lldb_xmm10_x86_64, // XMM10 + lldb_xmm11_x86_64, // XMM11 + lldb_xmm12_x86_64, // XMM12 + lldb_xmm13_x86_64, // XMM13 + lldb_xmm14_x86_64, // XMM14 + lldb_xmm15_x86_64, // XMM15 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, + lldb_sil_x86_64, // SIL + lldb_dil_x86_64, // DIL + lldb_bpl_x86_64, // BPL + lldb_spl_x86_64, // SPL + lldb_rax_x86_64, // RAX + lldb_rbx_x86_64, // RBX + lldb_rcx_x86_64, // RCX + lldb_rdx_x86_64, // RDX + lldb_rsi_x86_64, // RSI + lldb_rdi_x86_64, // RDI + lldb_rbp_x86_64, // RBP + lldb_rsp_x86_64, // RSP + lldb_r8_x86_64, // R8 + lldb_r9_x86_64, // R9 + lldb_r10_x86_64, // R10 + lldb_r11_x86_64, // R11 + lldb_r12_x86_64, // R12 + lldb_r13_x86_64, // R13 + lldb_r14_x86_64, // R14 + lldb_r15_x86_64, // R15 + lldb_r8l_x86_64, // R8B + lldb_r9l_x86_64, // R9B + lldb_r10l_x86_64, // R10B + lldb_r11l_x86_64, // R11B + lldb_r12l_x86_64, // R12B + lldb_r13l_x86_64, // R13B + lldb_r14l_x86_64, // R14B + lldb_r15l_x86_64, // R15B + lldb_r8w_x86_64, // R8W + lldb_r9w_x86_64, // R9W + lldb_r10w_x86_64, // R10W + lldb_r11w_x86_64, // R11W + lldb_r12w_x86_64, // R12W + lldb_r13w_x86_64, // R13W + lldb_r14w_x86_64, // R14W + lldb_r15w_x86_64, // R15W + lldb_r8d_x86_64, // R8D + lldb_r9d_x86_64, // R9D + lldb_r10d_x86_64, // R10D + lldb_r11d_x86_64, // R11D + lldb_r12d_x86_64, // R12D + lldb_r13d_x86_64, // R13D + lldb_r14d_x86_64, // R14D + lldb_r15d_x86_64, // R15D + lldb_ymm0_x86_64, // AMD64_YMM0 + lldb_ymm1_x86_64, // AMD64_YMM1 + lldb_ymm2_x86_64, // AMD64_YMM2 + lldb_ymm3_x86_64, // AMD64_YMM3 + lldb_ymm4_x86_64, // AMD64_YMM4 + lldb_ymm5_x86_64, // AMD64_YMM5 + lldb_ymm6_x86_64, // AMD64_YMM6 + lldb_ymm7_x86_64, // AMD64_YMM7 + lldb_ymm8_x86_64, // AMD64_YMM8 + lldb_ymm9_x86_64, // AMD64_YMM9 + lldb_ymm10_x86_64, // AMD64_YMM10 + lldb_ymm11_x86_64, // AMD64_YMM11 + lldb_ymm12_x86_64, // AMD64_YMM12 + lldb_ymm13_x86_64, // AMD64_YMM13 + lldb_ymm14_x86_64, // AMD64_YMM14 + lldb_ymm15_x86_64, // AMD64_YMM15 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_bnd0_x86_64, // BND0 + lldb_bnd1_x86_64, // BND1 + lldb_bnd2_x86_64 // BND2 +}; + +uint32_t lldb_private::npdb::GetLLDBRegisterNumber( + llvm::Triple::ArchType arch_type, llvm::codeview::RegisterId register_id) { + switch (arch_type) { + case llvm::Triple::x86: + if (static_cast<uint16_t>(register_id) < + sizeof(g_code_view_to_lldb_registers_x86) / + sizeof(g_code_view_to_lldb_registers_x86[0])) + return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>( + register_id)]; + + switch (register_id) { + case llvm::codeview::RegisterId::MXCSR: + return lldb_mxcsr_i386; + case llvm::codeview::RegisterId::BND0: + return lldb_bnd0_i386; + case llvm::codeview::RegisterId::BND1: + return lldb_bnd1_i386; + case llvm::codeview::RegisterId::BND2: + return lldb_bnd2_i386; + default: + return LLDB_INVALID_REGNUM; + } + case llvm::Triple::x86_64: + if (static_cast<uint16_t>(register_id) < + sizeof(g_code_view_to_lldb_registers_x86_64) / + sizeof(g_code_view_to_lldb_registers_x86_64[0])) + return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>( + register_id)]; + + return LLDB_INVALID_REGNUM; + default: + return LLDB_INVALID_REGNUM; + } +} diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h b/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h new file mode 100644 index 00000000000..b29e224b86f --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h @@ -0,0 +1,25 @@ +//===-- CodeViewRegisterMapping.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Plugins_SymbolFile_PDB_CodeViewRegisterMapping_h_ +#define lldb_Plugins_SymbolFile_PDB_CodeViewRegisterMapping_h_ + +#include "llvm/ADT/Triple.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" + +namespace lldb_private { +namespace npdb { + +uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, + llvm::codeview::RegisterId register_id); + +} // namespace npdb +} // namespace lldb_private + +#endif diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp index e26dabd5975..2b9a56e1ba8 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp @@ -8,7 +8,6 @@ #include "DWARFLocationExpression.h" -#include "Plugins/Process/Utility/lldb-x86-register-enums.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamBuffer.h" @@ -23,6 +22,8 @@ #include "llvm/Support/Endian.h" #include "PdbUtil.h" +#include "CodeViewRegisterMapping.h" +#include "PdbFPOProgramToDWARFExpression.h" using namespace lldb; using namespace lldb_private; @@ -30,448 +31,6 @@ using namespace lldb_private::npdb; using namespace llvm::codeview; using namespace llvm::pdb; -static const uint32_t g_code_view_to_lldb_registers_x86[] = { - LLDB_INVALID_REGNUM, // NONE - lldb_al_i386, // AL - lldb_cl_i386, // CL - lldb_dl_i386, // DL - lldb_bl_i386, // BL - lldb_ah_i386, // AH - lldb_ch_i386, // CH - lldb_dh_i386, // DH - lldb_bh_i386, // BH - lldb_ax_i386, // AX - lldb_cx_i386, // CX - lldb_dx_i386, // DX - lldb_bx_i386, // BX - lldb_sp_i386, // SP - lldb_bp_i386, // BP - lldb_si_i386, // SI - lldb_di_i386, // DI - lldb_eax_i386, // EAX - lldb_ecx_i386, // ECX - lldb_edx_i386, // EDX - lldb_ebx_i386, // EBX - lldb_esp_i386, // ESP - lldb_ebp_i386, // EBP - lldb_esi_i386, // ESI - lldb_edi_i386, // EDI - lldb_es_i386, // ES - lldb_cs_i386, // CS - lldb_ss_i386, // SS - lldb_ds_i386, // DS - lldb_fs_i386, // FS - lldb_gs_i386, // GS - LLDB_INVALID_REGNUM, // IP - LLDB_INVALID_REGNUM, // FLAGS - lldb_eip_i386, // EIP - lldb_eflags_i386, // EFLAGS - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // TEMP - LLDB_INVALID_REGNUM, // TEMPH - LLDB_INVALID_REGNUM, // QUOTE - LLDB_INVALID_REGNUM, // PCDR3 - LLDB_INVALID_REGNUM, // PCDR4 - LLDB_INVALID_REGNUM, // PCDR5 - LLDB_INVALID_REGNUM, // PCDR6 - LLDB_INVALID_REGNUM, // PCDR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CR0 - LLDB_INVALID_REGNUM, // CR1 - LLDB_INVALID_REGNUM, // CR2 - LLDB_INVALID_REGNUM, // CR3 - LLDB_INVALID_REGNUM, // CR4 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_i386, // DR0 - lldb_dr1_i386, // DR1 - lldb_dr2_i386, // DR2 - lldb_dr3_i386, // DR3 - lldb_dr4_i386, // DR4 - lldb_dr5_i386, // DR5 - lldb_dr6_i386, // DR6 - lldb_dr7_i386, // DR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // GDTR - LLDB_INVALID_REGNUM, // GDTL - LLDB_INVALID_REGNUM, // IDTR - LLDB_INVALID_REGNUM, // IDTL - LLDB_INVALID_REGNUM, // LDTR - LLDB_INVALID_REGNUM, // TR - LLDB_INVALID_REGNUM, // PSEUDO1 - LLDB_INVALID_REGNUM, // PSEUDO2 - LLDB_INVALID_REGNUM, // PSEUDO3 - LLDB_INVALID_REGNUM, // PSEUDO4 - LLDB_INVALID_REGNUM, // PSEUDO5 - LLDB_INVALID_REGNUM, // PSEUDO6 - LLDB_INVALID_REGNUM, // PSEUDO7 - LLDB_INVALID_REGNUM, // PSEUDO8 - LLDB_INVALID_REGNUM, // PSEUDO9 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_i386, // ST0 - lldb_st1_i386, // ST1 - lldb_st2_i386, // ST2 - lldb_st3_i386, // ST3 - lldb_st4_i386, // ST4 - lldb_st5_i386, // ST5 - lldb_st6_i386, // ST6 - lldb_st7_i386, // ST7 - LLDB_INVALID_REGNUM, // CTRL - LLDB_INVALID_REGNUM, // STAT - LLDB_INVALID_REGNUM, // TAG - LLDB_INVALID_REGNUM, // FPIP - LLDB_INVALID_REGNUM, // FPCS - LLDB_INVALID_REGNUM, // FPDO - LLDB_INVALID_REGNUM, // FPDS - LLDB_INVALID_REGNUM, // ISEM - LLDB_INVALID_REGNUM, // FPEIP - LLDB_INVALID_REGNUM, // FPEDO - lldb_mm0_i386, // MM0 - lldb_mm1_i386, // MM1 - lldb_mm2_i386, // MM2 - lldb_mm3_i386, // MM3 - lldb_mm4_i386, // MM4 - lldb_mm5_i386, // MM5 - lldb_mm6_i386, // MM6 - lldb_mm7_i386, // MM7 - lldb_xmm0_i386, // XMM0 - lldb_xmm1_i386, // XMM1 - lldb_xmm2_i386, // XMM2 - lldb_xmm3_i386, // XMM3 - lldb_xmm4_i386, // XMM4 - lldb_xmm5_i386, // XMM5 - lldb_xmm6_i386, // XMM6 - lldb_xmm7_i386 // XMM7 -}; - -static const uint32_t g_code_view_to_lldb_registers_x86_64[] = { - LLDB_INVALID_REGNUM, // NONE - lldb_al_x86_64, // AL - lldb_cl_x86_64, // CL - lldb_dl_x86_64, // DL - lldb_bl_x86_64, // BL - lldb_ah_x86_64, // AH - lldb_ch_x86_64, // CH - lldb_dh_x86_64, // DH - lldb_bh_x86_64, // BH - lldb_ax_x86_64, // AX - lldb_cx_x86_64, // CX - lldb_dx_x86_64, // DX - lldb_bx_x86_64, // BX - lldb_sp_x86_64, // SP - lldb_bp_x86_64, // BP - lldb_si_x86_64, // SI - lldb_di_x86_64, // DI - lldb_eax_x86_64, // EAX - lldb_ecx_x86_64, // ECX - lldb_edx_x86_64, // EDX - lldb_ebx_x86_64, // EBX - lldb_esp_x86_64, // ESP - lldb_ebp_x86_64, // EBP - lldb_esi_x86_64, // ESI - lldb_edi_x86_64, // EDI - lldb_es_x86_64, // ES - lldb_cs_x86_64, // CS - lldb_ss_x86_64, // SS - lldb_ds_x86_64, // DS - lldb_fs_x86_64, // FS - lldb_gs_x86_64, // GS - LLDB_INVALID_REGNUM, // IP - LLDB_INVALID_REGNUM, // FLAGS - LLDB_INVALID_REGNUM, // EIP - LLDB_INVALID_REGNUM, // EFLAGS - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // TEMP - LLDB_INVALID_REGNUM, // TEMPH - LLDB_INVALID_REGNUM, // QUOTE - LLDB_INVALID_REGNUM, // PCDR3 - LLDB_INVALID_REGNUM, // PCDR4 - LLDB_INVALID_REGNUM, // PCDR5 - LLDB_INVALID_REGNUM, // PCDR6 - LLDB_INVALID_REGNUM, // PCDR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CR0 - LLDB_INVALID_REGNUM, // CR1 - LLDB_INVALID_REGNUM, // CR2 - LLDB_INVALID_REGNUM, // CR3 - LLDB_INVALID_REGNUM, // CR4 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_x86_64, // DR0 - lldb_dr1_x86_64, // DR1 - lldb_dr2_x86_64, // DR2 - lldb_dr3_x86_64, // DR3 - lldb_dr4_x86_64, // DR4 - lldb_dr5_x86_64, // DR5 - lldb_dr6_x86_64, // DR6 - lldb_dr7_x86_64, // DR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // GDTR - LLDB_INVALID_REGNUM, // GDTL - LLDB_INVALID_REGNUM, // IDTR - LLDB_INVALID_REGNUM, // IDTL - LLDB_INVALID_REGNUM, // LDTR - LLDB_INVALID_REGNUM, // TR - LLDB_INVALID_REGNUM, // PSEUDO1 - LLDB_INVALID_REGNUM, // PSEUDO2 - LLDB_INVALID_REGNUM, // PSEUDO3 - LLDB_INVALID_REGNUM, // PSEUDO4 - LLDB_INVALID_REGNUM, // PSEUDO5 - LLDB_INVALID_REGNUM, // PSEUDO6 - LLDB_INVALID_REGNUM, // PSEUDO7 - LLDB_INVALID_REGNUM, // PSEUDO8 - LLDB_INVALID_REGNUM, // PSEUDO9 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_x86_64, // ST0 - lldb_st1_x86_64, // ST1 - lldb_st2_x86_64, // ST2 - lldb_st3_x86_64, // ST3 - lldb_st4_x86_64, // ST4 - lldb_st5_x86_64, // ST5 - lldb_st6_x86_64, // ST6 - lldb_st7_x86_64, // ST7 - LLDB_INVALID_REGNUM, // CTRL - LLDB_INVALID_REGNUM, // STAT - LLDB_INVALID_REGNUM, // TAG - LLDB_INVALID_REGNUM, // FPIP - LLDB_INVALID_REGNUM, // FPCS - LLDB_INVALID_REGNUM, // FPDO - LLDB_INVALID_REGNUM, // FPDS - LLDB_INVALID_REGNUM, // ISEM - LLDB_INVALID_REGNUM, // FPEIP - LLDB_INVALID_REGNUM, // FPEDO - lldb_mm0_x86_64, // MM0 - lldb_mm1_x86_64, // MM1 - lldb_mm2_x86_64, // MM2 - lldb_mm3_x86_64, // MM3 - lldb_mm4_x86_64, // MM4 - lldb_mm5_x86_64, // MM5 - lldb_mm6_x86_64, // MM6 - lldb_mm7_x86_64, // MM7 - lldb_xmm0_x86_64, // XMM0 - lldb_xmm1_x86_64, // XMM1 - lldb_xmm2_x86_64, // XMM2 - lldb_xmm3_x86_64, // XMM3 - lldb_xmm4_x86_64, // XMM4 - lldb_xmm5_x86_64, // XMM5 - lldb_xmm6_x86_64, // XMM6 - lldb_xmm7_x86_64, // XMM7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - lldb_mxcsr_x86_64, // MXCSR - LLDB_INVALID_REGNUM, // EDXEAX - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // EMM0L - LLDB_INVALID_REGNUM, // EMM1L - LLDB_INVALID_REGNUM, // EMM2L - LLDB_INVALID_REGNUM, // EMM3L - LLDB_INVALID_REGNUM, // EMM4L - LLDB_INVALID_REGNUM, // EMM5L - LLDB_INVALID_REGNUM, // EMM6L - LLDB_INVALID_REGNUM, // EMM7L - LLDB_INVALID_REGNUM, // EMM0H - LLDB_INVALID_REGNUM, // EMM1H - LLDB_INVALID_REGNUM, // EMM2H - LLDB_INVALID_REGNUM, // EMM3H - LLDB_INVALID_REGNUM, // EMM4H - LLDB_INVALID_REGNUM, // EMM5H - LLDB_INVALID_REGNUM, // EMM6H - LLDB_INVALID_REGNUM, // EMM7H - LLDB_INVALID_REGNUM, // MM00 - LLDB_INVALID_REGNUM, // MM01 - LLDB_INVALID_REGNUM, // MM10 - LLDB_INVALID_REGNUM, // MM11 - LLDB_INVALID_REGNUM, // MM20 - LLDB_INVALID_REGNUM, // MM21 - LLDB_INVALID_REGNUM, // MM30 - LLDB_INVALID_REGNUM, // MM31 - LLDB_INVALID_REGNUM, // MM40 - LLDB_INVALID_REGNUM, // MM41 - LLDB_INVALID_REGNUM, // MM50 - LLDB_INVALID_REGNUM, // MM51 - LLDB_INVALID_REGNUM, // MM60 - LLDB_INVALID_REGNUM, // MM61 - LLDB_INVALID_REGNUM, // MM70 - LLDB_INVALID_REGNUM, // MM71 - lldb_xmm8_x86_64, // XMM8 - lldb_xmm9_x86_64, // XMM9 - lldb_xmm10_x86_64, // XMM10 - lldb_xmm11_x86_64, // XMM11 - lldb_xmm12_x86_64, // XMM12 - lldb_xmm13_x86_64, // XMM13 - lldb_xmm14_x86_64, // XMM14 - lldb_xmm15_x86_64, // XMM15 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - lldb_sil_x86_64, // SIL - lldb_dil_x86_64, // DIL - lldb_bpl_x86_64, // BPL - lldb_spl_x86_64, // SPL - lldb_rax_x86_64, // RAX - lldb_rbx_x86_64, // RBX - lldb_rcx_x86_64, // RCX - lldb_rdx_x86_64, // RDX - lldb_rsi_x86_64, // RSI - lldb_rdi_x86_64, // RDI - lldb_rbp_x86_64, // RBP - lldb_rsp_x86_64, // RSP - lldb_r8_x86_64, // R8 - lldb_r9_x86_64, // R9 - lldb_r10_x86_64, // R10 - lldb_r11_x86_64, // R11 - lldb_r12_x86_64, // R12 - lldb_r13_x86_64, // R13 - lldb_r14_x86_64, // R14 - lldb_r15_x86_64, // R15 - lldb_r8l_x86_64, // R8B - lldb_r9l_x86_64, // R9B - lldb_r10l_x86_64, // R10B - lldb_r11l_x86_64, // R11B - lldb_r12l_x86_64, // R12B - lldb_r13l_x86_64, // R13B - lldb_r14l_x86_64, // R14B - lldb_r15l_x86_64, // R15B - lldb_r8w_x86_64, // R8W - lldb_r9w_x86_64, // R9W - lldb_r10w_x86_64, // R10W - lldb_r11w_x86_64, // R11W - lldb_r12w_x86_64, // R12W - lldb_r13w_x86_64, // R13W - lldb_r14w_x86_64, // R14W - lldb_r15w_x86_64, // R15W - lldb_r8d_x86_64, // R8D - lldb_r9d_x86_64, // R9D - lldb_r10d_x86_64, // R10D - lldb_r11d_x86_64, // R11D - lldb_r12d_x86_64, // R12D - lldb_r13d_x86_64, // R13D - lldb_r14d_x86_64, // R14D - lldb_r15d_x86_64, // R15D - lldb_ymm0_x86_64, // AMD64_YMM0 - lldb_ymm1_x86_64, // AMD64_YMM1 - lldb_ymm2_x86_64, // AMD64_YMM2 - lldb_ymm3_x86_64, // AMD64_YMM3 - lldb_ymm4_x86_64, // AMD64_YMM4 - lldb_ymm5_x86_64, // AMD64_YMM5 - lldb_ymm6_x86_64, // AMD64_YMM6 - lldb_ymm7_x86_64, // AMD64_YMM7 - lldb_ymm8_x86_64, // AMD64_YMM8 - lldb_ymm9_x86_64, // AMD64_YMM9 - lldb_ymm10_x86_64, // AMD64_YMM10 - lldb_ymm11_x86_64, // AMD64_YMM11 - lldb_ymm12_x86_64, // AMD64_YMM12 - lldb_ymm13_x86_64, // AMD64_YMM13 - lldb_ymm14_x86_64, // AMD64_YMM14 - lldb_ymm15_x86_64, // AMD64_YMM15 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_bnd0_x86_64, // BND0 - lldb_bnd1_x86_64, // BND1 - lldb_bnd2_x86_64 // BND2 -}; - -uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, - llvm::codeview::RegisterId register_id) { - switch (arch_type) { - case llvm::Triple::x86: - if (static_cast<uint16_t>(register_id) < - sizeof(g_code_view_to_lldb_registers_x86) / - sizeof(g_code_view_to_lldb_registers_x86[0])) - return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>( - register_id)]; - - switch (register_id) { - case llvm::codeview::RegisterId::MXCSR: - return lldb_mxcsr_i386; - case llvm::codeview::RegisterId::BND0: - return lldb_bnd0_i386; - case llvm::codeview::RegisterId::BND1: - return lldb_bnd1_i386; - case llvm::codeview::RegisterId::BND2: - return lldb_bnd2_i386; - default: - return LLDB_INVALID_REGNUM; - } - case llvm::Triple::x86_64: - if (static_cast<uint16_t>(register_id) < - sizeof(g_code_view_to_lldb_registers_x86_64) / - sizeof(g_code_view_to_lldb_registers_x86_64[0])) - return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>( - register_id)]; - - return LLDB_INVALID_REGNUM; - default: - return LLDB_INVALID_REGNUM; - } -} - uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) { if (register_id == llvm::codeview::RegisterId::VFRAME) return LLDB_REGNUM_GENERIC_FP; @@ -609,6 +168,33 @@ DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression( return MakeRegisterBasedLocationExpressionInternal(reg, offset, module); } +static bool EmitVFrameEvaluationDWARFExpression( + llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) { + // VFrame value always stored in $TO pseudo-register + return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type, + stream); +} + +DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression( + llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) { + return MakeLocationExpressionInternal( + module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { + const ArchSpec &architecture = module->GetArchitecture(); + + if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(), + stream)) + return false; + + stream.PutHex8(llvm::dwarf::DW_OP_consts); + stream.PutSLEB128(offset); + stream.PutHex8(llvm::dwarf::DW_OP_plus); + + register_kind = eRegisterKindLLDB; + + return true; + }); +} + DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression( uint16_t section, uint32_t offset, ModuleSP module) { assert(section > 0); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h index e714712e5bf..c37d715babd 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h @@ -30,6 +30,9 @@ MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg, DWARFExpression MakeRegRelLocationExpression(llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module); +DWARFExpression MakeVFrameRelLocationExpression(llvm::StringRef fpo_program, + int32_t offset, + lldb::ModuleSP module); DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset, lldb::ModuleSP module); DWARFExpression MakeConstantLocationExpression( diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp new file mode 100644 index 00000000000..07eb7dbaa91 --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp @@ -0,0 +1,528 @@ +//===-- PDBFPOProgramToDWARFExpression.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PdbFPOProgramToDWARFExpression.h" +#include "CodeViewRegisterMapping.h" + +#include "lldb/Core/StreamBuffer.h" +#include "lldb/Core/dwarf.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Stream.h" +#include "llvm/ADT/DenseMap.h" + +#include "llvm/ADT/StringExtras.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/EnumTables.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class FPOProgramNode; +class FPOProgramASTVisitor; + +class FPOProgramNode { +public: + enum Kind { + Register, + IntegerLiteral, + BinaryOp, + UnaryOp, + }; + +protected: + FPOProgramNode(Kind kind) : m_token_kind(kind) {} + +public: + virtual ~FPOProgramNode() = default; + virtual void Accept(FPOProgramASTVisitor *visitor) = 0; + + Kind GetKind() const { return m_token_kind; } + +private: + Kind m_token_kind; +}; + +class FPOProgramNodeRegisterRef : public FPOProgramNode { +public: + FPOProgramNodeRegisterRef(llvm::StringRef name) + : FPOProgramNode(Register), m_name(name) {} + + void Accept(FPOProgramASTVisitor *visitor) override; + + llvm::StringRef GetName() const { return m_name; } + uint32_t GetLLDBRegNum() const { return m_lldb_reg_num; } + + bool ResolveLLDBRegisterNum(llvm::Triple::ArchType arch_type); + +private: + llvm::StringRef m_name; + uint32_t m_lldb_reg_num = LLDB_INVALID_REGNUM; +}; + +bool FPOProgramNodeRegisterRef::ResolveLLDBRegisterNum( + llvm::Triple::ArchType arch_type) { + + llvm::StringRef reg_name = m_name.slice(1, m_name.size()); + + // lookup register name to get lldb register number + llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names = + llvm::codeview::getRegisterNames(); + auto it = llvm::find_if( + register_names, + [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) { + return reg_name.compare_lower(register_entry.Name) == 0; + }); + + if (it == register_names.end()) { + return false; + } + + auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value); + m_lldb_reg_num = npdb::GetLLDBRegisterNumber(arch_type, reg_id); + + return m_lldb_reg_num != LLDB_INVALID_REGNUM; +} + +class FPOProgramNodeIntegerLiteral : public FPOProgramNode { +public: + FPOProgramNodeIntegerLiteral(uint32_t value) + : FPOProgramNode(IntegerLiteral), m_value(value) {} + + void Accept(FPOProgramASTVisitor *visitor) override; + + uint32_t GetValue() const { return m_value; } + +private: + uint32_t m_value; +}; + +class FPOProgramNodeBinaryOp : public FPOProgramNode { +public: + enum OpType { + Plus, + Minus, + Align, + }; + + FPOProgramNodeBinaryOp(OpType op_type, FPOProgramNode *left, + FPOProgramNode *right) + : FPOProgramNode(BinaryOp), m_op_type(op_type), m_left(left), + m_right(right) {} + + void Accept(FPOProgramASTVisitor *visitor) override; + + OpType GetOpType() const { return m_op_type; } + + const FPOProgramNode *Left() const { return m_left; } + FPOProgramNode *&Left() { return m_left; } + + const FPOProgramNode *Right() const { return m_right; } + FPOProgramNode *&Right() { return m_right; } + +private: + OpType m_op_type; + FPOProgramNode *m_left; + FPOProgramNode *m_right; +}; + +class FPOProgramNodeUnaryOp : public FPOProgramNode { +public: + enum OpType { + Deref, + }; + + FPOProgramNodeUnaryOp(OpType op_type, FPOProgramNode *operand) + : FPOProgramNode(UnaryOp), m_op_type(op_type), m_operand(operand) {} + + void Accept(FPOProgramASTVisitor *visitor) override; + + OpType GetOpType() const { return m_op_type; } + + const FPOProgramNode *Operand() const { return m_operand; } + FPOProgramNode *&Operand() { return m_operand; } + +private: + OpType m_op_type; + FPOProgramNode *m_operand; +}; + +class FPOProgramASTVisitor { +public: + virtual ~FPOProgramASTVisitor() = default; + + virtual void Visit(FPOProgramNodeRegisterRef *node) {} + virtual void Visit(FPOProgramNodeIntegerLiteral *node) {} + virtual void Visit(FPOProgramNodeBinaryOp *node) {} + virtual void Visit(FPOProgramNodeUnaryOp *node) {} +}; + +void FPOProgramNodeRegisterRef::Accept(FPOProgramASTVisitor *visitor) { + visitor->Visit(this); +} + +void FPOProgramNodeIntegerLiteral::Accept(FPOProgramASTVisitor *visitor) { + visitor->Visit(this); +} + +void FPOProgramNodeBinaryOp::Accept(FPOProgramASTVisitor *visitor) { + visitor->Visit(this); +} + +void FPOProgramNodeUnaryOp::Accept(FPOProgramASTVisitor *visitor) { + visitor->Visit(this); +} + +class FPOProgramASTVisitorMergeDependent : public FPOProgramASTVisitor { +public: + FPOProgramASTVisitorMergeDependent( + const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> + &dependent_programs) + : m_dependent_programs(dependent_programs) {} + + void Merge(FPOProgramNode *&node_ref); + +private: + void Visit(FPOProgramNodeRegisterRef *node) override {} + void Visit(FPOProgramNodeIntegerLiteral *node) override {} + void Visit(FPOProgramNodeBinaryOp *node) override; + void Visit(FPOProgramNodeUnaryOp *node) override; + + void TryReplace(FPOProgramNode *&node_ref) const; + +private: + const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs; +}; + +void FPOProgramASTVisitorMergeDependent::Merge(FPOProgramNode *&node_ref) { + TryReplace(node_ref); + node_ref->Accept(this); +} + +void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeBinaryOp *node) { + Merge(node->Left()); + Merge(node->Right()); +} +void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeUnaryOp *node) { + Merge(node->Operand()); +} + +void FPOProgramASTVisitorMergeDependent::TryReplace( + FPOProgramNode *&node_ref) const { + + while (node_ref->GetKind() == FPOProgramNode::Register) { + auto *node_register_ref = + static_cast<FPOProgramNodeRegisterRef *>(node_ref); + + auto it = m_dependent_programs.find(node_register_ref->GetName()); + if (it == m_dependent_programs.end()) { + break; + } + + node_ref = it->second; + } +} + +class FPOProgramASTVisitorResolveRegisterRefs : public FPOProgramASTVisitor { +public: + FPOProgramASTVisitorResolveRegisterRefs( + const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> + &dependent_programs, + llvm::Triple::ArchType arch_type) + : m_dependent_programs(dependent_programs), m_arch_type(arch_type) {} + + bool Resolve(FPOProgramNode *program); + +private: + void Visit(FPOProgramNodeRegisterRef *node) override; + void Visit(FPOProgramNodeIntegerLiteral *node) override {} + void Visit(FPOProgramNodeBinaryOp *node) override; + void Visit(FPOProgramNodeUnaryOp *node) override; + +private: + const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs; + llvm::Triple::ArchType m_arch_type; + bool m_no_error_flag = true; +}; + +bool FPOProgramASTVisitorResolveRegisterRefs::Resolve(FPOProgramNode *program) { + program->Accept(this); + return m_no_error_flag; +} + +void FPOProgramASTVisitorResolveRegisterRefs::Visit( + FPOProgramNodeRegisterRef *node) { + + // lookup register reference as lvalue in predecedent assignments + auto it = m_dependent_programs.find(node->GetName()); + if (it != m_dependent_programs.end()) { + // dependent programs are already resolved and valid + return; + } + // try to resolve register reference as lldb register name + m_no_error_flag = node->ResolveLLDBRegisterNum(m_arch_type); +} + +void FPOProgramASTVisitorResolveRegisterRefs::Visit( + FPOProgramNodeBinaryOp *node) { + m_no_error_flag = Resolve(node->Left()) && Resolve(node->Right()); +} + +void FPOProgramASTVisitorResolveRegisterRefs::Visit( + FPOProgramNodeUnaryOp *node) { + m_no_error_flag = Resolve(node->Operand()); +} + +class FPOProgramASTVisitorDWARFCodegen : public FPOProgramASTVisitor { +public: + FPOProgramASTVisitorDWARFCodegen(Stream &stream) : m_out_stream(stream) {} + + void Emit(FPOProgramNode *program); + +private: + void Visit(FPOProgramNodeRegisterRef *node) override; + void Visit(FPOProgramNodeIntegerLiteral *node) override; + void Visit(FPOProgramNodeBinaryOp *node) override; + void Visit(FPOProgramNodeUnaryOp *node) override; + +private: + Stream &m_out_stream; +}; + +void FPOProgramASTVisitorDWARFCodegen::Emit(FPOProgramNode *program) { + program->Accept(this); +} + +void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeRegisterRef *node) { + + uint32_t reg_num = node->GetLLDBRegNum(); + lldbassert(reg_num != LLDB_INVALID_REGNUM); + + if (reg_num > 31) { + m_out_stream.PutHex8(DW_OP_bregx); + m_out_stream.PutULEB128(reg_num); + } else + m_out_stream.PutHex8(DW_OP_breg0 + reg_num); + + m_out_stream.PutSLEB128(0); +} + +void FPOProgramASTVisitorDWARFCodegen::Visit( + FPOProgramNodeIntegerLiteral *node) { + uint32_t value = node->GetValue(); + m_out_stream.PutHex8(DW_OP_constu); + m_out_stream.PutULEB128(value); +} + +void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeBinaryOp *node) { + + Emit(node->Left()); + Emit(node->Right()); + + switch (node->GetOpType()) { + case FPOProgramNodeBinaryOp::Plus: + m_out_stream.PutHex8(DW_OP_plus); + // NOTE: can be optimized by using DW_OP_plus_uconst opcpode + // if right child node is constant value + break; + case FPOProgramNodeBinaryOp::Minus: + m_out_stream.PutHex8(DW_OP_minus); + break; + case FPOProgramNodeBinaryOp::Align: + // emit align operator a @ b as + // a & ~(b - 1) + // NOTE: implicitly assuming that b is power of 2 + m_out_stream.PutHex8(DW_OP_lit1); + m_out_stream.PutHex8(DW_OP_minus); + m_out_stream.PutHex8(DW_OP_not); + + m_out_stream.PutHex8(DW_OP_and); + break; + } +} + +void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp *node) { + Emit(node->Operand()); + + switch (node->GetOpType()) { + case FPOProgramNodeUnaryOp::Deref: + m_out_stream.PutHex8(DW_OP_deref); + break; + } +} + +class NodeAllocator { +public: + template <typename T, typename... Args> T *makeNode(Args &&... args) { + void *new_node_mem = m_alloc.Allocate(sizeof(T), alignof(T)); + return new (new_node_mem) T(std::forward<Args>(args)...); + } + +private: + llvm::BumpPtrAllocator m_alloc; +}; + +} // namespace + +static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, + NodeAllocator &alloc, + llvm::StringRef ®ister_name, + FPOProgramNode *&ast) { + llvm::SmallVector<llvm::StringRef, 16> tokens; + llvm::SplitString(program, tokens, " "); + + if (tokens.empty()) + return false; + + llvm::SmallVector<FPOProgramNode *, 4> eval_stack; + + llvm::DenseMap<llvm::StringRef, FPOProgramNodeBinaryOp::OpType> ops_binary = { + {"+", FPOProgramNodeBinaryOp::Plus}, + {"-", FPOProgramNodeBinaryOp::Minus}, + {"@", FPOProgramNodeBinaryOp::Align}, + }; + + llvm::DenseMap<llvm::StringRef, FPOProgramNodeUnaryOp::OpType> ops_unary = { + {"^", FPOProgramNodeUnaryOp::Deref}, + }; + + constexpr llvm::StringLiteral ra_search_keyword = ".raSearch"; + + // lvalue of assignment is always first token + // rvalue program goes next + for (size_t i = 1; i < tokens.size(); ++i) { + llvm::StringRef cur = tokens[i]; + + auto ops_binary_it = ops_binary.find(cur); + if (ops_binary_it != ops_binary.end()) { + // token is binary operator + if (eval_stack.size() < 2) { + return false; + } + FPOProgramNode *right = eval_stack.pop_back_val(); + FPOProgramNode *left = eval_stack.pop_back_val(); + FPOProgramNode *node = alloc.makeNode<FPOProgramNodeBinaryOp>( + ops_binary_it->second, left, right); + eval_stack.push_back(node); + continue; + } + + auto ops_unary_it = ops_unary.find(cur); + if (ops_unary_it != ops_unary.end()) { + // token is unary operator + if (eval_stack.empty()) { + return false; + } + FPOProgramNode *operand = eval_stack.pop_back_val(); + FPOProgramNode *node = + alloc.makeNode<FPOProgramNodeUnaryOp>(ops_unary_it->second, operand); + eval_stack.push_back(node); + continue; + } + + if (cur.startswith("$")) { + // token is register ref + eval_stack.push_back(alloc.makeNode<FPOProgramNodeRegisterRef>(cur)); + continue; + } + + if (cur == ra_search_keyword) { + // TODO: .raSearch is unsupported + return false; + } + + uint32_t value; + if (!cur.getAsInteger(10, value)) { + // token is integer literal + eval_stack.push_back(alloc.makeNode<FPOProgramNodeIntegerLiteral>(value)); + continue; + } + + // unexpected token + return false; + } + + if (eval_stack.size() != 1) { + return false; + } + + register_name = tokens[0]; + ast = eval_stack.pop_back_val(); + + return true; +} + +static FPOProgramNode *ParseFPOProgram(llvm::StringRef program, + llvm::StringRef register_name, + llvm::Triple::ArchType arch_type, + NodeAllocator &alloc) { + llvm::DenseMap<llvm::StringRef, FPOProgramNode *> dependent_programs; + + size_t cur = 0; + while (true) { + size_t assign_index = program.find('=', cur); + if (assign_index == llvm::StringRef::npos) { + llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos); + if (!tail.trim().empty()) { + // missing assign operator + return nullptr; + } + break; + } + llvm::StringRef assignment_program = program.slice(cur, assign_index); + + llvm::StringRef lvalue_name; + FPOProgramNode *rvalue_ast = nullptr; + if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name, + rvalue_ast)) { + return nullptr; + } + + lldbassert(rvalue_ast); + + // check & resolve assignment program + FPOProgramASTVisitorResolveRegisterRefs resolver(dependent_programs, + arch_type); + if (!resolver.Resolve(rvalue_ast)) { + return nullptr; + } + + if (lvalue_name == register_name) { + // found target assignment program - no need to parse further + + // emplace valid dependent subtrees to make target assignment independent + // from predecessors + FPOProgramASTVisitorMergeDependent merger(dependent_programs); + merger.Merge(rvalue_ast); + + return rvalue_ast; + } + + dependent_programs[lvalue_name] = rvalue_ast; + cur = assign_index + 1; + } + + return nullptr; +} + +bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( + llvm::StringRef program, llvm::StringRef register_name, + llvm::Triple::ArchType arch_type, Stream &stream) { + NodeAllocator node_alloc; + FPOProgramNode *target_program = + ParseFPOProgram(program, register_name, arch_type, node_alloc); + if (target_program == nullptr) { + return false; + } + + FPOProgramASTVisitorDWARFCodegen codegen(stream); + codegen.Emit(target_program); + return true; +} diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h new file mode 100644 index 00000000000..143914bc1e4 --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h @@ -0,0 +1,29 @@ +//===-- PDBFPOProgramToDWARFExpression.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Plugins_SymbolFile_PDB_PDBFPOProgramToDWARFExpression_h_ +#define lldb_Plugins_SymbolFile_PDB_PDBFPOProgramToDWARFExpression_h_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" + +namespace lldb_private { +class Stream; + +namespace npdb { + +bool TranslateFPOProgramToDWARFExpression(llvm::StringRef program, + llvm::StringRef register_name, + llvm::Triple::ArchType arch_type, + lldb_private::Stream &stream); + +} // namespace npdb +} // namespace lldb_private + +#endif diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h index 72f6effa222..b30e7870bbd 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h @@ -114,6 +114,7 @@ public: create(std::unique_ptr<llvm::pdb::PDBFile>); void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; } + lldb::addr_t GetLoadAddress() const { return m_load_address; } void ParseSectionContribs(); llvm::pdb::PDBFile &pdb() { return *m_file; } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 0677554c4cf..4a605d02ed1 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -14,9 +14,11 @@ #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" +#include "lldb/Symbol/Block.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/lldb-enumerations.h" @@ -42,7 +44,7 @@ MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range, gaps = gaps.drop_front(); } - result.Append(start, end); + result.Append(start, end - start); return result; } @@ -506,8 +508,78 @@ VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) { return {}; } +static auto +GetCorrespondingFrameData(lldb::addr_t load_addr, + const DebugFrameDataSubsectionRef &fpo_data, + const Variable::RangeList &ranges) { + lldbassert(!ranges.IsEmpty()); + + // assume that all variable ranges correspond to one frame data + using RangeListEntry = Variable::RangeList::Entry; + const RangeListEntry &range = ranges.GetEntryRef(0); + + auto it = fpo_data.begin(); + + // start by searching first frame data range containing variable range + for (; it != fpo_data.end(); ++it) { + RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize); + + if (fd_range.Contains(range)) { + break; + } + } + + // then first most nested entry that still contains variable range + auto found = it; + for (; it != fpo_data.end(); ++it) { + RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize); + + if (!fd_range.Contains(range)) { + break; + } + found = it; + } + + return found; +} + +static bool GetFrameDataProgram(PdbIndex &index, + const Variable::RangeList &ranges, + llvm::StringRef &out_program) { + const DebugFrameDataSubsectionRef &new_fpo_data = + index.dbi().getNewFpoRecords(); + + auto frame_data_it = + GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges); + if (frame_data_it == new_fpo_data.end()) + return false; + + PDBStringTable &strings = cantFail(index.pdb().getStringTable()); + out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc)); + return true; +} + +static RegisterId GetBaseFrameRegister(PdbIndex &index, + PdbCompilandSymId frame_proc_id, + bool is_parameter) { + CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id); + lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC); + + FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym); + cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs, + frame_proc)); + + CPUType cpu_type = index.compilands() + .GetCompiland(frame_proc_id.modi) + ->m_compile_opts->Machine; + + return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type) + : frame_proc.getLocalFramePtrReg(cpu_type); +} + VariableInfo lldb_private::npdb::GetVariableLocationInfo( - PdbIndex &index, PdbCompilandSymId var_id, lldb::ModuleSP module) { + PdbIndex &index, PdbCompilandSymId var_id, Block &block, + lldb::ModuleSP module) { CVSymbol sym = index.ReadSymbolRecord(var_id); @@ -542,13 +614,69 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( SymbolRecordKind::DefRangeFramePointerRelSym); cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>( loc_specifier_cvs, loc)); - // FIXME: The register needs to come from the S_FRAMEPROC symbol. - result.location = - MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module); - result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); - } else { - // FIXME: Handle other kinds + + Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); + + // TODO: may be better to pass function scope and not lookup it every + // time? find nearest parent function block + Block *cur = █ + while (cur->GetParent()) { + cur = cur->GetParent(); + } + PdbCompilandSymId func_scope_id = + PdbSymUid(cur->GetID()).asCompilandSym(); + CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id); + lldbassert(func_block_cvs.kind() == S_GPROC32 || + func_block_cvs.kind() == S_LPROC32); + + PdbCompilandSymId frame_proc_id( + func_scope_id.modi, func_scope_id.offset + func_block_cvs.length()); + + bool is_parameter = + ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None); + RegisterId base_reg = + GetBaseFrameRegister(index, frame_proc_id, is_parameter); + + if (base_reg == RegisterId::VFRAME) { + llvm::StringRef program; + if (GetFrameDataProgram(index, ranges, program)) { + result.location = + MakeVFrameRelLocationExpression(program, loc.Offset, module); + result.ranges = std::move(ranges); + } else { + // invalid variable + } + } else { + result.location = + MakeRegRelLocationExpression(base_reg, loc.Offset, module); + result.ranges = std::move(ranges); + } + } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) { + DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym); + cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>( + loc_specifier_cvs, loc)); + + Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); + + RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register; + + if (base_reg == RegisterId::VFRAME) { + llvm::StringRef program; + if (GetFrameDataProgram(index, ranges, program)) { + result.location = MakeVFrameRelLocationExpression( + program, loc.Hdr.BasePointerOffset, module); + result.ranges = std::move(ranges); + } else { + // invalid variable + } + } else { + result.location = MakeRegRelLocationExpression( + base_reg, loc.Hdr.BasePointerOffset, module); + result.ranges = std::move(ranges); + } } + + // FIXME: Handle other kinds return result; } llvm_unreachable("Symbol is not a local variable!"); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h index 46ae4912c1b..6f675b56dca 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h @@ -141,7 +141,7 @@ LookThroughModifierRecord(llvm::codeview::CVType modifier); llvm::StringRef DropNameScope(llvm::StringRef name); VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol); -VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, +VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, Block& block, lldb::ModuleSP module); size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 6165dd81259..fecae7af0e1 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1315,7 +1315,9 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) { ModuleSP module = GetObjectFile()->GetModule(); - VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module); + Block &block = GetOrCreateBlock(scope_id); + VariableInfo var_info = + GetVariableLocationInfo(*m_index, var_id, block, module); if (!var_info.location || !var_info.ranges) return nullptr; diff --git a/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt index 19698a7187f..64168d056ce 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt @@ -8,7 +8,7 @@ add_lldb_library(lldbPluginSymbolFilePDB PLUGIN clangLex lldbCore lldbSymbol - lldbUtility + lldbUtility lldbPluginSymbolFileNativePDB LINK_COMPONENTS DebugInfoPDB diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp index f57c3b6cb8e..0026aaeee98 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp @@ -12,483 +12,60 @@ #include "lldb/Core/StreamBuffer.h" #include "lldb/Core/dwarf.h" #include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/Variable.h" #include "lldb/Utility/DataBufferHeap.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "Plugins/Process/Utility/lldb-x86-register-enums.h" +#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h" +#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h" using namespace lldb; using namespace lldb_private; +using namespace lldb_private::npdb; using namespace llvm::pdb; -namespace { -const uint32_t g_code_view_to_lldb_registers_x86[] = { - LLDB_INVALID_REGNUM, // NONE - lldb_al_i386, // AL - lldb_cl_i386, // CL - lldb_dl_i386, // DL - lldb_bl_i386, // BL - lldb_ah_i386, // AH - lldb_ch_i386, // CH - lldb_dh_i386, // DH - lldb_bh_i386, // BH - lldb_ax_i386, // AX - lldb_cx_i386, // CX - lldb_dx_i386, // DX - lldb_bx_i386, // BX - lldb_sp_i386, // SP - lldb_bp_i386, // BP - lldb_si_i386, // SI - lldb_di_i386, // DI - lldb_eax_i386, // EAX - lldb_ecx_i386, // ECX - lldb_edx_i386, // EDX - lldb_ebx_i386, // EBX - lldb_esp_i386, // ESP - lldb_ebp_i386, // EBP - lldb_esi_i386, // ESI - lldb_edi_i386, // EDI - lldb_es_i386, // ES - lldb_cs_i386, // CS - lldb_ss_i386, // SS - lldb_ds_i386, // DS - lldb_fs_i386, // FS - lldb_gs_i386, // GS - LLDB_INVALID_REGNUM, // IP - LLDB_INVALID_REGNUM, // FLAGS - lldb_eip_i386, // EIP - lldb_eflags_i386, // EFLAGS - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // TEMP - LLDB_INVALID_REGNUM, // TEMPH - LLDB_INVALID_REGNUM, // QUOTE - LLDB_INVALID_REGNUM, // PCDR3 - LLDB_INVALID_REGNUM, // PCDR4 - LLDB_INVALID_REGNUM, // PCDR5 - LLDB_INVALID_REGNUM, // PCDR6 - LLDB_INVALID_REGNUM, // PCDR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CR0 - LLDB_INVALID_REGNUM, // CR1 - LLDB_INVALID_REGNUM, // CR2 - LLDB_INVALID_REGNUM, // CR3 - LLDB_INVALID_REGNUM, // CR4 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_i386, // DR0 - lldb_dr1_i386, // DR1 - lldb_dr2_i386, // DR2 - lldb_dr3_i386, // DR3 - lldb_dr4_i386, // DR4 - lldb_dr5_i386, // DR5 - lldb_dr6_i386, // DR6 - lldb_dr7_i386, // DR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // GDTR - LLDB_INVALID_REGNUM, // GDTL - LLDB_INVALID_REGNUM, // IDTR - LLDB_INVALID_REGNUM, // IDTL - LLDB_INVALID_REGNUM, // LDTR - LLDB_INVALID_REGNUM, // TR - LLDB_INVALID_REGNUM, // PSEUDO1 - LLDB_INVALID_REGNUM, // PSEUDO2 - LLDB_INVALID_REGNUM, // PSEUDO3 - LLDB_INVALID_REGNUM, // PSEUDO4 - LLDB_INVALID_REGNUM, // PSEUDO5 - LLDB_INVALID_REGNUM, // PSEUDO6 - LLDB_INVALID_REGNUM, // PSEUDO7 - LLDB_INVALID_REGNUM, // PSEUDO8 - LLDB_INVALID_REGNUM, // PSEUDO9 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_i386, // ST0 - lldb_st1_i386, // ST1 - lldb_st2_i386, // ST2 - lldb_st3_i386, // ST3 - lldb_st4_i386, // ST4 - lldb_st5_i386, // ST5 - lldb_st6_i386, // ST6 - lldb_st7_i386, // ST7 - LLDB_INVALID_REGNUM, // CTRL - LLDB_INVALID_REGNUM, // STAT - LLDB_INVALID_REGNUM, // TAG - LLDB_INVALID_REGNUM, // FPIP - LLDB_INVALID_REGNUM, // FPCS - LLDB_INVALID_REGNUM, // FPDO - LLDB_INVALID_REGNUM, // FPDS - LLDB_INVALID_REGNUM, // ISEM - LLDB_INVALID_REGNUM, // FPEIP - LLDB_INVALID_REGNUM, // FPEDO - lldb_mm0_i386, // MM0 - lldb_mm1_i386, // MM1 - lldb_mm2_i386, // MM2 - lldb_mm3_i386, // MM3 - lldb_mm4_i386, // MM4 - lldb_mm5_i386, // MM5 - lldb_mm6_i386, // MM6 - lldb_mm7_i386, // MM7 - lldb_xmm0_i386, // XMM0 - lldb_xmm1_i386, // XMM1 - lldb_xmm2_i386, // XMM2 - lldb_xmm3_i386, // XMM3 - lldb_xmm4_i386, // XMM4 - lldb_xmm5_i386, // XMM5 - lldb_xmm6_i386, // XMM6 - lldb_xmm7_i386 // XMM7 -}; - -const uint32_t g_code_view_to_lldb_registers_x86_64[] = { - LLDB_INVALID_REGNUM, // NONE - lldb_al_x86_64, // AL - lldb_cl_x86_64, // CL - lldb_dl_x86_64, // DL - lldb_bl_x86_64, // BL - lldb_ah_x86_64, // AH - lldb_ch_x86_64, // CH - lldb_dh_x86_64, // DH - lldb_bh_x86_64, // BH - lldb_ax_x86_64, // AX - lldb_cx_x86_64, // CX - lldb_dx_x86_64, // DX - lldb_bx_x86_64, // BX - lldb_sp_x86_64, // SP - lldb_bp_x86_64, // BP - lldb_si_x86_64, // SI - lldb_di_x86_64, // DI - lldb_eax_x86_64, // EAX - lldb_ecx_x86_64, // ECX - lldb_edx_x86_64, // EDX - lldb_ebx_x86_64, // EBX - lldb_esp_x86_64, // ESP - lldb_ebp_x86_64, // EBP - lldb_esi_x86_64, // ESI - lldb_edi_x86_64, // EDI - lldb_es_x86_64, // ES - lldb_cs_x86_64, // CS - lldb_ss_x86_64, // SS - lldb_ds_x86_64, // DS - lldb_fs_x86_64, // FS - lldb_gs_x86_64, // GS - LLDB_INVALID_REGNUM, // IP - LLDB_INVALID_REGNUM, // FLAGS - LLDB_INVALID_REGNUM, // EIP - LLDB_INVALID_REGNUM, // EFLAGS - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // TEMP - LLDB_INVALID_REGNUM, // TEMPH - LLDB_INVALID_REGNUM, // QUOTE - LLDB_INVALID_REGNUM, // PCDR3 - LLDB_INVALID_REGNUM, // PCDR4 - LLDB_INVALID_REGNUM, // PCDR5 - LLDB_INVALID_REGNUM, // PCDR6 - LLDB_INVALID_REGNUM, // PCDR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CR0 - LLDB_INVALID_REGNUM, // CR1 - LLDB_INVALID_REGNUM, // CR2 - LLDB_INVALID_REGNUM, // CR3 - LLDB_INVALID_REGNUM, // CR4 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_x86_64, // DR0 - lldb_dr1_x86_64, // DR1 - lldb_dr2_x86_64, // DR2 - lldb_dr3_x86_64, // DR3 - lldb_dr4_x86_64, // DR4 - lldb_dr5_x86_64, // DR5 - lldb_dr6_x86_64, // DR6 - lldb_dr7_x86_64, // DR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // GDTR - LLDB_INVALID_REGNUM, // GDTL - LLDB_INVALID_REGNUM, // IDTR - LLDB_INVALID_REGNUM, // IDTL - LLDB_INVALID_REGNUM, // LDTR - LLDB_INVALID_REGNUM, // TR - LLDB_INVALID_REGNUM, // PSEUDO1 - LLDB_INVALID_REGNUM, // PSEUDO2 - LLDB_INVALID_REGNUM, // PSEUDO3 - LLDB_INVALID_REGNUM, // PSEUDO4 - LLDB_INVALID_REGNUM, // PSEUDO5 - LLDB_INVALID_REGNUM, // PSEUDO6 - LLDB_INVALID_REGNUM, // PSEUDO7 - LLDB_INVALID_REGNUM, // PSEUDO8 - LLDB_INVALID_REGNUM, // PSEUDO9 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_x86_64, // ST0 - lldb_st1_x86_64, // ST1 - lldb_st2_x86_64, // ST2 - lldb_st3_x86_64, // ST3 - lldb_st4_x86_64, // ST4 - lldb_st5_x86_64, // ST5 - lldb_st6_x86_64, // ST6 - lldb_st7_x86_64, // ST7 - LLDB_INVALID_REGNUM, // CTRL - LLDB_INVALID_REGNUM, // STAT - LLDB_INVALID_REGNUM, // TAG - LLDB_INVALID_REGNUM, // FPIP - LLDB_INVALID_REGNUM, // FPCS - LLDB_INVALID_REGNUM, // FPDO - LLDB_INVALID_REGNUM, // FPDS - LLDB_INVALID_REGNUM, // ISEM - LLDB_INVALID_REGNUM, // FPEIP - LLDB_INVALID_REGNUM, // FPEDO - lldb_mm0_x86_64, // MM0 - lldb_mm1_x86_64, // MM1 - lldb_mm2_x86_64, // MM2 - lldb_mm3_x86_64, // MM3 - lldb_mm4_x86_64, // MM4 - lldb_mm5_x86_64, // MM5 - lldb_mm6_x86_64, // MM6 - lldb_mm7_x86_64, // MM7 - lldb_xmm0_x86_64, // XMM0 - lldb_xmm1_x86_64, // XMM1 - lldb_xmm2_x86_64, // XMM2 - lldb_xmm3_x86_64, // XMM3 - lldb_xmm4_x86_64, // XMM4 - lldb_xmm5_x86_64, // XMM5 - lldb_xmm6_x86_64, // XMM6 - lldb_xmm7_x86_64, // XMM7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - lldb_mxcsr_x86_64, // MXCSR - LLDB_INVALID_REGNUM, // EDXEAX - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // EMM0L - LLDB_INVALID_REGNUM, // EMM1L - LLDB_INVALID_REGNUM, // EMM2L - LLDB_INVALID_REGNUM, // EMM3L - LLDB_INVALID_REGNUM, // EMM4L - LLDB_INVALID_REGNUM, // EMM5L - LLDB_INVALID_REGNUM, // EMM6L - LLDB_INVALID_REGNUM, // EMM7L - LLDB_INVALID_REGNUM, // EMM0H - LLDB_INVALID_REGNUM, // EMM1H - LLDB_INVALID_REGNUM, // EMM2H - LLDB_INVALID_REGNUM, // EMM3H - LLDB_INVALID_REGNUM, // EMM4H - LLDB_INVALID_REGNUM, // EMM5H - LLDB_INVALID_REGNUM, // EMM6H - LLDB_INVALID_REGNUM, // EMM7H - LLDB_INVALID_REGNUM, // MM00 - LLDB_INVALID_REGNUM, // MM01 - LLDB_INVALID_REGNUM, // MM10 - LLDB_INVALID_REGNUM, // MM11 - LLDB_INVALID_REGNUM, // MM20 - LLDB_INVALID_REGNUM, // MM21 - LLDB_INVALID_REGNUM, // MM30 - LLDB_INVALID_REGNUM, // MM31 - LLDB_INVALID_REGNUM, // MM40 - LLDB_INVALID_REGNUM, // MM41 - LLDB_INVALID_REGNUM, // MM50 - LLDB_INVALID_REGNUM, // MM51 - LLDB_INVALID_REGNUM, // MM60 - LLDB_INVALID_REGNUM, // MM61 - LLDB_INVALID_REGNUM, // MM70 - LLDB_INVALID_REGNUM, // MM71 - lldb_xmm8_x86_64, // XMM8 - lldb_xmm9_x86_64, // XMM9 - lldb_xmm10_x86_64, // XMM10 - lldb_xmm11_x86_64, // XMM11 - lldb_xmm12_x86_64, // XMM12 - lldb_xmm13_x86_64, // XMM13 - lldb_xmm14_x86_64, // XMM14 - lldb_xmm15_x86_64, // XMM15 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - lldb_sil_x86_64, // SIL - lldb_dil_x86_64, // DIL - lldb_bpl_x86_64, // BPL - lldb_spl_x86_64, // SPL - lldb_rax_x86_64, // RAX - lldb_rbx_x86_64, // RBX - lldb_rcx_x86_64, // RCX - lldb_rdx_x86_64, // RDX - lldb_rsi_x86_64, // RSI - lldb_rdi_x86_64, // RDI - lldb_rbp_x86_64, // RBP - lldb_rsp_x86_64, // RSP - lldb_r8_x86_64, // R8 - lldb_r9_x86_64, // R9 - lldb_r10_x86_64, // R10 - lldb_r11_x86_64, // R11 - lldb_r12_x86_64, // R12 - lldb_r13_x86_64, // R13 - lldb_r14_x86_64, // R14 - lldb_r15_x86_64, // R15 - lldb_r8l_x86_64, // R8B - lldb_r9l_x86_64, // R9B - lldb_r10l_x86_64, // R10B - lldb_r11l_x86_64, // R11B - lldb_r12l_x86_64, // R12B - lldb_r13l_x86_64, // R13B - lldb_r14l_x86_64, // R14B - lldb_r15l_x86_64, // R15B - lldb_r8w_x86_64, // R8W - lldb_r9w_x86_64, // R9W - lldb_r10w_x86_64, // R10W - lldb_r11w_x86_64, // R11W - lldb_r12w_x86_64, // R12W - lldb_r13w_x86_64, // R13W - lldb_r14w_x86_64, // R14W - lldb_r15w_x86_64, // R15W - lldb_r8d_x86_64, // R8D - lldb_r9d_x86_64, // R9D - lldb_r10d_x86_64, // R10D - lldb_r11d_x86_64, // R11D - lldb_r12d_x86_64, // R12D - lldb_r13d_x86_64, // R13D - lldb_r14d_x86_64, // R14D - lldb_r15d_x86_64, // R15D - lldb_ymm0_x86_64, // AMD64_YMM0 - lldb_ymm1_x86_64, // AMD64_YMM1 - lldb_ymm2_x86_64, // AMD64_YMM2 - lldb_ymm3_x86_64, // AMD64_YMM3 - lldb_ymm4_x86_64, // AMD64_YMM4 - lldb_ymm5_x86_64, // AMD64_YMM5 - lldb_ymm6_x86_64, // AMD64_YMM6 - lldb_ymm7_x86_64, // AMD64_YMM7 - lldb_ymm8_x86_64, // AMD64_YMM8 - lldb_ymm9_x86_64, // AMD64_YMM9 - lldb_ymm10_x86_64, // AMD64_YMM10 - lldb_ymm11_x86_64, // AMD64_YMM11 - lldb_ymm12_x86_64, // AMD64_YMM12 - lldb_ymm13_x86_64, // AMD64_YMM13 - lldb_ymm14_x86_64, // AMD64_YMM14 - lldb_ymm15_x86_64, // AMD64_YMM15 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_bnd0_x86_64, // BND0 - lldb_bnd1_x86_64, // BND1 - lldb_bnd2_x86_64 // BND2 -}; - -uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, - llvm::codeview::RegisterId register_id) { - switch (arch_type) { - case llvm::Triple::x86: - if (static_cast<uint16_t>(register_id) < - sizeof(g_code_view_to_lldb_registers_x86) / - sizeof(g_code_view_to_lldb_registers_x86[0])) - return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>( - register_id)]; - - switch (register_id) { - case llvm::codeview::RegisterId::MXCSR: - return lldb_mxcsr_i386; - case llvm::codeview::RegisterId::BND0: - return lldb_bnd0_i386; - case llvm::codeview::RegisterId::BND1: - return lldb_bnd1_i386; - case llvm::codeview::RegisterId::BND2: - return lldb_bnd2_i386; - default: - return LLDB_INVALID_REGNUM; +static std::unique_ptr<IPDBFrameData> +GetCorrespondingFrameData(const IPDBSession &session, + const Variable::RangeList &ranges) { + auto enumFrameData = session.getFrameData(); + if (!enumFrameData) + return nullptr; + + std::unique_ptr<IPDBFrameData> found; + while (auto fd = enumFrameData->getNext()) { + Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(), + fd->getLengthBlock()); + + for (size_t i = 0; i < ranges.GetSize(); i++) { + auto range = ranges.GetEntryAtIndex(i); + if (!range) + continue; + + if (!range->DoesIntersect(fdRange)) + continue; + + found = std::move(fd); + + break; } - case llvm::Triple::x86_64: - if (static_cast<uint16_t>(register_id) < - sizeof(g_code_view_to_lldb_registers_x86_64) / - sizeof(g_code_view_to_lldb_registers_x86_64[0])) - return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>( - register_id)]; - - return LLDB_INVALID_REGNUM; - default: - return LLDB_INVALID_REGNUM; } -} - -uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) { - if (register_id == llvm::codeview::RegisterId::VFRAME) - return LLDB_REGNUM_GENERIC_FP; - return LLDB_INVALID_REGNUM; + return found; } -uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type, - llvm::codeview::RegisterId register_id, - RegisterKind ®ister_kind) { - register_kind = eRegisterKindLLDB; - uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id); - if (reg_num != LLDB_INVALID_REGNUM) - return reg_num; - - register_kind = eRegisterKindGeneric; - return GetGenericRegisterNumber(register_id); +static bool EmitVFrameEvaluationDWARFExpression( + llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) { + // VFrame value always stored in $TO pseudo-register + return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type, + stream); } -} // namespace -DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, - const PDBSymbolData &symbol, - bool &is_constant) { +DWARFExpression ConvertPDBLocationToDWARFExpression( + ModuleSP module, const PDBSymbolData &symbol, + const Variable::RangeList &ranges, bool &is_constant) { is_constant = true; if (!module) @@ -530,10 +107,32 @@ DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, break; } case PDB_LocType::RegRel: { - uint32_t reg_num = - GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind); - if (reg_num == LLDB_INVALID_REGNUM) - return DWARFExpression(nullptr); + uint32_t reg_num; + auto reg_id = symbol.getRegisterId(); + if (reg_id == llvm::codeview::RegisterId::VFRAME) { + if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) { + if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type, + stream)) { + int32_t offset = symbol.getOffset(); + stream.PutHex8(DW_OP_consts); + stream.PutSLEB128(offset); + stream.PutHex8(DW_OP_plus); + + register_kind = eRegisterKindLLDB; + + is_constant = false; + break; + } + } + + register_kind = eRegisterKindGeneric; + reg_num = LLDB_REGNUM_GENERIC_FP; + } else { + register_kind = eRegisterKindLLDB; + reg_num = GetLLDBRegisterNumber(arch_type, reg_id); + if (reg_num == LLDB_INVALID_REGNUM) + return DWARFExpression(nullptr); + } if (reg_num > 31) { stream.PutHex8(DW_OP_bregx); @@ -549,8 +148,8 @@ DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, break; } case PDB_LocType::Enregistered: { - uint32_t reg_num = - GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind); + register_kind = eRegisterKindLLDB; + uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId()); if (reg_num == LLDB_INVALID_REGNUM) return DWARFExpression(nullptr); diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h b/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h index 7c34512e5f3..f984eecc9fe 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h @@ -10,6 +10,7 @@ #define lldb_Plugins_SymbolFile_PDB_PDBLocationToDWARFExpression_h_ #include "lldb/Core/Module.h" +#include "lldb/Symbol/Variable.h" namespace lldb_private { class DWARFExpression; @@ -30,6 +31,9 @@ class PDBSymbolData; /// @param[in] symbol /// The symbol with a location information to convert. /// +/// @param[in] ranges +/// Ranges where this variable is valid. +/// /// @param[out] is_constant /// Set to \b true if the result expression is a constant value data, /// and \b false if it is a DWARF bytecode. @@ -40,5 +44,6 @@ class PDBSymbolData; lldb_private::DWARFExpression ConvertPDBLocationToDWARFExpression(lldb::ModuleSP module, const llvm::pdb::PDBSymbolData &symbol, + const lldb_private::Variable::RangeList &ranges, bool &is_constant); #endif diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 6f3a1beb50a..368b15680b3 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -933,12 +933,25 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData( Variable::RangeList ranges; SymbolContextScope *context_scope = sc.comp_unit; - if (scope == eValueTypeVariableLocal) { + if (scope == eValueTypeVariableLocal || scope == eValueTypeVariableArgument) { if (sc.function) { - context_scope = sc.function->GetBlock(true).FindBlockByID( - pdb_data.getLexicalParentId()); - if (context_scope == nullptr) - context_scope = sc.function; + Block &function_block = sc.function->GetBlock(true); + Block *block = + function_block.FindBlockByID(pdb_data.getLexicalParentId()); + if (!block) + block = &function_block; + + context_scope = block; + + for (size_t i = 0, num_ranges = block->GetNumRanges(); i < num_ranges; + ++i) { + AddressRange range; + if (!block->GetRangeAtIndex(i, range)) + continue; + + ranges.Append(range.GetBaseAddress().GetFileAddress(), + range.GetByteSize()); + } } } @@ -951,7 +964,7 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData( bool is_constant; DWARFExpression location = ConvertPDBLocationToDWARFExpression( - GetObjectFile()->GetModule(), pdb_data, is_constant); + GetObjectFile()->GetModule(), pdb_data, ranges, is_constant); var_sp = std::make_shared<Variable>( var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope, diff --git a/lldb/unittests/SymbolFile/CMakeLists.txt b/lldb/unittests/SymbolFile/CMakeLists.txt index cc12e467905..804555f8c90 100644 --- a/lldb/unittests/SymbolFile/CMakeLists.txt +++ b/lldb/unittests/SymbolFile/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(DWARF) +add_subdirectory(NativePDB) if (LLVM_ENABLE_DIA_SDK) add_subdirectory(PDB) endif() diff --git a/lldb/unittests/SymbolFile/NativePDB/CMakeLists.txt b/lldb/unittests/SymbolFile/NativePDB/CMakeLists.txt new file mode 100644 index 00000000000..b82199f21dd --- /dev/null +++ b/lldb/unittests/SymbolFile/NativePDB/CMakeLists.txt @@ -0,0 +1,13 @@ +add_lldb_unittest(SymbolFileNativePDBTests + PdbFPOProgramToDWARFExpressionTests.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbPluginSymbolFileNativePDB + lldbUtilityHelpers + LINK_COMPONENTS + Support + DebugInfoPDB + ) diff --git a/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp b/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp new file mode 100644 index 00000000000..9721e6de990 --- /dev/null +++ b/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp @@ -0,0 +1,166 @@ +//===-- PDBFPOProgramToDWARFExpressionTests.cpp -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h" + +#include "lldb/Core/StreamBuffer.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/StreamString.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::npdb; + +/// Valid programs tests + +static void +CheckValidProgramTranslation(llvm::StringRef fpo_program, + llvm::StringRef target_register_name, + llvm::StringRef expected_dwarf_expression) { + // initial setup + ArchSpec arch_spec("i686-pc-windows"); + llvm::Triple::ArchType arch_type = arch_spec.GetMachine(); + ByteOrder byte_order = arch_spec.GetByteOrder(); + uint32_t address_size = arch_spec.GetAddressByteSize(); + uint32_t byte_size = arch_spec.GetDataByteSize(); + + // program translation + StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); + ASSERT_TRUE(TranslateFPOProgramToDWARFExpression( + fpo_program, target_register_name, arch_type, stream)); + + // print dwarf expression to comparable textual representation + DataBufferSP buffer = + std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); + DataExtractor extractor(buffer, byte_order, address_size, byte_size); + + StreamString result_dwarf_expression; + ASSERT_TRUE(DWARFExpression::PrintDWARFExpression( + result_dwarf_expression, extractor, address_size, 4, false)); + + // actual check + ASSERT_STREQ(expected_dwarf_expression.data(), + result_dwarf_expression.GetString().data()); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentConst) { + CheckValidProgramTranslation("$T0 0 = ", "$T0", "DW_OP_constu 0x0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentRegisterRef) { + CheckValidProgramTranslation("$T0 $ebp = ", "$T0", "DW_OP_breg6 +0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionPlus) { + CheckValidProgramTranslation("$T0 $ebp 4 + = ", "$T0", + "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_plus "); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionDeref) { + CheckValidProgramTranslation("$T0 $ebp ^ = ", "$T0", + "DW_OP_breg6 +0, DW_OP_deref "); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionMinus) { + CheckValidProgramTranslation( + "$T0 $ebp 4 - = ", "$T0", + "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_minus "); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionAlign) { + CheckValidProgramTranslation("$T0 $ebp 128 @ = ", "$T0", + "DW_OP_breg6 +0, DW_OP_constu 0x80, DW_OP_lit1 " + ", DW_OP_minus , DW_OP_not , DW_OP_and "); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, MultipleIndependentAssignments) { + CheckValidProgramTranslation("$T1 1 = $T0 0 =", "$T0", "DW_OP_constu 0x0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, MultipleDependentAssignments) { + CheckValidProgramTranslation( + "$T1 $ebp 4 + = $T0 $T1 8 - 128 @ = ", "$T0", + "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_plus , DW_OP_constu 0x8, " + "DW_OP_minus , DW_OP_constu 0x80, DW_OP_lit1 , DW_OP_minus , DW_OP_not , " + "DW_OP_and "); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, DependencyChain) { + CheckValidProgramTranslation("$T1 0 = $T0 $T1 = $ebp $T0 =", "$ebp", + "DW_OP_constu 0x0"); +} + +/// Invalid programs tests +static void +CheckInvalidProgramTranslation(llvm::StringRef fpo_program, + llvm::StringRef target_register_name) { + // initial setup + ArchSpec arch_spec("i686-pc-windows"); + llvm::Triple::ArchType arch_type = arch_spec.GetMachine(); + ByteOrder byte_order = arch_spec.GetByteOrder(); + uint32_t address_size = arch_spec.GetAddressByteSize(); + + // program translation + StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); + EXPECT_FALSE(TranslateFPOProgramToDWARFExpression( + fpo_program, target_register_name, arch_type, stream)); + EXPECT_EQ(0, stream.GetSize()); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentSingle) { + CheckInvalidProgramTranslation("$T0 0", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentMultiple) { + CheckInvalidProgramTranslation("$T1 0 = $T0 0", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, UnknownOp) { + CheckInvalidProgramTranslation("$T0 $ebp 0 & = ", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpBinary) { + CheckInvalidProgramTranslation("$T0 0 + = ", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpUnary) { + CheckInvalidProgramTranslation("$T0 ^ = ", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, MissingTargetRegister) { + CheckInvalidProgramTranslation("$T1 0 = ", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, UnresolvedRegisterReference) { + CheckInvalidProgramTranslation("$T0 $abc = ", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, + UnresolvedRegisterAssignmentReference) { + CheckInvalidProgramTranslation("$T2 0 = $T0 $T1 = ", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, + UnresolvedCyclicRegisterAssignmentReference) { + CheckInvalidProgramTranslation("$T1 $T0 = $T0 $T1 = ", "$T0"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, + UnresolvedDependentCyclicRegisterAssignmentReference) { + CheckInvalidProgramTranslation("$T1 $T0 = $T0 $T1 = $T2 $T1 =", "$T2"); +} + +TEST(PDBFPOProgramToDWARFExpressionTests, UnsupportedRASearch) { + CheckInvalidProgramTranslation("$T0 .raSearch = ", "$T0"); +} |