LLDB  mainline
PDBLocationToDWARFExpression.cpp
Go to the documentation of this file.
1 //===-- PDBLocationToDWARFExpression.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/Section.h"
12 #include "lldb/Core/StreamBuffer.h"
13 #include "lldb/Core/dwarf.h"
15 #include "lldb/Symbol/Variable.h"
17 
18 #include "llvm/DebugInfo/CodeView/CodeView.h"
19 #include "llvm/DebugInfo/PDB/IPDBSession.h"
20 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
21 
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 using namespace lldb_private::npdb;
28 using namespace llvm::pdb;
29 
30 static std::unique_ptr<IPDBFrameData>
31 GetCorrespondingFrameData(const IPDBSession &session,
32  const Variable::RangeList &ranges) {
33  auto enumFrameData = session.getFrameData();
34  if (!enumFrameData)
35  return nullptr;
36 
37  std::unique_ptr<IPDBFrameData> found;
38  while (auto fd = enumFrameData->getNext()) {
39  Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(),
40  fd->getLengthBlock());
41 
42  for (size_t i = 0; i < ranges.GetSize(); i++) {
43  auto range = ranges.GetEntryAtIndex(i);
44  if (!range)
45  continue;
46 
47  if (!range->DoesIntersect(fdRange))
48  continue;
49 
50  found = std::move(fd);
51 
52  break;
53  }
54  }
55 
56  return found;
57 }
58 
60  llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
61  // VFrame value always stored in $TO pseudo-register
62  return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
63  stream);
64 }
65 
67  ModuleSP module, const PDBSymbolData &symbol,
68  const Variable::RangeList &ranges, bool &is_constant) {
69  is_constant = true;
70 
71  if (!module)
72  return DWARFExpression(nullptr);
73 
74  const ArchSpec &architecture = module->GetArchitecture();
75  llvm::Triple::ArchType arch_type = architecture.GetMachine();
76  ByteOrder byte_order = architecture.GetByteOrder();
77  uint32_t address_size = architecture.GetAddressByteSize();
78  uint32_t byte_size = architecture.GetDataByteSize();
79  if (byte_order == eByteOrderInvalid || address_size == 0)
80  return DWARFExpression(nullptr);
81 
82  RegisterKind register_kind = eRegisterKindDWARF;
83  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
84  switch (symbol.getLocationType()) {
85  case PDB_LocType::Static:
86  case PDB_LocType::TLS: {
87  stream.PutHex8(DW_OP_addr);
88 
89  SectionList *section_list = module->GetSectionList();
90  if (!section_list)
91  return DWARFExpression(nullptr);
92 
93  uint32_t section_id = symbol.getAddressSection();
94 
95  auto section = section_list->FindSectionByID(section_id);
96  if (!section)
97  return DWARFExpression(nullptr);
98 
99  uint32_t offset = symbol.getAddressOffset();
100  stream.PutMaxHex64(section->GetFileAddress() + offset, address_size,
101  byte_order);
102 
103  is_constant = false;
104 
105  break;
106  }
107  case PDB_LocType::RegRel: {
108  uint32_t reg_num;
109  auto reg_id = symbol.getRegisterId();
110  if (reg_id == llvm::codeview::RegisterId::VFRAME) {
111  if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) {
112  if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type,
113  stream)) {
114  int32_t offset = symbol.getOffset();
115  stream.PutHex8(DW_OP_consts);
116  stream.PutSLEB128(offset);
117  stream.PutHex8(DW_OP_plus);
118 
119  register_kind = eRegisterKindLLDB;
120 
121  is_constant = false;
122  break;
123  }
124  }
125 
126  register_kind = eRegisterKindGeneric;
127  reg_num = LLDB_REGNUM_GENERIC_FP;
128  } else {
129  register_kind = eRegisterKindLLDB;
130  reg_num = GetLLDBRegisterNumber(arch_type, reg_id);
131  if (reg_num == LLDB_INVALID_REGNUM)
132  return DWARFExpression(nullptr);
133  }
134 
135  if (reg_num > 31) {
136  stream.PutHex8(DW_OP_bregx);
137  stream.PutULEB128(reg_num);
138  } else
139  stream.PutHex8(DW_OP_breg0 + reg_num);
140 
141  int32_t offset = symbol.getOffset();
142  stream.PutSLEB128(offset);
143 
144  is_constant = false;
145 
146  break;
147  }
148  case PDB_LocType::Enregistered: {
149  register_kind = eRegisterKindLLDB;
150  uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId());
151  if (reg_num == LLDB_INVALID_REGNUM)
152  return DWARFExpression(nullptr);
153 
154  if (reg_num > 31) {
155  stream.PutHex8(DW_OP_regx);
156  stream.PutULEB128(reg_num);
157  } else
158  stream.PutHex8(DW_OP_reg0 + reg_num);
159 
160  is_constant = false;
161 
162  break;
163  }
164  case PDB_LocType::Constant: {
165  Variant value = symbol.getValue();
166  stream.PutRawBytes(&value.Value, sizeof(value.Value),
168  break;
169  }
170  default:
171  return DWARFExpression(nullptr);
172  }
173 
174  DataBufferSP buffer =
175  std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
176  DataExtractor extractor(buffer, byte_order, address_size, byte_size);
177  DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize());
178  result.SetRegisterKind(register_kind);
179 
180  return result;
181 }
An data extractor class.
Definition: DataExtractor.h:47
DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, const PDBSymbolData &symbol, const Variable::RangeList &ranges, bool &is_constant)
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 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
size_t PutMaxHex64(uint64_t uvalue, size_t byte_size, lldb::ByteOrder byte_order=lldb::eByteOrderInvalid)
Definition: Stream.cpp:338
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:65
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
static std::unique_ptr< IPDBFrameData > GetCorrespondingFrameData(const IPDBSession &session, const Variable::RangeList &ranges)
const Entry * GetEntryAtIndex(size_t i) const
Definition: RangeMap.h:477
static bool EmitVFrameEvaluationDWARFExpression(llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream)
const char * GetData() const
Definition: StreamBuffer.h:38
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
size_t GetSize() const
Definition: RangeMap.h:475
lldb::ByteOrder InlHostByteOrder()
Definition: Endian.h:25
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
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:726
size_t PutRawBytes(const void *s, size_t src_len, lldb::ByteOrder src_byte_order=lldb::eByteOrderInvalid, lldb::ByteOrder dst_byte_order=lldb::eByteOrderInvalid)
Definition: Stream.cpp:379
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90