20
20
#include < algorithm>
21
21
#include < map>
22
22
#include < optional>
23
- #include < vector>
24
23
#include < utility>
24
+ #include < vector>
25
25
26
26
using namespace lldb_private ;
27
27
using namespace minidump ;
@@ -75,8 +75,7 @@ UUID MinidumpParser::GetModuleUUID(const minidump::Module *module) {
75
75
if (GetArchitecture ().GetTriple ().isOSBinFormatELF ()) {
76
76
if (pdb70_uuid->Age != 0 )
77
77
return UUID (pdb70_uuid, sizeof (*pdb70_uuid));
78
- return UUID (&pdb70_uuid->Uuid ,
79
- sizeof (pdb70_uuid->Uuid ));
78
+ return UUID (&pdb70_uuid->Uuid , sizeof (pdb70_uuid->Uuid ));
80
79
}
81
80
return UUID (*pdb70_uuid);
82
81
} else if (cv_signature == CvSignature::ElfBuildId)
@@ -429,62 +428,65 @@ MinidumpParser::GetExceptionStreams() {
429
428
430
429
std::optional<minidump::Range>
431
430
MinidumpParser::FindMemoryRange (lldb::addr_t addr) {
432
- Log *log = GetLog (LLDBLog::Modules);
431
+ if (m_memory_ranges.IsEmpty ())
432
+ PopulateMemoryRanges ();
433
+
434
+ const MemoryRangeVector::Entry *entry =
435
+ m_memory_ranges.FindEntryThatContains (addr);
436
+ if (!entry)
437
+ return std::nullopt;
433
438
439
+ return entry->data ;
440
+ }
441
+
442
+ void MinidumpParser::PopulateMemoryRanges () {
443
+ Log *log = GetLog (LLDBLog::Modules);
434
444
auto ExpectedMemory = GetMinidumpFile ().getMemoryList ();
435
- if (!ExpectedMemory) {
436
- LLDB_LOG_ERROR (log, ExpectedMemory.takeError (),
437
- " Failed to read memory list: {0}" );
438
- } else {
445
+ if (ExpectedMemory) {
439
446
for (const auto &memory_desc : *ExpectedMemory) {
440
447
const LocationDescriptor &loc_desc = memory_desc.Memory ;
441
448
const lldb::addr_t range_start = memory_desc.StartOfMemoryRange ;
442
449
const size_t range_size = loc_desc.DataSize ;
443
-
444
- if (loc_desc.RVA + loc_desc.DataSize > GetData ().size ())
445
- return std::nullopt;
446
-
447
- if (range_start <= addr && addr < range_start + range_size) {
448
- auto ExpectedSlice = GetMinidumpFile ().getRawData (loc_desc);
449
- if (!ExpectedSlice) {
450
- LLDB_LOG_ERROR (log, ExpectedSlice.takeError (),
451
- " Failed to get memory slice: {0}" );
452
- return std::nullopt;
453
- }
454
- return minidump::Range (range_start, *ExpectedSlice);
450
+ auto ExpectedSlice = GetMinidumpFile ().getRawData (loc_desc);
451
+ if (!ExpectedSlice) {
452
+ LLDB_LOG_ERROR (log, ExpectedSlice.takeError (),
453
+ " Failed to get memory slice: {0}" );
454
+ continue ;
455
455
}
456
+ m_memory_ranges.Append (MemoryRangeVector::Entry (
457
+ range_start, range_size,
458
+ minidump::Range (range_start, *ExpectedSlice)));
456
459
}
460
+ } else {
461
+ LLDB_LOG_ERROR (log, ExpectedMemory.takeError (),
462
+ " Failed to read memory list: {0}" );
457
463
}
458
464
459
465
if (!GetStream (StreamType::Memory64List).empty ()) {
460
466
llvm::Error err = llvm::Error::success ();
461
- for (const auto &memory_desc : GetMinidumpFile ().getMemory64List (err)) {
462
- if (memory_desc. first . StartOfMemoryRange <= addr
463
- && addr < memory_desc.first .StartOfMemoryRange + memory_desc.first .DataSize ) {
464
- return minidump::Range (memory_desc.first .StartOfMemoryRange , memory_desc. second );
465
- }
467
+ for (const auto &memory_desc : GetMinidumpFile ().getMemory64List (err)) {
468
+ m_memory_ranges. Append ( MemoryRangeVector::Entry (
469
+ memory_desc.first .StartOfMemoryRange , memory_desc.first .DataSize ,
470
+ minidump::Range (memory_desc.first .StartOfMemoryRange ,
471
+ memory_desc. second )));
466
472
}
467
473
468
474
if (err)
469
475
LLDB_LOG_ERROR (log, std::move (err), " Failed to read memory64 list: {0}" );
470
476
}
471
477
472
- return std::nullopt ;
478
+ m_memory_ranges. Sort () ;
473
479
}
474
480
475
481
llvm::ArrayRef<uint8_t > MinidumpParser::GetMemory (lldb::addr_t addr,
476
482
size_t size) {
477
- // I don't have a sense of how frequently this is called or how many memory
478
- // ranges a Minidump typically has, so I'm not sure if searching for the
479
- // appropriate range linearly each time is stupid. Perhaps we should build
480
- // an index for faster lookups.
481
483
std::optional<minidump::Range> range = FindMemoryRange (addr);
482
484
if (!range)
483
485
return {};
484
486
485
487
// There's at least some overlap between the beginning of the desired range
486
- // (addr) and the current range. Figure out where the overlap begins and how
487
- // much overlap there is.
488
+ // (addr) and the current range. Figure out where the overlap begins and
489
+ // how much overlap there is.
488
490
489
491
const size_t offset = addr - range->start ;
490
492
@@ -495,7 +497,8 @@ llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr,
495
497
return range->range_ref .slice (offset, overlap);
496
498
}
497
499
498
- llvm::iterator_range<FallibleMemory64Iterator> MinidumpParser::GetMemory64Iterator (llvm::Error &err) {
500
+ llvm::iterator_range<FallibleMemory64Iterator>
501
+ MinidumpParser::GetMemory64Iterator (llvm::Error &err) {
499
502
llvm::ErrorAsOutParameter ErrAsOutParam (&err);
500
503
return m_file->getMemory64List (err);
501
504
}
@@ -607,8 +610,7 @@ std::pair<MemoryRegionInfos, bool> MinidumpParser::BuildMemoryRegions() {
607
610
case StreamType::ST: \
608
611
return #ST
609
612
610
- llvm::StringRef
611
- MinidumpParser::GetStreamTypeAsString (StreamType stream_type) {
613
+ llvm::StringRef MinidumpParser::GetStreamTypeAsString (StreamType stream_type) {
612
614
switch (stream_type) {
613
615
ENUM_TO_CSTR (Unused);
614
616
ENUM_TO_CSTR (ThreadList);
0 commit comments