mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 12:06:08 +00:00
[Coverage] Support overriding compilation directory
When making compilation relocatable, for example in distributed compilation scenarios, we want to set compilation dir to a relative value like `.` but this presents a problem when generating reports because if the file path is relative as well, for example `..`, you may end up writing files outside of the output directory. This change introduces a flag that allows overriding the compilation directory that's stored inside the profile with a different value that is absolute. Differential Revision: https://reviews.llvm.org/D100232
This commit is contained in:
parent
a0162a81b1
commit
8280ece0c9
@ -603,7 +603,7 @@ public:
|
|||||||
/// Ignores non-instrumented object files unless all are not instrumented.
|
/// Ignores non-instrumented object files unless all are not instrumented.
|
||||||
static Expected<std::unique_ptr<CoverageMapping>>
|
static Expected<std::unique_ptr<CoverageMapping>>
|
||||||
load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
|
load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
|
||||||
ArrayRef<StringRef> Arches = None);
|
ArrayRef<StringRef> Arches = None, StringRef CompilationDir = "");
|
||||||
|
|
||||||
/// The number of functions that couldn't have their profiles mapped.
|
/// The number of functions that couldn't have their profiles mapped.
|
||||||
///
|
///
|
||||||
|
@ -202,13 +202,15 @@ public:
|
|||||||
|
|
||||||
static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
|
static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
|
||||||
create(MemoryBufferRef ObjectBuffer, StringRef Arch,
|
create(MemoryBufferRef ObjectBuffer, StringRef Arch,
|
||||||
SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers);
|
SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
|
||||||
|
StringRef CompilationDir = "");
|
||||||
|
|
||||||
static Expected<std::unique_ptr<BinaryCoverageReader>>
|
static Expected<std::unique_ptr<BinaryCoverageReader>>
|
||||||
createCoverageReaderFromBuffer(StringRef Coverage, std::string &&FuncRecords,
|
createCoverageReaderFromBuffer(StringRef Coverage, std::string &&FuncRecords,
|
||||||
InstrProfSymtab &&ProfileNames,
|
InstrProfSymtab &&ProfileNames,
|
||||||
uint8_t BytesInAddress,
|
uint8_t BytesInAddress,
|
||||||
support::endianness Endian);
|
support::endianness Endian,
|
||||||
|
StringRef CompilationDir = "");
|
||||||
|
|
||||||
Error readNextRecord(CoverageMappingRecord &Record) override;
|
Error readNextRecord(CoverageMappingRecord &Record) override;
|
||||||
};
|
};
|
||||||
@ -216,14 +218,17 @@ public:
|
|||||||
/// Reader for the raw coverage filenames.
|
/// Reader for the raw coverage filenames.
|
||||||
class RawCoverageFilenamesReader : public RawCoverageReader {
|
class RawCoverageFilenamesReader : public RawCoverageReader {
|
||||||
std::vector<std::string> &Filenames;
|
std::vector<std::string> &Filenames;
|
||||||
|
StringRef CompilationDir;
|
||||||
|
|
||||||
// Read an uncompressed sequence of filenames.
|
// Read an uncompressed sequence of filenames.
|
||||||
Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames);
|
Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RawCoverageFilenamesReader(StringRef Data,
|
RawCoverageFilenamesReader(StringRef Data,
|
||||||
std::vector<std::string> &Filenames)
|
std::vector<std::string> &Filenames,
|
||||||
: RawCoverageReader(Data), Filenames(Filenames) {}
|
StringRef CompilationDir = "")
|
||||||
|
: RawCoverageReader(Data), Filenames(Filenames),
|
||||||
|
CompilationDir(CompilationDir) {}
|
||||||
RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
|
RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
|
||||||
RawCoverageFilenamesReader &
|
RawCoverageFilenamesReader &
|
||||||
operator=(const RawCoverageFilenamesReader &) = delete;
|
operator=(const RawCoverageFilenamesReader &) = delete;
|
||||||
|
@ -319,7 +319,8 @@ static Error handleMaybeNoDataFoundError(Error E) {
|
|||||||
|
|
||||||
Expected<std::unique_ptr<CoverageMapping>>
|
Expected<std::unique_ptr<CoverageMapping>>
|
||||||
CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
|
CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
|
||||||
StringRef ProfileFilename, ArrayRef<StringRef> Arches) {
|
StringRef ProfileFilename, ArrayRef<StringRef> Arches,
|
||||||
|
StringRef CompilationDir) {
|
||||||
auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
|
auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
|
||||||
if (Error E = ProfileReaderOrErr.takeError())
|
if (Error E = ProfileReaderOrErr.takeError())
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
@ -336,8 +337,8 @@ CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
|
|||||||
MemoryBufferRef CovMappingBufRef =
|
MemoryBufferRef CovMappingBufRef =
|
||||||
CovMappingBufOrErr.get()->getMemBufferRef();
|
CovMappingBufOrErr.get()->getMemBufferRef();
|
||||||
SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
|
SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
|
||||||
auto CoverageReadersOrErr =
|
auto CoverageReadersOrErr = BinaryCoverageReader::create(
|
||||||
BinaryCoverageReader::create(CovMappingBufRef, Arch, Buffers);
|
CovMappingBufRef, Arch, Buffers, CompilationDir);
|
||||||
if (Error E = CoverageReadersOrErr.takeError()) {
|
if (Error E = CoverageReadersOrErr.takeError()) {
|
||||||
E = handleMaybeNoDataFoundError(std::move(E));
|
E = handleMaybeNoDataFoundError(std::move(E));
|
||||||
if (E)
|
if (E)
|
||||||
|
@ -138,7 +138,8 @@ Error RawCoverageFilenamesReader::read(CovMapVersion Version) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size());
|
StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size());
|
||||||
RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames);
|
RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames,
|
||||||
|
CompilationDir);
|
||||||
return Delegate.readUncompressed(Version, NumFilenames);
|
return Delegate.readUncompressed(Version, NumFilenames);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +169,11 @@ Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
|
|||||||
if (sys::path::is_absolute(Filename)) {
|
if (sys::path::is_absolute(Filename)) {
|
||||||
Filenames.push_back(Filename.str());
|
Filenames.push_back(Filename.str());
|
||||||
} else {
|
} else {
|
||||||
SmallString<256> P(CWD);
|
SmallString<256> P;
|
||||||
|
if (!CompilationDir.empty())
|
||||||
|
P.assign(CompilationDir);
|
||||||
|
else
|
||||||
|
P.assign(CWD);
|
||||||
llvm::sys::path::append(P, Filename);
|
llvm::sys::path::append(P, Filename);
|
||||||
Filenames.push_back(static_cast<std::string>(P));
|
Filenames.push_back(static_cast<std::string>(P));
|
||||||
}
|
}
|
||||||
@ -520,7 +525,7 @@ struct CovMapFuncRecordReader {
|
|||||||
template <class IntPtrT, support::endianness Endian>
|
template <class IntPtrT, support::endianness Endian>
|
||||||
static Expected<std::unique_ptr<CovMapFuncRecordReader>>
|
static Expected<std::unique_ptr<CovMapFuncRecordReader>>
|
||||||
get(CovMapVersion Version, InstrProfSymtab &P,
|
get(CovMapVersion Version, InstrProfSymtab &P,
|
||||||
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
|
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
|
||||||
std::vector<std::string> &F);
|
std::vector<std::string> &F);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -535,6 +540,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
|
|||||||
// in \c Records.
|
// in \c Records.
|
||||||
DenseMap<NameRefType, size_t> FunctionRecords;
|
DenseMap<NameRefType, size_t> FunctionRecords;
|
||||||
InstrProfSymtab &ProfileNames;
|
InstrProfSymtab &ProfileNames;
|
||||||
|
StringRef CompilationDir;
|
||||||
std::vector<std::string> &Filenames;
|
std::vector<std::string> &Filenames;
|
||||||
std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
|
std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
|
||||||
|
|
||||||
@ -594,9 +600,9 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
|
|||||||
public:
|
public:
|
||||||
VersionedCovMapFuncRecordReader(
|
VersionedCovMapFuncRecordReader(
|
||||||
InstrProfSymtab &P,
|
InstrProfSymtab &P,
|
||||||
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
|
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
|
||||||
std::vector<std::string> &F)
|
std::vector<std::string> &F)
|
||||||
: ProfileNames(P), Filenames(F), Records(R) {}
|
: ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}
|
||||||
|
|
||||||
~VersionedCovMapFuncRecordReader() override = default;
|
~VersionedCovMapFuncRecordReader() override = default;
|
||||||
|
|
||||||
@ -629,7 +635,8 @@ public:
|
|||||||
return make_error<CoverageMapError>(coveragemap_error::malformed);
|
return make_error<CoverageMapError>(coveragemap_error::malformed);
|
||||||
size_t FilenamesBegin = Filenames.size();
|
size_t FilenamesBegin = Filenames.size();
|
||||||
StringRef FilenameRegion(CovBuf, FilenamesSize);
|
StringRef FilenameRegion(CovBuf, FilenamesSize);
|
||||||
RawCoverageFilenamesReader Reader(FilenameRegion, Filenames);
|
RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,
|
||||||
|
CompilationDir);
|
||||||
if (auto Err = Reader.read(Version))
|
if (auto Err = Reader.read(Version))
|
||||||
return std::move(Err);
|
return std::move(Err);
|
||||||
CovBuf += FilenamesSize;
|
CovBuf += FilenamesSize;
|
||||||
@ -735,14 +742,14 @@ public:
|
|||||||
template <class IntPtrT, support::endianness Endian>
|
template <class IntPtrT, support::endianness Endian>
|
||||||
Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
|
Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
|
||||||
CovMapVersion Version, InstrProfSymtab &P,
|
CovMapVersion Version, InstrProfSymtab &P,
|
||||||
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
|
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
|
||||||
std::vector<std::string> &F) {
|
std::vector<std::string> &F) {
|
||||||
using namespace coverage;
|
using namespace coverage;
|
||||||
|
|
||||||
switch (Version) {
|
switch (Version) {
|
||||||
case CovMapVersion::Version1:
|
case CovMapVersion::Version1:
|
||||||
return std::make_unique<VersionedCovMapFuncRecordReader<
|
return std::make_unique<VersionedCovMapFuncRecordReader<
|
||||||
CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F);
|
CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F);
|
||||||
case CovMapVersion::Version2:
|
case CovMapVersion::Version2:
|
||||||
case CovMapVersion::Version3:
|
case CovMapVersion::Version3:
|
||||||
case CovMapVersion::Version4:
|
case CovMapVersion::Version4:
|
||||||
@ -753,19 +760,19 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
|
|||||||
return std::move(E);
|
return std::move(E);
|
||||||
if (Version == CovMapVersion::Version2)
|
if (Version == CovMapVersion::Version2)
|
||||||
return std::make_unique<VersionedCovMapFuncRecordReader<
|
return std::make_unique<VersionedCovMapFuncRecordReader<
|
||||||
CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F);
|
CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F);
|
||||||
else if (Version == CovMapVersion::Version3)
|
else if (Version == CovMapVersion::Version3)
|
||||||
return std::make_unique<VersionedCovMapFuncRecordReader<
|
return std::make_unique<VersionedCovMapFuncRecordReader<
|
||||||
CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F);
|
CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F);
|
||||||
else if (Version == CovMapVersion::Version4)
|
else if (Version == CovMapVersion::Version4)
|
||||||
return std::make_unique<VersionedCovMapFuncRecordReader<
|
return std::make_unique<VersionedCovMapFuncRecordReader<
|
||||||
CovMapVersion::Version4, IntPtrT, Endian>>(P, R, F);
|
CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F);
|
||||||
else if (Version == CovMapVersion::Version5)
|
else if (Version == CovMapVersion::Version5)
|
||||||
return std::make_unique<VersionedCovMapFuncRecordReader<
|
return std::make_unique<VersionedCovMapFuncRecordReader<
|
||||||
CovMapVersion::Version5, IntPtrT, Endian>>(P, R, F);
|
CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F);
|
||||||
else if (Version == CovMapVersion::Version6)
|
else if (Version == CovMapVersion::Version6)
|
||||||
return std::make_unique<VersionedCovMapFuncRecordReader<
|
return std::make_unique<VersionedCovMapFuncRecordReader<
|
||||||
CovMapVersion::Version6, IntPtrT, Endian>>(P, R, F);
|
CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);
|
||||||
}
|
}
|
||||||
llvm_unreachable("Unsupported version");
|
llvm_unreachable("Unsupported version");
|
||||||
}
|
}
|
||||||
@ -774,7 +781,7 @@ template <typename T, support::endianness Endian>
|
|||||||
static Error readCoverageMappingData(
|
static Error readCoverageMappingData(
|
||||||
InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
|
InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
|
||||||
std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
|
std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
|
||||||
std::vector<std::string> &Filenames) {
|
StringRef CompilationDir, std::vector<std::string> &Filenames) {
|
||||||
using namespace coverage;
|
using namespace coverage;
|
||||||
|
|
||||||
// Read the records in the coverage data section.
|
// Read the records in the coverage data section.
|
||||||
@ -785,7 +792,7 @@ static Error readCoverageMappingData(
|
|||||||
return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
|
return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
|
||||||
Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
|
Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
|
||||||
CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
|
CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
|
||||||
Filenames);
|
CompilationDir, Filenames);
|
||||||
if (Error E = ReaderExpected.takeError())
|
if (Error E = ReaderExpected.takeError())
|
||||||
return E;
|
return E;
|
||||||
auto Reader = std::move(ReaderExpected.get());
|
auto Reader = std::move(ReaderExpected.get());
|
||||||
@ -817,8 +824,9 @@ static const char *TestingFormatMagic = "llvmcovmtestdata";
|
|||||||
|
|
||||||
Expected<std::unique_ptr<BinaryCoverageReader>>
|
Expected<std::unique_ptr<BinaryCoverageReader>>
|
||||||
BinaryCoverageReader::createCoverageReaderFromBuffer(
|
BinaryCoverageReader::createCoverageReaderFromBuffer(
|
||||||
StringRef Coverage, std::string &&FuncRecords, InstrProfSymtab &&ProfileNames,
|
StringRef Coverage, std::string &&FuncRecords,
|
||||||
uint8_t BytesInAddress, support::endianness Endian) {
|
InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress,
|
||||||
|
support::endianness Endian, StringRef CompilationDir) {
|
||||||
std::unique_ptr<BinaryCoverageReader> Reader(
|
std::unique_ptr<BinaryCoverageReader> Reader(
|
||||||
new BinaryCoverageReader(std::move(FuncRecords)));
|
new BinaryCoverageReader(std::move(FuncRecords)));
|
||||||
Reader->ProfileNames = std::move(ProfileNames);
|
Reader->ProfileNames = std::move(ProfileNames);
|
||||||
@ -827,23 +835,23 @@ BinaryCoverageReader::createCoverageReaderFromBuffer(
|
|||||||
if (Error E =
|
if (Error E =
|
||||||
readCoverageMappingData<uint32_t, support::endianness::little>(
|
readCoverageMappingData<uint32_t, support::endianness::little>(
|
||||||
Reader->ProfileNames, Coverage, FuncRecordsRef,
|
Reader->ProfileNames, Coverage, FuncRecordsRef,
|
||||||
Reader->MappingRecords, Reader->Filenames))
|
Reader->MappingRecords, CompilationDir, Reader->Filenames))
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
} else if (BytesInAddress == 4 && Endian == support::endianness::big) {
|
} else if (BytesInAddress == 4 && Endian == support::endianness::big) {
|
||||||
if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
|
if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
|
||||||
Reader->ProfileNames, Coverage, FuncRecordsRef,
|
Reader->ProfileNames, Coverage, FuncRecordsRef,
|
||||||
Reader->MappingRecords, Reader->Filenames))
|
Reader->MappingRecords, CompilationDir, Reader->Filenames))
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
} else if (BytesInAddress == 8 && Endian == support::endianness::little) {
|
} else if (BytesInAddress == 8 && Endian == support::endianness::little) {
|
||||||
if (Error E =
|
if (Error E =
|
||||||
readCoverageMappingData<uint64_t, support::endianness::little>(
|
readCoverageMappingData<uint64_t, support::endianness::little>(
|
||||||
Reader->ProfileNames, Coverage, FuncRecordsRef,
|
Reader->ProfileNames, Coverage, FuncRecordsRef,
|
||||||
Reader->MappingRecords, Reader->Filenames))
|
Reader->MappingRecords, CompilationDir, Reader->Filenames))
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
} else if (BytesInAddress == 8 && Endian == support::endianness::big) {
|
} else if (BytesInAddress == 8 && Endian == support::endianness::big) {
|
||||||
if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
|
if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
|
||||||
Reader->ProfileNames, Coverage, FuncRecordsRef,
|
Reader->ProfileNames, Coverage, FuncRecordsRef,
|
||||||
Reader->MappingRecords, Reader->Filenames))
|
Reader->MappingRecords, CompilationDir, Reader->Filenames))
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
} else
|
} else
|
||||||
return make_error<CoverageMapError>(coveragemap_error::malformed);
|
return make_error<CoverageMapError>(coveragemap_error::malformed);
|
||||||
@ -851,7 +859,7 @@ BinaryCoverageReader::createCoverageReaderFromBuffer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Expected<std::unique_ptr<BinaryCoverageReader>>
|
static Expected<std::unique_ptr<BinaryCoverageReader>>
|
||||||
loadTestingFormat(StringRef Data) {
|
loadTestingFormat(StringRef Data, StringRef CompilationDir) {
|
||||||
uint8_t BytesInAddress = 8;
|
uint8_t BytesInAddress = 8;
|
||||||
support::endianness Endian = support::endianness::little;
|
support::endianness Endian = support::endianness::little;
|
||||||
|
|
||||||
@ -911,7 +919,7 @@ loadTestingFormat(StringRef Data) {
|
|||||||
}
|
}
|
||||||
return BinaryCoverageReader::createCoverageReaderFromBuffer(
|
return BinaryCoverageReader::createCoverageReaderFromBuffer(
|
||||||
CoverageMapping, CoverageRecords.str(), std::move(ProfileNames),
|
CoverageMapping, CoverageRecords.str(), std::move(ProfileNames),
|
||||||
BytesInAddress, Endian);
|
BytesInAddress, Endian, CompilationDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find all sections that match \p Name. There may be more than one if comdats
|
/// Find all sections that match \p Name. There may be more than one if comdats
|
||||||
@ -941,7 +949,8 @@ static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Expected<std::unique_ptr<BinaryCoverageReader>>
|
static Expected<std::unique_ptr<BinaryCoverageReader>>
|
||||||
loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) {
|
loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
|
||||||
|
StringRef CompilationDir = "") {
|
||||||
std::unique_ptr<ObjectFile> OF;
|
std::unique_ptr<ObjectFile> OF;
|
||||||
if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
|
if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
|
||||||
// If we have a universal binary, try to look up the object for the
|
// If we have a universal binary, try to look up the object for the
|
||||||
@ -1013,7 +1022,7 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) {
|
|||||||
|
|
||||||
return BinaryCoverageReader::createCoverageReaderFromBuffer(
|
return BinaryCoverageReader::createCoverageReaderFromBuffer(
|
||||||
CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
|
CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
|
||||||
BytesInAddress, Endian);
|
BytesInAddress, Endian, CompilationDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether \p Arch is invalid or empty, given \p Bin.
|
/// Determine whether \p Arch is invalid or empty, given \p Bin.
|
||||||
@ -1032,12 +1041,14 @@ static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {
|
|||||||
Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
|
Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
|
||||||
BinaryCoverageReader::create(
|
BinaryCoverageReader::create(
|
||||||
MemoryBufferRef ObjectBuffer, StringRef Arch,
|
MemoryBufferRef ObjectBuffer, StringRef Arch,
|
||||||
SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) {
|
SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
|
||||||
|
StringRef CompilationDir) {
|
||||||
std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
|
std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
|
||||||
|
|
||||||
if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
|
if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
|
||||||
// This is a special format used for testing.
|
// This is a special format used for testing.
|
||||||
auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer());
|
auto ReaderOrErr =
|
||||||
|
loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);
|
||||||
if (!ReaderOrErr)
|
if (!ReaderOrErr)
|
||||||
return ReaderOrErr.takeError();
|
return ReaderOrErr.takeError();
|
||||||
Readers.push_back(std::move(ReaderOrErr.get()));
|
Readers.push_back(std::move(ReaderOrErr.get()));
|
||||||
@ -1070,7 +1081,8 @@ BinaryCoverageReader::create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return BinaryCoverageReader::create(
|
return BinaryCoverageReader::create(
|
||||||
ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers);
|
ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
|
||||||
|
CompilationDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1083,7 +1095,7 @@ BinaryCoverageReader::create(
|
|||||||
return ChildBufOrErr.takeError();
|
return ChildBufOrErr.takeError();
|
||||||
|
|
||||||
auto ChildReadersOrErr = BinaryCoverageReader::create(
|
auto ChildReadersOrErr = BinaryCoverageReader::create(
|
||||||
ChildBufOrErr.get(), Arch, ObjectFileBuffers);
|
ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir);
|
||||||
if (!ChildReadersOrErr)
|
if (!ChildReadersOrErr)
|
||||||
return ChildReadersOrErr.takeError();
|
return ChildReadersOrErr.takeError();
|
||||||
for (auto &Reader : ChildReadersOrErr.get())
|
for (auto &Reader : ChildReadersOrErr.get())
|
||||||
@ -1102,7 +1114,7 @@ BinaryCoverageReader::create(
|
|||||||
return std::move(Readers);
|
return std::move(Readers);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch);
|
auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir);
|
||||||
if (!ReaderOrErr)
|
if (!ReaderOrErr)
|
||||||
return ReaderOrErr.takeError();
|
return ReaderOrErr.takeError();
|
||||||
Readers.push_back(std::move(ReaderOrErr.get()));
|
Readers.push_back(std::move(ReaderOrErr.get()));
|
||||||
|
BIN
llvm/test/tools/llvm-cov/Inputs/compilation_dir.covmapping
Normal file
BIN
llvm/test/tools/llvm-cov/Inputs/compilation_dir.covmapping
Normal file
Binary file not shown.
8
llvm/test/tools/llvm-cov/Inputs/compilation_dir.proftext
Normal file
8
llvm/test/tools/llvm-cov/Inputs/compilation_dir.proftext
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
main
|
||||||
|
# Func Hash:
|
||||||
|
0
|
||||||
|
# Num Counters:
|
||||||
|
1
|
||||||
|
# Counter Values:
|
||||||
|
1
|
||||||
|
|
3
llvm/test/tools/llvm-cov/compilation_dir.c
Normal file
3
llvm/test/tools/llvm-cov/compilation_dir.c
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// RUN: llvm-profdata merge %S/Inputs/compilation_dir.proftext -o %t.profdata
|
||||||
|
// RUN: llvm-cov show %S/Inputs/compilation_dir.covmapping -instr-profile=%t.profdata -compilation-dir=%S | FileCheck %s
|
||||||
|
int main() {} // CHECK: [[@LINE]]| 1|int main() {}
|
@ -434,7 +434,8 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
|
|||||||
warning("profile data may be out of date - object is newer",
|
warning("profile data may be out of date - object is newer",
|
||||||
ObjectFilename);
|
ObjectFilename);
|
||||||
auto CoverageOrErr =
|
auto CoverageOrErr =
|
||||||
CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches);
|
CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches,
|
||||||
|
ViewOpts.CompilationDirectory);
|
||||||
if (Error E = CoverageOrErr.takeError()) {
|
if (Error E = CoverageOrErr.takeError()) {
|
||||||
error("Failed to load coverage: " + toString(std::move(E)),
|
error("Failed to load coverage: " + toString(std::move(E)),
|
||||||
join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "));
|
join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "));
|
||||||
@ -739,6 +740,10 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
|
|||||||
cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
|
cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
|
||||||
cl::aliasopt(NumThreads));
|
cl::aliasopt(NumThreads));
|
||||||
|
|
||||||
|
cl::opt<std::string> CompilationDirectory(
|
||||||
|
"compilation-dir", cl::init(""),
|
||||||
|
cl::desc("Directory used as a base for relative coverage mapping paths"));
|
||||||
|
|
||||||
auto commandLineParser = [&, this](int argc, const char **argv) -> int {
|
auto commandLineParser = [&, this](int argc, const char **argv) -> int {
|
||||||
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
|
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
|
||||||
ViewOpts.Debug = DebugDump;
|
ViewOpts.Debug = DebugDump;
|
||||||
@ -873,6 +878,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
|
|||||||
ViewOpts.ShowInstantiationSummary = InstantiationSummary;
|
ViewOpts.ShowInstantiationSummary = InstantiationSummary;
|
||||||
ViewOpts.ExportSummaryOnly = SummaryOnly;
|
ViewOpts.ExportSummaryOnly = SummaryOnly;
|
||||||
ViewOpts.NumThreads = NumThreads;
|
ViewOpts.NumThreads = NumThreads;
|
||||||
|
ViewOpts.CompilationDirectory = CompilationDirectory;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,7 @@ struct CoverageViewOptions {
|
|||||||
std::string ProjectTitle;
|
std::string ProjectTitle;
|
||||||
std::string CreatedTimeStr;
|
std::string CreatedTimeStr;
|
||||||
unsigned NumThreads;
|
unsigned NumThreads;
|
||||||
|
std::string CompilationDirectory;
|
||||||
|
|
||||||
/// Change the output's stream color if the colors are enabled.
|
/// Change the output's stream color if the colors are enabled.
|
||||||
ColoredRawOstream colored_ostream(raw_ostream &OS,
|
ColoredRawOstream colored_ostream(raw_ostream &OS,
|
||||||
|
@ -900,7 +900,7 @@ INSTANTIATE_TEST_CASE_P(ParameterizedCovMapTest, CoverageMappingTest,
|
|||||||
std::pair<bool, bool>({true, true})),);
|
std::pair<bool, bool>({true, true})),);
|
||||||
|
|
||||||
TEST(CoverageMappingTest, filename_roundtrip) {
|
TEST(CoverageMappingTest, filename_roundtrip) {
|
||||||
std::vector<std::string> Paths({"", "a", "b", "c", "d", "e"});
|
std::vector<std::string> Paths({"dir", "a", "b", "c", "d", "e"});
|
||||||
|
|
||||||
for (bool Compress : {false, true}) {
|
for (bool Compress : {false, true}) {
|
||||||
std::string EncodedFilenames;
|
std::string EncodedFilenames;
|
||||||
@ -915,8 +915,37 @@ TEST(CoverageMappingTest, filename_roundtrip) {
|
|||||||
EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded());
|
EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded());
|
||||||
|
|
||||||
ASSERT_EQ(ReadFilenames.size(), Paths.size());
|
ASSERT_EQ(ReadFilenames.size(), Paths.size());
|
||||||
for (unsigned I = 1; I < Paths.size(); ++I)
|
for (unsigned I = 1; I < Paths.size(); ++I) {
|
||||||
ASSERT_TRUE(ReadFilenames[I] == Paths[I]);
|
SmallString<256> P(Paths[0]);
|
||||||
|
llvm::sys::path::append(P, Paths[I]);
|
||||||
|
ASSERT_TRUE(ReadFilenames[I] == P);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoverageMappingTest, filename_compilation_dir) {
|
||||||
|
std::vector<std::string> Paths({"dir", "a", "b", "c", "d", "e"});
|
||||||
|
|
||||||
|
for (bool Compress : {false, true}) {
|
||||||
|
std::string EncodedFilenames;
|
||||||
|
{
|
||||||
|
raw_string_ostream OS(EncodedFilenames);
|
||||||
|
CoverageFilenamesSectionWriter Writer(Paths);
|
||||||
|
Writer.write(OS, Compress);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef CompilationDir = "out";
|
||||||
|
std::vector<std::string> ReadFilenames;
|
||||||
|
RawCoverageFilenamesReader Reader(EncodedFilenames, ReadFilenames,
|
||||||
|
CompilationDir);
|
||||||
|
EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded());
|
||||||
|
|
||||||
|
ASSERT_EQ(ReadFilenames.size(), Paths.size());
|
||||||
|
for (unsigned I = 1; I < Paths.size(); ++I) {
|
||||||
|
SmallString<256> P(CompilationDir);
|
||||||
|
llvm::sys::path::append(P, Paths[I]);
|
||||||
|
ASSERT_TRUE(ReadFilenames[I] == P);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user