| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "SymbolFileWasm.h" |
| #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" |
| #include "Utility/WasmVirtualRegisters.h" |
| #include "lldb/Utility/LLDBLog.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| using namespace lldb_private::plugin::dwarf; |
| |
| SymbolFileWasm::SymbolFileWasm(ObjectFileSP objfile_sp, |
| SectionList *dwo_section_list) |
| : SymbolFileDWARF(objfile_sp, dwo_section_list) {} |
| |
| SymbolFileWasm::~SymbolFileWasm() = default; |
| |
| lldb::offset_t |
| SymbolFileWasm::GetVendorDWARFOpcodeSize(const DataExtractor &data, |
| const lldb::offset_t data_offset, |
| const uint8_t op) const { |
| if (op != llvm::dwarf::DW_OP_WASM_location) |
| return LLDB_INVALID_OFFSET; |
| |
| lldb::offset_t offset = data_offset; |
| const uint8_t wasm_op = data.GetU8(&offset); |
| switch (wasm_op) { |
| case 0: // LOCAL |
| case 1: // GLOBAL_FIXED |
| case 2: // OPERAND_STACK |
| data.GetULEB128(&offset); |
| break; |
| case 3: // GLOBAL_RELOC |
| data.GetU32(&offset); |
| break; |
| default: |
| return LLDB_INVALID_OFFSET; |
| } |
| |
| return offset - data_offset; |
| } |
| |
| bool SymbolFileWasm::ParseVendorDWARFOpcode(uint8_t op, |
| const DataExtractor &opcodes, |
| lldb::offset_t &offset, |
| RegisterContext *reg_ctx, |
| lldb::RegisterKind reg_kind, |
| std::vector<Value> &stack) const { |
| if (op != llvm::dwarf::DW_OP_WASM_location) |
| return false; |
| |
| uint32_t index = 0; |
| uint8_t tag = eWasmTagNotAWasmLocation; |
| |
| /// |DWARF Location Index | WebAssembly Construct | |
| /// |---------------------|-----------------------| |
| /// |0 | Local | |
| /// |1 or 3 | Global | |
| /// |2 | Operand Stack | |
| const uint8_t wasm_op = opcodes.GetU8(&offset); |
| switch (wasm_op) { |
| case 0: // LOCAL |
| index = opcodes.GetULEB128(&offset); |
| tag = eWasmTagLocal; |
| break; |
| case 1: // GLOBAL_FIXED |
| index = opcodes.GetULEB128(&offset); |
| tag = eWasmTagGlobal; |
| break; |
| case 2: // OPERAND_STACK |
| index = opcodes.GetULEB128(&offset); |
| tag = eWasmTagOperandStack; |
| break; |
| case 3: // GLOBAL_RELOC |
| index = opcodes.GetU32(&offset); |
| tag = eWasmTagGlobal; |
| break; |
| default: |
| return false; |
| } |
| |
| const uint32_t reg_num = GetWasmRegister(tag, index); |
| |
| Value tmp; |
| llvm::Error error = DWARFExpression::ReadRegisterValueAsScalar( |
| reg_ctx, reg_kind, reg_num, tmp); |
| if (error) { |
| LLDB_LOG_ERROR(GetLog(DWARFLog::DebugInfo), std::move(error), "{0}"); |
| return false; |
| } |
| |
| stack.push_back(tmp); |
| return true; |
| } |