[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / tools / llvm-profgen / llvm-profgen.cpp
blob0ab93ca0bd65bbf1bebcfef2e731a4a4518c1a69
1 //===- llvm-profgen.cpp - LLVM SPGO profile generation tool -----*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // llvm-profgen generates SPGO profiles from perf script ouput.
11 //===----------------------------------------------------------------------===//
13 #include "ErrorHandling.h"
14 #include "PerfReader.h"
15 #include "ProfileGenerator.h"
16 #include "ProfiledBinary.h"
17 #include "llvm/Support/CommandLine.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/InitLLVM.h"
20 #include "llvm/Support/TargetSelect.h"
22 static cl::OptionCategory ProfGenCategory("ProfGen Options");
24 static cl::opt<std::string> PerfScriptFilename(
25 "perfscript", cl::value_desc("perfscript"), cl::ZeroOrMore,
26 llvm::cl::MiscFlags::CommaSeparated,
27 cl::desc("Path of perf-script trace created by Linux perf tool with "
28 "`script` command(the raw perf.data should be profiled with -b)"),
29 cl::cat(ProfGenCategory));
30 static cl::alias PSA("ps", cl::desc("Alias for --perfscript"),
31 cl::aliasopt(PerfScriptFilename));
33 static cl::opt<std::string> PerfDataFilename(
34 "perfdata", cl::value_desc("perfdata"), cl::ZeroOrMore,
35 llvm::cl::MiscFlags::CommaSeparated,
36 cl::desc("Path of raw perf data created by Linux perf tool (it should be "
37 "profiled with -b)"),
38 cl::cat(ProfGenCategory));
39 static cl::alias PDA("pd", cl::desc("Alias for --perfdata"),
40 cl::aliasopt(PerfDataFilename));
42 static cl::opt<std::string> UnsymbolizedProfFilename(
43 "unsymbolized-profile", cl::value_desc("unsymbolized profile"),
44 cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated,
45 cl::desc("Path of the unsymbolized profile created by "
46 "`llvm-profgen` with `--skip-symbolization`"),
47 cl::cat(ProfGenCategory));
48 static cl::alias UPA("up", cl::desc("Alias for --unsymbolized-profile"),
49 cl::aliasopt(UnsymbolizedProfFilename));
51 static cl::opt<std::string> BinaryPath(
52 "binary", cl::value_desc("binary"), cl::Required,
53 cl::desc("Path of profiled binary, only one binary is supported."),
54 cl::cat(ProfGenCategory));
56 extern cl::opt<bool> ShowDisassemblyOnly;
57 extern cl::opt<bool> ShowSourceLocations;
58 extern cl::opt<bool> SkipSymbolization;
60 using namespace llvm;
61 using namespace sampleprof;
63 // Validate the command line input.
64 static void validateCommandLine() {
65 // Allow the missing perfscript if we only use to show binary disassembly.
66 if (!ShowDisassemblyOnly) {
67 // Validate input profile is provided only once
68 uint16_t HasPerfData = PerfDataFilename.getNumOccurrences();
69 uint16_t HasPerfScript = PerfScriptFilename.getNumOccurrences();
70 uint16_t HasUnsymbolizedProfile =
71 UnsymbolizedProfFilename.getNumOccurrences();
72 uint16_t S = HasPerfData + HasPerfScript + HasUnsymbolizedProfile;
73 if (S != 1) {
74 std::string Msg =
75 S > 1
76 ? "`--perfscript`, `--perfdata` and `--unsymbolized-profile` "
77 "cannot be used together."
78 : "Perf input file is missing, please use one of `--perfscript`, "
79 "`--perfdata` and `--unsymbolized-profile` for the input.";
80 exitWithError(Msg);
83 auto CheckFileExists = [](bool H, StringRef File) {
84 if (H && !llvm::sys::fs::exists(File)) {
85 std::string Msg = "Input perf file(" + File.str() + ") doesn't exist.";
86 exitWithError(Msg);
90 CheckFileExists(HasPerfData, PerfDataFilename);
91 CheckFileExists(HasPerfScript, PerfScriptFilename);
92 CheckFileExists(HasUnsymbolizedProfile, UnsymbolizedProfFilename);
95 if (!llvm::sys::fs::exists(BinaryPath)) {
96 std::string Msg = "Input binary(" + BinaryPath + ") doesn't exist.";
97 exitWithError(Msg);
100 if (CSProfileGenerator::MaxCompressionSize < -1) {
101 exitWithError("Value of --compress-recursion should >= -1");
103 if (ShowSourceLocations && !ShowDisassemblyOnly) {
104 exitWithError("--show-source-locations should work together with "
105 "--show-disassembly-only!");
109 static PerfInputFile getPerfInputFile() {
110 PerfInputFile File;
111 if (PerfDataFilename.getNumOccurrences()) {
112 File.InputFile = PerfDataFilename;
113 File.Format = PerfFormat::PerfData;
114 } else if (PerfScriptFilename.getNumOccurrences()) {
115 File.InputFile = PerfScriptFilename;
116 File.Format = PerfFormat::PerfScript;
117 } else if (UnsymbolizedProfFilename.getNumOccurrences()) {
118 File.InputFile = UnsymbolizedProfFilename;
119 File.Format = PerfFormat::UnsymbolizedProfile;
121 return File;
124 int main(int argc, const char *argv[]) {
125 InitLLVM X(argc, argv);
127 // Initialize targets and assembly printers/parsers.
128 InitializeAllTargetInfos();
129 InitializeAllTargetMCs();
130 InitializeAllDisassemblers();
132 cl::HideUnrelatedOptions({&ProfGenCategory, &getColorCategory()});
133 cl::ParseCommandLineOptions(argc, argv, "llvm SPGO profile generator\n");
134 validateCommandLine();
136 // Load symbols and disassemble the code of a given binary.
137 std::unique_ptr<ProfiledBinary> Binary =
138 std::make_unique<ProfiledBinary>(BinaryPath);
139 if (ShowDisassemblyOnly)
140 return EXIT_SUCCESS;
142 PerfInputFile PerfFile = getPerfInputFile();
143 std::unique_ptr<PerfReaderBase> Reader =
144 PerfReaderBase::create(Binary.get(), PerfFile);
145 // Parse perf events and samples
146 Reader->parsePerfTraces();
148 if (SkipSymbolization)
149 return EXIT_SUCCESS;
151 std::unique_ptr<ProfileGeneratorBase> Generator =
152 ProfileGeneratorBase::create(Binary.get(), Reader->getSampleCounters(),
153 Reader->profileIsCSFlat());
154 Generator->generateProfile();
155 Generator->write();
157 return EXIT_SUCCESS;