brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.8 KiB · 61bd6fc Raw
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