Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
213845 views
//===-- DWARFExpression.cpp -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"9#include "llvm/ADT/SmallString.h"10#include "llvm/Support/Format.h"11#include <cassert>12#include <cstdint>13#include <vector>1415using namespace llvm;16using namespace dwarf;1718namespace llvm {1920typedef DWARFExpression::Operation Op;21typedef Op::Description Desc;2223static std::vector<Desc> getOpDescriptions() {24std::vector<Desc> Descriptions;25Descriptions.resize(0xff);26Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr);27Descriptions[DW_OP_deref] = Desc(Op::Dwarf2);28Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1);29Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1);30Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2);31Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2);32Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4);33Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4);34Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8);35Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8);36Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB);37Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB);38Descriptions[DW_OP_dup] = Desc(Op::Dwarf2);39Descriptions[DW_OP_drop] = Desc(Op::Dwarf2);40Descriptions[DW_OP_over] = Desc(Op::Dwarf2);41Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1);42Descriptions[DW_OP_swap] = Desc(Op::Dwarf2);43Descriptions[DW_OP_rot] = Desc(Op::Dwarf2);44Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2);45Descriptions[DW_OP_abs] = Desc(Op::Dwarf2);46Descriptions[DW_OP_and] = Desc(Op::Dwarf2);47Descriptions[DW_OP_div] = Desc(Op::Dwarf2);48Descriptions[DW_OP_minus] = Desc(Op::Dwarf2);49Descriptions[DW_OP_mod] = Desc(Op::Dwarf2);50Descriptions[DW_OP_mul] = Desc(Op::Dwarf2);51Descriptions[DW_OP_neg] = Desc(Op::Dwarf2);52Descriptions[DW_OP_not] = Desc(Op::Dwarf2);53Descriptions[DW_OP_or] = Desc(Op::Dwarf2);54Descriptions[DW_OP_plus] = Desc(Op::Dwarf2);55Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB);56Descriptions[DW_OP_shl] = Desc(Op::Dwarf2);57Descriptions[DW_OP_shr] = Desc(Op::Dwarf2);58Descriptions[DW_OP_shra] = Desc(Op::Dwarf2);59Descriptions[DW_OP_xor] = Desc(Op::Dwarf2);60Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2);61Descriptions[DW_OP_eq] = Desc(Op::Dwarf2);62Descriptions[DW_OP_ge] = Desc(Op::Dwarf2);63Descriptions[DW_OP_gt] = Desc(Op::Dwarf2);64Descriptions[DW_OP_le] = Desc(Op::Dwarf2);65Descriptions[DW_OP_lt] = Desc(Op::Dwarf2);66Descriptions[DW_OP_ne] = Desc(Op::Dwarf2);67Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);68for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA)69Descriptions[LA] = Desc(Op::Dwarf2);70for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA)71Descriptions[LA] = Desc(Op::Dwarf2);72for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA)73Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB);74Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB);75Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB);76Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB);77Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB);78Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1);79Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1);80Descriptions[DW_OP_nop] = Desc(Op::Dwarf2);81Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3);82Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2);83Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4);84Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr);85Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3);86Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3);87Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB);88Descriptions[DW_OP_implicit_value] =89Desc(Op::Dwarf4, Op::SizeLEB, Op::SizeBlock);90Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf4);91Descriptions[DW_OP_implicit_pointer] =92Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB);93Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB);94Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB);95Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB);96Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);97Descriptions[DW_OP_regval_type] =98Desc(Op::Dwarf5, Op::SizeLEB, Op::BaseTypeRef);99Descriptions[DW_OP_WASM_location] =100Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg);101Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);102Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);103Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);104Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);105Descriptions[DW_OP_GNU_implicit_pointer] =106Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB);107// This Description acts as a marker that getSubOpDesc must be called108// to fetch the final Description for the operation. Each such final109// Description must share the same first SizeSubOpLEB operand.110Descriptions[DW_OP_LLVM_user] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);111return Descriptions;112}113114static Desc getDescImpl(ArrayRef<Desc> Descriptions, unsigned Opcode) {115// Handle possible corrupted or unsupported operation.116if (Opcode >= Descriptions.size())117return {};118return Descriptions[Opcode];119}120121static Desc getOpDesc(unsigned Opcode) {122static std::vector<Desc> Descriptions = getOpDescriptions();123return getDescImpl(Descriptions, Opcode);124}125126static std::vector<Desc> getSubOpDescriptions() {127static constexpr unsigned LlvmUserDescriptionsSize = 1128#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1129#include "llvm/BinaryFormat/Dwarf.def"130;131std::vector<Desc> Descriptions;132Descriptions.resize(LlvmUserDescriptionsSize);133Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);134return Descriptions;135}136137static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) {138assert(Opcode == DW_OP_LLVM_user);139static std::vector<Desc> Descriptions = getSubOpDescriptions();140return getDescImpl(Descriptions, SubOpcode);141}142143bool DWARFExpression::Operation::extract(DataExtractor Data,144uint8_t AddressSize, uint64_t Offset,145std::optional<DwarfFormat> Format) {146EndOffset = Offset;147Opcode = Data.getU8(&Offset);148149Desc = getOpDesc(Opcode);150if (Desc.Version == Operation::DwarfNA)151return false;152153Operands.resize(Desc.Op.size());154OperandEndOffsets.resize(Desc.Op.size());155for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) {156unsigned Size = Desc.Op[Operand];157unsigned Signed = Size & Operation::SignBit;158159switch (Size & ~Operation::SignBit) {160case Operation::SizeSubOpLEB:161assert(Operand == 0 && "SubOp operand must be the first operand");162Operands[Operand] = Data.getULEB128(&Offset);163Desc = getSubOpDesc(Opcode, Operands[Operand]);164if (Desc.Version == Operation::DwarfNA)165return false;166assert(Desc.Op[Operand] == Operation::SizeSubOpLEB &&167"SizeSubOpLEB Description must begin with SizeSubOpLEB operand");168break;169case Operation::Size1:170Operands[Operand] = Data.getU8(&Offset);171if (Signed)172Operands[Operand] = (int8_t)Operands[Operand];173break;174case Operation::Size2:175Operands[Operand] = Data.getU16(&Offset);176if (Signed)177Operands[Operand] = (int16_t)Operands[Operand];178break;179case Operation::Size4:180Operands[Operand] = Data.getU32(&Offset);181if (Signed)182Operands[Operand] = (int32_t)Operands[Operand];183break;184case Operation::Size8:185Operands[Operand] = Data.getU64(&Offset);186break;187case Operation::SizeAddr:188Operands[Operand] = Data.getUnsigned(&Offset, AddressSize);189break;190case Operation::SizeRefAddr:191if (!Format)192return false;193Operands[Operand] =194Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format));195break;196case Operation::SizeLEB:197if (Signed)198Operands[Operand] = Data.getSLEB128(&Offset);199else200Operands[Operand] = Data.getULEB128(&Offset);201break;202case Operation::BaseTypeRef:203Operands[Operand] = Data.getULEB128(&Offset);204break;205case Operation::WasmLocationArg:206assert(Operand == 1);207switch (Operands[0]) {208case 0:209case 1:210case 2:211case 4:212Operands[Operand] = Data.getULEB128(&Offset);213break;214case 3: // global as uint32215Operands[Operand] = Data.getU32(&Offset);216break;217default:218return false; // Unknown Wasm location219}220break;221case Operation::SizeBlock:222// We need a size, so this cannot be the first operand223if (Operand == 0)224return false;225// Store the offset of the block as the value.226Operands[Operand] = Offset;227Offset += Operands[Operand - 1];228break;229default:230llvm_unreachable("Unknown DWARFExpression Op size");231}232233OperandEndOffsets[Operand] = Offset;234}235236EndOffset = Offset;237return true;238}239240std::optional<unsigned> DWARFExpression::Operation::getSubCode() const {241if (!Desc.Op.size() || Desc.Op[0] != Operation::SizeSubOpLEB)242return std::nullopt;243return Operands[0];244}245246bool DWARFExpression::operator==(const DWARFExpression &RHS) const {247if (AddressSize != RHS.AddressSize || Format != RHS.Format)248return false;249return Data.getData() == RHS.Data.getData();250}251252} // namespace llvm253254255