Index: lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp =================================================================== --- lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp +++ lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp @@ -5,11 +5,22 @@ 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; } Index: lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script =================================================================== --- lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script +++ 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 variable loc_0 frame variable loc_1 + +continue + +frame variable arg_0 + +frame variable loc_0 +frame variable loc_1 + Index: lit/SymbolFile/PDB/variables-locations.test =================================================================== --- lit/SymbolFile/PDB/variables-locations.test +++ 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_0 = true CHECK: loc_1 = 3333 + +CHECK: arg_0 = 22 + +CHECK: loc_0 = (a = 1234) +CHECK: loc_1 = 5678 Index: source/Expression/DWARFExpression.cpp =================================================================== --- source/Expression/DWARFExpression.cpp +++ source/Expression/DWARFExpression.cpp @@ -3203,7 +3203,7 @@ break; default: s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); - return true; + return false; } switch (size) { @@ -3249,7 +3249,7 @@ break; } - return false; + return true; } bool DWARFExpression::PrintDWARFExpression(Stream &s, const DataExtractor &data, Index: source/Plugins/SymbolFile/NativePDB/CMakeLists.txt =================================================================== --- source/Plugins/SymbolFile/NativePDB/CMakeLists.txt +++ 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 @@ clangLex lldbCore lldbSymbol - lldbUtility + lldbUtility LINK_COMPONENTS DebugInfoCodeView DebugInfoPDB Index: source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h =================================================================== --- /dev/null +++ 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 Index: source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp =================================================================== --- /dev/null +++ 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(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( + 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(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( + register_id)]; + + return LLDB_INVALID_REGNUM; + default: + return LLDB_INVALID_REGNUM; + } +} Index: source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h =================================================================== --- source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h +++ source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h @@ -30,6 +30,9 @@ 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( Index: source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp =================================================================== --- source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ 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 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(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( - 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(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( - 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 @@ 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); Index: source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h =================================================================== --- /dev/null +++ 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 Index: source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp =================================================================== --- /dev/null +++ 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> register_names = + llvm::codeview::getRegisterNames(); + auto it = llvm::find_if( + register_names, + [®_name](const llvm::EnumEntry ®ister_entry) { + return reg_name.compare_lower(register_entry.Name) == 0; + }); + + if (it == register_names.end()) { + return false; + } + + auto reg_id = static_cast(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 + &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 &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(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 + &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 &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 T *makeNode(Args &&... args) { + void *new_node_mem = m_alloc.Allocate(sizeof(T), alignof(T)); + return new (new_node_mem) T(std::forward(args)...); + } + +private: + llvm::BumpPtrAllocator m_alloc; +}; + +} // namespace + +static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, + NodeAllocator &alloc, + llvm::StringRef ®ister_name, + FPOProgramNode *&ast) { + llvm::SmallVector tokens; + llvm::SplitString(program, tokens, " "); + + if (tokens.empty()) + return false; + + llvm::SmallVector eval_stack; + + llvm::DenseMap ops_binary = { + {"+", FPOProgramNodeBinaryOp::Plus}, + {"-", FPOProgramNodeBinaryOp::Minus}, + {"@", FPOProgramNodeBinaryOp::Align}, + }; + + llvm::DenseMap 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( + 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(ops_unary_it->second, operand); + eval_stack.push_back(node); + continue; + } + + if (cur.startswith("$")) { + // token is register ref + eval_stack.push_back(alloc.makeNode(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(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 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; +} Index: source/Plugins/SymbolFile/NativePDB/PdbIndex.h =================================================================== --- source/Plugins/SymbolFile/NativePDB/PdbIndex.h +++ source/Plugins/SymbolFile/NativePDB/PdbIndex.h @@ -114,6 +114,7 @@ create(std::unique_ptr); 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; } Index: source/Plugins/SymbolFile/NativePDB/PdbUtil.h =================================================================== --- source/Plugins/SymbolFile/NativePDB/PdbUtil.h +++ source/Plugins/SymbolFile/NativePDB/PdbUtil.h @@ -141,7 +141,7 @@ 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); Index: source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp =================================================================== --- source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ 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 @@ gaps = gaps.drop_front(); } - result.Append(start, end); + result.Append(start, end - start); return result; } @@ -506,8 +508,78 @@ 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(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 @@ SymbolRecordKind::DefRangeFramePointerRelSym); cantFail(SymbolDeserializer::deserializeAs( 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( + 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!"); Index: source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp =================================================================== --- source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1315,7 +1315,9 @@ 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; Index: source/Plugins/SymbolFile/PDB/CMakeLists.txt =================================================================== --- source/Plugins/SymbolFile/PDB/CMakeLists.txt +++ source/Plugins/SymbolFile/PDB/CMakeLists.txt @@ -8,7 +8,7 @@ clangLex lldbCore lldbSymbol - lldbUtility + lldbUtility lldbPluginSymbolFileNativePDB LINK_COMPONENTS DebugInfoPDB Index: source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h =================================================================== --- source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h +++ 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 @@ /// @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 @@ lldb_private::DWARFExpression ConvertPDBLocationToDWARFExpression(lldb::ModuleSP module, const llvm::pdb::PDBSymbolData &symbol, + const lldb_private::Variable::RangeList &ranges, bool &is_constant); #endif Index: source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp =================================================================== --- source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp +++ 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(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( - 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 +GetCorrespondingFrameData(const IPDBSession &session, + const Variable::RangeList &ranges) { + auto enumFrameData = session.getFrameData(); + if (!enumFrameData) + return nullptr; + + std::unique_ptr found; + while (auto fd = enumFrameData->getNext()) { + Range 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(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( - 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 @@ 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 @@ 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); Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp =================================================================== --- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -933,12 +933,25 @@ 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 @@ bool is_constant; DWARFExpression location = ConvertPDBLocationToDWARFExpression( - GetObjectFile()->GetModule(), pdb_data, is_constant); + GetObjectFile()->GetModule(), pdb_data, ranges, is_constant); var_sp = std::make_shared( var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope, Index: unittests/SymbolFile/CMakeLists.txt =================================================================== --- unittests/SymbolFile/CMakeLists.txt +++ unittests/SymbolFile/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(DWARF) +add_subdirectory(NativePDB) if (LLVM_ENABLE_DIA_SDK) add_subdirectory(PDB) endif() Index: unittests/SymbolFile/NativePDB/CMakeLists.txt =================================================================== --- /dev/null +++ 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 + ) Index: unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp =================================================================== --- /dev/null +++ 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(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"); +}