diff --git a/llvm/include/llvm/DebugInfo/Symbolize/MarkupContext.h b/llvm/include/llvm/DebugInfo/Symbolize/MarkupContext.h --- a/llvm/include/llvm/DebugInfo/Symbolize/MarkupContext.h +++ b/llvm/include/llvm/DebugInfo/Symbolize/MarkupContext.h @@ -8,7 +8,7 @@ /// /// \file /// This file declares an object that represents a process context that relates -/// virtual addresses to module addresses. +/// addresses to module addresses. /// //===----------------------------------------------------------------------===// @@ -30,7 +30,7 @@ namespace symbolize { -/// A process context that allows converting between virtual addresses and +/// A process context that allows converting between addresses and /// module-relative addresses. class MarkupContext { public: @@ -48,7 +48,9 @@ uint64_t ModuleRelativeAddr; bool contains(uint64_t Addr) const; - uint64_t getModuleRelativeAddr(uint64_t Addr) const; + bool containsMRAddr(uint64_t MRAddr) const; + uint64_t toModuleRelativeAddr(uint64_t Addr) const; + uint64_t fromModuleRelativeAddr(uint64_t MRAddr) const; }; private: @@ -58,6 +60,9 @@ // Ordered map from starting address to mmap. std::map MMaps; + // Ordered map from starting module-relative address to mmap. + std::map MMapsByMRAddr; + public: bool empty() const; void clear(); @@ -74,8 +79,13 @@ /// Returns the MMap that contains the given address or nullptr if none. const MMap *getContainingMMap(uint64_t Addr) const; + /// Returns the MMap that contains the given module-relative address or + /// nullptr if none. + const MMap *getContainingMMapForMRAddr(uint64_t MRAddr) const; + private: const MMap *getOverlappingMMap(const MMap &Map) const; + const MMap *getOverlappingMRAddrMMap(const MMap &Map) const; }; } // end namespace symbolize diff --git a/llvm/lib/DebugInfo/Symbolize/MarkupContext.cpp b/llvm/lib/DebugInfo/Symbolize/MarkupContext.cpp --- a/llvm/lib/DebugInfo/Symbolize/MarkupContext.cpp +++ b/llvm/lib/DebugInfo/Symbolize/MarkupContext.cpp @@ -40,6 +40,7 @@ void MarkupContext::clear() { Modules.clear(); MMaps.clear(); + MMapsByMRAddr.clear(); } void MarkupContext::dump(json::OStream &JOS) const { @@ -88,7 +89,12 @@ (void)Res; assert(Res.second && "Overlap check should have ensured unique starting address."); - return {&Res.first->second, true}; + auto ReverseRes = + MMapsByMRAddr.try_emplace(MM.ModuleRelativeAddr, &Res.first->second); + (void)ReverseRes; + assert(ReverseRes.second && + "Overlap check should have ensured unique starting address."); + return {&Res.first->second, Res.second}; } const MarkupContext::MMap * @@ -105,6 +111,20 @@ return I->second.contains(Addr) ? &I->second : nullptr; } +const MarkupContext::MMap * +MarkupContext::getContainingMMapForMRAddr(uint64_t MRAddr) const { + // Find the first mmap starting >= MRAddr. + auto I = MMapsByMRAddr.lower_bound(MRAddr); + if (I != MMapsByMRAddr.end() && I->second->containsMRAddr(MRAddr)) + return I->second; + + // The previous mmap is the last one starting < MRAddr. + if (I == MMapsByMRAddr.begin()) + return nullptr; + --I; + return I->second->containsMRAddr(MRAddr) ? I->second : nullptr; +} + // Checks for an existing mmap that overlaps the given one and returns a pointer // to it. Checking for overlaps in insertMMap ensures the overlap is unique. const MarkupContext::MMap * @@ -121,6 +141,24 @@ if (I->second.contains(Map.Addr)) return &I->second; } + return getOverlappingMRAddrMMap(Map); +} + +const MarkupContext::MMap * +MarkupContext::getOverlappingMRAddrMMap(const MMap &Map) const { + // If the given map contains the start of another mmap, they overlap. + auto I = MMapsByMRAddr.upper_bound(Map.ModuleRelativeAddr); + if (I != MMapsByMRAddr.end() && + Map.containsMRAddr(I->second->ModuleRelativeAddr)) + return I->second; + + // If no element starts inside the given mmap, the only possible overlap would + // be if the preceding mmap contains the start point of the given mmap. + if (I != MMapsByMRAddr.begin()) { + --I; + if (I->second->containsMRAddr(Map.ModuleRelativeAddr)) + return I->second; + } return nullptr; } @@ -128,7 +166,15 @@ return this->Addr <= Addr && Addr < this->Addr + Size; } -// Returns the module-relative address for a given virtual address. -uint64_t MarkupContext::MMap::getModuleRelativeAddr(uint64_t Addr) const { +bool MarkupContext::MMap::containsMRAddr(uint64_t MRAddr) const { + return this->ModuleRelativeAddr <= MRAddr && + MRAddr < this->ModuleRelativeAddr + Size; +} + +uint64_t MarkupContext::MMap::toModuleRelativeAddr(uint64_t Addr) const { return Addr - this->Addr + ModuleRelativeAddr; } + +uint64_t MarkupContext::MMap::fromModuleRelativeAddr(uint64_t MRAddr) const { + return MRAddr - ModuleRelativeAddr + this->Addr; +} diff --git a/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp b/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp --- a/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp +++ b/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp @@ -117,7 +117,7 @@ WithColor::error(errs()) << formatv("overlapping mmap: #{0:x} [{1:x}-{2:x}]\n", MMap.Mod->ID, MMap.Addr, MMap.Addr + MMap.Size - 1); - reportLocation(Node.Fields[0].begin()); + reportLocation(Node.Text.begin()); return true; } @@ -290,7 +290,7 @@ } Expected LI = Symbolizer.symbolizeCode( - MMap->Mod->BuildID, {MMap->getModuleRelativeAddr(*Addr)}); + MMap->Mod->BuildID, {MMap->toModuleRelativeAddr(*Addr)}); if (!LI) { WithColor::defaultErrorHandler(LI.takeError()); printRawElement(Node); @@ -345,7 +345,7 @@ printRawElement(Node); return true; } - uint64_t MRA = MMap->getModuleRelativeAddr(*Addr); + uint64_t MRA = MMap->toModuleRelativeAddr(*Addr); Expected II = Symbolizer.symbolizeInlinedCode(MMap->Mod->BuildID, {MRA}); @@ -411,7 +411,7 @@ } Expected Symbol = Symbolizer.symbolizeData( - MMap->Mod->BuildID, {MMap->getModuleRelativeAddr(*Addr)}); + MMap->Mod->BuildID, {MMap->toModuleRelativeAddr(*Addr)}); if (!Symbol) { WithColor::defaultErrorHandler(Symbol.takeError()); printRawElement(Node); diff --git a/llvm/test/DebugInfo/symbolize-filter-markup-data.test b/llvm/test/DebugInfo/symbolize-filter-markup-data.test --- a/llvm/test/DebugInfo/symbolize-filter-markup-data.test +++ b/llvm/test/DebugInfo/symbolize-filter-markup-data.test @@ -9,9 +9,9 @@ RUN: --implicit-check-not {{.}} RUN: FileCheck %s --check-prefix=ERR --input-file=%t.err --match-full-lines -CHECK: [[BEGIN:\[{3}]]ELF module #0x0 "a.o"; BuildID=abcdef [0x0-0x4](r),[0x10-0x11](r)[[END:\]{3}]] -CHECK: long long byte -CHECK: long byte +CHECK: [[BEGIN:\[{3}]]ELF module #0x0 "a.o"; BuildID=abcdef [0x0-0x3](r),[0x10-0x10](r)[[END:\]{3}]] +CHECK: long long +CHECK: byte CHECK: [[BEGIN]]data:0x5[[END]] ERR: error: expected 1 field(s); found 0 @@ -19,10 +19,10 @@ ;--- input {{{module:0:a.o:elf:abcdef}}} -{{{mmap:0:5:load:0:r:0}}} -{{{mmap:0x10:2:load:0:r:0x3}}} -{{{data:0x0}}} {{{data:0x1}}} {{{data:0x4}}} -{{{data:0x10}}} {{{data:0x11}}} +{{{mmap:0:4:load:0:r:0}}} +{{{mmap:0x10:1:load:0:r:0x4}}} +{{{data:0x0}}} {{{data:0x1}}} +{{{data:0x10}}} {{{data}}} {{{data:0x5}}} diff --git a/llvm/test/DebugInfo/symbolize-filter-markup-dump-context.test b/llvm/test/DebugInfo/symbolize-filter-markup-dump-context.test --- a/llvm/test/DebugInfo/symbolize-filter-markup-dump-context.test +++ b/llvm/test/DebugInfo/symbolize-filter-markup-dump-context.test @@ -26,7 +26,7 @@ CHECK-NEXT: "type": "load", CHECK-NEXT: "moduleID": 1, CHECK-NEXT: "mode": "r", -CHECK-NEXT: "moduleRelativeAddress": 2 +CHECK-NEXT: "moduleRelativeAddress": 32 CHECK-NEXT: }, CHECK-NEXT: { CHECK-NEXT: "address": 32, @@ -34,7 +34,7 @@ CHECK-NEXT: "type": "load", CHECK-NEXT: "moduleID": 1, CHECK-NEXT: "mode": "w", -CHECK-NEXT: "moduleRelativeAddress": 3 +CHECK-NEXT: "moduleRelativeAddress": 64 CHECK-NEXT: }, CHECK-NEXT: { CHECK-NEXT: "address": 80, @@ -42,7 +42,7 @@ CHECK-NEXT: "type": "load", CHECK-NEXT: "moduleID": 0, CHECK-NEXT: "mode": "rx", -CHECK-NEXT: "moduleRelativeAddress": 4 +CHECK-NEXT: "moduleRelativeAddress": 128 CHECK-NEXT: } CHECK-NEXT: ] CHECK-NEXT: }, @@ -63,9 +63,9 @@ ;--- log {{{module:1:a.o:elf:cd}}} {{{module:0:b.o:elf:ab}}} -{{{mmap:0x10:0x10:load:1:r:0x2}}} -{{{mmap:0x20:0x30:load:1:w:0x3}}} -{{{mmap:0x50:0x60:load:0:rx:0x4}}} +{{{mmap:0x10:0x10:load:1:r:0x20}}} +{{{mmap:0x20:0x30:load:1:w:0x40}}} +{{{mmap:0x50:0x60:load:0:rx:0x80}}} {{{pc:0x20}}} {{{reset}}} {{{module:0:c.o:elf:ef}}} diff --git a/llvm/test/DebugInfo/symbolize-filter-markup-mmap.test b/llvm/test/DebugInfo/symbolize-filter-markup-mmap.test --- a/llvm/test/DebugInfo/symbolize-filter-markup-mmap.test +++ b/llvm/test/DebugInfo/symbolize-filter-markup-mmap.test @@ -17,15 +17,16 @@ ERR: error: overlapping mmap: #0x0 [0xa-0xb] ERR: error: overlapping mmap: #0x0 [0xa-0xb] ERR: error: overlapping mmap: #0x0 [0xa-0xb] +ERR: error: overlapping mmap: #0x0 [0x1-0x1] ;--- log {{{module:0:a.o:elf:abb50d82b6bdc861}}} {{{mmap:0x1:1:load:0:r:0}}} -{{{mmap:0x2:1:load:0:w:0}}} -{{{mmap:0x3:1:load:0:x:0}}} -{{{mmap:0x4:1:load:0:rwx:0}}} -{{{mmap:0x0:1:load:0:RWX:0}}} -{{{mmap:0xa:2:load:0:r:0}}} +{{{mmap:0x2:1:load:0:w:0x4}}} +{{{mmap:0x3:1:load:0:x:0x6}}} +{{{mmap:0x4:1:load:0:rwx:0x8}}} +{{{mmap:0x0:1:load:0:RWX:0xa}}} +{{{mmap:0xa:2:load:0:r:0xc}}} {{{mmap}}} {{{mmap:0:1:unknown}}} @@ -35,6 +36,7 @@ {{{mmap:0:10000000:load:0::0}}} {{{mmap:0:10000000:load:0:g:0}}} {{{mmap:0:10000000:load:0:wr:0}}} -{{{mmap:0xa:1:load:0:r:0}}} -{{{mmap:0x9:2:load:0:r:0}}} -{{{mmap:0x9:5:load:0:r:0}}} +{{{mmap:0xa:1:load:0:r:0xe}}} +{{{mmap:0x9:2:load:0:r:0x11}}} +{{{mmap:0x9:5:load:0:r:0x13}}} +{{{mmap:0xc:1:load:0:r:0}}}