271 lines · cpp
1//===-- DWARFExpression.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"10#include <cassert>11#include <cstdint>12#include <vector>13 14using namespace llvm;15using namespace dwarf;16 17namespace llvm {18 19typedef DWARFExpression::Operation Op;20typedef Op::Description Desc;21 22static std::vector<Desc> getOpDescriptions() {23 std::vector<Desc> Descriptions;24 Descriptions.resize(0xff);25 Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr);26 Descriptions[DW_OP_deref] = Desc(Op::Dwarf2);27 Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1);28 Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1);29 Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2);30 Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2);31 Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4);32 Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4);33 Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8);34 Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8);35 Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB);36 Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB);37 Descriptions[DW_OP_dup] = Desc(Op::Dwarf2);38 Descriptions[DW_OP_drop] = Desc(Op::Dwarf2);39 Descriptions[DW_OP_over] = Desc(Op::Dwarf2);40 Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1);41 Descriptions[DW_OP_swap] = Desc(Op::Dwarf2);42 Descriptions[DW_OP_rot] = Desc(Op::Dwarf2);43 Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2);44 Descriptions[DW_OP_abs] = Desc(Op::Dwarf2);45 Descriptions[DW_OP_and] = Desc(Op::Dwarf2);46 Descriptions[DW_OP_div] = Desc(Op::Dwarf2);47 Descriptions[DW_OP_minus] = Desc(Op::Dwarf2);48 Descriptions[DW_OP_mod] = Desc(Op::Dwarf2);49 Descriptions[DW_OP_mul] = Desc(Op::Dwarf2);50 Descriptions[DW_OP_neg] = Desc(Op::Dwarf2);51 Descriptions[DW_OP_not] = Desc(Op::Dwarf2);52 Descriptions[DW_OP_or] = Desc(Op::Dwarf2);53 Descriptions[DW_OP_plus] = Desc(Op::Dwarf2);54 Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB);55 Descriptions[DW_OP_shl] = Desc(Op::Dwarf2);56 Descriptions[DW_OP_shr] = Desc(Op::Dwarf2);57 Descriptions[DW_OP_shra] = Desc(Op::Dwarf2);58 Descriptions[DW_OP_xor] = Desc(Op::Dwarf2);59 Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2);60 Descriptions[DW_OP_eq] = Desc(Op::Dwarf2);61 Descriptions[DW_OP_ge] = Desc(Op::Dwarf2);62 Descriptions[DW_OP_gt] = Desc(Op::Dwarf2);63 Descriptions[DW_OP_le] = Desc(Op::Dwarf2);64 Descriptions[DW_OP_lt] = Desc(Op::Dwarf2);65 Descriptions[DW_OP_ne] = Desc(Op::Dwarf2);66 Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);67 for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA)68 Descriptions[LA] = Desc(Op::Dwarf2);69 for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA)70 Descriptions[LA] = Desc(Op::Dwarf2);71 for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA)72 Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB);73 Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB);74 Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB);75 Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB);76 Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB);77 Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1);78 Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1);79 Descriptions[DW_OP_nop] = Desc(Op::Dwarf2);80 Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3);81 Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2);82 Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4);83 Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr);84 Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3);85 Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3);86 Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB);87 Descriptions[DW_OP_implicit_value] =88 Desc(Op::Dwarf4, Op::SizeLEB, Op::SizeBlock);89 Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf4);90 Descriptions[DW_OP_implicit_pointer] =91 Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB);92 Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB);93 Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB);94 Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB);95 Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);96 Descriptions[DW_OP_regval_type] =97 Desc(Op::Dwarf5, Op::SizeLEB, Op::BaseTypeRef);98 Descriptions[DW_OP_WASM_location] =99 Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg);100 Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);101 Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);102 Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);103 Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);104 Descriptions[DW_OP_GNU_implicit_pointer] =105 Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB);106 // This Description acts as a marker that getSubOpDesc must be called107 // to fetch the final Description for the operation. Each such final108 // Description must share the same first SizeSubOpLEB operand.109 Descriptions[DW_OP_LLVM_user] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);110 return Descriptions;111}112 113static Desc getDescImpl(ArrayRef<Desc> Descriptions, unsigned Opcode) {114 // Handle possible corrupted or unsupported operation.115 if (Opcode >= Descriptions.size())116 return {};117 return Descriptions[Opcode];118}119 120static Desc getOpDesc(unsigned Opcode) {121 static std::vector<Desc> Descriptions = getOpDescriptions();122 return getDescImpl(Descriptions, Opcode);123}124 125static std::vector<Desc> getSubOpDescriptions() {126 static constexpr unsigned LlvmUserDescriptionsSize = 1127#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1128#include "llvm/BinaryFormat/Dwarf.def"129 ;130 std::vector<Desc> Descriptions;131 Descriptions.resize(LlvmUserDescriptionsSize);132 Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);133 Descriptions[DW_OP_LLVM_form_aspace_address] =134 Desc(Op::Dwarf5, Op::SizeSubOpLEB);135 Descriptions[DW_OP_LLVM_push_lane] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);136 Descriptions[DW_OP_LLVM_offset] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);137 Descriptions[DW_OP_LLVM_offset_uconst] =138 Desc(Op::Dwarf5, Op::SizeSubOpLEB, Op::SizeLEB);139 Descriptions[DW_OP_LLVM_bit_offset] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);140 Descriptions[DW_OP_LLVM_call_frame_entry_reg] =141 Desc(Op::Dwarf5, Op::SizeSubOpLEB, Op::SizeLEB);142 Descriptions[DW_OP_LLVM_undefined] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);143 Descriptions[DW_OP_LLVM_aspace_bregx] =144 Desc(Op::Dwarf5, Op::SizeSubOpLEB, Op::SizeLEB, Op::SizeLEB);145 Descriptions[DW_OP_LLVM_piece_end] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);146 Descriptions[DW_OP_LLVM_extend] =147 Desc(Op::Dwarf5, Op::SizeSubOpLEB, Op::SizeLEB, Op::SizeLEB);148 Descriptions[DW_OP_LLVM_select_bit_piece] =149 Desc(Op::Dwarf5, Op::SizeSubOpLEB, Op::SizeLEB, Op::SizeLEB);150 return Descriptions;151}152 153static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) {154 assert(Opcode == DW_OP_LLVM_user);155 static std::vector<Desc> Descriptions = getSubOpDescriptions();156 return getDescImpl(Descriptions, SubOpcode);157}158 159bool DWARFExpression::Operation::extract(DataExtractor Data,160 uint8_t AddressSize, uint64_t Offset,161 std::optional<DwarfFormat> Format) {162 EndOffset = Offset;163 Opcode = Data.getU8(&Offset);164 165 Desc = getOpDesc(Opcode);166 if (Desc.Version == Operation::DwarfNA)167 return false;168 169 Operands.resize(Desc.Op.size());170 OperandEndOffsets.resize(Desc.Op.size());171 for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) {172 unsigned Size = Desc.Op[Operand];173 unsigned Signed = Size & Operation::SignBit;174 175 switch (Size & ~Operation::SignBit) {176 case Operation::SizeSubOpLEB:177 assert(Operand == 0 && "SubOp operand must be the first operand");178 Operands[Operand] = Data.getULEB128(&Offset);179 Desc = getSubOpDesc(Opcode, Operands[Operand]);180 if (Desc.Version == Operation::DwarfNA)181 return false;182 assert(Desc.Op[Operand] == Operation::SizeSubOpLEB &&183 "SizeSubOpLEB Description must begin with SizeSubOpLEB operand");184 Operands.resize(Desc.Op.size());185 OperandEndOffsets.resize(Desc.Op.size());186 break;187 case Operation::Size1:188 Operands[Operand] = Data.getU8(&Offset);189 if (Signed)190 Operands[Operand] = (int8_t)Operands[Operand];191 break;192 case Operation::Size2:193 Operands[Operand] = Data.getU16(&Offset);194 if (Signed)195 Operands[Operand] = (int16_t)Operands[Operand];196 break;197 case Operation::Size4:198 Operands[Operand] = Data.getU32(&Offset);199 if (Signed)200 Operands[Operand] = (int32_t)Operands[Operand];201 break;202 case Operation::Size8:203 Operands[Operand] = Data.getU64(&Offset);204 break;205 case Operation::SizeAddr:206 Operands[Operand] = Data.getUnsigned(&Offset, AddressSize);207 break;208 case Operation::SizeRefAddr:209 if (!Format)210 return false;211 Operands[Operand] =212 Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format));213 break;214 case Operation::SizeLEB:215 if (Signed)216 Operands[Operand] = Data.getSLEB128(&Offset);217 else218 Operands[Operand] = Data.getULEB128(&Offset);219 break;220 case Operation::BaseTypeRef:221 Operands[Operand] = Data.getULEB128(&Offset);222 break;223 case Operation::WasmLocationArg:224 assert(Operand == 1);225 switch (Operands[0]) {226 case 0:227 case 1:228 case 2:229 case 4:230 Operands[Operand] = Data.getULEB128(&Offset);231 break;232 case 3: // global as uint32233 Operands[Operand] = Data.getU32(&Offset);234 break;235 default:236 return false; // Unknown Wasm location237 }238 break;239 case Operation::SizeBlock:240 // We need a size, so this cannot be the first operand241 if (Operand == 0)242 return false;243 // Store the offset of the block as the value.244 Operands[Operand] = Offset;245 Offset += Operands[Operand - 1];246 break;247 default:248 llvm_unreachable("Unknown DWARFExpression Op size");249 }250 251 OperandEndOffsets[Operand] = Offset;252 }253 254 EndOffset = Offset;255 return true;256}257 258std::optional<unsigned> DWARFExpression::Operation::getSubCode() const {259 if (!Desc.Op.size() || Desc.Op[0] != Operation::SizeSubOpLEB)260 return std::nullopt;261 return Operands[0];262}263 264bool DWARFExpression::operator==(const DWARFExpression &RHS) const {265 if (AddressSize != RHS.AddressSize || Format != RHS.Format)266 return false;267 return Data.getData() == RHS.Data.getData();268}269 270} // namespace llvm271