Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Core/Section.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- Section.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/Core/Section.h"
10
#include "lldb/Core/Address.h"
11
#include "lldb/Core/Module.h"
12
#include "lldb/Symbol/ObjectFile.h"
13
#include "lldb/Target/SectionLoadList.h"
14
#include "lldb/Target/Target.h"
15
#include "lldb/Utility/FileSpec.h"
16
#include "lldb/Utility/VMRange.h"
17
18
#include <cinttypes>
19
#include <limits>
20
#include <utility>
21
22
namespace lldb_private {
23
class DataExtractor;
24
}
25
using namespace lldb;
26
using namespace lldb_private;
27
28
67.5k
const char *Section::GetTypeAsCString() const {
29
67.5k
  switch (m_type) {
30
0
  case eSectionTypeInvalid:
31
0
    return "invalid";
32
312
  case eSectionTypeCode:
33
312
    return "code";
34
332
  case eSectionTypeContainer:
35
332
    return "container";
36
93
  case eSectionTypeData:
37
93
    return "data";
38
128
  case eSectionTypeDataCString:
39
128
    return "data-cstr";
40
8
  case eSectionTypeDataCStringPointers:
41
8
    return "data-cstr-ptr";
42
0
  case eSectionTypeDataSymbolAddress:
43
0
    return "data-symbol-addr";
44
0
  case eSectionTypeData4:
45
0
    return "data-4-byte";
46
0
  case eSectionTypeData8:
47
0
    return "data-8-byte";
48
0
  case eSectionTypeData16:
49
0
    return "data-16-byte";
50
280
  case eSectionTypeDataPointers:
51
280
    return "data-ptrs";
52
12
  case eSectionTypeDebug:
53
12
    return "debug";
54
108
  case eSectionTypeZeroFill:
55
108
    return "zero-fill";
56
0
  case eSectionTypeDataObjCMessageRefs:
57
0
    return "objc-message-refs";
58
0
  case eSectionTypeDataObjCCFStrings:
59
0
    return "objc-cfstrings";
60
20
  case eSectionTypeDWARFDebugAbbrev:
61
20
    return "dwarf-abbrev";
62
1
  case eSectionTypeDWARFDebugAbbrevDwo:
63
1
    return "dwarf-abbrev-dwo";
64
3
  case eSectionTypeDWARFDebugAddr:
65
3
    return "dwarf-addr";
66
7
  case eSectionTypeDWARFDebugAranges:
67
7
    return "dwarf-aranges";
68
1
  case eSectionTypeDWARFDebugCuIndex:
69
1
    return "dwarf-cu-index";
70
1
  case eSectionTypeDWARFDebugTuIndex:
71
1
    return "dwarf-tu-index";
72
3
  case eSectionTypeDWARFDebugFrame:
73
3
    return "dwarf-frame";
74
30
  case eSectionTypeDWARFDebugInfo:
75
30
    return "dwarf-info";
76
1
  case eSectionTypeDWARFDebugInfoDwo:
77
1
    return "dwarf-info-dwo";
78
18
  case eSectionTypeDWARFDebugLine:
79
18
    return "dwarf-line";
80
2
  case eSectionTypeDWARFDebugLineStr:
81
2
    return "dwarf-line-str";
82
2
  case eSectionTypeDWARFDebugLoc:
83
2
    return "dwarf-loc";
84
2
  case eSectionTypeDWARFDebugLocDwo:
85
2
    return "dwarf-loc-dwo";
86
2
  case eSectionTypeDWARFDebugLocLists:
87
2
    return "dwarf-loclists";
88
2
  case eSectionTypeDWARFDebugLocListsDwo:
89
2
    return "dwarf-loclists-dwo";
90
1
  case eSectionTypeDWARFDebugMacInfo:
91
1
    return "dwarf-macinfo";
92
2
  case eSectionTypeDWARFDebugMacro:
93
2
    return "dwarf-macro";
94
1
  case eSectionTypeDWARFDebugPubNames:
95
1
    return "dwarf-pubnames";
96
1
  case eSectionTypeDWARFDebugPubTypes:
97
1
    return "dwarf-pubtypes";
98
4
  case eSectionTypeDWARFDebugRanges:
99
4
    return "dwarf-ranges";
100
2
  case eSectionTypeDWARFDebugRngLists:
101
2
    return "dwarf-rnglists";
102
2
  case eSectionTypeDWARFDebugRngListsDwo:
103
2
    return "dwarf-rnglists-dwo";
104
18
  case eSectionTypeDWARFDebugStr:
105
18
    return "dwarf-str";
106
1
  case eSectionTypeDWARFDebugStrDwo:
107
1
    return "dwarf-str-dwo";
108
1
  case eSectionTypeDWARFDebugStrOffsets:
109
1
    return "dwarf-str-offsets";
110
1
  case eSectionTypeDWARFDebugStrOffsetsDwo:
111
1
    return "dwarf-str-offsets-dwo";
112
3
  case eSectionTypeDWARFDebugTypes:
113
3
    return "dwarf-types";
114
2
  case eSectionTypeDWARFDebugTypesDwo:
115
2
    return "dwarf-types-dwo";
116
2
  case eSectionTypeDWARFDebugNames:
117
2
    return "dwarf-names";
118
16
  case eSectionTypeELFSymbolTable:
119
16
    return "elf-symbol-table";
120
1
  case eSectionTypeELFDynamicSymbols:
121
1
    return "elf-dynamic-symbols";
122
18
  case eSectionTypeELFRelocationEntries:
123
18
    return "elf-relocation-entries";
124
1
  case eSectionTypeELFDynamicLinkInfo:
125
1
    return "elf-dynamic-link-info";
126
8
  case eSectionTypeDWARFAppleNames:
127
8
    return "apple-names";
128
8
  case eSectionTypeDWARFAppleTypes:
129
8
    return "apple-types";
130
8
  case eSectionTypeDWARFAppleNamespaces:
131
8
    return "apple-namespaces";
132
8
  case eSectionTypeDWARFAppleObjC:
133
8
    return "apple-objc";
134
49
  case eSectionTypeEHFrame:
135
49
    return "eh-frame";
136
0
  case eSectionTypeARMexidx:
137
0
    return "ARM.exidx";
138
0
  case eSectionTypeARMextab:
139
0
    return "ARM.extab";
140
92
  case eSectionTypeCompactUnwind:
141
92
    return "compact-unwind";
142
0
  case eSectionTypeGoSymtab:
143
0
    return "go-symtab";
144
0
  case eSectionTypeAbsoluteAddress:
145
0
    return "absolute";
146
1
  case eSectionTypeDWARFGNUDebugAltLink:
147
1
    return "dwarf-gnu-debugaltlink";
148
0
  case eSectionTypeCTF:
149
0
    return "ctf";
150
65.9k
  case eSectionTypeOther:
151
65.9k
    return "regular";
152
0
  case eSectionTypeSwiftModules:
153
0
    return "swift-modules";
154
67.5k
  }
155
0
  return "unknown";
156
67.5k
}
157
158
Section::Section(const ModuleSP &module_sp, ObjectFile *obj_file,
159
                 user_id_t sect_id, ConstString name,
160
                 SectionType sect_type, addr_t file_addr, addr_t byte_size,
161
                 lldb::offset_t file_offset, lldb::offset_t file_size,
162
                 uint32_t log2align, uint32_t flags,
163
                 uint32_t target_byte_size /*=1*/)
164
404k
    : ModuleChild(module_sp), UserID(sect_id), Flags(flags),
165
404k
      m_obj_file(obj_file), m_type(sect_type), m_parent_wp(), m_name(name),
166
404k
      m_file_addr(file_addr), m_byte_size(byte_size),
167
404k
      m_file_offset(file_offset), m_file_size(file_size),
168
404k
      m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false),
169
404k
      m_thread_specific(false), m_readable(false), m_writable(false),
170
404k
      m_executable(false), m_relocated(false), m_target_byte_size(target_byte_size) {
171
404k
}
172
173
Section::Section(const lldb::SectionSP &parent_section_sp,
174
                 const ModuleSP &module_sp, ObjectFile *obj_file,
175
                 user_id_t sect_id, ConstString name,
176
                 SectionType sect_type, addr_t file_addr, addr_t byte_size,
177
                 lldb::offset_t file_offset, lldb::offset_t file_size,
178
                 uint32_t log2align, uint32_t flags,
179
                 uint32_t target_byte_size /*=1*/)
180
1.72M
    : ModuleChild(module_sp), UserID(sect_id), Flags(flags),
181
1.72M
      m_obj_file(obj_file), m_type(sect_type), m_parent_wp(), m_name(name),
182
1.72M
      m_file_addr(file_addr), m_byte_size(byte_size),
183
1.72M
      m_file_offset(file_offset), m_file_size(file_size),
184
1.72M
      m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false),
185
1.72M
      m_thread_specific(false), m_readable(false), m_writable(false),
186
1.72M
      m_executable(false), m_relocated(false), m_target_byte_size(target_byte_size) {
187
1.72M
  if (parent_section_sp)
188
1.64M
    m_parent_wp = parent_section_sp;
189
1.72M
}
190
191
2.04M
Section::~Section() = default;
192
193
1.16G
addr_t Section::GetFileAddress() const {
194
1.16G
  SectionSP parent_sp(GetParent());
195
1.16G
  if (parent_sp) {
196
    // This section has a parent which means m_file_addr is an offset into the
197
    // parent section, so the file address for this section is the file address
198
    // of the parent plus the offset
199
572M
    return parent_sp->GetFileAddress() + m_file_addr;
200
572M
  }
201
  // This section has no parent, so m_file_addr is the file base address
202
596M
  return m_file_addr;
203
1.16G
}
204
205
0
bool Section::SetFileAddress(lldb::addr_t file_addr) {
206
0
  SectionSP parent_sp(GetParent());
207
0
  if (parent_sp) {
208
0
    if (m_file_addr >= file_addr)
209
0
      return parent_sp->SetFileAddress(m_file_addr - file_addr);
210
0
    return false;
211
0
  } else {
212
    // This section has no parent, so m_file_addr is the file base address
213
0
    m_file_addr = file_addr;
214
0
    return true;
215
0
  }
216
0
}
217
218
6.68M
lldb::addr_t Section::GetOffset() const {
219
  // This section has a parent which means m_file_addr is an offset.
220
6.68M
  SectionSP parent_sp(GetParent());
221
6.68M
  if (parent_sp)
222
6.68M
    return m_file_addr;
223
224
  // This section has no parent, so there is no offset to be had
225
0
  return 0;
226
6.68M
}
227
228
10.3M
addr_t Section::GetLoadBaseAddress(Target *target) const {
229
10.3M
  addr_t load_base_addr = LLDB_INVALID_ADDRESS;
230
10.3M
  SectionSP parent_sp(GetParent());
231
10.3M
  if (parent_sp) {
232
5.15M
    load_base_addr = parent_sp->GetLoadBaseAddress(target);
233
5.15M
    if (load_base_addr != LLDB_INVALID_ADDRESS)
234
5.15M
      load_base_addr += GetOffset();
235
5.15M
  }
236
10.3M
  if (load_base_addr == LLDB_INVALID_ADDRESS) {
237
5.16M
    load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress(
238
5.16M
        const_cast<Section *>(this)->shared_from_this());
239
5.16M
  }
240
10.3M
  return load_base_addr;
241
10.3M
}
242
243
bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr,
244
1.96M
                                      bool allow_section_end) const {
245
1.96M
  const size_t num_children = m_children.GetSize();
246
2.53M
  for (size_t i = 0; i < num_children; 
i++570k
) {
247
1.53M
    Section *child_section = m_children.GetSectionAtIndex(i).get();
248
249
1.53M
    addr_t child_offset = child_section->GetOffset();
250
1.53M
    if (child_offset <= offset &&
251
1.53M
        offset - child_offset <
252
1.51M
            child_section->GetByteSize() + (allow_section_end ? 
1410k
:
01.10M
))
253
962k
      return child_section->ResolveContainedAddress(offset - child_offset,
254
962k
                                                    so_addr, allow_section_end);
255
1.53M
  }
256
1.00M
  so_addr.SetOffset(offset);
257
1.00M
  so_addr.SetSection(const_cast<Section *>(this)->shared_from_this());
258
259
  // Ensure that there are no orphaned (i.e., moduleless) sections.
260
1.00M
  assert(GetModule().get());
261
1.00M
  return true;
262
1.00M
}
263
264
78.6M
bool Section::ContainsFileAddress(addr_t vm_addr) const {
265
78.6M
  const addr_t file_addr = GetFileAddress();
266
78.6M
  if (file_addr != LLDB_INVALID_ADDRESS && !IsThreadSpecific()) {
267
78.6M
    if (file_addr <= vm_addr) {
268
78.6M
      const addr_t offset = (vm_addr - file_addr) * m_target_byte_size;
269
78.6M
      return offset < GetByteSize();
270
78.6M
    }
271
78.6M
  }
272
20.9k
  return false;
273
78.6M
}
274
275
void Section::Dump(llvm::raw_ostream &s, unsigned indent, Target *target,
276
1.70k
                   uint32_t depth) const {
277
1.70k
  s.indent(indent);
278
1.70k
  s << llvm::format("0x%8.8" PRIx64 " %-16s ", GetID(), GetTypeAsCString());
279
1.70k
  bool resolved = true;
280
1.70k
  addr_t addr = LLDB_INVALID_ADDRESS;
281
282
1.70k
  if (GetByteSize() == 0)
283
68
    s.indent(39);
284
1.63k
  else {
285
1.63k
    if (target)
286
138
      addr = GetLoadBaseAddress(target);
287
288
1.63k
    if (addr == LLDB_INVALID_ADDRESS) {
289
1.56k
      if (target)
290
60
        resolved = false;
291
1.56k
      addr = GetFileAddress();
292
1.56k
    }
293
294
1.63k
    VMRange range(addr, addr + m_byte_size);
295
1.63k
    range.Dump(s, 0);
296
1.63k
  }
297
298
1.70k
  s << llvm::format("%c %c%c%c  0x%8.8" PRIx64 " 0x%8.8" PRIx64 " 0x%8.8x ",
299
1.70k
                    resolved ? 
' '1.64k
:
'*'60
, m_readable ?
'r'1.63k
:
'-'68
,
300
1.70k
                    m_writable ? 
'w'789
:
'-'918
, m_executable ?
'x'768
:
'-'939
,
301
1.70k
                    m_file_offset, m_file_size, Get());
302
303
1.70k
  DumpName(s);
304
305
1.70k
  s << "\n";
306
307
1.70k
  if (depth > 0)
308
1.70k
    m_children.Dump(s, indent, target, false, depth - 1);
309
1.70k
}
310
311
57.9k
void Section::DumpName(llvm::raw_ostream &s) const {
312
57.9k
  SectionSP parent_sp(GetParent());
313
57.9k
  if (parent_sp) {
314
28.7k
    parent_sp->DumpName(s);
315
28.7k
    s << '.';
316
29.1k
  } else {
317
    // The top most section prints the module basename
318
29.1k
    const char *name = nullptr;
319
29.1k
    ModuleSP module_sp(GetModule());
320
321
29.1k
    if (m_obj_file) {
322
29.1k
      const FileSpec &file_spec = m_obj_file->GetFileSpec();
323
29.1k
      name = file_spec.GetFilename().AsCString();
324
29.1k
    }
325
29.1k
    if ((!name || !name[0]) && 
module_sp0
)
326
0
      name = module_sp->GetFileSpec().GetFilename().AsCString();
327
29.1k
    if (name && name[0])
328
29.1k
      s << name << '.';
329
29.1k
  }
330
57.9k
  s << m_name;
331
57.9k
}
332
333
136M
bool Section::IsDescendant(const Section *section) {
334
136M
  if (this == section)
335
31.1M
    return true;
336
105M
  SectionSP parent_sp(GetParent());
337
105M
  if (parent_sp)
338
68.4M
    return parent_sp->IsDescendant(section);
339
37.3M
  return false;
340
105M
}
341
342
96
bool Section::Slide(addr_t slide_amount, bool slide_children) {
343
96
  if (m_file_addr != LLDB_INVALID_ADDRESS) {
344
96
    if (slide_amount == 0)
345
0
      return true;
346
347
96
    m_file_addr += slide_amount;
348
349
96
    if (slide_children)
350
0
      m_children.Slide(slide_amount, slide_children);
351
352
96
    return true;
353
96
  }
354
0
  return false;
355
96
}
356
357
/// Get the permissions as OR'ed bits from lldb::Permissions
358
83.9k
uint32_t Section::GetPermissions() const {
359
83.9k
  uint32_t permissions = 0;
360
83.9k
  if (m_readable)
361
18.2k
    permissions |= ePermissionsReadable;
362
83.9k
  if (m_writable)
363
167
    permissions |= ePermissionsWritable;
364
83.9k
  if (m_executable)
365
18.0k
    permissions |= ePermissionsExecutable;
366
83.9k
  return permissions;
367
83.9k
}
368
369
/// Set the permissions using bits OR'ed from lldb::Permissions
370
2.06M
void Section::SetPermissions(uint32_t permissions) {
371
2.06M
  m_readable = (permissions & ePermissionsReadable) != 0;
372
2.06M
  m_writable = (permissions & ePermissionsWritable) != 0;
373
2.06M
  m_executable = (permissions & ePermissionsExecutable) != 0;
374
2.06M
}
375
376
lldb::offset_t Section::GetSectionData(void *dst, lldb::offset_t dst_len,
377
0
                                       lldb::offset_t offset) {
378
0
  if (m_obj_file)
379
0
    return m_obj_file->ReadSectionData(this, offset, dst, dst_len);
380
0
  return 0;
381
0
}
382
383
28.2k
lldb::offset_t Section::GetSectionData(DataExtractor &section_data) {
384
28.2k
  if (m_obj_file)
385
28.2k
    return m_obj_file->ReadSectionData(this, section_data);
386
0
  return 0;
387
28.2k
}
388
389
14.3k
bool Section::ContainsOnlyDebugInfo() const {
390
14.3k
  switch (m_type) {
391
48
  case eSectionTypeInvalid:
392
2.70k
  case eSectionTypeCode:
393
3.70k
  case eSectionTypeContainer:
394
4.33k
  case eSectionTypeData:
395
5.66k
  case eSectionTypeDataCString:
396
5.74k
  case eSectionTypeDataCStringPointers:
397
5.74k
  case eSectionTypeDataSymbolAddress:
398
5.74k
  case eSectionTypeData4:
399
5.74k
  case eSectionTypeData8:
400
5.74k
  case eSectionTypeData16:
401
8.70k
  case eSectionTypeDataPointers:
402
9.78k
  case eSectionTypeZeroFill:
403
9.78k
  case eSectionTypeDataObjCMessageRefs:
404
9.78k
  case eSectionTypeDataObjCCFStrings:
405
9.78k
  case eSectionTypeELFSymbolTable:
406
9.78k
  case eSectionTypeELFDynamicSymbols:
407
9.78k
  case eSectionTypeELFRelocationEntries:
408
9.78k
  case eSectionTypeELFDynamicLinkInfo:
409
10.2k
  case eSectionTypeEHFrame:
410
10.2k
  case eSectionTypeARMexidx:
411
10.2k
  case eSectionTypeARMextab:
412
11.1k
  case eSectionTypeCompactUnwind:
413
11.1k
  case eSectionTypeGoSymtab:
414
11.1k
  case eSectionTypeAbsoluteAddress:
415
13.8k
  case eSectionTypeOther:
416
  // Used for "__dof_cache" in mach-o or ".debug" for COFF which isn't debug
417
  // information that we parse at all. This was causing system files with no
418
  // debug info to show debug info byte sizes in the "statistics dump" output
419
  // for each module. New "eSectionType" enums should be created for dedicated
420
  // debug info that has a predefined format if we wish for these sections to
421
  // show up as debug info.
422
14.0k
  case eSectionTypeDebug:
423
14.0k
    return false;
424
425
42
  case eSectionTypeDWARFDebugAbbrev:
426
42
  case eSectionTypeDWARFDebugAbbrevDwo:
427
42
  case eSectionTypeDWARFDebugAddr:
428
63
  case eSectionTypeDWARFDebugAranges:
429
63
  case eSectionTypeDWARFDebugCuIndex:
430
63
  case eSectionTypeDWARFDebugTuIndex:
431
75
  case eSectionTypeDWARFDebugFrame:
432
115
  case eSectionTypeDWARFDebugInfo:
433
115
  case eSectionTypeDWARFDebugInfoDwo:
434
155
  case eSectionTypeDWARFDebugLine:
435
155
  case eSectionTypeDWARFDebugLineStr:
436
155
  case eSectionTypeDWARFDebugLoc:
437
155
  case eSectionTypeDWARFDebugLocDwo:
438
155
  case eSectionTypeDWARFDebugLocLists:
439
155
  case eSectionTypeDWARFDebugLocListsDwo:
440
155
  case eSectionTypeDWARFDebugMacInfo:
441
155
  case eSectionTypeDWARFDebugMacro:
442
155
  case eSectionTypeDWARFDebugPubNames:
443
155
  case eSectionTypeDWARFDebugPubTypes:
444
161
  case eSectionTypeDWARFDebugRanges:
445
161
  case eSectionTypeDWARFDebugRngLists:
446
161
  case eSectionTypeDWARFDebugRngListsDwo:
447
203
  case eSectionTypeDWARFDebugStr:
448
203
  case eSectionTypeDWARFDebugStrDwo:
449
203
  case eSectionTypeDWARFDebugStrOffsets:
450
203
  case eSectionTypeDWARFDebugStrOffsetsDwo:
451
203
  case eSectionTypeDWARFDebugTypes:
452
203
  case eSectionTypeDWARFDebugTypesDwo:
453
203
  case eSectionTypeDWARFDebugNames:
454
231
  case eSectionTypeDWARFAppleNames:
455
259
  case eSectionTypeDWARFAppleTypes:
456
287
  case eSectionTypeDWARFAppleNamespaces:
457
315
  case eSectionTypeDWARFAppleObjC:
458
315
  case eSectionTypeDWARFGNUDebugAltLink:
459
315
  case eSectionTypeCTF:
460
315
  case eSectionTypeSwiftModules:
461
315
    return true;
462
14.3k
  }
463
0
  return false;
464
14.3k
}
465
466
467
#pragma mark SectionList
468
469
5.03k
SectionList &SectionList::operator=(const SectionList &rhs) {
470
5.03k
  if (this != &rhs)
471
5.03k
    m_sections = rhs.m_sections;
472
5.03k
  return *this;
473
5.03k
}
474
475
2.48M
size_t SectionList::AddSection(const lldb::SectionSP &section_sp) {
476
2.48M
  if (section_sp) {
477
2.48M
    size_t section_index = m_sections.size();
478
2.48M
    m_sections.push_back(section_sp);
479
2.48M
    return section_index;
480
2.48M
  }
481
482
0
  return std::numeric_limits<size_t>::max();
483
2.48M
}
484
485
// Warning, this can be slow as it's removing items from a std::vector.
486
0
bool SectionList::DeleteSection(size_t idx) {
487
0
  if (idx < m_sections.size()) {
488
0
    m_sections.erase(m_sections.begin() + idx);
489
0
    return true;
490
0
  }
491
0
  return false;
492
0
}
493
494
0
size_t SectionList::FindSectionIndex(const Section *sect) {
495
0
  iterator sect_iter;
496
0
  iterator begin = m_sections.begin();
497
0
  iterator end = m_sections.end();
498
0
  for (sect_iter = begin; sect_iter != end; ++sect_iter) {
499
0
    if (sect_iter->get() == sect) {
500
      // The secton was already in this section list
501
0
      return std::distance(begin, sect_iter);
502
0
    }
503
0
  }
504
0
  return UINT32_MAX;
505
0
}
506
507
0
size_t SectionList::AddUniqueSection(const lldb::SectionSP &sect_sp) {
508
0
  size_t sect_idx = FindSectionIndex(sect_sp.get());
509
0
  if (sect_idx == UINT32_MAX) {
510
0
    sect_idx = AddSection(sect_sp);
511
0
  }
512
0
  return sect_idx;
513
0
}
514
515
bool SectionList::ReplaceSection(user_id_t sect_id,
516
                                 const lldb::SectionSP &sect_sp,
517
54
                                 uint32_t depth) {
518
54
  iterator sect_iter, end = m_sections.end();
519
96
  for (sect_iter = m_sections.begin(); sect_iter != end; 
++sect_iter42
) {
520
54
    if ((*sect_iter)->GetID() == sect_id) {
521
12
      *sect_iter = sect_sp;
522
12
      return true;
523
42
    } else if (depth > 0) {
524
42
      if ((*sect_iter)
525
42
              ->GetChildren()
526
42
              .ReplaceSection(sect_id, sect_sp, depth - 1))
527
0
        return true;
528
42
    }
529
54
  }
530
42
  return false;
531
54
}
532
533
2.96M
size_t SectionList::GetNumSections(uint32_t depth) const {
534
2.96M
  size_t count = m_sections.size();
535
2.96M
  if (depth > 0) {
536
111k
    const_iterator sect_iter, end = m_sections.end();
537
459k
    for (sect_iter = m_sections.begin(); sect_iter != end; 
++sect_iter347k
) {
538
347k
      count += (*sect_iter)->GetChildren().GetNumSections(depth - 1);
539
347k
    }
540
111k
  }
541
2.96M
  return count;
542
2.96M
}
543
544
4.40M
SectionSP SectionList::GetSectionAtIndex(size_t idx) const {
545
4.40M
  SectionSP sect_sp;
546
4.40M
  if (idx < m_sections.size())
547
4.40M
    sect_sp = m_sections[idx];
548
4.40M
  return sect_sp;
549
4.40M
}
550
551
SectionSP
552
22.1M
SectionList::FindSectionByName(ConstString section_dstr) const {
553
22.1M
  SectionSP sect_sp;
554
  // Check if we have a valid section string
555
22.1M
  if (section_dstr && 
!m_sections.empty()22.1M
) {
556
4.05M
    const_iterator sect_iter;
557
4.05M
    const_iterator end = m_sections.end();
558
4.05M
    for (sect_iter = m_sections.begin();
559
25.2M
         sect_iter != end && 
sect_sp.get() == nullptr21.8M
;
++sect_iter21.1M
) {
560
21.1M
      Section *child_section = sect_iter->get();
561
21.1M
      if (child_section) {
562
21.1M
        if (child_section->GetName() == section_dstr) {
563
929k
          sect_sp = *sect_iter;
564
20.2M
        } else {
565
20.2M
          sect_sp =
566
20.2M
              child_section->GetChildren().FindSectionByName(section_dstr);
567
20.2M
        }
568
21.1M
      }
569
21.1M
    }
570
4.05M
  }
571
22.1M
  return sect_sp;
572
22.1M
}
573
574
8.72M
SectionSP SectionList::FindSectionByID(user_id_t sect_id) const {
575
8.72M
  SectionSP sect_sp;
576
8.72M
  if (sect_id) {
577
8.72M
    const_iterator sect_iter;
578
8.72M
    const_iterator end = m_sections.end();
579
8.72M
    for (sect_iter = m_sections.begin();
580
16.7M
         sect_iter != end && 
sect_sp.get() == nullptr9.37M
;
++sect_iter8.03M
) {
581
8.72M
      if ((*sect_iter)->GetID() == sect_id) {
582
681k
        sect_sp = *sect_iter;
583
681k
        break;
584
8.03M
      } else {
585
8.03M
        sect_sp = (*sect_iter)->GetChildren().FindSectionByID(sect_id);
586
8.03M
      }
587
8.72M
    }
588
8.72M
  }
589
8.72M
  return sect_sp;
590
8.72M
}
591
592
SectionSP SectionList::FindSectionByType(SectionType sect_type,
593
                                         bool check_children,
594
6.40M
                                         size_t start_idx) const {
595
6.40M
  SectionSP sect_sp;
596
6.40M
  size_t num_sections = m_sections.size();
597
12.4M
  for (size_t idx = start_idx; idx < num_sections; 
++idx5.99M
) {
598
6.12M
    if (m_sections[idx]->GetType() == sect_type) {
599
81.7k
      sect_sp = m_sections[idx];
600
81.7k
      break;
601
6.04M
    } else if (check_children) {
602
6.04M
      sect_sp = m_sections[idx]->GetChildren().FindSectionByType(
603
6.04M
          sect_type, check_children, 0);
604
6.04M
      if (sect_sp)
605
41.9k
        break;
606
6.04M
    }
607
6.12M
  }
608
6.40M
  return sect_sp;
609
6.40M
}
610
611
SectionSP SectionList::FindSectionContainingFileAddress(addr_t vm_addr,
612
65.4M
                                                        uint32_t depth) const {
613
65.4M
  SectionSP sect_sp;
614
65.4M
  const_iterator sect_iter;
615
65.4M
  const_iterator end = m_sections.end();
616
65.4M
  for (sect_iter = m_sections.begin();
617
122M
       sect_iter != end && 
sect_sp.get() == nullptr100M
;
++sect_iter56.8M
) {
618
56.8M
    Section *sect = sect_iter->get();
619
56.8M
    if (sect->ContainsFileAddress(vm_addr)) {
620
      // The file address is in this section. We need to make sure one of our
621
      // child sections doesn't contain this address as well as obeying the
622
      // depth limit that was passed in.
623
43.6M
      if (depth > 0)
624
43.6M
        sect_sp = sect->GetChildren().FindSectionContainingFileAddress(
625
43.6M
            vm_addr, depth - 1);
626
627
43.6M
      if (sect_sp.get() == nullptr && 
!sect->IsFake()21.8M
)
628
21.8M
        sect_sp = *sect_iter;
629
43.6M
    }
630
56.8M
  }
631
65.4M
  return sect_sp;
632
65.4M
}
633
634
0
bool SectionList::ContainsSection(user_id_t sect_id) const {
635
0
  return FindSectionByID(sect_id).get() != nullptr;
636
0
}
637
638
void SectionList::Dump(llvm::raw_ostream &s, unsigned indent, Target *target,
639
1.81k
                       bool show_header, uint32_t depth) const {
640
1.81k
  bool target_has_loaded_sections =
641
1.81k
      target && 
!target->GetSectionLoadList().IsEmpty()145
;
642
1.81k
  if (show_header && 
!m_sections.empty()106
) {
643
106
    s.indent(indent);
644
106
    s << llvm::formatv(
645
106
        "SectID     Type             {0} Address                          "
646
106
        "   Perm File Off.  File Size  Flags "
647
106
        "     Section Name\n",
648
106
        target_has_loaded_sections ? 
"Load"6
:
"File"100
);
649
106
    s.indent(indent);
650
106
    s << "---------- ---------------- "
651
106
         "---------------------------------------  ---- ---------- "
652
106
         "---------- "
653
106
         "---------- ----------------------------\n";
654
106
  }
655
656
1.81k
  for (const auto &section_sp : m_sections)
657
1.70k
    section_sp->Dump(s, indent, target_has_loaded_sections ? 
target138
:
nullptr1.56k
,
658
1.70k
                     depth);
659
1.81k
}
660
661
48
size_t SectionList::Slide(addr_t slide_amount, bool slide_children) {
662
48
  size_t count = 0;
663
48
  const_iterator pos, end = m_sections.end();
664
96
  for (pos = m_sections.begin(); pos != end; 
++pos48
) {
665
48
    if ((*pos)->Slide(slide_amount, slide_children))
666
48
      ++count;
667
48
  }
668
48
  return count;
669
48
}
670
671
2.92k
uint64_t SectionList::GetDebugInfoSize() const {
672
2.92k
  uint64_t debug_info_size = 0;
673
16.3k
  for (const auto &section : m_sections) {
674
16.3k
    const SectionList &sub_sections = section->GetChildren();
675
16.3k
    if (sub_sections.GetSize() > 0)
676
1.96k
      debug_info_size += sub_sections.GetDebugInfoSize();
677
14.3k
    else if (section->ContainsOnlyDebugInfo())
678
315
      debug_info_size += section->GetFileSize();
679
16.3k
  }
680
2.92k
  return debug_info_size;
681
2.92k
}
682
683
namespace llvm {
684
namespace json {
685
686
bool fromJSON(const llvm::json::Value &value,
687
5
              lldb_private::JSONSection &section, llvm::json::Path path) {
688
5
  llvm::json::ObjectMapper o(value, path);
689
5
  return o && o.map("name", section.name) && o.map("type", section.type) &&
690
5
         o.map("size", section.address) && o.map("size", section.size);
691
5
}
692
693
bool fromJSON(const llvm::json::Value &value, lldb::SectionType &type,
694
1
              llvm::json::Path path) {
695
1
  if (auto str = value.getAsString()) {
696
1
    type = llvm::StringSwitch<lldb::SectionType>(*str)
697
1
               .Case("code", eSectionTypeCode)
698
1
               .Case("container", eSectionTypeContainer)
699
1
               .Case("data", eSectionTypeData)
700
1
               .Case("debug", eSectionTypeDebug)
701
1
               .Default(eSectionTypeInvalid);
702
703
1
    if (type == eSectionTypeInvalid) {
704
0
      path.report("invalid section type");
705
0
      return false;
706
0
    }
707
708
1
    return true;
709
1
  }
710
0
  path.report("expected string");
711
0
  return false;
712
1
}
713
} // namespace json
714
} // namespace llvm