diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt index 7e849c6270da..6a20f025507a 100644 --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -156,8 +156,3 @@ add_compiler_rt_object_libraries(RTSanitizerCommonLibc if(COMPILER_RT_INCLUDE_TESTS) add_subdirectory(tests) endif() - -if (!MSVC) - add_llvm_tool(sancov sancov.cc) - target_link_libraries(sancov LLVMSupport LLVMSymbolize LLVMObject LLVMDebugInfoDWARF LLVMDebugInfoPDB) -endif() diff --git a/compiler-rt/lib/sanitizer_common/sancov.cc b/compiler-rt/lib/sanitizer_common/sancov.cc deleted file mode 100644 index 1e3e77cd21fa..000000000000 --- a/compiler-rt/lib/sanitizer_common/sancov.cc +++ /dev/null @@ -1,283 +0,0 @@ -//===-- sancov.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a command-line tool for reading and analyzing sanitizer -// coverage. -//===----------------------------------------------------------------------===// -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/Symbolize/Symbolize.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Errc.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/LineIterator.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/raw_ostream.h" - -#include -#include -#include -#include - -using namespace llvm; - -namespace { - -// --------- COMMAND LINE FLAGS --------- - -enum ActionType { PrintAction, CoveredFunctionsAction }; - -cl::opt Action( - cl::desc("Action (required)"), cl::Required, - cl::values(clEnumValN(PrintAction, "print", "Print coverage addresses"), - clEnumValN(CoveredFunctionsAction, "covered_functions", - "Print all covered funcions."), - clEnumValEnd)); - -static cl::list ClInputFiles(cl::Positional, cl::OneOrMore, - cl::desc("")); - -static cl::opt - ClBinaryName("obj", cl::Required, - cl::desc("Path to object file to be symbolized")); - -static cl::opt - ClDemangle("demangle", cl::init(true), - cl::desc("Print demangled function name.")); - -// --------- FORMAT SPECIFICATION --------- - -struct FileHeader { - uint32_t Bitness; - uint32_t Magic; -}; - -static const uint32_t BinCoverageMagic = 0xC0BFFFFF; -static const uint32_t Bitness32 = 0xFFFFFF32; -static const uint32_t Bitness64 = 0xFFFFFF64; - -// --------- - -template static void FailIfError(const ErrorOr &E) { - if (E) - return; - - auto Error = E.getError(); - errs() << "Error: " << Error.message() << "(" << Error.value() << ")\n"; - exit(-2); -} - -template -static void readInts(const char *Start, const char *End, - std::vector *V) { - const T *S = reinterpret_cast(Start); - const T *E = reinterpret_cast(End); - V->reserve(E - S); - std::copy(S, E, std::back_inserter(*V)); -} - -static std::string CommonPrefix(std::string A, std::string B) { - if (A.size() > B.size()) - return std::string(B.begin(), - std::mismatch(B.begin(), B.end(), A.begin()).first); - else - return std::string(A.begin(), - std::mismatch(A.begin(), A.end(), B.begin()).first); -} - -static std::string demangle(std::string Name) { - if (Name.substr(0, 2) != "_Z") - return Name; - - int status = 0; - char *DemangledName = - abi::__cxa_demangle(Name.c_str(), nullptr, nullptr, &status); - if (status != 0) - return Name; - std::string Result = DemangledName; - free(DemangledName); - return Result; -} - -class CoverageData { - public: - // Read single file coverage data. - static ErrorOr> read(std::string FileName) { - ErrorOr> BufOrErr = - MemoryBuffer::getFile(FileName); - if (!BufOrErr) - return BufOrErr.getError(); - std::unique_ptr Buf = std::move(BufOrErr.get()); - if (Buf->getBufferSize() < 8) { - errs() << "File too small (<8): " << Buf->getBufferSize(); - return make_error_code(errc::illegal_byte_sequence); - } - const FileHeader *Header = - reinterpret_cast(Buf->getBufferStart()); - - if (Header->Magic != BinCoverageMagic) { - errs() << "Wrong magic: " << Header->Magic; - return make_error_code(errc::illegal_byte_sequence); - } - - std::unique_ptr> Addrs(new std::vector()); - - switch (Header->Bitness) { - case Bitness64: - readInts(Buf->getBufferStart() + 8, Buf->getBufferEnd(), - Addrs.get()); - break; - case Bitness32: - readInts(Buf->getBufferStart() + 8, Buf->getBufferEnd(), - Addrs.get()); - break; - default: - errs() << "Unsupported bitness: " << Header->Bitness; - return make_error_code(errc::illegal_byte_sequence); - } - - return std::unique_ptr(new CoverageData(std::move(Addrs))); - } - - // Merge multiple coverage data together. - static std::unique_ptr - merge(const std::vector> &Covs) { - std::set Addrs; - - for (const auto &Cov : Covs) - Addrs.insert(Cov->Addrs->begin(), Cov->Addrs->end()); - - std::unique_ptr> AddrsVector( - new std::vector(Addrs.begin(), Addrs.end())); - return std::unique_ptr( - new CoverageData(std::move(AddrsVector))); - } - - // Read list of files and merges their coverage info. - static ErrorOr> - readAndMerge(const std::vector &FileNames) { - std::vector> Covs; - for (const auto &FileName : FileNames) { - auto Cov = read(FileName); - if (!Cov) - return Cov.getError(); - Covs.push_back(std::move(Cov.get())); - } - return merge(Covs); - } - - // Print coverage addresses. - void printAddrs(raw_ostream &out) { // NOLINT(runtime/references) - for (auto Addr : *Addrs) { - out << "0x"; - out.write_hex(Addr); - out << "\n"; - } - } - - // Print list of covered functions. - // Line format: : - void printCoveredFunctions(raw_ostream &out) { // NOLINT(runtime/references) - if (Addrs->empty()) - return; - symbolize::LLVMSymbolizer Symbolizer; - - struct FileLoc { - std::string FileName; - uint32_t Line; - bool operator<(const FileLoc &Rhs) const { - return std::tie(FileName, Line) < std::tie(Rhs.FileName, Rhs.Line); - } - }; - - // FileLoc -> FunctionName - std::map Fns; - - // Fill in Fns map. - for (auto Addr : *Addrs) { - auto InliningInfo = Symbolizer.symbolizeInlinedCode(ClBinaryName, Addr); - FailIfError(InliningInfo); - for (uint32_t i = 0; i < InliningInfo->getNumberOfFrames(); ++i) { - auto FrameInfo = InliningInfo->getFrame(i); - SmallString<256> FileName(FrameInfo.FileName); - sys::path::remove_dots(FileName, /* remove_dot_dot */ true); - uint32_t Line = FrameInfo.Line; - std::string FunctionName = FrameInfo.FunctionName; - if (ClDemangle) - FunctionName = demangle(FrameInfo.FunctionName); - - FileLoc Loc = { FileName.str(), Line }; - Fns[Loc] = FunctionName; - } - } - - // Compute file names common prefix. - std::string FilePrefix = Fns.begin()->first.FileName; - for (const auto &P : Fns) - FilePrefix = CommonPrefix(FilePrefix, P.first.FileName); - - // Print first function occurence in a file. - { - std::string LastFileName; - std::set ProcessedFunctions; - - for (const auto &P : Fns) { - std::string FileName = P.first.FileName; - std::string FunctionName = P.second; - uint32_t Line = P.first.Line; - - if (LastFileName != FileName) - ProcessedFunctions.clear(); - LastFileName = FileName; - - if (ProcessedFunctions.find(FunctionName) != ProcessedFunctions.end()) - continue; - ProcessedFunctions.insert(FunctionName); - - out << FileName.substr(FilePrefix.size()) << ":" << Line << " " - << FunctionName << "\n"; - } - } - } - - private: - explicit CoverageData(std::unique_ptr> Addrs) - : Addrs(std::move(Addrs)) {} - - std::unique_ptr> Addrs; -}; -} // namespace - -int main(int argc, char **argv) { - // Print stack trace if we signal out. - sys::PrintStackTraceOnErrorSignal(); - PrettyStackTraceProgram X(argc, argv); - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - cl::ParseCommandLineOptions(argc, argv, "Sanitizer Coverage Processing Tool"); - - auto CovData = CoverageData::readAndMerge(ClInputFiles); - FailIfError(CovData); - - switch (Action) { - case PrintAction: { - CovData.get()->printAddrs(outs()); - return 0; - } - case CoveredFunctionsAction: { - CovData.get()->printCoveredFunctions(outs()); - return 0; - } - } -}