Coverage Report

Created: 2022-01-15 10:30

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