Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Symbol/Block.cpp
39587 views
1
//===-- Block.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 "lldb/Symbol/Block.h"
10
11
#include "lldb/Core/Module.h"
12
#include "lldb/Core/Section.h"
13
#include "lldb/Symbol/Function.h"
14
#include "lldb/Symbol/SymbolFile.h"
15
#include "lldb/Symbol/VariableList.h"
16
#include "lldb/Utility/LLDBLog.h"
17
#include "lldb/Utility/Log.h"
18
19
#include <memory>
20
21
using namespace lldb;
22
using namespace lldb_private;
23
24
Block::Block(lldb::user_id_t uid)
25
: UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(),
26
m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false),
27
m_parsed_block_variables(false), m_parsed_child_blocks(false) {}
28
29
Block::~Block() = default;
30
31
void Block::GetDescription(Stream *s, Function *function,
32
lldb::DescriptionLevel level, Target *target) const {
33
*s << "id = " << ((const UserID &)*this);
34
35
size_t num_ranges = m_ranges.GetSize();
36
if (num_ranges > 0) {
37
38
addr_t base_addr = LLDB_INVALID_ADDRESS;
39
if (target)
40
base_addr =
41
function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
42
if (base_addr == LLDB_INVALID_ADDRESS)
43
base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
44
45
s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
46
for (size_t i = 0; i < num_ranges; ++i) {
47
const Range &range = m_ranges.GetEntryRef(i);
48
DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
49
base_addr + range.GetRangeEnd(), 4);
50
}
51
}
52
53
if (m_inlineInfoSP.get() != nullptr) {
54
bool show_fullpaths = (level == eDescriptionLevelVerbose);
55
m_inlineInfoSP->Dump(s, show_fullpaths);
56
}
57
}
58
59
void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
60
bool show_context) const {
61
if (depth < 0) {
62
Block *parent = GetParent();
63
if (parent) {
64
// We have a depth that is less than zero, print our parent blocks first
65
parent->Dump(s, base_addr, depth + 1, show_context);
66
}
67
}
68
69
s->Printf("%p: ", static_cast<const void *>(this));
70
s->Indent();
71
*s << "Block" << static_cast<const UserID &>(*this);
72
const Block *parent_block = GetParent();
73
if (parent_block) {
74
s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
75
}
76
if (m_inlineInfoSP.get() != nullptr) {
77
bool show_fullpaths = false;
78
m_inlineInfoSP->Dump(s, show_fullpaths);
79
}
80
81
if (!m_ranges.IsEmpty()) {
82
*s << ", ranges =";
83
84
size_t num_ranges = m_ranges.GetSize();
85
for (size_t i = 0; i < num_ranges; ++i) {
86
const Range &range = m_ranges.GetEntryRef(i);
87
if (parent_block != nullptr && !parent_block->Contains(range))
88
*s << '!';
89
else
90
*s << ' ';
91
DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
92
base_addr + range.GetRangeEnd(), 4);
93
}
94
}
95
s->EOL();
96
97
if (depth > 0) {
98
s->IndentMore();
99
100
if (m_variable_list_sp.get()) {
101
m_variable_list_sp->Dump(s, show_context);
102
}
103
104
collection::const_iterator pos, end = m_children.end();
105
for (pos = m_children.begin(); pos != end; ++pos)
106
(*pos)->Dump(s, base_addr, depth - 1, show_context);
107
108
s->IndentLess();
109
}
110
}
111
112
Block *Block::FindBlockByID(user_id_t block_id) {
113
if (block_id == GetID())
114
return this;
115
116
Block *matching_block = nullptr;
117
collection::const_iterator pos, end = m_children.end();
118
for (pos = m_children.begin(); pos != end; ++pos) {
119
matching_block = (*pos)->FindBlockByID(block_id);
120
if (matching_block)
121
break;
122
}
123
return matching_block;
124
}
125
126
Block *Block::FindInnermostBlockByOffset(const lldb::addr_t offset) {
127
if (!Contains(offset))
128
return nullptr;
129
for (const BlockSP &block_sp : m_children) {
130
if (Block *block = block_sp->FindInnermostBlockByOffset(offset))
131
return block;
132
}
133
return this;
134
}
135
136
void Block::CalculateSymbolContext(SymbolContext *sc) {
137
if (m_parent_scope)
138
m_parent_scope->CalculateSymbolContext(sc);
139
sc->block = this;
140
}
141
142
lldb::ModuleSP Block::CalculateSymbolContextModule() {
143
if (m_parent_scope)
144
return m_parent_scope->CalculateSymbolContextModule();
145
return lldb::ModuleSP();
146
}
147
148
CompileUnit *Block::CalculateSymbolContextCompileUnit() {
149
if (m_parent_scope)
150
return m_parent_scope->CalculateSymbolContextCompileUnit();
151
return nullptr;
152
}
153
154
Function *Block::CalculateSymbolContextFunction() {
155
if (m_parent_scope)
156
return m_parent_scope->CalculateSymbolContextFunction();
157
return nullptr;
158
}
159
160
Block *Block::CalculateSymbolContextBlock() { return this; }
161
162
void Block::DumpSymbolContext(Stream *s) {
163
Function *function = CalculateSymbolContextFunction();
164
if (function)
165
function->DumpSymbolContext(s);
166
s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
167
}
168
169
void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {
170
if (!m_ranges.IsEmpty()) {
171
size_t num_ranges = m_ranges.GetSize();
172
for (size_t i = 0; i < num_ranges; ++i) {
173
const Range &range = m_ranges.GetEntryRef(i);
174
DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
175
base_addr + range.GetRangeEnd(), 4);
176
}
177
}
178
}
179
180
bool Block::Contains(addr_t range_offset) const {
181
return m_ranges.FindEntryThatContains(range_offset) != nullptr;
182
}
183
184
bool Block::Contains(const Block *block) const {
185
if (this == block)
186
return false; // This block doesn't contain itself...
187
188
// Walk the parent chain for "block" and see if any if them match this block
189
const Block *block_parent;
190
for (block_parent = block->GetParent(); block_parent != nullptr;
191
block_parent = block_parent->GetParent()) {
192
if (this == block_parent)
193
return true; // One of the parents of "block" is this object!
194
}
195
return false;
196
}
197
198
bool Block::Contains(const Range &range) const {
199
return m_ranges.FindEntryThatContains(range) != nullptr;
200
}
201
202
Block *Block::GetParent() const {
203
if (m_parent_scope)
204
return m_parent_scope->CalculateSymbolContextBlock();
205
return nullptr;
206
}
207
208
Block *Block::GetContainingInlinedBlock() {
209
if (GetInlinedFunctionInfo())
210
return this;
211
return GetInlinedParent();
212
}
213
214
Block *Block::GetInlinedParent() {
215
Block *parent_block = GetParent();
216
if (parent_block) {
217
if (parent_block->GetInlinedFunctionInfo())
218
return parent_block;
219
else
220
return parent_block->GetInlinedParent();
221
}
222
return nullptr;
223
}
224
225
Block *Block::GetContainingInlinedBlockWithCallSite(
226
const Declaration &find_call_site) {
227
Block *inlined_block = GetContainingInlinedBlock();
228
229
while (inlined_block) {
230
const auto *function_info = inlined_block->GetInlinedFunctionInfo();
231
232
if (function_info &&
233
function_info->GetCallSite().FileAndLineEqual(find_call_site))
234
return inlined_block;
235
inlined_block = inlined_block->GetInlinedParent();
236
}
237
return nullptr;
238
}
239
240
bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) {
241
const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
242
if (range_ptr) {
243
range = *range_ptr;
244
return true;
245
}
246
range.Clear();
247
return false;
248
}
249
250
bool Block::GetRangeContainingAddress(const Address &addr,
251
AddressRange &range) {
252
Function *function = CalculateSymbolContextFunction();
253
if (function) {
254
const AddressRange &func_range = function->GetAddressRange();
255
if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
256
const addr_t addr_offset = addr.GetOffset();
257
const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
258
if (addr_offset >= func_offset &&
259
addr_offset < func_offset + func_range.GetByteSize()) {
260
addr_t offset = addr_offset - func_offset;
261
262
const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
263
264
if (range_ptr) {
265
range.GetBaseAddress() = func_range.GetBaseAddress();
266
range.GetBaseAddress().SetOffset(func_offset +
267
range_ptr->GetRangeBase());
268
range.SetByteSize(range_ptr->GetByteSize());
269
return true;
270
}
271
}
272
}
273
}
274
range.Clear();
275
return false;
276
}
277
278
bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,
279
Target &target, AddressRange &range) {
280
Address load_address;
281
load_address.SetLoadAddress(load_addr, &target);
282
AddressRange containing_range;
283
return GetRangeContainingAddress(load_address, containing_range);
284
}
285
286
uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
287
Function *function = CalculateSymbolContextFunction();
288
if (function) {
289
const AddressRange &func_range = function->GetAddressRange();
290
if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
291
const addr_t addr_offset = addr.GetOffset();
292
const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
293
if (addr_offset >= func_offset &&
294
addr_offset < func_offset + func_range.GetByteSize()) {
295
addr_t offset = addr_offset - func_offset;
296
return m_ranges.FindEntryIndexThatContains(offset);
297
}
298
}
299
}
300
return UINT32_MAX;
301
}
302
303
bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
304
if (range_idx < m_ranges.GetSize()) {
305
Function *function = CalculateSymbolContextFunction();
306
if (function) {
307
const Range &vm_range = m_ranges.GetEntryRef(range_idx);
308
range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
309
range.GetBaseAddress().Slide(vm_range.GetRangeBase());
310
range.SetByteSize(vm_range.GetByteSize());
311
return true;
312
}
313
}
314
return false;
315
}
316
317
AddressRanges Block::GetRanges() {
318
AddressRanges ranges;
319
Function *function = CalculateSymbolContextFunction();
320
if (!function)
321
return ranges;
322
for (size_t i = 0, e = m_ranges.GetSize(); i < e; ++i) {
323
ranges.emplace_back();
324
auto &range = ranges.back();
325
const Range &vm_range = m_ranges.GetEntryRef(i);
326
range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
327
range.GetBaseAddress().Slide(vm_range.GetRangeBase());
328
range.SetByteSize(vm_range.GetByteSize());
329
}
330
return ranges;
331
}
332
333
bool Block::GetStartAddress(Address &addr) {
334
if (m_ranges.IsEmpty())
335
return false;
336
337
Function *function = CalculateSymbolContextFunction();
338
if (function) {
339
addr = function->GetAddressRange().GetBaseAddress();
340
addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase());
341
return true;
342
}
343
return false;
344
}
345
346
void Block::FinalizeRanges() {
347
m_ranges.Sort();
348
m_ranges.CombineConsecutiveRanges();
349
}
350
351
void Block::AddRange(const Range &range) {
352
Block *parent_block = GetParent();
353
if (parent_block && !parent_block->Contains(range)) {
354
Log *log = GetLog(LLDBLog::Symbols);
355
if (log) {
356
ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule());
357
Function *function = m_parent_scope->CalculateSymbolContextFunction();
358
const addr_t function_file_addr =
359
function->GetAddressRange().GetBaseAddress().GetFileAddress();
360
const addr_t block_start_addr = function_file_addr + range.GetRangeBase();
361
const addr_t block_end_addr = function_file_addr + range.GetRangeEnd();
362
Type *func_type = function->GetType();
363
364
const Declaration &func_decl = func_type->GetDeclaration();
365
if (func_decl.GetLine()) {
366
LLDB_LOGF(log,
367
"warning: %s:%u block {0x%8.8" PRIx64
368
"} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64
369
") which is not contained in parent block {0x%8.8" PRIx64
370
"} in function {0x%8.8" PRIx64 "} from %s",
371
func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(),
372
GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
373
block_end_addr, parent_block->GetID(), function->GetID(),
374
module_sp->GetFileSpec().GetPath().c_str());
375
} else {
376
LLDB_LOGF(log,
377
"warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64
378
" - 0x%" PRIx64
379
") which is not contained in parent block {0x%8.8" PRIx64
380
"} in function {0x%8.8" PRIx64 "} from %s",
381
GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
382
block_end_addr, parent_block->GetID(), function->GetID(),
383
module_sp->GetFileSpec().GetPath().c_str());
384
}
385
}
386
parent_block->AddRange(range);
387
}
388
m_ranges.Append(range);
389
}
390
391
// Return the current number of bytes that this object occupies in memory
392
size_t Block::MemorySize() const {
393
size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
394
if (m_inlineInfoSP.get())
395
mem_size += m_inlineInfoSP->MemorySize();
396
if (m_variable_list_sp.get())
397
mem_size += m_variable_list_sp->MemorySize();
398
return mem_size;
399
}
400
401
void Block::AddChild(const BlockSP &child_block_sp) {
402
if (child_block_sp) {
403
child_block_sp->SetParentScope(this);
404
m_children.push_back(child_block_sp);
405
}
406
}
407
408
void Block::SetInlinedFunctionInfo(const char *name, const char *mangled,
409
const Declaration *decl_ptr,
410
const Declaration *call_decl_ptr) {
411
m_inlineInfoSP = std::make_shared<InlineFunctionInfo>(name, mangled, decl_ptr,
412
call_decl_ptr);
413
}
414
415
VariableListSP Block::GetBlockVariableList(bool can_create) {
416
if (!m_parsed_block_variables) {
417
if (m_variable_list_sp.get() == nullptr && can_create) {
418
m_parsed_block_variables = true;
419
SymbolContext sc;
420
CalculateSymbolContext(&sc);
421
assert(sc.module_sp);
422
sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc);
423
}
424
}
425
return m_variable_list_sp;
426
}
427
428
uint32_t
429
Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,
430
bool stop_if_child_block_is_inlined_function,
431
const std::function<bool(Variable *)> &filter,
432
VariableList *variable_list) {
433
uint32_t num_variables_added = 0;
434
VariableList *block_var_list = GetBlockVariableList(can_create).get();
435
if (block_var_list) {
436
for (const VariableSP &var_sp : *block_var_list) {
437
if (filter(var_sp.get())) {
438
num_variables_added++;
439
variable_list->AddVariable(var_sp);
440
}
441
}
442
}
443
444
if (get_child_block_variables) {
445
collection::const_iterator pos, end = m_children.end();
446
for (pos = m_children.begin(); pos != end; ++pos) {
447
Block *child_block = pos->get();
448
if (!stop_if_child_block_is_inlined_function ||
449
child_block->GetInlinedFunctionInfo() == nullptr) {
450
num_variables_added += child_block->AppendBlockVariables(
451
can_create, get_child_block_variables,
452
stop_if_child_block_is_inlined_function, filter, variable_list);
453
}
454
}
455
}
456
return num_variables_added;
457
}
458
459
uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,
460
bool stop_if_block_is_inlined_function,
461
const std::function<bool(Variable *)> &filter,
462
VariableList *variable_list) {
463
uint32_t num_variables_added = 0;
464
VariableListSP variable_list_sp(GetBlockVariableList(can_create));
465
466
bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;
467
if (variable_list_sp) {
468
for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) {
469
VariableSP variable = variable_list_sp->GetVariableAtIndex(i);
470
if (filter(variable.get())) {
471
num_variables_added++;
472
variable_list->AddVariable(variable);
473
}
474
}
475
}
476
477
if (get_parent_variables) {
478
if (stop_if_block_is_inlined_function && is_inlined_function)
479
return num_variables_added;
480
481
Block *parent_block = GetParent();
482
if (parent_block)
483
num_variables_added += parent_block->AppendVariables(
484
can_create, get_parent_variables, stop_if_block_is_inlined_function,
485
filter, variable_list);
486
}
487
return num_variables_added;
488
}
489
490
SymbolFile *Block::GetSymbolFile() {
491
if (ModuleSP module_sp = CalculateSymbolContextModule())
492
return module_sp->GetSymbolFile();
493
return nullptr;
494
}
495
496
CompilerDeclContext Block::GetDeclContext() {
497
if (SymbolFile *sym_file = GetSymbolFile())
498
return sym_file->GetDeclContextForUID(GetID());
499
return CompilerDeclContext();
500
}
501
502
void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) {
503
m_parsed_block_info = b;
504
if (set_children) {
505
m_parsed_child_blocks = true;
506
collection::const_iterator pos, end = m_children.end();
507
for (pos = m_children.begin(); pos != end; ++pos)
508
(*pos)->SetBlockInfoHasBeenParsed(b, true);
509
}
510
}
511
512
void Block::SetDidParseVariables(bool b, bool set_children) {
513
m_parsed_block_variables = b;
514
if (set_children) {
515
collection::const_iterator pos, end = m_children.end();
516
for (pos = m_children.begin(); pos != end; ++pos)
517
(*pos)->SetDidParseVariables(b, true);
518
}
519
}
520
521
Block *Block::GetSibling() const {
522
if (m_parent_scope) {
523
Block *parent_block = GetParent();
524
if (parent_block)
525
return parent_block->GetSiblingForChild(this);
526
}
527
return nullptr;
528
}
529
// A parent of child blocks can be asked to find a sibling block given
530
// one of its child blocks
531
Block *Block::GetSiblingForChild(const Block *child_block) const {
532
if (!m_children.empty()) {
533
collection::const_iterator pos, end = m_children.end();
534
for (pos = m_children.begin(); pos != end; ++pos) {
535
if (pos->get() == child_block) {
536
if (++pos != end)
537
return pos->get();
538
break;
539
}
540
}
541
}
542
return nullptr;
543
}
544
545