brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · 6eb193a Raw
171 lines · cpp
1//===- llvm-cxxmap.cpp ----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// llvm-cxxmap computes a correspondence between old symbol names and new10// symbol names based on a symbol equivalence file.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/ADT/DenseMap.h"15#include "llvm/ADT/DenseSet.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/ProfileData/SymbolRemappingReader.h"18#include "llvm/Support/CommandLine.h"19#include "llvm/Support/FileSystem.h"20#include "llvm/Support/InitLLVM.h"21#include "llvm/Support/LineIterator.h"22#include "llvm/Support/MemoryBuffer.h"23#include "llvm/Support/WithColor.h"24#include "llvm/Support/raw_ostream.h"25 26using namespace llvm;27 28static cl::OptionCategory CXXMapCategory("CXX Map Options");29 30static cl::opt<std::string> OldSymbolFile(cl::Positional, cl::Required,31                                          cl::desc("<symbol-file>"),32                                          cl::cat(CXXMapCategory));33static cl::opt<std::string> NewSymbolFile(cl::Positional, cl::Required,34                                          cl::desc("<symbol-file>"),35                                          cl::cat(CXXMapCategory));36static cl::opt<std::string> RemappingFile("remapping-file", cl::Required,37                                          cl::desc("Remapping file"),38                                          cl::cat(CXXMapCategory));39static cl::alias RemappingFileA("r", cl::aliasopt(RemappingFile),40                                cl::cat(CXXMapCategory));41static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),42                                           cl::init("-"),43                                           cl::desc("Output file"),44                                           cl::cat(CXXMapCategory));45static cl::alias OutputFilenameA("o", cl::aliasopt(OutputFilename),46                                 cl::cat(CXXMapCategory));47 48static cl::opt<bool> WarnAmbiguous(49    "Wambiguous",50    cl::desc("Warn on equivalent symbols in the output symbol list"),51    cl::cat(CXXMapCategory));52static cl::opt<bool> WarnIncomplete(53    "Wincomplete",54    cl::desc("Warn on input symbols missing from output symbol list"),55    cl::cat(CXXMapCategory));56 57static void warn(Twine Message, Twine Whence = "",58                 std::string Hint = "") {59  WithColor::warning();60  std::string WhenceStr = Whence.str();61  if (!WhenceStr.empty())62    errs() << WhenceStr << ": ";63  errs() << Message << "\n";64  if (!Hint.empty())65    WithColor::note() << Hint << "\n";66}67 68static void exitWithError(Twine Message, Twine Whence = "",69                          std::string Hint = "") {70  WithColor::error();71  std::string WhenceStr = Whence.str();72  if (!WhenceStr.empty())73    errs() << WhenceStr << ": ";74  errs() << Message << "\n";75  if (!Hint.empty())76    WithColor::note() << Hint << "\n";77  ::exit(1);78}79 80static void exitWithError(Error E, StringRef Whence = "") {81  exitWithError(toString(std::move(E)), Whence);82}83 84static void exitWithErrorCode(std::error_code EC, StringRef Whence = "") {85  exitWithError(EC.message(), Whence);86}87 88static void remapSymbols(MemoryBuffer &OldSymbolFile,89                         MemoryBuffer &NewSymbolFile,90                         MemoryBuffer &RemappingFile,91                         raw_ostream &Out) {92  // Load the remapping file and prepare to canonicalize symbols.93  SymbolRemappingReader Reader;94  if (Error E = Reader.read(RemappingFile))95    exitWithError(std::move(E));96 97  // Canonicalize the new symbols.98  DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;99  DenseSet<StringRef> UnparseableSymbols;100  for (line_iterator LineIt(NewSymbolFile, /*SkipBlanks=*/true, '#');101       !LineIt.is_at_eof(); ++LineIt) {102    StringRef Symbol = *LineIt;103 104    auto K = Reader.insert(Symbol);105    if (!K) {106      UnparseableSymbols.insert(Symbol);107      continue;108    }109 110    auto ItAndIsNew = MappedNames.insert({K, Symbol});111    if (WarnAmbiguous && !ItAndIsNew.second &&112        ItAndIsNew.first->second != Symbol) {113      warn("symbol " + Symbol + " is equivalent to earlier symbol " +114               ItAndIsNew.first->second,115           NewSymbolFile.getBufferIdentifier() + ":" +116               Twine(LineIt.line_number()),117           "later symbol will not be the target of any remappings");118    }119  }120 121  // Figure out which new symbol each old symbol is equivalent to.122  for (line_iterator LineIt(OldSymbolFile, /*SkipBlanks=*/true, '#');123       !LineIt.is_at_eof(); ++LineIt) {124    StringRef Symbol = *LineIt;125 126    auto K = Reader.lookup(Symbol);127    StringRef NewSymbol = MappedNames.lookup(K);128 129    if (NewSymbol.empty()) {130      if (WarnIncomplete && !UnparseableSymbols.count(Symbol)) {131        warn("no new symbol matches old symbol " + Symbol,132             OldSymbolFile.getBufferIdentifier() + ":" +133                 Twine(LineIt.line_number()));134      }135      continue;136    }137 138    Out << Symbol << " " << NewSymbol << "\n";139  }140}141 142int main(int argc, const char *argv[]) {143  InitLLVM X(argc, argv);144 145  cl::HideUnrelatedOptions({&CXXMapCategory, &getColorCategory()});146  cl::ParseCommandLineOptions(argc, argv, "LLVM C++ mangled name remapper\n");147 148  auto OldSymbolBufOrError =149      MemoryBuffer::getFileOrSTDIN(OldSymbolFile, /*IsText=*/true);150  if (!OldSymbolBufOrError)151    exitWithErrorCode(OldSymbolBufOrError.getError(), OldSymbolFile);152 153  auto NewSymbolBufOrError =154      MemoryBuffer::getFileOrSTDIN(NewSymbolFile, /*IsText=*/true);155  if (!NewSymbolBufOrError)156    exitWithErrorCode(NewSymbolBufOrError.getError(), NewSymbolFile);157 158  auto RemappingBufOrError =159      MemoryBuffer::getFileOrSTDIN(RemappingFile, /*IsText=*/true);160  if (!RemappingBufOrError)161    exitWithErrorCode(RemappingBufOrError.getError(), RemappingFile);162 163  std::error_code EC;164  raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);165  if (EC)166    exitWithErrorCode(EC, OutputFilename);167 168  remapSymbols(*OldSymbolBufOrError.get(), *NewSymbolBufOrError.get(),169               *RemappingBufOrError.get(), OS);170}171