[llvm-branch-commits] [llvm] obj2yaml: Add "detailed" output in CovMap dump (PR #129473)
NAKAMURA Takumi via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Mar 6 19:44:46 PST 2025
https://github.com/chapuni updated https://github.com/llvm/llvm-project/pull/129473
>From e2dd98690a0f43b35ee22d59efeb04d2c7fead68 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
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 <memory>
#include <optional>
#include <string>
+#include <variant>
#include <vector>
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<VectorOrRef>.
+template <typename T, typename Vec = std::vector<T>> class VectorOrRef {
+ using Ref = MutableArrayRef<T>;
+
+ /// Holds vector type initially.
+ std::variant<Vec, Ref> Array;
+
+public:
+ // FIXME: Iterator impl is minimal easy.
+ using iterator = T *;
+
+ iterator begin() {
+ if (auto *V = std::get_if<Vec>(&Array))
+ return &V->front();
+ return &std::get<Ref>(Array).front();
+ }
+
+ iterator end() {
+ if (auto *V = std::get_if<Vec>(&Array))
+ return &V->back() + 1;
+ return &std::get<Ref>(Array).back() + 1;
+ }
+
+ size_t size() const {
+ if (const auto *V = std::get_if<Vec>(&Array))
+ return V->size();
+ return std::get<Ref>(Array).size();
+ }
+
+ T &operator[](int Idx) {
+ if (auto *V = std::get_if<Vec>(&Array))
+ return (*V)[Idx];
+ return std::get<Ref>(Array)[Idx];
+ }
+
+ void resize(size_t Size) { std::get<Vec>(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<uint64_t, struct CovMapTy *>;
+
/// An element of CovFun array.
struct CovFunTy {
std::optional<llvm::yaml::Hex64> NameRef; ///< Hash value of the symbol.
@@ -157,7 +214,8 @@ struct CovFunTy {
/// Depends on CovMap and SymTab(IPSK_names)
Expected<uint64_t> decode(const ArrayRef<uint8_t> 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<std::vector<std::string>> Files;
+ std::optional<VectorOrRef<std::string>> Files;
void mapping(llvm::yaml::IO &IO);
@@ -188,7 +246,7 @@ struct CovMapTy {
StringRef getWD() const { return (WD ? *WD : StringRef()); }
Expected<uint64_t> decode(const ArrayRef<uint8_t> 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 <typename T>
+struct SequenceTraits<llvm::coverage::yaml::VectorOrRef<T>> {
+ static size_t size(IO &io, llvm::coverage::yaml::VectorOrRef<T> &seq) {
+ return seq.size();
+ }
+ static T &element(IO &, llvm::coverage::yaml::VectorOrRef<T> &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<Decoder> get(endianness Endianness,
- bool CovMapEnabled);
+ static std::unique_ptr<Decoder>
+ 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<uint8_t> Content) = 0;
- /// Make contents on ELFYAML object. CovMap is predecoded.
- virtual Error make(ELFYAML::CovMapSectionBase *Base,
- ArrayRef<uint8_t> 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<uint8_t> Content, bool IsLE)
+ DecoderContext(const ArrayRef<uint8_t> 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<ArrayRef<StringRef>> &AccFilesOpt,
}
Expected<uint64_t> CovFunTy::decode(const ArrayRef<uint8_t> 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<uint64_t> CovFunTy::decode(const ArrayRef<uint8_t> 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<uint64_t> CovFunTy::decode(const ArrayRef<uint8_t> 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<uint64_t> CovFunTy::decode(const ArrayRef<uint8_t> 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<uint64_t> CovMapTy::decode(const ArrayRef<uint8_t> 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<uint64_t> CovMapTy::decode(const ArrayRef<uint8_t> Content,
.read(static_cast<CovMapVersion>(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<uint8_t> 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<std::vector<CovFunTy>> decode(ArrayRef<uint8_t> CovFunA,
- unsigned AddressAlign,
- endianness Endianness) {
+ static Expected<std::vector<CovFunTy>>
+ decode(ArrayRef<uint8_t> CovFunA, unsigned AddressAlign,
+ endianness Endianness, CovMapByRefTy &CovMapByRef,
+ InstrProfSymtab *Symtab, const DecoderParam &Param) {
std::vector<CovFunTy> 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<CovFunTy *> UnresolvedCovFuns;
protected:
- DenseMap<uint64_t, struct CovMapTy *> CovMapByRef;
+ CovMapByRefTy CovMapByRef;
std::vector<CovMapTy> TempCovMaps; // For Decoder
public:
@@ -702,6 +770,23 @@ class CovMapFilenamesResolver {
}
}
+ void decMaybeResetFilenames(std::vector<CovMapTy> &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<InstrProfSymtab> ProfileNames;
+ InstrProfSymtab::PrfNamesChunksTy PrfNames;
+
+ MapVector<uint64_t, std::pair<ArrayRef<uint8_t>, unsigned>> CovFunBlobs;
+ DenseMap<uint64_t, std::vector<CovFunTy>> TempCovFuns;
+
public:
- DecoderImpl(endianness Endianness, bool CovMapEnabled)
- : Decoder(Endianness), ProfileNames(std::make_unique<InstrProfSymtab>()) {
- enabled = CovMapEnabled;
+ DecoderImpl(endianness Endianness, const DecoderParam &Param)
+ : Decoder(Endianness), Param(Param),
+ ProfileNames(std::make_unique<InstrProfSymtab>()) {
+ enabled = (Param.Detailed || Param.Raw);
}
- Error acquire(unsigned AddressAlign, StringRef Name,
+ Error acquire(uint64_t Offset, unsigned AddressAlign, StringRef Name,
ArrayRef<uint8_t> 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<CovMapSection>();
- 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<uint8_t> 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<CovMapSection>(Base)) {
// Store predecoded CovMaps.
S->CovMaps = std::move(TempCovMaps);
return Error::success();
} else if (auto *S = dyn_cast<PrfNamesSection>(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<CovFunSection>(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> Decoder::get(endianness Endianness,
- bool CovMapEnabled) {
- return std::make_unique<DecoderImpl>(Endianness, CovMapEnabled);
+ const DecoderParam &Param) {
+ return std::make_unique<DecoderImpl>(Endianness, Param);
}
std::unique_ptr<Encoder> 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<bool>
+ CovMapDetailed("covmap", cl::desc("Dump detailed YAML in Coverage Map."),
+ cl::cat(Cat));
static cl::opt<bool> CovMapRaw("covmap-raw",
cl::desc("Dump raw YAML in Coverage Map."),
cl::cat(Cat));
+static cl::opt<bool> CovMapDLoc("covmap-dloc",
+ cl::desc("Prefer dLoc over absolute Loc."),
+ cl::cat(Cat));
namespace {
@@ -588,7 +594,11 @@ ELFDumper<ELFT>::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<ELFT>::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<ELFT>::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();
More information about the llvm-branch-commits
mailing list