Path: blob/main/contrib/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp
35231 views
//===- llvm-cxxmap.cpp ----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// llvm-cxxmap computes a correspondence between old symbol names and new9// symbol names based on a symbol equivalence file.10//11//===----------------------------------------------------------------------===//1213#include "llvm/ADT/DenseMap.h"14#include "llvm/ADT/DenseSet.h"15#include "llvm/ADT/StringRef.h"16#include "llvm/ProfileData/SymbolRemappingReader.h"17#include "llvm/Support/CommandLine.h"18#include "llvm/Support/FileSystem.h"19#include "llvm/Support/InitLLVM.h"20#include "llvm/Support/LineIterator.h"21#include "llvm/Support/MemoryBuffer.h"22#include "llvm/Support/WithColor.h"23#include "llvm/Support/raw_ostream.h"2425using namespace llvm;2627cl::OptionCategory CXXMapCategory("CXX Map Options");2829cl::opt<std::string> OldSymbolFile(cl::Positional, cl::Required,30cl::desc("<symbol-file>"),31cl::cat(CXXMapCategory));32cl::opt<std::string> NewSymbolFile(cl::Positional, cl::Required,33cl::desc("<symbol-file>"),34cl::cat(CXXMapCategory));35cl::opt<std::string> RemappingFile("remapping-file", cl::Required,36cl::desc("Remapping file"),37cl::cat(CXXMapCategory));38cl::alias RemappingFileA("r", cl::aliasopt(RemappingFile),39cl::cat(CXXMapCategory));40cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),41cl::init("-"), cl::desc("Output file"),42cl::cat(CXXMapCategory));43cl::alias OutputFilenameA("o", cl::aliasopt(OutputFilename),44cl::cat(CXXMapCategory));4546cl::opt<bool> WarnAmbiguous(47"Wambiguous",48cl::desc("Warn on equivalent symbols in the output symbol list"),49cl::cat(CXXMapCategory));50cl::opt<bool> WarnIncomplete(51"Wincomplete",52cl::desc("Warn on input symbols missing from output symbol list"),53cl::cat(CXXMapCategory));5455static void warn(Twine Message, Twine Whence = "",56std::string Hint = "") {57WithColor::warning();58std::string WhenceStr = Whence.str();59if (!WhenceStr.empty())60errs() << WhenceStr << ": ";61errs() << Message << "\n";62if (!Hint.empty())63WithColor::note() << Hint << "\n";64}6566static void exitWithError(Twine Message, Twine Whence = "",67std::string Hint = "") {68WithColor::error();69std::string WhenceStr = Whence.str();70if (!WhenceStr.empty())71errs() << WhenceStr << ": ";72errs() << Message << "\n";73if (!Hint.empty())74WithColor::note() << Hint << "\n";75::exit(1);76}7778static void exitWithError(Error E, StringRef Whence = "") {79exitWithError(toString(std::move(E)), Whence);80}8182static void exitWithErrorCode(std::error_code EC, StringRef Whence = "") {83exitWithError(EC.message(), Whence);84}8586static void remapSymbols(MemoryBuffer &OldSymbolFile,87MemoryBuffer &NewSymbolFile,88MemoryBuffer &RemappingFile,89raw_ostream &Out) {90// Load the remapping file and prepare to canonicalize symbols.91SymbolRemappingReader Reader;92if (Error E = Reader.read(RemappingFile))93exitWithError(std::move(E));9495// Canonicalize the new symbols.96DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;97DenseSet<StringRef> UnparseableSymbols;98for (line_iterator LineIt(NewSymbolFile, /*SkipBlanks=*/true, '#');99!LineIt.is_at_eof(); ++LineIt) {100StringRef Symbol = *LineIt;101102auto K = Reader.insert(Symbol);103if (!K) {104UnparseableSymbols.insert(Symbol);105continue;106}107108auto ItAndIsNew = MappedNames.insert({K, Symbol});109if (WarnAmbiguous && !ItAndIsNew.second &&110ItAndIsNew.first->second != Symbol) {111warn("symbol " + Symbol + " is equivalent to earlier symbol " +112ItAndIsNew.first->second,113NewSymbolFile.getBufferIdentifier() + ":" +114Twine(LineIt.line_number()),115"later symbol will not be the target of any remappings");116}117}118119// Figure out which new symbol each old symbol is equivalent to.120for (line_iterator LineIt(OldSymbolFile, /*SkipBlanks=*/true, '#');121!LineIt.is_at_eof(); ++LineIt) {122StringRef Symbol = *LineIt;123124auto K = Reader.lookup(Symbol);125StringRef NewSymbol = MappedNames.lookup(K);126127if (NewSymbol.empty()) {128if (WarnIncomplete && !UnparseableSymbols.count(Symbol)) {129warn("no new symbol matches old symbol " + Symbol,130OldSymbolFile.getBufferIdentifier() + ":" +131Twine(LineIt.line_number()));132}133continue;134}135136Out << Symbol << " " << NewSymbol << "\n";137}138}139140int main(int argc, const char *argv[]) {141InitLLVM X(argc, argv);142143cl::HideUnrelatedOptions({&CXXMapCategory, &getColorCategory()});144cl::ParseCommandLineOptions(argc, argv, "LLVM C++ mangled name remapper\n");145146auto OldSymbolBufOrError =147MemoryBuffer::getFileOrSTDIN(OldSymbolFile, /*IsText=*/true);148if (!OldSymbolBufOrError)149exitWithErrorCode(OldSymbolBufOrError.getError(), OldSymbolFile);150151auto NewSymbolBufOrError =152MemoryBuffer::getFileOrSTDIN(NewSymbolFile, /*IsText=*/true);153if (!NewSymbolBufOrError)154exitWithErrorCode(NewSymbolBufOrError.getError(), NewSymbolFile);155156auto RemappingBufOrError =157MemoryBuffer::getFileOrSTDIN(RemappingFile, /*IsText=*/true);158if (!RemappingBufOrError)159exitWithErrorCode(RemappingBufOrError.getError(), RemappingFile);160161std::error_code EC;162raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);163if (EC)164exitWithErrorCode(EC, OutputFilename);165166remapSymbols(*OldSymbolBufOrError.get(), *NewSymbolBufOrError.get(),167*RemappingBufOrError.get(), OS);168}169170171