xref: /llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp (revision e22ce615fe31a78857a8574c12a32bddc6da465e)
13164fcfdSRichard Smith //===- llvm-cxxmap.cpp ----------------------------------------------------===//
23164fcfdSRichard Smith //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63164fcfdSRichard Smith //
73164fcfdSRichard Smith //===----------------------------------------------------------------------===//
83164fcfdSRichard Smith //
93164fcfdSRichard Smith // llvm-cxxmap computes a correspondence between old symbol names and new
103164fcfdSRichard Smith // symbol names based on a symbol equivalence file.
113164fcfdSRichard Smith //
123164fcfdSRichard Smith //===----------------------------------------------------------------------===//
133164fcfdSRichard Smith 
143164fcfdSRichard Smith #include "llvm/ADT/DenseMap.h"
15ba7a92c0SNico Weber #include "llvm/ADT/DenseSet.h"
163164fcfdSRichard Smith #include "llvm/ADT/StringRef.h"
176c8fe965SSimon Pilgrim #include "llvm/ProfileData/SymbolRemappingReader.h"
183164fcfdSRichard Smith #include "llvm/Support/CommandLine.h"
19ba7a92c0SNico Weber #include "llvm/Support/FileSystem.h"
203164fcfdSRichard Smith #include "llvm/Support/InitLLVM.h"
213164fcfdSRichard Smith #include "llvm/Support/LineIterator.h"
223164fcfdSRichard Smith #include "llvm/Support/MemoryBuffer.h"
233164fcfdSRichard Smith #include "llvm/Support/WithColor.h"
243164fcfdSRichard Smith #include "llvm/Support/raw_ostream.h"
253164fcfdSRichard Smith 
263164fcfdSRichard Smith using namespace llvm;
273164fcfdSRichard Smith 
28669275f8STimm Bäder cl::OptionCategory CXXMapCategory("CXX Map Options");
29669275f8STimm Bäder 
303164fcfdSRichard Smith cl::opt<std::string> OldSymbolFile(cl::Positional, cl::Required,
31669275f8STimm Bäder                                    cl::desc("<symbol-file>"),
32669275f8STimm Bäder                                    cl::cat(CXXMapCategory));
333164fcfdSRichard Smith cl::opt<std::string> NewSymbolFile(cl::Positional, cl::Required,
34669275f8STimm Bäder                                    cl::desc("<symbol-file>"),
35669275f8STimm Bäder                                    cl::cat(CXXMapCategory));
363164fcfdSRichard Smith cl::opt<std::string> RemappingFile("remapping-file", cl::Required,
37669275f8STimm Bäder                                    cl::desc("Remapping file"),
38669275f8STimm Bäder                                    cl::cat(CXXMapCategory));
39669275f8STimm Bäder cl::alias RemappingFileA("r", cl::aliasopt(RemappingFile),
40669275f8STimm Bäder                          cl::cat(CXXMapCategory));
413164fcfdSRichard Smith cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
42669275f8STimm Bäder                                     cl::init("-"), cl::desc("Output file"),
43669275f8STimm Bäder                                     cl::cat(CXXMapCategory));
44669275f8STimm Bäder cl::alias OutputFilenameA("o", cl::aliasopt(OutputFilename),
45669275f8STimm Bäder                           cl::cat(CXXMapCategory));
463164fcfdSRichard Smith 
473164fcfdSRichard Smith cl::opt<bool> WarnAmbiguous(
483164fcfdSRichard Smith     "Wambiguous",
49669275f8STimm Bäder     cl::desc("Warn on equivalent symbols in the output symbol list"),
50669275f8STimm Bäder     cl::cat(CXXMapCategory));
513164fcfdSRichard Smith cl::opt<bool> WarnIncomplete(
523164fcfdSRichard Smith     "Wincomplete",
53669275f8STimm Bäder     cl::desc("Warn on input symbols missing from output symbol list"),
54669275f8STimm Bäder     cl::cat(CXXMapCategory));
553164fcfdSRichard Smith 
warn(Twine Message,Twine Whence="",std::string Hint="")563164fcfdSRichard Smith static void warn(Twine Message, Twine Whence = "",
573164fcfdSRichard Smith                  std::string Hint = "") {
583164fcfdSRichard Smith   WithColor::warning();
593164fcfdSRichard Smith   std::string WhenceStr = Whence.str();
603164fcfdSRichard Smith   if (!WhenceStr.empty())
613164fcfdSRichard Smith     errs() << WhenceStr << ": ";
623164fcfdSRichard Smith   errs() << Message << "\n";
633164fcfdSRichard Smith   if (!Hint.empty())
643164fcfdSRichard Smith     WithColor::note() << Hint << "\n";
653164fcfdSRichard Smith }
663164fcfdSRichard Smith 
exitWithError(Twine Message,Twine Whence="",std::string Hint="")673164fcfdSRichard Smith static void exitWithError(Twine Message, Twine Whence = "",
683164fcfdSRichard Smith                           std::string Hint = "") {
693164fcfdSRichard Smith   WithColor::error();
703164fcfdSRichard Smith   std::string WhenceStr = Whence.str();
713164fcfdSRichard Smith   if (!WhenceStr.empty())
723164fcfdSRichard Smith     errs() << WhenceStr << ": ";
733164fcfdSRichard Smith   errs() << Message << "\n";
743164fcfdSRichard Smith   if (!Hint.empty())
753164fcfdSRichard Smith     WithColor::note() << Hint << "\n";
763164fcfdSRichard Smith   ::exit(1);
773164fcfdSRichard Smith }
783164fcfdSRichard Smith 
exitWithError(Error E,StringRef Whence="")793164fcfdSRichard Smith static void exitWithError(Error E, StringRef Whence = "") {
803164fcfdSRichard Smith   exitWithError(toString(std::move(E)), Whence);
813164fcfdSRichard Smith }
823164fcfdSRichard Smith 
exitWithErrorCode(std::error_code EC,StringRef Whence="")833164fcfdSRichard Smith static void exitWithErrorCode(std::error_code EC, StringRef Whence = "") {
843164fcfdSRichard Smith   exitWithError(EC.message(), Whence);
853164fcfdSRichard Smith }
863164fcfdSRichard Smith 
remapSymbols(MemoryBuffer & OldSymbolFile,MemoryBuffer & NewSymbolFile,MemoryBuffer & RemappingFile,raw_ostream & Out)873164fcfdSRichard Smith static void remapSymbols(MemoryBuffer &OldSymbolFile,
883164fcfdSRichard Smith                          MemoryBuffer &NewSymbolFile,
893164fcfdSRichard Smith                          MemoryBuffer &RemappingFile,
903164fcfdSRichard Smith                          raw_ostream &Out) {
913164fcfdSRichard Smith   // Load the remapping file and prepare to canonicalize symbols.
923164fcfdSRichard Smith   SymbolRemappingReader Reader;
933164fcfdSRichard Smith   if (Error E = Reader.read(RemappingFile))
943164fcfdSRichard Smith     exitWithError(std::move(E));
953164fcfdSRichard Smith 
963164fcfdSRichard Smith   // Canonicalize the new symbols.
973164fcfdSRichard Smith   DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;
983164fcfdSRichard Smith   DenseSet<StringRef> UnparseableSymbols;
993164fcfdSRichard Smith   for (line_iterator LineIt(NewSymbolFile, /*SkipBlanks=*/true, '#');
1003164fcfdSRichard Smith        !LineIt.is_at_eof(); ++LineIt) {
1013164fcfdSRichard Smith     StringRef Symbol = *LineIt;
1023164fcfdSRichard Smith 
1033164fcfdSRichard Smith     auto K = Reader.insert(Symbol);
1043164fcfdSRichard Smith     if (!K) {
1053164fcfdSRichard Smith       UnparseableSymbols.insert(Symbol);
1063164fcfdSRichard Smith       continue;
1073164fcfdSRichard Smith     }
1083164fcfdSRichard Smith 
1093164fcfdSRichard Smith     auto ItAndIsNew = MappedNames.insert({K, Symbol});
1103164fcfdSRichard Smith     if (WarnAmbiguous && !ItAndIsNew.second &&
1113164fcfdSRichard Smith         ItAndIsNew.first->second != Symbol) {
1123164fcfdSRichard Smith       warn("symbol " + Symbol + " is equivalent to earlier symbol " +
1133164fcfdSRichard Smith                ItAndIsNew.first->second,
1143164fcfdSRichard Smith            NewSymbolFile.getBufferIdentifier() + ":" +
1153164fcfdSRichard Smith                Twine(LineIt.line_number()),
1163164fcfdSRichard Smith            "later symbol will not be the target of any remappings");
1173164fcfdSRichard Smith     }
1183164fcfdSRichard Smith   }
1193164fcfdSRichard Smith 
1203164fcfdSRichard Smith   // Figure out which new symbol each old symbol is equivalent to.
1213164fcfdSRichard Smith   for (line_iterator LineIt(OldSymbolFile, /*SkipBlanks=*/true, '#');
1223164fcfdSRichard Smith        !LineIt.is_at_eof(); ++LineIt) {
1233164fcfdSRichard Smith     StringRef Symbol = *LineIt;
1243164fcfdSRichard Smith 
1253164fcfdSRichard Smith     auto K = Reader.lookup(Symbol);
1263164fcfdSRichard Smith     StringRef NewSymbol = MappedNames.lookup(K);
1273164fcfdSRichard Smith 
1283164fcfdSRichard Smith     if (NewSymbol.empty()) {
1293164fcfdSRichard Smith       if (WarnIncomplete && !UnparseableSymbols.count(Symbol)) {
1303164fcfdSRichard Smith         warn("no new symbol matches old symbol " + Symbol,
1313164fcfdSRichard Smith              OldSymbolFile.getBufferIdentifier() + ":" +
1323164fcfdSRichard Smith                  Twine(LineIt.line_number()));
1333164fcfdSRichard Smith       }
1343164fcfdSRichard Smith       continue;
1353164fcfdSRichard Smith     }
1363164fcfdSRichard Smith 
1373164fcfdSRichard Smith     Out << Symbol << " " << NewSymbol << "\n";
1383164fcfdSRichard Smith   }
1393164fcfdSRichard Smith }
1403164fcfdSRichard Smith 
main(int argc,const char * argv[])1413164fcfdSRichard Smith int main(int argc, const char *argv[]) {
1423164fcfdSRichard Smith   InitLLVM X(argc, argv);
1433164fcfdSRichard Smith 
144669275f8STimm Bäder   cl::HideUnrelatedOptions({&CXXMapCategory, &getColorCategory()});
1453164fcfdSRichard Smith   cl::ParseCommandLineOptions(argc, argv, "LLVM C++ mangled name remapper\n");
1463164fcfdSRichard Smith 
147*e22ce615SSean Perry   auto OldSymbolBufOrError =
148*e22ce615SSean Perry       MemoryBuffer::getFileOrSTDIN(OldSymbolFile, /*IsText=*/true);
1493164fcfdSRichard Smith   if (!OldSymbolBufOrError)
1503164fcfdSRichard Smith     exitWithErrorCode(OldSymbolBufOrError.getError(), OldSymbolFile);
1513164fcfdSRichard Smith 
152*e22ce615SSean Perry   auto NewSymbolBufOrError =
153*e22ce615SSean Perry       MemoryBuffer::getFileOrSTDIN(NewSymbolFile, /*IsText=*/true);
1543164fcfdSRichard Smith   if (!NewSymbolBufOrError)
1553164fcfdSRichard Smith     exitWithErrorCode(NewSymbolBufOrError.getError(), NewSymbolFile);
1563164fcfdSRichard Smith 
157*e22ce615SSean Perry   auto RemappingBufOrError =
158*e22ce615SSean Perry       MemoryBuffer::getFileOrSTDIN(RemappingFile, /*IsText=*/true);
1593164fcfdSRichard Smith   if (!RemappingBufOrError)
1603164fcfdSRichard Smith     exitWithErrorCode(RemappingBufOrError.getError(), RemappingFile);
1613164fcfdSRichard Smith 
1623164fcfdSRichard Smith   std::error_code EC;
16382b3e28eSAbhina Sreeskantharajan   raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
1643164fcfdSRichard Smith   if (EC)
1653164fcfdSRichard Smith     exitWithErrorCode(EC, OutputFilename);
1663164fcfdSRichard Smith 
1673164fcfdSRichard Smith   remapSymbols(*OldSymbolBufOrError.get(), *NewSymbolBufOrError.get(),
1683164fcfdSRichard Smith                *RemappingBufOrError.get(), OS);
1693164fcfdSRichard Smith }
170