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