Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 1 | //===-- UnixLocalInferiorProcess.cpp - A Local process on a Unixy system --===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the LLVM research group and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file provides one implementation of the InferiorProcess class, which is |
| 11 | // designed to be used on unixy systems (those that support pipe, fork, exec, |
| 12 | // and signals). |
| 13 | // |
| 14 | // When the process is started, the debugger creates a pair of pipes, forks, and |
Brian Gaeke | c2376a0 | 2004-01-05 17:22:52 +0000 | [diff] [blame] | 15 | // makes the child start executing the program. The child executes the process |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 16 | // with an IntrinsicLowering instance that turns debugger intrinsics into actual |
| 17 | // callbacks. |
| 18 | // |
| 19 | // This target takes advantage of the fact that the Module* addresses in the |
| 20 | // parent and the Module* addresses in the child will be the same, due to the |
| 21 | // use of fork(). As such, global addresses looked up in the child can be sent |
| 22 | // over the pipe to the debugger. |
| 23 | // |
| 24 | //===----------------------------------------------------------------------===// |
| 25 | |
| 26 | #include "llvm/Debugger/InferiorProcess.h" |
| 27 | #include "llvm/IntrinsicLowering.h" |
| 28 | #include "llvm/Constant.h" |
| 29 | #include "llvm/Module.h" |
| 30 | #include "llvm/ModuleProvider.h" |
| 31 | #include "llvm/Type.h" |
| 32 | #include "llvm/iOther.h" |
| 33 | #include "llvm/ExecutionEngine/GenericValue.h" |
| 34 | #include "llvm/ExecutionEngine/ExecutionEngine.h" |
| 35 | #include "Support/FileUtilities.h" |
| 36 | #include "Support/StringExtras.h" |
| 37 | #include <cerrno> |
Brian Gaeke | c2376a0 | 2004-01-05 17:22:52 +0000 | [diff] [blame] | 38 | #include <csignal> |
| 39 | #include <unistd.h> // Unix-specific debugger support |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 40 | #include <sys/types.h> |
| 41 | #include <sys/wait.h> |
| 42 | using namespace llvm; |
| 43 | |
| 44 | // runChild - Entry point for the child process. |
| 45 | static void runChild(Module *M, const std::vector<std::string> &Arguments, |
| 46 | const char * const *envp, |
| 47 | FDHandle ReadFD, FDHandle WriteFD); |
| 48 | |
| 49 | //===----------------------------------------------------------------------===// |
| 50 | // Parent/Child Pipe Protocol |
| 51 | //===----------------------------------------------------------------------===// |
| 52 | // |
| 53 | // The parent/child communication protocol is designed to have the child process |
| 54 | // responding to requests that the debugger makes. Whenever the child process |
| 55 | // has stopped (due to a break point, single stepping, etc), the child process |
| 56 | // enters a message processing loop, where it reads and responds to commands |
| 57 | // until the parent decides that it wants to continue execution in some way. |
| 58 | // |
Brian Gaeke | c2376a0 | 2004-01-05 17:22:52 +0000 | [diff] [blame] | 59 | // Whenever the child process stops, it notifies the debugger by sending a |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 60 | // character over the wire. |
| 61 | // |
| 62 | |
| 63 | namespace { |
| 64 | /// LocationToken - Objects of this type are sent across the pipe from the |
| 65 | /// child to the parent to indicate where various stack frames are located. |
| 66 | struct LocationToken { |
| 67 | unsigned Line, Col; |
| 68 | const GlobalVariable *File; |
| 69 | LocationToken(unsigned L = 0, unsigned C = 0, const GlobalVariable *F = 0) |
| 70 | : Line(L), Col(C), File(F) {} |
| 71 | }; |
| 72 | } |
| 73 | |
| 74 | // Once the debugger process has received the LocationToken, it can make |
| 75 | // requests of the child by sending one of the following enum values followed by |
| 76 | // any data required by that command. The child responds with data appropriate |
| 77 | // to the command. |
| 78 | // |
| 79 | namespace { |
| 80 | /// CommandID - This enum defines all of the commands that the child process |
| 81 | /// can respond to. The actual expected data and responses are defined as the |
| 82 | /// enum values are defined. |
| 83 | /// |
| 84 | enum CommandID { |
| 85 | //===------------------------------------------------------------------===// |
| 86 | // Execution commands - These are sent to the child to from the debugger to |
| 87 | // get it to do certain things. |
| 88 | // |
| 89 | |
| 90 | // StepProgram: void->char - This command causes the program to continue |
| 91 | // execution, but stop as soon as it reaches another stoppoint. |
| 92 | StepProgram, |
| 93 | |
| 94 | // FinishProgram: FrameDesc*->char - This command causes the program to |
| 95 | // continue execution until the specified function frame returns. |
| 96 | FinishProgram, |
| 97 | |
| 98 | // ContProgram: void->char - This command causes the program to continue |
| 99 | // execution, stopping at some point in the future. |
| 100 | ContProgram, |
| 101 | |
| 102 | // GetSubprogramDescriptor: FrameDesc*->GlobalValue* - This command returns |
| 103 | // the GlobalValue* descriptor object for the specified stack frame. |
| 104 | GetSubprogramDescriptor, |
| 105 | |
| 106 | // GetParentFrame: FrameDesc*->FrameDesc* - This command returns the frame |
| 107 | // descriptor for the parent stack frame to the specified one, or null if |
| 108 | // there is none. |
| 109 | GetParentFrame, |
| 110 | |
| 111 | // GetFrameLocation - FrameDesc*->LocationToken - This command returns the |
| 112 | // location that a particular stack frame is stopped at. |
| 113 | GetFrameLocation, |
| 114 | |
| 115 | // AddBreakpoint - LocationToken->unsigned - This command instructs the |
| 116 | // target to install a breakpoint at the specified location. |
| 117 | AddBreakpoint, |
| 118 | |
| 119 | // RemoveBreakpoint - unsigned->void - This command instructs the target to |
| 120 | // remove a breakpoint. |
| 121 | RemoveBreakpoint, |
| 122 | }; |
| 123 | } |
| 124 | |
| 125 | |
| 126 | |
| 127 | |
| 128 | //===----------------------------------------------------------------------===// |
| 129 | // Parent Process Code |
| 130 | //===----------------------------------------------------------------------===// |
| 131 | |
| 132 | namespace { |
| 133 | class IP : public InferiorProcess { |
| 134 | // ReadFD, WriteFD - The file descriptors to read/write to the inferior |
| 135 | // process. |
| 136 | FDHandle ReadFD, WriteFD; |
| 137 | |
| 138 | // ChildPID - The unix PID of the child process we forked. |
| 139 | mutable pid_t ChildPID; |
| 140 | public: |
| 141 | IP(Module *M, const std::vector<std::string> &Arguments, |
| 142 | const char * const *envp); |
| 143 | ~IP(); |
| 144 | |
| 145 | std::string getStatus() const; |
| 146 | |
| 147 | /// Execution method implementations... |
| 148 | virtual void stepProgram(); |
| 149 | virtual void finishProgram(void *Frame); |
| 150 | virtual void contProgram(); |
| 151 | |
| 152 | |
| 153 | // Stack frame method implementations... |
| 154 | virtual void *getPreviousFrame(void *Frame) const; |
| 155 | virtual const GlobalVariable *getSubprogramDesc(void *Frame) const; |
| 156 | virtual void getFrameLocation(void *Frame, unsigned &LineNo, |
| 157 | unsigned &ColNo, |
| 158 | const GlobalVariable *&SourceDesc) const; |
| 159 | |
| 160 | // Breakpoint implementation methods |
| 161 | virtual unsigned addBreakpoint(unsigned LineNo, unsigned ColNo, |
| 162 | const GlobalVariable *SourceDesc); |
| 163 | virtual void removeBreakpoint(unsigned ID); |
| 164 | |
| 165 | |
| 166 | private: |
| 167 | /// startChild - This starts up the child process, and initializes the |
| 168 | /// ChildPID member. |
| 169 | /// |
| 170 | void startChild(Module *M, const std::vector<std::string> &Arguments, |
| 171 | const char * const *envp); |
| 172 | |
| 173 | /// killChild - Kill or reap the child process. This throws the |
| 174 | /// InferiorProcessDead exception an exit code if the process had already |
| 175 | /// died, otherwise it just kills it and returns. |
| 176 | void killChild() const; |
| 177 | |
| 178 | private: |
| 179 | // Methods for communicating with the child process. If the child exits or |
| 180 | // dies while attempting to communicate with it, ChildPID is set to zero and |
| 181 | // an exception is thrown. |
| 182 | |
| 183 | /// readFromChild - Low-level primitive to read some data from the child, |
| 184 | /// throwing an exception if it dies. |
| 185 | void readFromChild(void *Buffer, unsigned Size) const; |
| 186 | |
| 187 | /// writeToChild - Low-level primitive to send some data to the child |
| 188 | /// process, throwing an exception if the child died. |
| 189 | void writeToChild(void *Buffer, unsigned Size) const; |
| 190 | |
| 191 | /// sendCommand - Send a command token and the request data to the child. |
| 192 | /// |
| 193 | void sendCommand(CommandID Command, void *Data, unsigned Size) const; |
| 194 | |
| 195 | /// waitForStop - This method waits for the child process to reach a stop |
| 196 | /// point. |
| 197 | void waitForStop(); |
| 198 | }; |
| 199 | } |
| 200 | |
| 201 | // create - This is the factory method for the InferiorProcess class. Since |
| 202 | // there is currently only one subclass of InferiorProcess, we just define it |
| 203 | // here. |
| 204 | InferiorProcess * |
| 205 | InferiorProcess::create(Module *M, const std::vector<std::string> &Arguments, |
| 206 | const char * const *envp) { |
| 207 | return new IP(M, Arguments, envp); |
| 208 | } |
| 209 | |
| 210 | /// IP constructor - Create some pipes, them fork a child process. The child |
| 211 | /// process should start execution of the debugged program, but stop at the |
| 212 | /// first available opportunity. |
| 213 | IP::IP(Module *M, const std::vector<std::string> &Arguments, |
| 214 | const char * const *envp) |
| 215 | : InferiorProcess(M) { |
| 216 | |
| 217 | // Start the child running... |
| 218 | startChild(M, Arguments, envp); |
| 219 | |
| 220 | // Okay, we created the program and it is off and running. Wait for it to |
| 221 | // stop now. |
| 222 | try { |
| 223 | waitForStop(); |
| 224 | } catch (InferiorProcessDead &IPD) { |
| 225 | throw "Error waiting for the child process to stop. " |
| 226 | "It exited with status " + itostr(IPD.getExitCode()); |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | IP::~IP() { |
| 231 | // If the child is still running, kill it. |
| 232 | if (!ChildPID) return; |
| 233 | |
| 234 | killChild(); |
| 235 | } |
| 236 | |
| 237 | /// getStatus - Return information about the unix process being debugged. |
| 238 | /// |
| 239 | std::string IP::getStatus() const { |
| 240 | if (ChildPID == 0) |
| 241 | return "Unix target. ERROR: child process appears to be dead!\n"; |
| 242 | |
| 243 | return "Unix target: PID #" + utostr((unsigned)ChildPID) + "\n"; |
| 244 | } |
| 245 | |
| 246 | |
| 247 | /// startChild - This starts up the child process, and initializes the |
| 248 | /// ChildPID member. |
| 249 | /// |
| 250 | void IP::startChild(Module *M, const std::vector<std::string> &Arguments, |
| 251 | const char * const *envp) { |
| 252 | // Create the pipes. Make sure to immediately assign the returned file |
| 253 | // descriptors to FDHandle's so they get destroyed if an exception is thrown. |
| 254 | int FDs[2]; |
| 255 | if (pipe(FDs)) throw "Error creating a pipe!"; |
| 256 | FDHandle ChildReadFD(FDs[0]); |
| 257 | WriteFD = FDs[1]; |
| 258 | |
| 259 | if (pipe(FDs)) throw "Error creating a pipe!"; |
| 260 | ReadFD = FDs[0]; |
| 261 | FDHandle ChildWriteFD(FDs[1]); |
| 262 | |
| 263 | // Fork off the child process. |
| 264 | switch (ChildPID = fork()) { |
| 265 | case -1: throw "Error forking child process!"; |
| 266 | case 0: // child |
| 267 | delete this; // Free parent pipe file descriptors |
| 268 | runChild(M, Arguments, envp, ChildReadFD, ChildWriteFD); |
| 269 | exit(1); |
| 270 | default: break; |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | /// sendCommand - Send a command token and the request data to the child. |
| 275 | /// |
| 276 | void IP::sendCommand(CommandID Command, void *Data, unsigned Size) const { |
| 277 | writeToChild(&Command, sizeof(Command)); |
| 278 | writeToChild(Data, Size); |
| 279 | } |
| 280 | |
| 281 | /// stepProgram - Implement the 'step' command, continuing execution until |
| 282 | /// the next possible stop point. |
| 283 | void IP::stepProgram() { |
| 284 | sendCommand(StepProgram, 0, 0); |
| 285 | waitForStop(); |
| 286 | } |
| 287 | |
| 288 | /// finishProgram - Implement the 'finish' command, executing the program until |
| 289 | /// the current function returns to its caller. |
| 290 | void IP::finishProgram(void *Frame) { |
| 291 | sendCommand(FinishProgram, &Frame, sizeof(Frame)); |
| 292 | waitForStop(); |
| 293 | } |
| 294 | |
| 295 | /// contProgram - Implement the 'cont' command, continuing execution until |
| 296 | /// a breakpoint is encountered. |
| 297 | void IP::contProgram() { |
| 298 | sendCommand(ContProgram, 0, 0); |
| 299 | waitForStop(); |
| 300 | } |
| 301 | |
| 302 | |
| 303 | //===----------------------------------------------------------------------===// |
| 304 | // Stack manipulation methods |
| 305 | // |
| 306 | |
| 307 | /// getPreviousFrame - Given the descriptor for the current stack frame, |
| 308 | /// return the descriptor for the caller frame. This returns null when it |
| 309 | /// runs out of frames. |
| 310 | void *IP::getPreviousFrame(void *Frame) const { |
| 311 | sendCommand(GetParentFrame, &Frame, sizeof(Frame)); |
| 312 | readFromChild(&Frame, sizeof(Frame)); |
| 313 | return Frame; |
| 314 | } |
| 315 | |
| 316 | /// getSubprogramDesc - Return the subprogram descriptor for the current |
| 317 | /// stack frame. |
| 318 | const GlobalVariable *IP::getSubprogramDesc(void *Frame) const { |
| 319 | sendCommand(GetSubprogramDescriptor, &Frame, sizeof(Frame)); |
| 320 | const GlobalVariable *Desc; |
| 321 | readFromChild(&Desc, sizeof(Desc)); |
| 322 | return Desc; |
| 323 | } |
| 324 | |
| 325 | /// getFrameLocation - This method returns the source location where each stack |
| 326 | /// frame is stopped. |
| 327 | void IP::getFrameLocation(void *Frame, unsigned &LineNo, unsigned &ColNo, |
| 328 | const GlobalVariable *&SourceDesc) const { |
| 329 | sendCommand(GetFrameLocation, &Frame, sizeof(Frame)); |
| 330 | LocationToken Loc; |
| 331 | readFromChild(&Loc, sizeof(Loc)); |
| 332 | LineNo = Loc.Line; |
| 333 | ColNo = Loc.Col; |
| 334 | SourceDesc = Loc.File; |
| 335 | } |
| 336 | |
| 337 | |
| 338 | //===----------------------------------------------------------------------===// |
| 339 | // Breakpoint manipulation methods |
| 340 | // |
| 341 | unsigned IP::addBreakpoint(unsigned LineNo, unsigned ColNo, |
| 342 | const GlobalVariable *SourceDesc) { |
| 343 | LocationToken Loc; |
| 344 | Loc.Line = LineNo; |
| 345 | Loc.Col = ColNo; |
| 346 | Loc.File = SourceDesc; |
| 347 | sendCommand(AddBreakpoint, &Loc, sizeof(Loc)); |
| 348 | unsigned ID; |
| 349 | readFromChild(&ID, sizeof(ID)); |
| 350 | return ID; |
| 351 | } |
| 352 | |
| 353 | void IP::removeBreakpoint(unsigned ID) { |
| 354 | sendCommand(RemoveBreakpoint, &ID, sizeof(ID)); |
| 355 | } |
| 356 | |
| 357 | |
| 358 | //===----------------------------------------------------------------------===// |
| 359 | // Methods for communication with the child process |
| 360 | // |
| 361 | // Methods for communicating with the child process. If the child exits or dies |
| 362 | // while attempting to communicate with it, ChildPID is set to zero and an |
| 363 | // exception is thrown. |
| 364 | // |
| 365 | |
| 366 | /// readFromChild - Low-level primitive to read some data from the child, |
| 367 | /// throwing an exception if it dies. |
| 368 | void IP::readFromChild(void *Buffer, unsigned Size) const { |
| 369 | assert(ChildPID && |
| 370 | "Child process died and still attempting to communicate with it!"); |
| 371 | while (Size) { |
| 372 | ssize_t Amount = read(ReadFD, Buffer, Size); |
| 373 | if (Amount == 0) { |
| 374 | // If we cannot communicate with the process, kill it. |
| 375 | killChild(); |
| 376 | // If killChild succeeded, then the process must have closed the pipe FD |
| 377 | // or something, because the child existed, but we cannot communicate with |
| 378 | // it. |
| 379 | throw InferiorProcessDead(-1); |
| 380 | } else if (Amount == -1) { |
| 381 | if (errno != EINTR) { |
| 382 | ChildPID = 0; |
| 383 | killChild(); |
| 384 | throw "Error reading from child process!"; |
| 385 | } |
| 386 | } else { |
| 387 | // We read a chunk. |
| 388 | Buffer = (char*)Buffer + Amount; |
| 389 | Size -= Amount; |
| 390 | } |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | /// writeToChild - Low-level primitive to send some data to the child |
| 395 | /// process, throwing an exception if the child died. |
| 396 | void IP::writeToChild(void *Buffer, unsigned Size) const { |
| 397 | while (Size) { |
| 398 | ssize_t Amount = write(WriteFD, Buffer, Size); |
| 399 | if (Amount < 0 && errno == EINTR) continue; |
| 400 | if (Amount <= 0) { |
| 401 | // If we cannot communicate with the process, kill it. |
| 402 | killChild(); |
| 403 | |
| 404 | // If killChild succeeded, then the process must have closed the pipe FD |
| 405 | // or something, because the child existed, but we cannot communicate with |
| 406 | // it. |
| 407 | throw InferiorProcessDead(-1); |
| 408 | } else { |
| 409 | // We wrote a chunk. |
| 410 | Buffer = (char*)Buffer + Amount; |
| 411 | Size -= Amount; |
| 412 | } |
| 413 | } |
| 414 | } |
| 415 | |
| 416 | /// killChild - Kill or reap the child process. This throws the |
| 417 | /// InferiorProcessDead exception an exit code if the process had already |
| 418 | /// died, otherwise it just returns the exit code if it had to be killed. |
| 419 | void IP::killChild() const { |
| 420 | assert(ChildPID != 0 && "Child has already been reaped!"); |
| 421 | |
Chris Lattner | 411a9a6 | 2004-01-14 21:18:03 +0000 | [diff] [blame] | 422 | // If the process terminated on its own accord, closing the pipe file |
| 423 | // descriptors, we will get here. Check to see if the process has already |
| 424 | // died in this manner, gracefully. |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 425 | int Status = 0; |
| 426 | int PID; |
| 427 | do { |
| 428 | PID = waitpid(ChildPID, &Status, WNOHANG); |
| 429 | } while (PID < 0 && errno == EINTR); |
| 430 | if (PID < 0) throw "Error waiting for child to exit!"; |
| 431 | |
Chris Lattner | 411a9a6 | 2004-01-14 21:18:03 +0000 | [diff] [blame] | 432 | // Ok, there is a slight race condition here. It's possible that we will find |
| 433 | // out that the file descriptor closed before waitpid will indicate that the |
| 434 | // process gracefully died. If we don't know that the process gracefully |
| 435 | // died, wait a bit and try again. This is pretty nasty. |
| 436 | if (PID == 0) { |
| 437 | usleep(10000); // Wait a bit. |
| 438 | |
| 439 | // Try again. |
| 440 | Status = 0; |
| 441 | do { |
| 442 | PID = waitpid(ChildPID, &Status, WNOHANG); |
| 443 | } while (PID < 0 && errno == EINTR); |
| 444 | if (PID < 0) throw "Error waiting for child to exit!"; |
| 445 | } |
| 446 | |
| 447 | // If the child process was already dead, then indicate that the process |
| 448 | // terminated on its own. |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 449 | if (PID) { |
| 450 | assert(PID == ChildPID && "Didn't reap child?"); |
| 451 | ChildPID = 0; // Child has been reaped |
| 452 | if (WIFEXITED(Status)) |
| 453 | throw InferiorProcessDead(WEXITSTATUS(Status)); |
| 454 | else if (WIFSIGNALED(Status)) |
| 455 | throw InferiorProcessDead(WTERMSIG(Status)); |
| 456 | throw InferiorProcessDead(-1); |
| 457 | } |
| 458 | |
| 459 | // Otherwise, the child exists and has not yet been killed. |
| 460 | if (kill(ChildPID, SIGKILL) < 0) |
| 461 | throw "Error killing child process!"; |
| 462 | |
| 463 | do { |
| 464 | PID = waitpid(ChildPID, 0, 0); |
| 465 | } while (PID < 0 && errno == EINTR); |
| 466 | if (PID <= 0) throw "Error waiting for child to exit!"; |
| 467 | |
| 468 | assert(PID == ChildPID && "Didn't reap child?"); |
| 469 | } |
| 470 | |
| 471 | |
| 472 | /// waitForStop - This method waits for the child process to reach a stop |
| 473 | /// point. When it does, it fills in the CurLocation member and returns. |
| 474 | void IP::waitForStop() { |
| 475 | char Dummy; |
| 476 | readFromChild(&Dummy, sizeof(char)); |
| 477 | } |
| 478 | |
| 479 | |
| 480 | //===----------------------------------------------------------------------===// |
| 481 | // Child Process Code |
| 482 | //===----------------------------------------------------------------------===// |
| 483 | |
| 484 | namespace { |
| 485 | class SourceSubprogram; |
| 486 | |
| 487 | /// SourceRegion - Instances of this class represent the regions that are |
| 488 | /// active in the program. |
| 489 | class SourceRegion { |
| 490 | /// Parent - A pointer to the region that encloses the current one. |
| 491 | SourceRegion *Parent; |
| 492 | |
| 493 | /// CurSubprogram - The subprogram that contains this region. This allows |
| 494 | /// efficient stack traversals. |
| 495 | SourceSubprogram *CurSubprogram; |
| 496 | |
| 497 | /// CurLine, CurCol, CurFile - The last location visited by this region. |
| 498 | /// This is used for getting the source location of callers in stack frames. |
| 499 | unsigned CurLine, CurCol; |
| 500 | void *CurFileDesc; |
| 501 | |
| 502 | //std::vector<void*> ActiveObjects; |
| 503 | public: |
| 504 | SourceRegion(SourceRegion *p, SourceSubprogram *Subprogram = 0) |
| 505 | : Parent(p), CurSubprogram(Subprogram ? Subprogram : p->getSubprogram()) { |
| 506 | CurLine = 0; CurCol = 0; |
| 507 | CurFileDesc = 0; |
| 508 | } |
| 509 | |
| 510 | virtual ~SourceRegion() {} |
| 511 | |
| 512 | SourceRegion *getParent() const { return Parent; } |
| 513 | SourceSubprogram *getSubprogram() const { return CurSubprogram; } |
| 514 | |
| 515 | void updateLocation(unsigned Line, unsigned Col, void *File) { |
| 516 | CurLine = Line; |
| 517 | CurCol = Col; |
| 518 | CurFileDesc = File; |
| 519 | } |
| 520 | |
| 521 | /// Return a LocationToken for the place that this stack frame stopped or |
| 522 | /// called a sub-function. |
| 523 | LocationToken getLocation(ExecutionEngine *EE) { |
| 524 | LocationToken LT; |
| 525 | LT.Line = CurLine; |
| 526 | LT.Col = CurCol; |
| 527 | const GlobalValue *GV = EE->getGlobalValueAtAddress(CurFileDesc); |
| 528 | LT.File = dyn_cast_or_null<GlobalVariable>(GV); |
| 529 | return LT; |
| 530 | } |
| 531 | }; |
| 532 | |
| 533 | /// SourceSubprogram - This is a stack-frame that represents a source program. |
| 534 | /// |
| 535 | class SourceSubprogram : public SourceRegion { |
| 536 | /// Desc - A pointer to the descriptor for the subprogram that this frame |
| 537 | /// represents. |
| 538 | void *Desc; |
| 539 | public: |
| 540 | SourceSubprogram(SourceRegion *P, void *desc) |
| 541 | : SourceRegion(P, this), Desc(desc) {} |
| 542 | void *getDescriptor() const { return Desc; } |
| 543 | }; |
| 544 | |
| 545 | |
| 546 | /// Child class - This class contains all of the information and methods used |
| 547 | /// by the child side of the debugger. The single instance of this object is |
| 548 | /// pointed to by the "TheChild" global variable. |
| 549 | class Child { |
| 550 | /// M - The module for the program currently being debugged. |
| 551 | /// |
| 552 | Module *M; |
| 553 | |
| 554 | /// EE - The execution engine that we are using to run the program. |
| 555 | /// |
| 556 | ExecutionEngine *EE; |
| 557 | |
| 558 | /// ReadFD, WriteFD - The file descriptor handles for this side of the |
| 559 | /// debugger pipe. |
| 560 | FDHandle ReadFD, WriteFD; |
| 561 | |
| 562 | /// RegionStack - A linked list of all of the regions dynamically active. |
| 563 | /// |
| 564 | SourceRegion *RegionStack; |
| 565 | |
| 566 | /// StopAtNextOpportunity - If this flag is set, the child process will stop |
| 567 | /// and report to the debugger at the next possible chance it gets. |
| 568 | volatile bool StopAtNextOpportunity; |
| 569 | |
| 570 | /// StopWhenSubprogramReturns - If this is non-null, the debugger requests |
| 571 | /// that the program stops when the specified function frame is destroyed. |
| 572 | SourceSubprogram *StopWhenSubprogramReturns; |
| 573 | |
| 574 | /// Breakpoints - This contains a list of active breakpoints and their IDs. |
| 575 | /// |
| 576 | std::vector<std::pair<unsigned, LocationToken> > Breakpoints; |
| 577 | |
| 578 | /// CurBreakpoint - The last assigned breakpoint. |
| 579 | /// |
| 580 | unsigned CurBreakpoint; |
| 581 | |
| 582 | public: |
| 583 | Child(Module *m, ExecutionEngine *ee, FDHandle &Read, FDHandle &Write) |
| 584 | : M(m), EE(ee), ReadFD(Read), WriteFD(Write), |
| 585 | RegionStack(0), CurBreakpoint(0) { |
| 586 | StopAtNextOpportunity = true; |
| 587 | StopWhenSubprogramReturns = 0; |
| 588 | } |
| 589 | |
| 590 | /// writeToParent - Send the specified buffer of data to the debugger |
| 591 | /// process. |
Brian Gaeke | c2376a0 | 2004-01-05 17:22:52 +0000 | [diff] [blame] | 592 | /// |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 593 | void writeToParent(const void *Buffer, unsigned Size); |
| 594 | |
| 595 | /// readFromParent - Read the specified number of bytes from the parent. |
| 596 | /// |
| 597 | void readFromParent(void *Buffer, unsigned Size); |
| 598 | |
| 599 | /// childStopped - This method is called whenever the child has stopped |
| 600 | /// execution due to a breakpoint, step command, interruption, or whatever. |
| 601 | /// This stops the process, responds to any requests from the debugger, and |
| 602 | /// when commanded to, can continue execution by returning. |
| 603 | /// |
| 604 | void childStopped(); |
| 605 | |
| 606 | /// startSubprogram - This method creates a new region for the subroutine |
| 607 | /// with the specified descriptor. |
Brian Gaeke | c2376a0 | 2004-01-05 17:22:52 +0000 | [diff] [blame] | 608 | /// |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 609 | void startSubprogram(void *FuncDesc); |
| 610 | |
| 611 | /// startRegion - This method initiates the creation of an anonymous region. |
| 612 | /// |
| 613 | void startRegion(); |
| 614 | |
| 615 | /// endRegion - This method terminates the last active region. |
| 616 | /// |
| 617 | void endRegion(); |
| 618 | |
| 619 | /// reachedLine - This method is automatically called by the program every |
| 620 | /// time it executes an llvm.dbg.stoppoint intrinsic. If the debugger wants |
| 621 | /// us to stop here, we do so, otherwise we continue execution. |
Brian Gaeke | c2376a0 | 2004-01-05 17:22:52 +0000 | [diff] [blame] | 622 | /// |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 623 | void reachedLine(unsigned Line, unsigned Col, void *SourceDesc); |
| 624 | }; |
| 625 | |
| 626 | /// TheChild - The single instance of the Child class, which only gets created |
| 627 | /// in the child process. |
| 628 | Child *TheChild = 0; |
| 629 | } // end anonymous namespace |
| 630 | |
| 631 | |
| 632 | // writeToParent - Send the specified buffer of data to the debugger process. |
| 633 | void Child::writeToParent(const void *Buffer, unsigned Size) { |
| 634 | while (Size) { |
| 635 | ssize_t Amount = write(WriteFD, Buffer, Size); |
| 636 | if (Amount < 0 && errno == EINTR) continue; |
| 637 | if (Amount <= 0) { |
| 638 | write(2, "ERROR: Connection to debugger lost!\n", 36); |
| 639 | abort(); |
| 640 | } else { |
| 641 | // We wrote a chunk. |
| 642 | Buffer = (const char*)Buffer + Amount; |
| 643 | Size -= Amount; |
| 644 | } |
| 645 | } |
| 646 | } |
| 647 | |
| 648 | // readFromParent - Read the specified number of bytes from the parent. |
| 649 | void Child::readFromParent(void *Buffer, unsigned Size) { |
| 650 | while (Size) { |
| 651 | ssize_t Amount = read(ReadFD, Buffer, Size); |
| 652 | if (Amount < 0 && errno == EINTR) continue; |
| 653 | if (Amount <= 0) { |
| 654 | write(2, "ERROR: Connection to debugger lost!\n", 36); |
| 655 | abort(); |
| 656 | } else { |
| 657 | // We read a chunk. |
| 658 | Buffer = (char*)Buffer + Amount; |
| 659 | Size -= Amount; |
| 660 | } |
| 661 | } |
| 662 | } |
| 663 | |
| 664 | /// childStopped - This method is called whenever the child has stopped |
| 665 | /// execution due to a breakpoint, step command, interruption, or whatever. |
| 666 | /// This stops the process, responds to any requests from the debugger, and when |
| 667 | /// commanded to, can continue execution by returning. |
| 668 | /// |
| 669 | void Child::childStopped() { |
| 670 | // Since we stopped, notify the parent that we did so. |
| 671 | char Token = 0; |
| 672 | writeToParent(&Token, sizeof(char)); |
| 673 | |
| 674 | StopAtNextOpportunity = false; |
| 675 | StopWhenSubprogramReturns = 0; |
| 676 | |
| 677 | // Now that the debugger knows that we stopped, read commands from it and |
| 678 | // respond to them appropriately. |
| 679 | CommandID Command; |
| 680 | while (1) { |
| 681 | SourceRegion *Frame; |
| 682 | const void *Result; |
| 683 | readFromParent(&Command, sizeof(CommandID)); |
| 684 | |
| 685 | switch (Command) { |
| 686 | case StepProgram: |
| 687 | // To step the program, just return. |
| 688 | StopAtNextOpportunity = true; |
| 689 | return; |
| 690 | |
| 691 | case FinishProgram: // Run until exit from the specified function... |
| 692 | readFromParent(&Frame, sizeof(Frame)); |
| 693 | // The user wants us to stop when the specified FUNCTION exits, not when |
| 694 | // the specified REGION exits. |
| 695 | StopWhenSubprogramReturns = Frame->getSubprogram(); |
| 696 | return; |
| 697 | |
| 698 | case ContProgram: |
| 699 | // To continue, just return back to execution. |
| 700 | return; |
| 701 | |
| 702 | case GetSubprogramDescriptor: |
| 703 | readFromParent(&Frame, sizeof(Frame)); |
| 704 | Result = |
| 705 | EE->getGlobalValueAtAddress(Frame->getSubprogram()->getDescriptor()); |
| 706 | writeToParent(&Result, sizeof(Result)); |
| 707 | break; |
| 708 | |
| 709 | case GetParentFrame: |
| 710 | readFromParent(&Frame, sizeof(Frame)); |
| 711 | Result = Frame ? Frame->getSubprogram()->getParent() : RegionStack; |
| 712 | writeToParent(&Result, sizeof(Result)); |
| 713 | break; |
| 714 | |
| 715 | case GetFrameLocation: { |
| 716 | readFromParent(&Frame, sizeof(Frame)); |
| 717 | LocationToken LT = Frame->getLocation(EE); |
| 718 | writeToParent(<, sizeof(LT)); |
| 719 | break; |
| 720 | } |
| 721 | case AddBreakpoint: { |
| 722 | LocationToken Loc; |
| 723 | readFromParent(&Loc, sizeof(Loc)); |
| 724 | // Convert the GlobalVariable pointer to the address it was emitted to. |
| 725 | Loc.File = (GlobalVariable*)EE->getPointerToGlobal(Loc.File); |
| 726 | unsigned ID = CurBreakpoint++; |
| 727 | Breakpoints.push_back(std::make_pair(ID, Loc)); |
| 728 | writeToParent(&ID, sizeof(ID)); |
| 729 | break; |
| 730 | } |
| 731 | case RemoveBreakpoint: { |
| 732 | unsigned ID = 0; |
| 733 | readFromParent(&ID, sizeof(ID)); |
| 734 | for (unsigned i = 0, e = Breakpoints.size(); i != e; ++i) |
| 735 | if (Breakpoints[i].first == ID) { |
| 736 | Breakpoints.erase(Breakpoints.begin()+i); |
| 737 | break; |
| 738 | } |
| 739 | break; |
| 740 | } |
| 741 | default: |
| 742 | assert(0 && "Unknown command!"); |
| 743 | } |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | |
| 748 | |
| 749 | /// startSubprogram - This method creates a new region for the subroutine |
| 750 | /// with the specified descriptor. |
| 751 | void Child::startSubprogram(void *SPDesc) { |
| 752 | RegionStack = new SourceSubprogram(RegionStack, SPDesc); |
| 753 | } |
| 754 | |
| 755 | /// startRegion - This method initiates the creation of an anonymous region. |
| 756 | /// |
| 757 | void Child::startRegion() { |
| 758 | RegionStack = new SourceRegion(RegionStack); |
| 759 | } |
| 760 | |
| 761 | /// endRegion - This method terminates the last active region. |
| 762 | /// |
| 763 | void Child::endRegion() { |
| 764 | SourceRegion *R = RegionStack->getParent(); |
| 765 | |
| 766 | // If the debugger wants us to stop when this frame is destroyed, do so. |
| 767 | if (RegionStack == StopWhenSubprogramReturns) { |
| 768 | StopAtNextOpportunity = true; |
| 769 | StopWhenSubprogramReturns = 0; |
| 770 | } |
| 771 | |
| 772 | delete RegionStack; |
| 773 | RegionStack = R; |
| 774 | } |
| 775 | |
| 776 | |
| 777 | |
| 778 | |
| 779 | /// reachedLine - This method is automatically called by the program every time |
| 780 | /// it executes an llvm.dbg.stoppoint intrinsic. If the debugger wants us to |
| 781 | /// stop here, we do so, otherwise we continue execution. Note that the Data |
| 782 | /// pointer coming in is a pointer to the LLVM global variable that represents |
| 783 | /// the source file we are in. We do not use the contents of the global |
| 784 | /// directly in the child, but we do use its address. |
| 785 | /// |
| 786 | void Child::reachedLine(unsigned Line, unsigned Col, void *SourceDesc) { |
| 787 | if (RegionStack) |
| 788 | RegionStack->updateLocation(Line, Col, SourceDesc); |
| 789 | |
| 790 | // If we hit a breakpoint, stop the program. |
| 791 | for (unsigned i = 0, e = Breakpoints.size(); i != e; ++i) |
| 792 | if (Line == Breakpoints[i].second.Line && |
| 793 | SourceDesc == (void*)Breakpoints[i].second.File && |
| 794 | Col == Breakpoints[i].second.Col) { |
| 795 | childStopped(); |
| 796 | return; |
| 797 | } |
| 798 | |
| 799 | // If we are single stepping the program, make sure to stop it. |
| 800 | if (StopAtNextOpportunity) |
| 801 | childStopped(); |
| 802 | } |
| 803 | |
| 804 | |
| 805 | |
| 806 | |
| 807 | //===----------------------------------------------------------------------===// |
| 808 | // Child class wrapper functions |
| 809 | // |
| 810 | // These functions are invoked directly by the program as it executes, in place |
| 811 | // of the debugging intrinsic functions that it contains. |
| 812 | // |
| 813 | |
| 814 | |
| 815 | /// llvm_debugger_stop - Every time the program reaches a new source line, it |
| 816 | /// will call back to this function. If the debugger has a breakpoint or |
| 817 | /// otherwise wants us to stop on this line, we do so, and notify the debugger |
| 818 | /// over the pipe. |
| 819 | /// |
| 820 | extern "C" |
| 821 | void *llvm_debugger_stop(void *Dummy, unsigned Line, unsigned Col, |
| 822 | void *SourceDescriptor) { |
| 823 | TheChild->reachedLine(Line, Col, SourceDescriptor); |
| 824 | return Dummy; |
| 825 | } |
| 826 | |
| 827 | |
| 828 | /// llvm_dbg_region_start - This function is invoked every time an anonymous |
| 829 | /// region of the source program is entered. |
| 830 | /// |
| 831 | extern "C" |
| 832 | void *llvm_dbg_region_start(void *Dummy) { |
| 833 | TheChild->startRegion(); |
| 834 | return Dummy; |
| 835 | } |
| 836 | |
| 837 | /// llvm_dbg_subprogram - This function is invoked every time a source-language |
| 838 | /// subprogram has been entered. |
| 839 | /// |
| 840 | extern "C" |
| 841 | void *llvm_dbg_subprogram(void *FuncDesc) { |
| 842 | TheChild->startSubprogram(FuncDesc); |
| 843 | return 0; |
| 844 | } |
| 845 | |
| 846 | /// llvm_dbg_region_end - This function is invoked every time a source-language |
| 847 | /// region (started with llvm.dbg.region.start or llvm.dbg.func.start) is |
| 848 | /// terminated. |
| 849 | /// |
| 850 | extern "C" |
| 851 | void llvm_dbg_region_end(void *Dummy) { |
| 852 | TheChild->endRegion(); |
| 853 | } |
| 854 | |
| 855 | |
| 856 | |
| 857 | |
| 858 | namespace { |
| 859 | /// DebuggerIntrinsicLowering - This class implements a simple intrinsic |
| 860 | /// lowering class that revectors debugging intrinsics to call actual |
| 861 | /// functions (defined above), instead of being turned into noops. |
| 862 | struct DebuggerIntrinsicLowering : public DefaultIntrinsicLowering { |
| 863 | virtual void LowerIntrinsicCall(CallInst *CI) { |
| 864 | Module *M = CI->getParent()->getParent()->getParent(); |
| 865 | switch (CI->getCalledFunction()->getIntrinsicID()) { |
| 866 | case Intrinsic::dbg_stoppoint: |
| 867 | // Turn call into a call to llvm_debugger_stop |
| 868 | CI->setOperand(0, M->getOrInsertFunction("llvm_debugger_stop", |
| 869 | CI->getCalledFunction()->getFunctionType())); |
| 870 | break; |
| 871 | case Intrinsic::dbg_region_start: |
| 872 | // Turn call into a call to llvm_dbg_region_start |
| 873 | CI->setOperand(0, M->getOrInsertFunction("llvm_dbg_region_start", |
| 874 | CI->getCalledFunction()->getFunctionType())); |
| 875 | break; |
| 876 | |
| 877 | case Intrinsic::dbg_region_end: |
Brian Gaeke | c2376a0 | 2004-01-05 17:22:52 +0000 | [diff] [blame] | 878 | // Turn call into a call to llvm_dbg_region_end |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 879 | CI->setOperand(0, M->getOrInsertFunction("llvm_dbg_region_end", |
| 880 | CI->getCalledFunction()->getFunctionType())); |
| 881 | break; |
| 882 | case Intrinsic::dbg_func_start: |
Brian Gaeke | c2376a0 | 2004-01-05 17:22:52 +0000 | [diff] [blame] | 883 | // Turn call into a call to llvm_dbg_subprogram |
Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 884 | CI->setOperand(0, M->getOrInsertFunction("llvm_dbg_subprogram", |
| 885 | CI->getCalledFunction()->getFunctionType())); |
| 886 | break; |
| 887 | default: |
| 888 | DefaultIntrinsicLowering::LowerIntrinsicCall(CI); |
| 889 | break; |
| 890 | } |
| 891 | } |
| 892 | }; |
| 893 | } // end anonymous namespace |
| 894 | |
| 895 | |
| 896 | static void runChild(Module *M, const std::vector<std::string> &Arguments, |
| 897 | const char * const *envp, |
| 898 | FDHandle ReadFD, FDHandle WriteFD) { |
| 899 | |
| 900 | // Create an execution engine that uses our custom intrinsic lowering object |
| 901 | // to revector debugging intrinsic functions into actual functions defined |
| 902 | // above. |
| 903 | ExecutionEngine *EE = |
| 904 | ExecutionEngine::create(new ExistingModuleProvider(M), false, |
| 905 | new DebuggerIntrinsicLowering()); |
| 906 | assert(EE && "Couldn't create an ExecutionEngine, not even an interpreter?"); |
| 907 | |
| 908 | // Call the main function from M as if its signature were: |
| 909 | // int main (int argc, char **argv, const char **envp) |
| 910 | // using the contents of Args to determine argc & argv, and the contents of |
| 911 | // EnvVars to determine envp. |
| 912 | // |
| 913 | Function *Fn = M->getMainFunction(); |
| 914 | if (!Fn) exit(1); |
| 915 | |
| 916 | // Create the child class instance which will be used by the debugger |
| 917 | // callbacks to keep track of the current state of the process. |
| 918 | assert(TheChild == 0 && "A child process has already been created??"); |
| 919 | TheChild = new Child(M, EE, ReadFD, WriteFD); |
| 920 | |
| 921 | // Run main... |
| 922 | int Result = EE->runFunctionAsMain(Fn, Arguments, envp); |
| 923 | |
| 924 | // If the program didn't explicitly call exit, call exit now, for the program. |
| 925 | // This ensures that any atexit handlers get called correctly. |
| 926 | Function *Exit = M->getOrInsertFunction("exit", Type::VoidTy, Type::IntTy, 0); |
| 927 | |
| 928 | std::vector<GenericValue> Args; |
| 929 | GenericValue ResultGV; |
| 930 | ResultGV.IntVal = Result; |
| 931 | Args.push_back(ResultGV); |
| 932 | EE->runFunction(Exit, Args); |
| 933 | abort(); |
| 934 | } |