From e2dd98690a0f43b35ee22d59efeb04d2c7fead68 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Mon, 3 Mar 2025 12:26:08 +0900 Subject: [PATCH] detailed --- llvm/include/llvm/ObjectYAML/CovMap.h | 97 ++++++++-- llvm/lib/ObjectYAML/CovMap.cpp | 190 ++++++++++++++++---- llvm/test/tools/obj2yaml/ELF/covmap-be.yaml | 7 + llvm/test/tools/obj2yaml/ELF/covmap.yaml | 7 + llvm/tools/obj2yaml/elf2yaml.cpp | 25 ++- 5 files changed, 269 insertions(+), 57 deletions(-) diff --git a/llvm/include/llvm/ObjectYAML/CovMap.h b/llvm/include/llvm/ObjectYAML/CovMap.h index 406204ee024fb..b55d902f999e8 100644 --- a/llvm/include/llvm/ObjectYAML/CovMap.h +++ b/llvm/include/llvm/ObjectYAML/CovMap.h @@ -24,6 +24,7 @@ #define LLVM_OBJECTYAML_COVMAP_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ObjectYAML/ELFYAML.h" #include "llvm/Support/Endian.h" @@ -34,14 +35,67 @@ #include #include #include +#include #include namespace llvm { +class InstrProfSymtab; class raw_ostream; } // namespace llvm namespace llvm::coverage::yaml { +/// This works like vector container but can be replaced with +/// MutableArrayRef. See also SequenceTraits. +template > class VectorOrRef { + using Ref = MutableArrayRef; + + /// Holds vector type initially. + std::variant Array; + +public: + // FIXME: Iterator impl is minimal easy. + using iterator = T *; + + iterator begin() { + if (auto *V = std::get_if(&Array)) + return &V->front(); + return &std::get(Array).front(); + } + + iterator end() { + if (auto *V = std::get_if(&Array)) + return &V->back() + 1; + return &std::get(Array).back() + 1; + } + + size_t size() const { + if (const auto *V = std::get_if(&Array)) + return V->size(); + return std::get(Array).size(); + } + + T &operator[](int Idx) { + if (auto *V = std::get_if(&Array)) + return (*V)[Idx]; + return std::get(Array)[Idx]; + } + + void resize(size_t Size) { std::get(Array).resize(Size); } + + VectorOrRef() = default; + + /// Initialize with MutableArrayRef. + VectorOrRef(Ref &&Tmp) : Array(std::move(Tmp)) {} +}; + +/// Options for Decoder. +struct DecoderParam { + bool Detailed; ///< Generate and show processed records. + bool Raw; ///< Show raw data oriented records. + bool dLoc; ///< Show raw dLoc (differential Loc). +}; + struct DecoderContext; /// Base Counter, corresponding to coverage::Counter. @@ -143,6 +197,9 @@ struct FileRecsTy { void mapping(llvm::yaml::IO &IO); }; +/// Key is FilenamesRef. +using CovMapByRefTy = llvm::DenseMap; + /// An element of CovFun array. struct CovFunTy { std::optional NameRef; ///< Hash value of the symbol. @@ -157,7 +214,8 @@ struct CovFunTy { /// Depends on CovMap and SymTab(IPSK_names) Expected decode(const ArrayRef Content, uint64_t Offset, - endianness Endianness); + endianness Endianness, CovMapByRefTy &CovMapByRef, + InstrProfSymtab *SymTab, const DecoderParam &Param); void encode(raw_ostream &OS, endianness Endianness) const; }; @@ -180,7 +238,7 @@ struct CovMapTy { /// This may be ArrayRef in Decoder since Filenames has been /// filled. On the other hand in Encoder, this should be a vector /// since YAML parser doesn't endorse references. - std::optional> Files; + std::optional> Files; void mapping(llvm::yaml::IO &IO); @@ -188,7 +246,7 @@ struct CovMapTy { StringRef getWD() const { return (WD ? *WD : StringRef()); } Expected decode(const ArrayRef Content, uint64_t Offset, - endianness Endianness); + endianness Endianness, const DecoderParam &Param); /// Generate Accumulated list with WD. /// Returns a single element {WD} if AccFiles is not given. @@ -210,6 +268,21 @@ struct CovMapTy { } // namespace llvm::coverage::yaml +namespace llvm::yaml { +template +struct SequenceTraits> { + static size_t size(IO &io, llvm::coverage::yaml::VectorOrRef &seq) { + return seq.size(); + } + static T &element(IO &, llvm::coverage::yaml::VectorOrRef &seq, + size_t index) { + if (index >= seq.size()) + seq.resize(index + 1); + return seq[index]; + } +}; +} // namespace llvm::yaml + LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::coverage::yaml::CovMapTy) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::coverage::yaml::CovFunTy) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::coverage::yaml::ExpressionTy) @@ -265,17 +338,21 @@ class Decoder { virtual ~Decoder() {} /// Returns DecoderImpl. - static std::unique_ptr get(endianness Endianness, - bool CovMapEnabled); + static std::unique_ptr + get(endianness Endianness, const coverage::yaml::DecoderParam &Param); /// Called from the Sections loop in advance of the final dump. - /// Decoder predecodes CovMap for Version info. - virtual Error acquire(unsigned AddressAlign, StringRef Name, + /// Decoder predecodes Names and CovMap, and captures Contents of + /// CovFuns. + virtual Error acquire(uint64_t Offset, unsigned AddressAlign, StringRef Name, ArrayRef Content) = 0; - /// Make contents on ELFYAML object. CovMap is predecoded. - virtual Error make(ELFYAML::CovMapSectionBase *Base, - ArrayRef Content) = 0; + /// Called before the final dump after `acquire`. + /// Decode contents partially and resolve names. + virtual Error fixup() = 0; + + /// Make contents on ELFYAML object with predecoded contents. + virtual Error make(ELFYAML::CovMapSectionBase *Base, uint64_t Offset) = 0; /// Suppress emission of CovMap unless enabled. static bool enabled; diff --git a/llvm/lib/ObjectYAML/CovMap.cpp b/llvm/lib/ObjectYAML/CovMap.cpp index dcf90f7b109cb..94970cd41d5a7 100644 --- a/llvm/lib/ObjectYAML/CovMap.cpp +++ b/llvm/lib/ObjectYAML/CovMap.cpp @@ -13,8 +13,10 @@ #include "llvm/ObjectYAML/CovMap.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ObjectYAML/ELFYAML.h" +#include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" #include "llvm/ProfileData/InstrProf.h" @@ -42,12 +44,15 @@ using namespace llvm::covmap; bool Decoder::enabled; // DataExtractor w/ single Cursor -struct coverage::yaml::DecoderContext : DataExtractor, DataExtractor::Cursor { +struct coverage::yaml::DecoderContext : DataExtractor, + DataExtractor::Cursor, + DecoderParam { uint64_t LineStart = 0; - DecoderContext(const ArrayRef Content, bool IsLE) + DecoderContext(const ArrayRef Content, bool IsLE, + const DecoderParam &Param) : DataExtractor(Content, IsLE, /*AddressSize=*/0), - DataExtractor::Cursor(0) {} + DataExtractor::Cursor(0), DecoderParam(Param) {} bool eof() { return DataExtractor::eof(*this); } uint32_t getU32() { return DataExtractor::getU32(*this); } @@ -91,8 +96,24 @@ Error CounterTy::decodeOrTag(DecoderContext &Data) { else Val = V; // w/o Tag } else { - Tag = T; - Val = V; + if (Data.Raw) { + Tag = T; + Val = V; + } else { + switch (T) { + case Zero: + llvm_unreachable("Zero should be handled in advance"); + case Ref: + RefOpt = V; + break; + case Sub: + SubOpt = V; + break; + case Add: + AddOpt = V; + break; + } + } } return Error::success(); @@ -211,12 +232,14 @@ Error RecTy::decode(DecoderContext &Data) { case Decision: if (auto E = DecisionOpt.emplace().decode(Data)) return E; - ExtTag = Decision; + if (Data.Raw) + ExtTag = Decision; break; case Branch: if (auto E = decodeBranch()) return E; - ExtTag = Branch; + if (Data.Raw) + ExtTag = Branch; break; case MCDCBranch: { if (auto E = decodeBranch()) @@ -231,7 +254,8 @@ Error RecTy::decode(DecoderContext &Data) { if (!I2OrErr) return I2OrErr.takeError(); MCDC = {*I0OrErr, *I1OrErr, *I2OrErr}; - ExtTag = MCDCBranch; + if (Data.Raw) + ExtTag = MCDCBranch; break; } default: @@ -363,8 +387,11 @@ CovMapTy::encodeFilenames(const std::optional> &AccFilesOpt, } Expected CovFunTy::decode(const ArrayRef Content, - uint64_t Offset, endianness Endianness) { - DecoderContext Data(Content, (Endianness == endianness::little)); + uint64_t Offset, endianness Endianness, + CovMapByRefTy &CovMapByRef, + InstrProfSymtab *Symtab, + const DecoderParam &Param) { + DecoderContext Data(Content, (Endianness == endianness::little), Param); Data.seek(Offset); uint32_t DataSize; @@ -383,9 +410,17 @@ Expected CovFunTy::decode(const ArrayRef Content, if (!Data) return Data.takeError(); + if (Data.Detailed) + FuncName = Symtab->getFuncOrVarNameIfDefined(*NameRef); + + if (!Data.Raw) + NameRef.reset(); + [[maybe_unused]] auto ExpectedEndOffset = Data.tell() + DataSize; // Decode body. + assert(CovMapByRef.contains(this->FilenamesRef)); + auto &CovMap = *CovMapByRef[this->FilenamesRef]; FileIDs.emplace(); auto NumFilesOrErr = Data.getULEB128(); @@ -414,6 +449,10 @@ Expected CovFunTy::decode(const ArrayRef Content, if (!NumRegionsOrErr) return NumRegionsOrErr.takeError(); auto &File = Files.emplace_back(); + if (Data.Detailed) { + File.Index = FileIdx; // Sequential number. + File.Filename = (*CovMap.Filenames)[(*FileIDs)[FileIdx]]; + } // Decode subarray. Data.LineStart = 0; @@ -421,9 +460,19 @@ Expected CovFunTy::decode(const ArrayRef Content, auto &Rec = File.Recs.emplace_back(); if (auto E = Rec.decode(Data)) return std::move(E); + + // Hide either Loc or dLoc. + if (!Data.Detailed || Data.dLoc) + Rec.Loc.reset(); + else if (!Data.Raw) + Rec.dLoc.reset(); } } + // Hide FileIDs. + if (!Data.Raw) + FileIDs.reset(); + assert(Data.tell() == ExpectedEndOffset); return Data.tell(); } @@ -454,8 +503,9 @@ void CovMapTy::encode(raw_ostream &OS, endianness Endianness) const { } Expected CovMapTy::decode(const ArrayRef Content, - uint64_t Offset, endianness Endianness) { - DecoderContext Data(Content, (Endianness == endianness::little)); + uint64_t Offset, endianness Endianness, + const DecoderParam &Param) { + DecoderContext Data(Content, (Endianness == endianness::little), Param); Data.seek(Offset); #define COVMAP_HEADER(Type, LLVMType, Name, Initializer) \ @@ -479,6 +529,17 @@ Expected CovMapTy::decode(const ArrayRef Content, .read(static_cast(Version))) return E; + if (Param.Detailed && useWD()) { + assert(this->Filenames->size() >= 1); + auto FilenamesI = this->Filenames->begin(); + StringRef WD = *FilenamesI++; + if (!WD.empty()) + this->WD = WD; + // Use Filenames as a storage. + this->Files.emplace( + MutableArrayRef(&*FilenamesI, &*this->Filenames->end())); + } + Offset = Data.tell(); return Offset; } @@ -527,7 +588,12 @@ void CovFunTy::mapping(llvm::yaml::IO &IO) { void CovMapTy::mapping(llvm::yaml::IO &IO) { IO.mapRequired("FilenamesRef", FilenamesRef); IO.mapOptional("Version", Version); - IO.mapOptional("Filenames", Filenames); + + if (!WD && !Files) + // Suppress this regardless of (Detailed && Raw). + // Since it is obviously redundant. + IO.mapOptional("Filenames", Filenames); + IO.mapOptional("WD", WD); IO.mapOptional("Files", Files); } @@ -592,7 +658,7 @@ struct CovMapSection : ELFYAML::CovMapSectionBase { } Error decode(ArrayRef Blob, unsigned AddressAlign, - endianness Endianness) { + endianness Endianness, const DecoderParam &Param) { uint64_t Offset = 0; while (true) { @@ -601,7 +667,7 @@ struct CovMapSection : ELFYAML::CovMapSectionBase { break; } auto &CovMap = CovMaps.emplace_back(); - auto Result = CovMap.decode(Blob, Offset, Endianness); + auto Result = CovMap.decode(Blob, Offset, Endianness, Param); if (!Result) { return Result.takeError(); } @@ -637,9 +703,10 @@ struct CovFunSection : ELFYAML::CovMapSectionBase { IO.mapOptional("CovFun", CovFuns); } - static Expected> decode(ArrayRef CovFunA, - unsigned AddressAlign, - endianness Endianness) { + static Expected> + decode(ArrayRef CovFunA, unsigned AddressAlign, + endianness Endianness, CovMapByRefTy &CovMapByRef, + InstrProfSymtab *Symtab, const DecoderParam &Param) { std::vector CovFuns; uint64_t Offset = 0; @@ -649,7 +716,8 @@ struct CovFunSection : ELFYAML::CovMapSectionBase { break; auto &CovFun = CovFuns.emplace_back(); - auto Result = CovFun.decode(CovFunA, Offset, Endianness); + auto Result = CovFun.decode(CovFunA, Offset, Endianness, CovMapByRef, + Symtab, Param); if (!Result) return Result.takeError(); @@ -675,7 +743,7 @@ class CovMapFilenamesResolver { std::vector UnresolvedCovFuns; protected: - DenseMap CovMapByRef; + CovMapByRefTy CovMapByRef; std::vector TempCovMaps; // For Decoder public: @@ -702,6 +770,23 @@ class CovMapFilenamesResolver { } } + void decMaybeResetFilenames(std::vector &CovMaps) { + for (auto &CovMap : CovMaps) { + auto FilenamesI = FilenamesByCovMap.find(CovMap.FilenamesRef); + if (FilenamesI == FilenamesByCovMap.end()) + continue; + + // Calculate FilenamesRef with Filenames from CovFuns. + // If matches, hide Filenames from CovMap. + auto [AccFilenamesRef, _] = + CovMap.encodeFilenames(FilenamesI->second.getArrayRef()); + if (CovMap.FilenamesRef == AccFilenamesRef) { + CovMap.Files.reset(); + CovMap.Filenames.reset(); // FilenamesI has been invalidated. + } + } + } + void encFixup() { for (auto &[_, CovMap] : CovMapByRef) { auto FilenamesI = FilenamesByCovMap.find(CovMap->FilenamesRef); @@ -757,15 +842,23 @@ class CovMapFilenamesResolver { }; class DecoderImpl : public Decoder, CovMapFilenamesResolver { + DecoderParam Param; + std::unique_ptr ProfileNames; + InstrProfSymtab::PrfNamesChunksTy PrfNames; + + MapVector, unsigned>> CovFunBlobs; + DenseMap> TempCovFuns; + public: - DecoderImpl(endianness Endianness, bool CovMapEnabled) - : Decoder(Endianness), ProfileNames(std::make_unique()) { - enabled = CovMapEnabled; + DecoderImpl(endianness Endianness, const DecoderParam &Param) + : Decoder(Endianness), Param(Param), + ProfileNames(std::make_unique()) { + enabled = (Param.Detailed || Param.Raw); } - Error acquire(unsigned AddressAlign, StringRef Name, + Error acquire(uint64_t Offset, unsigned AddressAlign, StringRef Name, ArrayRef Content) override { // Don't register anything. if (!enabled) @@ -775,33 +868,52 @@ class DecoderImpl : public Decoder, CovMapFilenamesResolver { // Decode CovMaps in advance, since only CovMap knows its Version. // CovMaps is restored (into CovMapSection) later. auto TempCovMap = std::make_unique(); - if (auto E = TempCovMap->decode(Content, AddressAlign, Endianness)) + if (auto E = TempCovMap->decode(Content, AddressAlign, Endianness, Param)) return E; moveAndCollectCovMap(std::move(TempCovMap->CovMaps)); + } else if (PrfNamesSection::nameMatches(Name)) { + // Decode PrfNames in advance since CovFun depends on it. + auto PrfNamesOrErr = ProfileNames->createAndGetList(Content); + if (!PrfNamesOrErr) + return PrfNamesOrErr.takeError(); + PrfNames = std::move(*PrfNamesOrErr); + } else if (CovFunSection::nameMatches(Name)) { + // Will be decoded after CovMap is met. + CovFunBlobs[Offset] = {Content, AddressAlign}; } return Error::success(); } - Error make(ELFYAML::CovMapSectionBase *Base, - ArrayRef Content) override { + Error fixup() override { + // Decode CovFun(s) with predecoded PrfNames and CovMap. + for (const auto &[Offset, CovFunBlob] : CovFunBlobs) { + auto CovFunsOrErr = + CovFunSection::decode(CovFunBlob.first, CovFunBlob.second, Endianness, + CovMapByRef, ProfileNames.get(), Param); + if (!CovFunsOrErr) + return CovFunsOrErr.takeError(); + TempCovFuns[Offset] = std::move(*CovFunsOrErr); + collectCovFunFilenames(TempCovFuns[Offset]); + } + // Hide Filenames if it is reproducible from CovFuns. + if (Param.Detailed) + decMaybeResetFilenames(TempCovMaps); + return Error::success(); + } + + Error make(ELFYAML::CovMapSectionBase *Base, uint64_t Offset) override { if (auto *S = dyn_cast(Base)) { // Store predecoded CovMaps. S->CovMaps = std::move(TempCovMaps); return Error::success(); } else if (auto *S = dyn_cast(Base)) { - // Decode PrfNames in advance since CovFun depends on it. - auto PrfNamesOrErr = ProfileNames->createAndGetList(Content); - if (!PrfNamesOrErr) - return PrfNamesOrErr.takeError(); - S->PrfNames = std::move(*PrfNamesOrErr); + S->PrfNames = std::move(PrfNames); return Error::success(); } else if (auto *S = dyn_cast(Base)) { - auto CovFunsOrErr = - CovFunSection::decode(Content, S->AddressAlign, Endianness); - if (!CovFunsOrErr) - return CovFunsOrErr.takeError(); - S->CovFuns = std::move(*CovFunsOrErr); + assert(S->CovFuns.empty()); + assert(TempCovFuns.contains(Offset)); + S->CovFuns = std::move(TempCovFuns[Offset]); return Error::success(); } @@ -826,8 +938,8 @@ class EncoderImpl : public Encoder, CovMapFilenamesResolver { } // namespace std::unique_ptr Decoder::get(endianness Endianness, - bool CovMapEnabled) { - return std::make_unique(Endianness, CovMapEnabled); + const DecoderParam &Param) { + return std::make_unique(Endianness, Param); } std::unique_ptr Encoder::get(endianness Endianness) { diff --git a/llvm/test/tools/obj2yaml/ELF/covmap-be.yaml b/llvm/test/tools/obj2yaml/ELF/covmap-be.yaml index 8423f1ad5f765..ec1352b40a9cc 100644 --- a/llvm/test/tools/obj2yaml/ELF/covmap-be.yaml +++ b/llvm/test/tools/obj2yaml/ELF/covmap-be.yaml @@ -1,8 +1,15 @@ # RUN: yaml2obj %s -o %t.o # RUN: obj2yaml %t.o > %t.plain.yaml # RUN: obj2yaml --covmap-raw %t.o > %t.raw.yaml +# RUN: obj2yaml --covmap --covmap-raw %t.o > %t.mixed.yaml +# RUN: obj2yaml --covmap --covmap-dloc %t.o > %t.dloc.yaml +# RUN: obj2yaml --covmap %t.o > %t.covmap.yaml +# RUN: sed -E '/^(#.*)?$/d' %s | diff %t.covmap.yaml - # RUN: yaml2obj %t.plain.yaml -o - | cmp %t.o - # RUN: yaml2obj %t.raw.yaml -o - | cmp %t.o - +# RUN: yaml2obj %t.mixed.yaml -o - | cmp %t.o - +# RUN: yaml2obj %t.dloc.yaml -o - | cmp %t.o - +# RUN: yaml2obj %t.covmap.yaml -o - | cmp %t.o - # FIXME: This is synthetically created. s/ELFDATA2LSB/ELF2DATAMSB/ s/EM_X86_64/EM_PPC64/ --- !ELF diff --git a/llvm/test/tools/obj2yaml/ELF/covmap.yaml b/llvm/test/tools/obj2yaml/ELF/covmap.yaml index db30d373d5be1..fc77a3d02f909 100644 --- a/llvm/test/tools/obj2yaml/ELF/covmap.yaml +++ b/llvm/test/tools/obj2yaml/ELF/covmap.yaml @@ -1,8 +1,15 @@ # RUN: yaml2obj %s -o %t.o # RUN: obj2yaml %t.o | tee %t.plain.yaml | FileCheck %s --check-prefixes=CHECK,PLAIN # RUN: obj2yaml --covmap-raw %t.o | tee %t.raw.yaml | FileCheck %s --check-prefixes=CHECK,COVMAP,RAWONLY,RAW,DLOC +# RUN: obj2yaml --covmap --covmap-raw %t.o | tee %t.mixed.yaml | FileCheck %s --check-prefixes=CHECK,COVMAP,RAW,DET,LOC,DLOC +# RUN: obj2yaml --covmap --covmap-dloc %t.o | tee %t.dloc.yaml | FileCheck %s --check-prefixes=CHECK,COVMAP,DET,DETONLY,DLOC +# RUN: obj2yaml --covmap %t.o | tee %t.covmap.yaml | FileCheck %s --check-prefixes=CHECK,COVMAP,DET,DETONLY,LOC +# RUN: sed -E '/^(#.*)?$/d' %s | diff %t.covmap.yaml - # RUN: yaml2obj %t.plain.yaml -o - | cmp %t.o - # RUN: yaml2obj %t.raw.yaml -o - | cmp %t.o - +# RUN: yaml2obj %t.mixed.yaml -o - | cmp %t.o - +# RUN: yaml2obj %t.dloc.yaml -o - | cmp %t.o - +# RUN: yaml2obj %t.covmap.yaml -o - | cmp %t.o - --- !ELF FileHeader: diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp index 50fd92e24aa3d..c8522636b6240 100644 --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -23,9 +23,15 @@ using namespace llvm; +static cl::opt + CovMapDetailed("covmap", cl::desc("Dump detailed YAML in Coverage Map."), + cl::cat(Cat)); static cl::opt CovMapRaw("covmap-raw", cl::desc("Dump raw YAML in Coverage Map."), cl::cat(Cat)); +static cl::opt CovMapDLoc("covmap-dloc", + cl::desc("Prefer dLoc over absolute Loc."), + cl::cat(Cat)); namespace { @@ -588,7 +594,11 @@ ELFDumper::dumpSections() { return Error::success(); }; - auto CovMapDecoder = covmap::Decoder::get(ELFT::Endianness, CovMapRaw); + coverage::yaml::DecoderParam Param; + Param.Detailed = CovMapDetailed; + Param.Raw = CovMapRaw; + Param.dLoc = CovMapDLoc; + auto CovMapDecoder = covmap::Decoder::get(ELFT::Endianness, Param); if (covmap::Decoder::enabled) { // Look up covmap-related sections in advance. for (const auto &Sec : Sections) { @@ -606,10 +616,13 @@ ELFDumper::dumpSections() { if (!ContentOrErr) return ContentOrErr.takeError(); - if (auto E = CovMapDecoder->acquire(Sec.sh_addralign, *NameOrErr, - *ContentOrErr)) + if (auto E = CovMapDecoder->acquire(Sec.sh_offset, Sec.sh_addralign, + *NameOrErr, *ContentOrErr)) return std::move(E); } + + if (auto E = CovMapDecoder->fixup()) + return std::move(E); } auto GetDumper = [this](unsigned Type) @@ -1708,11 +1721,7 @@ ELFDumper::dumpCovMap(const Elf_Shdr *Shdr, StringRef Name, if (Error E = dumpCommonSection(Shdr, *S)) return std::move(E); - auto ContentOrErr = Obj.getSectionContents(*Shdr); - if (!ContentOrErr) - return ContentOrErr.takeError(); - - if (auto E = CovMapDecoder->make(S.get(), *ContentOrErr)) + if (auto E = CovMapDecoder->make(S.get(), Shdr->sh_offset)) return std::move(E); return S.release();