From d839f654586a4f3a84b334fcc2c986343a1d7f98 Mon Sep 17 00:00:00 2001 From: Philip Pfaffe Date: Wed, 2 Nov 2022 10:51:18 +0000 Subject: [PATCH] [wasm] Always treat DWARF expression addresses as load addresses When resolving absolute addresses for DW_OP_addr or DW_OP_addrx, these are always load addresses rather than file addresses in wasm. Reviewed By: DavidSpickett Differential Revision: https://reviews.llvm.org/D135664 --- lldb/source/Expression/DWARFExpression.cpp | 30 ++++-- lldb/unittests/Expression/DWARFExpressionTest.cpp | 113 ++++++++++++++++++++++ 2 files changed, 136 insertions(+), 7 deletions(-) diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 1ccda94..3f302e5 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -847,10 +847,12 @@ bool DWARFExpression::Evaluate( Process *process = nullptr; StackFrame *frame = nullptr; + Target *target = nullptr; if (exe_ctx) { process = exe_ctx->GetProcessPtr(); frame = exe_ctx->GetFramePtr(); + target = exe_ctx->GetTargetPtr(); } if (reg_ctx == nullptr && frame) reg_ctx = frame->GetRegisterContext().get(); @@ -906,12 +908,19 @@ bool DWARFExpression::Evaluate( // address and whose size is the size of an address on the target machine. case DW_OP_addr: stack.push_back(Scalar(opcodes.GetAddress(&offset))); - stack.back().SetValueType(Value::ValueType::FileAddress); - // Convert the file address to a load address, so subsequent - // DWARF operators can operate on it. - if (frame) - stack.back().ConvertToLoadAddress(module_sp.get(), - frame->CalculateTarget().get()); + if (target && + target->GetArchitecture().GetCore() == ArchSpec::eCore_wasm32) { + // wasm file sections aren't mapped into memory, therefore addresses can + // never point into a file section and are always LoadAddresses. + stack.back().SetValueType(Value::ValueType::LoadAddress); + } else { + stack.back().SetValueType(Value::ValueType::FileAddress); + // Convert the file address to a load address, so subsequent + // DWARF operators can operate on it. + if (frame) + stack.back().ConvertToLoadAddress(module_sp.get(), + frame->CalculateTarget().get()); + } break; // The DW_OP_addr_sect_offset4 is used for any location expressions in @@ -2507,7 +2516,14 @@ bool DWARFExpression::Evaluate( uint64_t index = opcodes.GetULEB128(&offset); lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index); stack.push_back(Scalar(value)); - stack.back().SetValueType(Value::ValueType::FileAddress); + if (target && + target->GetArchitecture().GetCore() == ArchSpec::eCore_wasm32) { + // wasm file sections aren't mapped into memory, therefore addresses can + // never point into a file section and are always LoadAddresses. + stack.back().SetValueType(Value::ValueType::LoadAddress); + } else { + stack.back().SetValueType(Value::ValueType::FileAddress); + } } break; // OPCODE: DW_OP_GNU_const_index diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index 35a064f..4251eb0 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -8,6 +8,7 @@ #include "lldb/Expression/DWARFExpression.h" #include "Plugins/Platform/Linux/PlatformLinux.h" +#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "TestingSupport/Symbol/YAMLModuleTester.h" #include "lldb/Core/Debugger.h" @@ -401,3 +402,115 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) { Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, {}, {}, &exe_ctx), llvm::HasValue(GetScalar(32, 0x07060504, false))); } + +TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr) { + // Set up a wasm target + ArchSpec arch("wasm32-unknown-unknown-wasm"); + lldb::PlatformSP host_platform_sp = + platform_linux::PlatformLinux::CreateInstance(true, &arch); + ASSERT_TRUE(host_platform_sp); + Platform::SetHostPlatform(host_platform_sp); + lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); + ASSERT_TRUE(debugger_sp); + lldb::TargetSP target_sp; + lldb::PlatformSP platform_sp; + debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch, + lldb_private::eLoadDependentsNo, + platform_sp, target_sp); + + ExecutionContext exe_ctx(target_sp, false); + // DW_OP_addr takes a single operand of address size width: + uint8_t expr[] = {DW_OP_addr, 0x40, 0x0, 0x0, 0x0}; + DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle, + /*addr_size*/ 4); + Value result; + Status status; + ASSERT_TRUE(DWARFExpression::Evaluate( + &exe_ctx, /*reg_ctx*/ nullptr, /*module_sp*/ {}, extractor, + /*unit*/ nullptr, lldb::eRegisterKindLLDB, + /*initial_value_ptr*/ nullptr, + /*object_address_ptr*/ nullptr, result, &status)) + << status.ToError(); + + ASSERT_EQ(result.GetValueType(), Value::ValueType::LoadAddress); +} + +TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr_index) { + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_386 +DWARF: + debug_abbrev: + - Table: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_addr_base + Form: DW_FORM_sec_offset + + debug_info: + - Version: 5 + AddrSize: 4 + UnitType: DW_UT_compile + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x8 # Offset of the first Address past the header + - AbbrCode: 0x0 + + debug_addr: + - Version: 5 + AddressSize: 4 + Entries: + - Address: 0x1234 + - Address: 0x5678 +)"; + + // Can't use DWARFExpressionTester from above because subsystems overlap with + // the fixture. + SubsystemRAII subsystems; + llvm::Expected file = TestFile::fromYaml(yamldata); + EXPECT_THAT_EXPECTED(file, llvm::Succeeded()); + auto module_sp = std::make_shared(file->moduleSpec()); + auto *dwarf_cu = llvm::cast(module_sp->GetSymbolFile()) + ->DebugInfo() + .GetUnitAtIndex(0); + ASSERT_TRUE(dwarf_cu); + dwarf_cu->ExtractDIEsIfNeeded(); + + // Set up a wasm target + ArchSpec arch("wasm32-unknown-unknown-wasm"); + lldb::PlatformSP host_platform_sp = + platform_linux::PlatformLinux::CreateInstance(true, &arch); + ASSERT_TRUE(host_platform_sp); + Platform::SetHostPlatform(host_platform_sp); + lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); + ASSERT_TRUE(debugger_sp); + lldb::TargetSP target_sp; + lldb::PlatformSP platform_sp; + debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch, + lldb_private::eLoadDependentsNo, + platform_sp, target_sp); + + ExecutionContext exe_ctx(target_sp, false); + // DW_OP_addrx takes a single leb128 operand, the index in the addr table: + uint8_t expr[] = {DW_OP_addrx, 0x01}; + DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle, + /*addr_size*/ 4); + Value result; + Status status; + ASSERT_TRUE(DWARFExpression::Evaluate( + &exe_ctx, /*reg_ctx*/ nullptr, /*module_sp*/ {}, extractor, dwarf_cu, + lldb::eRegisterKindLLDB, + /*initial_value_ptr*/ nullptr, + /*object_address_ptr*/ nullptr, result, &status)) + << status.ToError(); + + ASSERT_EQ(result.GetValueType(), Value::ValueType::LoadAddress); + ASSERT_EQ(result.GetScalar().UInt(), 0x5678u); +} -- 2.7.4