1 //===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains code used to execute the program utilizing one of the 11 // various ways of running LLVM bitcode. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "BugDriver.h" 16 #include "ToolRunner.h" 17 #include "llvm/Support/CommandLine.h" 18 #include "llvm/Support/Debug.h" 19 #include "llvm/Support/FileUtilities.h" 20 #include "llvm/Support/Program.h" 21 #include "llvm/Support/SystemUtils.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <fstream> 24 25 using namespace llvm; 26 27 namespace { 28 // OutputType - Allow the user to specify the way code should be run, to test 29 // for miscompilation. 30 // 31 enum OutputType { 32 AutoPick, 33 RunLLI, 34 RunJIT, 35 RunLLC, 36 RunLLCIA, 37 LLC_Safe, 38 CompileCustom, 39 Custom 40 }; 41 42 cl::opt<double> AbsTolerance("abs-tolerance", 43 cl::desc("Absolute error tolerated"), 44 cl::init(0.0)); 45 cl::opt<double> RelTolerance("rel-tolerance", 46 cl::desc("Relative error tolerated"), 47 cl::init(0.0)); 48 49 cl::opt<OutputType> InterpreterSel( 50 cl::desc("Specify the \"test\" i.e. suspect back-end:"), 51 cl::values(clEnumValN(AutoPick, "auto", "Use best guess"), 52 clEnumValN(RunLLI, "run-int", "Execute with the interpreter"), 53 clEnumValN(RunJIT, "run-jit", "Execute with JIT"), 54 clEnumValN(RunLLC, "run-llc", "Compile with LLC"), 55 clEnumValN(RunLLCIA, "run-llc-ia", 56 "Compile with LLC with integrated assembler"), 57 clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"), 58 clEnumValN(CompileCustom, "compile-custom", 59 "Use -compile-command to define a command to " 60 "compile the bitcode. Useful to avoid linking."), 61 clEnumValN(Custom, "run-custom", 62 "Use -exec-command to define a command to execute " 63 "the bitcode. Useful for cross-compilation.")), 64 cl::init(AutoPick)); 65 66 cl::opt<OutputType> SafeInterpreterSel( 67 cl::desc("Specify \"safe\" i.e. known-good backend:"), 68 cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"), 69 clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"), 70 clEnumValN(Custom, "safe-run-custom", 71 "Use -exec-command to define a command to execute " 72 "the bitcode. Useful for cross-compilation.")), 73 cl::init(AutoPick)); 74 75 cl::opt<std::string> SafeInterpreterPath( 76 "safe-path", cl::desc("Specify the path to the \"safe\" backend program"), 77 cl::init("")); 78 79 cl::opt<bool> AppendProgramExitCode( 80 "append-exit-code", 81 cl::desc("Append the exit code to the output so it gets diff'd too"), 82 cl::init(false)); 83 84 cl::opt<std::string> 85 InputFile("input", cl::init("/dev/null"), 86 cl::desc("Filename to pipe in as stdin (default: /dev/null)")); 87 88 cl::list<std::string> 89 AdditionalSOs("additional-so", cl::desc("Additional shared objects to load " 90 "into executing programs")); 91 92 cl::list<std::string> AdditionalLinkerArgs( 93 "Xlinker", cl::desc("Additional arguments to pass to the linker")); 94 95 cl::opt<std::string> CustomCompileCommand( 96 "compile-command", cl::init("llc"), 97 cl::desc("Command to compile the bitcode (use with -compile-custom) " 98 "(default: llc)")); 99 100 cl::opt<std::string> CustomExecCommand( 101 "exec-command", cl::init("simulate"), 102 cl::desc("Command to execute the bitcode (use with -run-custom) " 103 "(default: simulate)")); 104 } 105 106 namespace llvm { 107 // Anything specified after the --args option are taken as arguments to the 108 // program being debugged. 109 cl::list<std::string> InputArgv("args", cl::Positional, 110 cl::desc("<program arguments>..."), 111 cl::ZeroOrMore, cl::PositionalEatsArgs); 112 113 cl::opt<std::string> 114 OutputPrefix("output-prefix", cl::init("bugpoint"), 115 cl::desc("Prefix to use for outputs (default: 'bugpoint')")); 116 } 117 118 namespace { 119 cl::list<std::string> ToolArgv("tool-args", cl::Positional, 120 cl::desc("<tool arguments>..."), cl::ZeroOrMore, 121 cl::PositionalEatsArgs); 122 123 cl::list<std::string> SafeToolArgv("safe-tool-args", cl::Positional, 124 cl::desc("<safe-tool arguments>..."), 125 cl::ZeroOrMore, cl::PositionalEatsArgs); 126 127 cl::opt<std::string> CCBinary("gcc", cl::init(""), 128 cl::desc("The gcc binary to use.")); 129 130 cl::list<std::string> CCToolArgv("gcc-tool-args", cl::Positional, 131 cl::desc("<gcc-tool arguments>..."), 132 cl::ZeroOrMore, cl::PositionalEatsArgs); 133 } 134 135 //===----------------------------------------------------------------------===// 136 // BugDriver method implementation 137 // 138 139 /// initializeExecutionEnvironment - This method is used to set up the 140 /// environment for executing LLVM programs. 141 /// 142 Error BugDriver::initializeExecutionEnvironment() { 143 outs() << "Initializing execution environment: "; 144 145 // Create an instance of the AbstractInterpreter interface as specified on 146 // the command line 147 SafeInterpreter = nullptr; 148 std::string Message; 149 150 if (CCBinary.empty()) { 151 if (ErrorOr<std::string> ClangPath = 152 FindProgramByName("clang", getToolName(), &AbsTolerance)) 153 CCBinary = *ClangPath; 154 else 155 CCBinary = "gcc"; 156 } 157 158 switch (InterpreterSel) { 159 case AutoPick: 160 if (!Interpreter) { 161 InterpreterSel = RunJIT; 162 Interpreter = 163 AbstractInterpreter::createJIT(getToolName(), Message, &ToolArgv); 164 } 165 if (!Interpreter) { 166 InterpreterSel = RunLLC; 167 Interpreter = AbstractInterpreter::createLLC( 168 getToolName(), Message, CCBinary, &ToolArgv, &CCToolArgv); 169 } 170 if (!Interpreter) { 171 InterpreterSel = RunLLI; 172 Interpreter = 173 AbstractInterpreter::createLLI(getToolName(), Message, &ToolArgv); 174 } 175 if (!Interpreter) { 176 InterpreterSel = AutoPick; 177 Message = "Sorry, I can't automatically select an interpreter!\n"; 178 } 179 break; 180 case RunLLI: 181 Interpreter = 182 AbstractInterpreter::createLLI(getToolName(), Message, &ToolArgv); 183 break; 184 case RunLLC: 185 case RunLLCIA: 186 case LLC_Safe: 187 Interpreter = AbstractInterpreter::createLLC( 188 getToolName(), Message, CCBinary, &ToolArgv, &CCToolArgv, 189 InterpreterSel == RunLLCIA); 190 break; 191 case RunJIT: 192 Interpreter = 193 AbstractInterpreter::createJIT(getToolName(), Message, &ToolArgv); 194 break; 195 case CompileCustom: 196 Interpreter = AbstractInterpreter::createCustomCompiler( 197 getToolName(), Message, CustomCompileCommand); 198 break; 199 case Custom: 200 Interpreter = AbstractInterpreter::createCustomExecutor( 201 getToolName(), Message, CustomExecCommand); 202 break; 203 } 204 if (!Interpreter) 205 errs() << Message; 206 else // Display informational messages on stdout instead of stderr 207 outs() << Message; 208 209 std::string Path = SafeInterpreterPath; 210 if (Path.empty()) 211 Path = getToolName(); 212 std::vector<std::string> SafeToolArgs = SafeToolArgv; 213 switch (SafeInterpreterSel) { 214 case AutoPick: 215 // In "llc-safe" mode, default to using LLC as the "safe" backend. 216 if (!SafeInterpreter && InterpreterSel == LLC_Safe) { 217 SafeInterpreterSel = RunLLC; 218 SafeToolArgs.push_back("--relocation-model=pic"); 219 SafeInterpreter = AbstractInterpreter::createLLC( 220 Path.c_str(), Message, CCBinary, &SafeToolArgs, &CCToolArgv); 221 } 222 223 if (!SafeInterpreter && InterpreterSel != RunLLC && 224 InterpreterSel != RunJIT) { 225 SafeInterpreterSel = RunLLC; 226 SafeToolArgs.push_back("--relocation-model=pic"); 227 SafeInterpreter = AbstractInterpreter::createLLC( 228 Path.c_str(), Message, CCBinary, &SafeToolArgs, &CCToolArgv); 229 } 230 if (!SafeInterpreter) { 231 SafeInterpreterSel = AutoPick; 232 Message = "Sorry, I can't automatically select a safe interpreter!\n"; 233 } 234 break; 235 case RunLLC: 236 case RunLLCIA: 237 SafeToolArgs.push_back("--relocation-model=pic"); 238 SafeInterpreter = AbstractInterpreter::createLLC( 239 Path.c_str(), Message, CCBinary, &SafeToolArgs, &CCToolArgv, 240 SafeInterpreterSel == RunLLCIA); 241 break; 242 case Custom: 243 SafeInterpreter = AbstractInterpreter::createCustomExecutor( 244 getToolName(), Message, CustomExecCommand); 245 break; 246 default: 247 Message = "Sorry, this back-end is not supported by bugpoint as the " 248 "\"safe\" backend right now!\n"; 249 break; 250 } 251 if (!SafeInterpreter) { 252 outs() << Message << "\nExiting.\n"; 253 exit(1); 254 } 255 256 cc = CC::create(getToolName(), Message, CCBinary, &CCToolArgv); 257 if (!cc) { 258 outs() << Message << "\nExiting.\n"; 259 exit(1); 260 } 261 262 // If there was an error creating the selected interpreter, quit with error. 263 if (Interpreter == nullptr) 264 return make_error<StringError>("Failed to init execution environment", 265 inconvertibleErrorCode()); 266 return Error::success(); 267 } 268 269 /// Try to compile the specified module, returning false and setting Error if an 270 /// error occurs. This is used for code generation crash testing. 271 Error BugDriver::compileProgram(Module &M) const { 272 // Emit the program to a bitcode file... 273 auto Temp = 274 sys::fs::TempFile::create(OutputPrefix + "-test-program-%%%%%%%.bc"); 275 if (!Temp) { 276 errs() << ToolName 277 << ": Error making unique filename: " << toString(Temp.takeError()) 278 << "\n"; 279 exit(1); 280 } 281 DiscardTemp Discard{*Temp}; 282 if (writeProgramToFile(Temp->FD, M)) { 283 errs() << ToolName << ": Error emitting bitcode to file '" << Temp->TmpName 284 << "'!\n"; 285 exit(1); 286 } 287 288 // Actually compile the program! 289 return Interpreter->compileProgram(Temp->TmpName, Timeout, MemoryLimit); 290 } 291 292 /// This method runs "Program", capturing the output of the program to a file, 293 /// returning the filename of the file. A recommended filename may be 294 /// optionally specified. 295 Expected<std::string> BugDriver::executeProgram(const Module &Program, 296 std::string OutputFile, 297 std::string BitcodeFile, 298 const std::string &SharedObj, 299 AbstractInterpreter *AI) const { 300 if (!AI) 301 AI = Interpreter; 302 assert(AI && "Interpreter should have been created already!"); 303 bool CreatedBitcode = false; 304 if (BitcodeFile.empty()) { 305 // Emit the program to a bitcode file... 306 SmallString<128> UniqueFilename; 307 int UniqueFD; 308 std::error_code EC = sys::fs::createUniqueFile( 309 OutputPrefix + "-test-program-%%%%%%%.bc", UniqueFD, UniqueFilename); 310 if (EC) { 311 errs() << ToolName << ": Error making unique filename: " << EC.message() 312 << "!\n"; 313 exit(1); 314 } 315 BitcodeFile = UniqueFilename.str(); 316 317 if (writeProgramToFile(BitcodeFile, UniqueFD, Program)) { 318 errs() << ToolName << ": Error emitting bitcode to file '" << BitcodeFile 319 << "'!\n"; 320 exit(1); 321 } 322 CreatedBitcode = true; 323 } 324 325 // Remove the temporary bitcode file when we are done. 326 std::string BitcodePath(BitcodeFile); 327 FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps); 328 329 if (OutputFile.empty()) 330 OutputFile = OutputPrefix + "-execution-output-%%%%%%%"; 331 332 // Check to see if this is a valid output filename... 333 SmallString<128> UniqueFile; 334 std::error_code EC = sys::fs::createUniqueFile(OutputFile, UniqueFile); 335 if (EC) { 336 errs() << ToolName << ": Error making unique filename: " << EC.message() 337 << "\n"; 338 exit(1); 339 } 340 OutputFile = UniqueFile.str(); 341 342 // Figure out which shared objects to run, if any. 343 std::vector<std::string> SharedObjs(AdditionalSOs); 344 if (!SharedObj.empty()) 345 SharedObjs.push_back(SharedObj); 346 347 Expected<int> RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, 348 OutputFile, AdditionalLinkerArgs, 349 SharedObjs, Timeout, MemoryLimit); 350 if (Error E = RetVal.takeError()) 351 return std::move(E); 352 353 if (*RetVal == -1) { 354 errs() << "<timeout>"; 355 static bool FirstTimeout = true; 356 if (FirstTimeout) { 357 outs() 358 << "\n" 359 "*** Program execution timed out! This mechanism is designed to " 360 "handle\n" 361 " programs stuck in infinite loops gracefully. The -timeout " 362 "option\n" 363 " can be used to change the timeout threshold or disable it " 364 "completely\n" 365 " (with -timeout=0). This message is only displayed once.\n"; 366 FirstTimeout = false; 367 } 368 } 369 370 if (AppendProgramExitCode) { 371 std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 372 outFile << "exit " << *RetVal << '\n'; 373 outFile.close(); 374 } 375 376 // Return the filename we captured the output to. 377 return OutputFile; 378 } 379 380 /// Used to create reference output with the "safe" backend, if reference output 381 /// is not provided. 382 Expected<std::string> 383 BugDriver::executeProgramSafely(const Module &Program, 384 const std::string &OutputFile) const { 385 return executeProgram(Program, OutputFile, "", "", SafeInterpreter); 386 } 387 388 Expected<std::string> 389 BugDriver::compileSharedObject(const std::string &BitcodeFile) { 390 assert(Interpreter && "Interpreter should have been created already!"); 391 std::string OutputFile; 392 393 // Using the known-good backend. 394 Expected<CC::FileType> FT = 395 SafeInterpreter->OutputCode(BitcodeFile, OutputFile); 396 if (Error E = FT.takeError()) 397 return std::move(E); 398 399 std::string SharedObjectFile; 400 if (Error E = cc->MakeSharedObject(OutputFile, *FT, SharedObjectFile, 401 AdditionalLinkerArgs)) 402 return std::move(E); 403 404 // Remove the intermediate C file 405 sys::fs::remove(OutputFile); 406 407 return SharedObjectFile; 408 } 409 410 /// Calls compileProgram and then records the output into ReferenceOutputFile. 411 /// Returns true if reference file created, false otherwise. Note: 412 /// initializeExecutionEnvironment should be called BEFORE this function. 413 Error BugDriver::createReferenceFile(Module &M, const std::string &Filename) { 414 if (Error E = compileProgram(*Program)) 415 return E; 416 417 Expected<std::string> Result = executeProgramSafely(*Program, Filename); 418 if (Error E = Result.takeError()) { 419 if (Interpreter != SafeInterpreter) { 420 E = joinErrors( 421 std::move(E), 422 make_error<StringError>( 423 "*** There is a bug running the \"safe\" backend. Either" 424 " debug it (for example with the -run-jit bugpoint option," 425 " if JIT is being used as the \"safe\" backend), or fix the" 426 " error some other way.\n", 427 inconvertibleErrorCode())); 428 } 429 return E; 430 } 431 ReferenceOutputFile = *Result; 432 outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; 433 return Error::success(); 434 } 435 436 /// This method executes the specified module and diffs the output against the 437 /// file specified by ReferenceOutputFile. If the output is different, 1 is 438 /// returned. If there is a problem with the code generator (e.g., llc 439 /// crashes), this will set ErrMsg. 440 Expected<bool> BugDriver::diffProgram(const Module &Program, 441 const std::string &BitcodeFile, 442 const std::string &SharedObject, 443 bool RemoveBitcode) const { 444 // Execute the program, generating an output file... 445 Expected<std::string> Output = 446 executeProgram(Program, "", BitcodeFile, SharedObject, nullptr); 447 if (Error E = Output.takeError()) 448 return std::move(E); 449 450 std::string Error; 451 bool FilesDifferent = false; 452 if (int Diff = DiffFilesWithTolerance(ReferenceOutputFile, *Output, 453 AbsTolerance, RelTolerance, &Error)) { 454 if (Diff == 2) { 455 errs() << "While diffing output: " << Error << '\n'; 456 exit(1); 457 } 458 FilesDifferent = true; 459 } else { 460 // Remove the generated output if there are no differences. 461 sys::fs::remove(*Output); 462 } 463 464 // Remove the bitcode file if we are supposed to. 465 if (RemoveBitcode) 466 sys::fs::remove(BitcodeFile); 467 return FilesDifferent; 468 } 469 470 bool BugDriver::isExecutingJIT() { return InterpreterSel == RunJIT; } 471