LLDB  mainline
DWARFLocationExpression.cpp
Go to the documentation of this file.
1 //===-- DWARFLocationExpression.cpp -----------------------------*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/Section.h"
13 #include "lldb/Core/StreamBuffer.h"
15 #include "lldb/Utility/ArchSpec.h"
17 
18 #include "llvm/BinaryFormat/Dwarf.h"
19 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
20 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
21 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
22 #include "llvm/Support/Endian.h"
23 
24 #include "PdbUtil.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 using namespace lldb_private::npdb;
31 using namespace llvm::codeview;
32 using namespace llvm::pdb;
33 
34 uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
35  if (register_id == llvm::codeview::RegisterId::VFRAME)
37 
38  return LLDB_INVALID_REGNUM;
39 }
40 
41 static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,
42  llvm::codeview::RegisterId register_id,
43  RegisterKind &register_kind) {
44  register_kind = eRegisterKindLLDB;
45  uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);
46  if (reg_num != LLDB_INVALID_REGNUM)
47  return reg_num;
48 
49  register_kind = eRegisterKindGeneric;
50  return GetGenericRegisterNumber(register_id);
51 }
52 
53 static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) {
54  switch (kind) {
55  case SimpleTypeKind::Int128:
56  case SimpleTypeKind::Int64:
57  case SimpleTypeKind::Int64Quad:
58  case SimpleTypeKind::Int32:
59  case SimpleTypeKind::Int32Long:
60  case SimpleTypeKind::Int16:
61  case SimpleTypeKind::Int16Short:
62  case SimpleTypeKind::Float128:
63  case SimpleTypeKind::Float80:
64  case SimpleTypeKind::Float64:
65  case SimpleTypeKind::Float32:
66  case SimpleTypeKind::Float16:
67  case SimpleTypeKind::NarrowCharacter:
68  case SimpleTypeKind::SignedCharacter:
69  case SimpleTypeKind::SByte:
70  return true;
71  default:
72  return false;
73  }
74 }
75 
76 static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti,
77  TpiStream &tpi) {
78  if (ti.isSimple()) {
79  SimpleTypeKind stk = ti.getSimpleKind();
81  }
82 
83  CVType cvt = tpi.getType(ti);
84  switch (cvt.kind()) {
85  case LF_MODIFIER: {
86  ModifierRecord mfr;
87  llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr));
88  return GetIntegralTypeInfo(mfr.ModifiedType, tpi);
89  }
90  case LF_POINTER: {
91  PointerRecord pr;
92  llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr));
93  return GetIntegralTypeInfo(pr.ReferentType, tpi);
94  }
95  case LF_ENUM: {
96  EnumRecord er;
97  llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
98  return GetIntegralTypeInfo(er.UnderlyingType, tpi);
99  }
100  default:
101  assert(false && "Type is not integral!");
102  return {0, false};
103  }
104 }
105 
106 template <typename StreamWriter>
107 static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module,
108  StreamWriter &&writer) {
109  const ArchSpec &architecture = module->GetArchitecture();
110  ByteOrder byte_order = architecture.GetByteOrder();
111  uint32_t address_size = architecture.GetAddressByteSize();
112  uint32_t byte_size = architecture.GetDataByteSize();
113  if (byte_order == eByteOrderInvalid || address_size == 0)
114  return DWARFExpression(nullptr);
115 
116  RegisterKind register_kind = eRegisterKindDWARF;
117  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
118 
119  if (!writer(stream, register_kind))
120  return DWARFExpression(nullptr);
121 
122  DataBufferSP buffer =
123  std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
124  DataExtractor extractor(buffer, byte_order, address_size, byte_size);
125  DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize());
126  result.SetRegisterKind(register_kind);
127 
128  return result;
129 }
130 
132  llvm::codeview::RegisterId reg, llvm::Optional<int32_t> relative_offset,
133  lldb::ModuleSP module) {
135  module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
136  uint32_t reg_num = GetRegisterNumber(
137  module->GetArchitecture().GetMachine(), reg, register_kind);
138  if (reg_num == LLDB_INVALID_REGNUM)
139  return false;
140 
141  if (reg_num > 31) {
142  llvm::dwarf::LocationAtom base = relative_offset
143  ? llvm::dwarf::DW_OP_bregx
144  : llvm::dwarf::DW_OP_regx;
145  stream.PutHex8(base);
146  stream.PutULEB128(reg_num);
147  } else {
148  llvm::dwarf::LocationAtom base = relative_offset
149  ? llvm::dwarf::DW_OP_breg0
150  : llvm::dwarf::DW_OP_reg0;
151  stream.PutHex8(base + reg_num);
152  }
153 
154  if (relative_offset)
155  stream.PutSLEB128(*relative_offset);
156 
157  return true;
158  });
159 }
160 
162  llvm::codeview::RegisterId reg, lldb::ModuleSP module) {
163  return MakeRegisterBasedLocationExpressionInternal(reg, llvm::None, module);
164 }
165 
167  llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module) {
168  return MakeRegisterBasedLocationExpressionInternal(reg, offset, module);
169 }
170 
172  llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
173  // VFrame value always stored in $TO pseudo-register
174  return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
175  stream);
176 }
177 
179  llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) {
181  module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
182  const ArchSpec &architecture = module->GetArchitecture();
183 
184  if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(),
185  stream))
186  return false;
187 
188  stream.PutHex8(llvm::dwarf::DW_OP_consts);
189  stream.PutSLEB128(offset);
190  stream.PutHex8(llvm::dwarf::DW_OP_plus);
191 
192  register_kind = eRegisterKindLLDB;
193 
194  return true;
195  });
196 }
197 
199  uint16_t section, uint32_t offset, ModuleSP module) {
200  assert(section > 0);
201  assert(module);
202 
204  module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
205  stream.PutHex8(llvm::dwarf::DW_OP_addr);
206 
207  SectionList *section_list = module->GetSectionList();
208  assert(section_list);
209 
210  auto section_ptr = section_list->FindSectionByID(section);
211  if (!section_ptr)
212  return false;
213 
214  stream.PutMaxHex64(section_ptr->GetFileAddress() + offset,
215  stream.GetAddressByteSize(), stream.GetByteOrder());
216 
217  return true;
218  });
219 }
220 
222  TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant,
223  ModuleSP module) {
224  const ArchSpec &architecture = module->GetArchitecture();
225  uint32_t address_size = architecture.GetAddressByteSize();
226 
227  size_t size = 0;
228  bool is_signed = false;
229  std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi);
230 
231  union {
232  llvm::support::little64_t I;
233  llvm::support::ulittle64_t U;
234  } Value;
235 
236  std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>();
237  buffer->SetByteSize(size);
238 
239  llvm::ArrayRef<uint8_t> bytes;
240  if (is_signed) {
241  Value.I = constant.getSExtValue();
242  } else {
243  Value.U = constant.getZExtValue();
244  }
245 
246  bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8)
247  .take_front(size);
248  buffer->CopyData(bytes.data(), size);
249  DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);
250  DWARFExpression result(nullptr, extractor, nullptr, 0, size);
251  return result;
252 }
An data extractor class.
Definition: DataExtractor.h:47
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
void SetRegisterKind(lldb::RegisterKind reg_kind)
Set the call-frame-info style register kind.
uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id)
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:742
"lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location expression and interprets it...
uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, llvm::codeview::RegisterId register_id)
An architecture specification class.
Definition: ArchSpec.h:32
static DWARFExpression MakeRegisterBasedLocationExpressionInternal(llvm::codeview::RegisterId reg, llvm::Optional< int32_t > relative_offset, lldb::ModuleSP module)
static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module, StreamWriter &&writer)
size_t PutMaxHex64(uint64_t uvalue, size_t byte_size, lldb::ByteOrder byte_order=lldb::eByteOrderInvalid)
Definition: Stream.cpp:338
lldb::ByteOrder GetByteOrder() const
Definition: Stream.cpp:242
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:65
DWARFExpression MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg, lldb::ModuleSP module)
lldb::SectionSP FindSectionByID(lldb::user_id_t sect_id) const
Definition: Section.cpp:527
uint32_t GetDataByteSize() const
Architecture data byte width accessor.
Definition: ArchSpec.cpp:718
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:788
DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset, lldb::ModuleSP module)
DWARFExpression MakeVFrameRelLocationExpression(llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module)
const char * GetData() const
Definition: StreamBuffer.h:38
static std::pair< size_t, bool > GetIntegralTypeInfo(TypeIndex ti, TpiStream &tpi)
DWARFExpression MakeConstantLocationExpression(llvm::codeview::TypeIndex underlying_ti, llvm::pdb::TpiStream &tpi, const llvm::APSInt &constant, lldb::ModuleSP module)
size_t size_t PutHex8(uint8_t uvalue)
Append an uint8_t value in the hexadecimal format to the stream.
Definition: Stream.cpp:284
Definition: SBAddress.h:15
static bool EmitVFrameEvaluationDWARFExpression(llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream)
DWARFExpression MakeRegRelLocationExpression(llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module)
static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind)
uint32_t GetAddressByteSize() const
Get the address size in bytes.
Definition: Stream.cpp:229
bool TranslateFPOProgramToDWARFExpression(llvm::StringRef program, llvm::StringRef register_name, llvm::Triple::ArchType arch_type, lldb_private::Stream &stream)
size_t PutSLEB128(int64_t uval)
Output a SLEB128 number to the stream.
Definition: Stream.cpp:45
size_t PutULEB128(uint64_t uval)
Output a ULEB128 number to the stream.
Definition: Stream.cpp:53
static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type, llvm::codeview::RegisterId register_id, RegisterKind &register_kind)
size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind)
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:726
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90