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 (sys::findProgramByName("clang")) 152 CCBinary = "clang"; 153 else 154 CCBinary = "gcc"; 155 } 156 157 switch (InterpreterSel) { 158 case AutoPick: 159 if (!Interpreter) { 160 InterpreterSel = RunJIT; 161 Interpreter = 162 AbstractInterpreter::createJIT(getToolName(), Message, &ToolArgv); 163 } 164 if (!Interpreter) { 165 InterpreterSel = RunLLC; 166 Interpreter = AbstractInterpreter::createLLC( 167 getToolName(), Message, CCBinary, &ToolArgv, &CCToolArgv); 168 } 169 if (!Interpreter) { 170 InterpreterSel = RunLLI; 171 Interpreter = 172 AbstractInterpreter::createLLI(getToolName(), Message, &ToolArgv); 173 } 174 if (!Interpreter) { 175 InterpreterSel = AutoPick; 176 Message = "Sorry, I can't automatically select an interpreter!\n"; 177 } 178 break; 179 case RunLLI: 180 Interpreter = 181 AbstractInterpreter::createLLI(getToolName(), Message, &ToolArgv); 182 break; 183 case RunLLC: 184 case RunLLCIA: 185 case LLC_Safe: 186 Interpreter = AbstractInterpreter::createLLC( 187 getToolName(), Message, CCBinary, &ToolArgv, &CCToolArgv, 188 InterpreterSel == RunLLCIA); 189 break; 190 case RunJIT: 191 Interpreter = 192 AbstractInterpreter::createJIT(getToolName(), Message, &ToolArgv); 193 break; 194 case CompileCustom: 195 Interpreter = AbstractInterpreter::createCustomCompiler( 196 Message, CustomCompileCommand); 197 break; 198 case Custom: 199 Interpreter = 200 AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); 201 break; 202 } 203 if (!Interpreter) 204 errs() << Message; 205 else // Display informational messages on stdout instead of stderr 206 outs() << Message; 207 208 std::string Path = SafeInterpreterPath; 209 if (Path.empty()) 210 Path = getToolName(); 211 std::vector<std::string> SafeToolArgs = SafeToolArgv; 212 switch (SafeInterpreterSel) { 213 case AutoPick: 214 // In "llc-safe" mode, default to using LLC as the "safe" backend. 215 if (!SafeInterpreter && InterpreterSel == LLC_Safe) { 216 SafeInterpreterSel = RunLLC; 217 SafeToolArgs.push_back("--relocation-model=pic"); 218 SafeInterpreter = AbstractInterpreter::createLLC( 219 Path.c_str(), Message, CCBinary, &SafeToolArgs, &CCToolArgv); 220 } 221 222 if (!SafeInterpreter && InterpreterSel != RunLLC && 223 InterpreterSel != RunJIT) { 224 SafeInterpreterSel = RunLLC; 225 SafeToolArgs.push_back("--relocation-model=pic"); 226 SafeInterpreter = AbstractInterpreter::createLLC( 227 Path.c_str(), Message, CCBinary, &SafeToolArgs, &CCToolArgv); 228 } 229 if (!SafeInterpreter) { 230 SafeInterpreterSel = AutoPick; 231 Message = "Sorry, I can't automatically select a safe interpreter!\n"; 232 } 233 break; 234 case RunLLC: 235 case RunLLCIA: 236 SafeToolArgs.push_back("--relocation-model=pic"); 237 SafeInterpreter = AbstractInterpreter::createLLC( 238 Path.c_str(), Message, CCBinary, &SafeToolArgs, &CCToolArgv, 239 SafeInterpreterSel == RunLLCIA); 240 break; 241 case Custom: 242 SafeInterpreter = 243 AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); 244 break; 245 default: 246 Message = "Sorry, this back-end is not supported by bugpoint as the " 247 "\"safe\" backend right now!\n"; 248 break; 249 } 250 if (!SafeInterpreter) { 251 outs() << Message << "\nExiting.\n"; 252 exit(1); 253 } 254 255 cc = CC::create(Message, CCBinary, &CCToolArgv); 256 if (!cc) { 257 outs() << Message << "\nExiting.\n"; 258 exit(1); 259 } 260 261 // If there was an error creating the selected interpreter, quit with error. 262 if (Interpreter == nullptr) 263 return make_error<StringError>("Failed to init execution environment", 264 inconvertibleErrorCode()); 265 return Error::success(); 266 } 267 268 /// compileProgram - Try to compile the specified module, returning false and 269 /// setting Error if an error occurs. This is used for code generation 270 /// crash testing. 271 /// 272 Error BugDriver::compileProgram(Module *M) const { 273 // Emit the program to a bitcode file... 274 SmallString<128> BitcodeFile; 275 int BitcodeFD; 276 std::error_code EC = sys::fs::createUniqueFile( 277 OutputPrefix + "-test-program-%%%%%%%.bc", BitcodeFD, BitcodeFile); 278 if (EC) { 279 errs() << ToolName << ": Error making unique filename: " << EC.message() 280 << "\n"; 281 exit(1); 282 } 283 if (writeProgramToFile(BitcodeFile.str(), BitcodeFD, M)) { 284 errs() << ToolName << ": Error emitting bitcode to file '" << BitcodeFile 285 << "'!\n"; 286 exit(1); 287 } 288 289 // Remove the temporary bitcode file when we are done. 290 FileRemover BitcodeFileRemover(BitcodeFile.str(), !SaveTemps); 291 292 // Actually compile the program! 293 return Interpreter->compileProgram(BitcodeFile.str(), Timeout, MemoryLimit); 294 } 295 296 /// executeProgram - This method runs "Program", capturing the output of the 297 /// program to a file, returning the filename of the file. A recommended 298 /// filename may be optionally specified. 299 /// 300 Expected<std::string> BugDriver::executeProgram(const Module *Program, 301 std::string OutputFile, 302 std::string BitcodeFile, 303 const std::string &SharedObj, 304 AbstractInterpreter *AI) const { 305 if (!AI) 306 AI = Interpreter; 307 assert(AI && "Interpreter should have been created already!"); 308 bool CreatedBitcode = false; 309 if (BitcodeFile.empty()) { 310 // Emit the program to a bitcode file... 311 SmallString<128> UniqueFilename; 312 int UniqueFD; 313 std::error_code EC = sys::fs::createUniqueFile( 314 OutputPrefix + "-test-program-%%%%%%%.bc", UniqueFD, UniqueFilename); 315 if (EC) { 316 errs() << ToolName << ": Error making unique filename: " << EC.message() 317 << "!\n"; 318 exit(1); 319 } 320 BitcodeFile = UniqueFilename.str(); 321 322 if (writeProgramToFile(BitcodeFile, UniqueFD, Program)) { 323 errs() << ToolName << ": Error emitting bitcode to file '" << BitcodeFile 324 << "'!\n"; 325 exit(1); 326 } 327 CreatedBitcode = true; 328 } 329 330 // Remove the temporary bitcode file when we are done. 331 std::string BitcodePath(BitcodeFile); 332 FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps); 333 334 if (OutputFile.empty()) 335 OutputFile = OutputPrefix + "-execution-output-%%%%%%%"; 336 337 // Check to see if this is a valid output filename... 338 SmallString<128> UniqueFile; 339 std::error_code EC = sys::fs::createUniqueFile(OutputFile, UniqueFile); 340 if (EC) { 341 errs() << ToolName << ": Error making unique filename: " << EC.message() 342 << "\n"; 343 exit(1); 344 } 345 OutputFile = UniqueFile.str(); 346 347 // Figure out which shared objects to run, if any. 348 std::vector<std::string> SharedObjs(AdditionalSOs); 349 if (!SharedObj.empty()) 350 SharedObjs.push_back(SharedObj); 351 352 Expected<int> RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, 353 OutputFile, AdditionalLinkerArgs, 354 SharedObjs, Timeout, MemoryLimit); 355 if (Error E = RetVal.takeError()) 356 return std::move(E); 357 358 if (*RetVal == -1) { 359 errs() << "<timeout>"; 360 static bool FirstTimeout = true; 361 if (FirstTimeout) { 362 outs() 363 << "\n" 364 "*** Program execution timed out! This mechanism is designed to " 365 "handle\n" 366 " programs stuck in infinite loops gracefully. The -timeout " 367 "option\n" 368 " can be used to change the timeout threshold or disable it " 369 "completely\n" 370 " (with -timeout=0). This message is only displayed once.\n"; 371 FirstTimeout = false; 372 } 373 } 374 375 if (AppendProgramExitCode) { 376 std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 377 outFile << "exit " << *RetVal << '\n'; 378 outFile.close(); 379 } 380 381 // Return the filename we captured the output to. 382 return OutputFile; 383 } 384 385 /// executeProgramSafely - Used to create reference output with the "safe" 386 /// backend, if reference output is not provided. 387 /// 388 Expected<std::string> 389 BugDriver::executeProgramSafely(const Module *Program, 390 const std::string &OutputFile) const { 391 return executeProgram(Program, OutputFile, "", "", SafeInterpreter); 392 } 393 394 Expected<std::string> 395 BugDriver::compileSharedObject(const std::string &BitcodeFile) { 396 assert(Interpreter && "Interpreter should have been created already!"); 397 std::string OutputFile; 398 399 // Using the known-good backend. 400 Expected<CC::FileType> FT = 401 SafeInterpreter->OutputCode(BitcodeFile, OutputFile); 402 if (Error E = FT.takeError()) 403 return std::move(E); 404 405 std::string SharedObjectFile; 406 if (Error E = cc->MakeSharedObject(OutputFile, *FT, SharedObjectFile, 407 AdditionalLinkerArgs)) 408 return std::move(E); 409 410 // Remove the intermediate C file 411 sys::fs::remove(OutputFile); 412 413 return SharedObjectFile; 414 } 415 416 /// createReferenceFile - calls compileProgram and then records the output 417 /// into ReferenceOutputFile. Returns true if reference file created, false 418 /// otherwise. Note: initializeExecutionEnvironment should be called BEFORE 419 /// this function. 420 /// 421 Error BugDriver::createReferenceFile(Module *M, const std::string &Filename) { 422 if (Error E = compileProgram(Program)) 423 return E; 424 425 Expected<std::string> Result = executeProgramSafely(Program, Filename); 426 if (Error E = Result.takeError()) { 427 if (Interpreter != SafeInterpreter) { 428 E = joinErrors( 429 std::move(E), 430 make_error<StringError>( 431 "*** There is a bug running the \"safe\" backend. Either" 432 " debug it (for example with the -run-jit bugpoint option," 433 " if JIT is being used as the \"safe\" backend), or fix the" 434 " error some other way.\n", 435 inconvertibleErrorCode())); 436 } 437 return E; 438 } 439 ReferenceOutputFile = *Result; 440 outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; 441 return Error::success(); 442 } 443 444 /// diffProgram - This method executes the specified module and diffs the 445 /// output against the file specified by ReferenceOutputFile. If the output 446 /// is different, 1 is returned. If there is a problem with the code 447 /// generator (e.g., llc crashes), this will set ErrMsg. 448 /// 449 Expected<bool> BugDriver::diffProgram(const Module *Program, 450 const std::string &BitcodeFile, 451 const std::string &SharedObject, 452 bool RemoveBitcode) const { 453 // Execute the program, generating an output file... 454 Expected<std::string> Output = 455 executeProgram(Program, "", BitcodeFile, SharedObject, nullptr); 456 if (Error E = Output.takeError()) 457 return std::move(E); 458 459 std::string Error; 460 bool FilesDifferent = false; 461 if (int Diff = DiffFilesWithTolerance(ReferenceOutputFile, *Output, 462 AbsTolerance, RelTolerance, &Error)) { 463 if (Diff == 2) { 464 errs() << "While diffing output: " << Error << '\n'; 465 exit(1); 466 } 467 FilesDifferent = true; 468 } else { 469 // Remove the generated output if there are no differences. 470 sys::fs::remove(*Output); 471 } 472 473 // Remove the bitcode file if we are supposed to. 474 if (RemoveBitcode) 475 sys::fs::remove(BitcodeFile); 476 return FilesDifferent; 477 } 478 479 bool BugDriver::isExecutingJIT() { return InterpreterSel == RunJIT; } 480