| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 1 | //===-- Debugger.cpp - LLVM debugger library implementation ---------------===// | 
| Misha Brukman | edf128a | 2005-04-21 22:36:52 +0000 | [diff] [blame^] | 2 | // | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 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. | 
| Misha Brukman | edf128a | 2005-04-21 22:36:52 +0000 | [diff] [blame^] | 7 | // | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// | 
| Misha Brukman | edf128a | 2005-04-21 22:36:52 +0000 | [diff] [blame^] | 9 | // | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 10 | // This file contains the main implementation of the LLVM debugger library. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "llvm/Debugger/Debugger.h" | 
|  | 15 | #include "llvm/Module.h" | 
|  | 16 | #include "llvm/ModuleProvider.h" | 
|  | 17 | #include "llvm/Bytecode/Reader.h" | 
|  | 18 | #include "llvm/Debugger/InferiorProcess.h" | 
| Reid Spencer | 551ccae | 2004-09-01 22:55:40 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/StringExtras.h" | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 20 | using namespace llvm; | 
|  | 21 |  | 
|  | 22 | /// Debugger constructor - Initialize the debugger to its initial, empty, state. | 
|  | 23 | /// | 
|  | 24 | Debugger::Debugger() : Environment(0), Program(0), Process(0) { | 
|  | 25 | } | 
|  | 26 |  | 
|  | 27 | Debugger::~Debugger() { | 
|  | 28 | // Killing the program could throw an exception.  We don't want to progagate | 
|  | 29 | // the exception out of our destructor though. | 
|  | 30 | try { | 
|  | 31 | killProgram(); | 
|  | 32 | } catch (const char *) { | 
|  | 33 | } catch (const std::string &) { | 
|  | 34 | } | 
| Misha Brukman | edf128a | 2005-04-21 22:36:52 +0000 | [diff] [blame^] | 35 |  | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 36 | unloadProgram(); | 
|  | 37 | } | 
|  | 38 |  | 
|  | 39 | /// getProgramPath - Get the path of the currently loaded program, or an | 
|  | 40 | /// empty string if none is loaded. | 
|  | 41 | std::string Debugger::getProgramPath() const { | 
|  | 42 | return Program ? Program->getModuleIdentifier() : ""; | 
|  | 43 | } | 
|  | 44 |  | 
|  | 45 | static Module * | 
|  | 46 | getMaterializedModuleProvider(const std::string &Filename) { | 
|  | 47 | try { | 
|  | 48 | std::auto_ptr<ModuleProvider> Result(getBytecodeModuleProvider(Filename)); | 
|  | 49 | if (!Result.get()) return 0; | 
| Misha Brukman | edf128a | 2005-04-21 22:36:52 +0000 | [diff] [blame^] | 50 |  | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 51 | Result->materializeModule(); | 
|  | 52 | return Result.release()->releaseModule(); | 
|  | 53 | } catch (...) { | 
|  | 54 | return 0; | 
|  | 55 | } | 
|  | 56 | } | 
|  | 57 |  | 
|  | 58 | /// loadProgram - If a program is currently loaded, unload it.  Then search | 
|  | 59 | /// the PATH for the specified program, loading it when found.  If the | 
|  | 60 | /// specified program cannot be found, an exception is thrown to indicate the | 
|  | 61 | /// error. | 
|  | 62 | void Debugger::loadProgram(const std::string &Filename) { | 
|  | 63 | if ((Program = getMaterializedModuleProvider(Filename)) || | 
|  | 64 | (Program = getMaterializedModuleProvider(Filename+".bc"))) | 
|  | 65 | return;   // Successfully loaded the program. | 
|  | 66 |  | 
|  | 67 | // Search the program path for the file... | 
|  | 68 | if (const char *PathS = getenv("PATH")) { | 
|  | 69 | std::string Path = PathS; | 
|  | 70 |  | 
|  | 71 | std::string Directory = getToken(Path, ":"); | 
|  | 72 | while (!Directory.empty()) { | 
|  | 73 | if ((Program = getMaterializedModuleProvider(Directory +"/"+ Filename)) || | 
|  | 74 | (Program = getMaterializedModuleProvider(Directory +"/"+ Filename | 
|  | 75 | + ".bc"))) | 
|  | 76 | return;   // Successfully loaded the program. | 
|  | 77 |  | 
|  | 78 | Directory = getToken(Path, ":"); | 
|  | 79 | } | 
|  | 80 | } | 
|  | 81 |  | 
|  | 82 | throw "Could not find program '" + Filename + "'!"; | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | /// unloadProgram - If a program is running, kill it, then unload all traces | 
|  | 86 | /// of the current program.  If no program is loaded, this method silently | 
|  | 87 | /// succeeds. | 
|  | 88 | void Debugger::unloadProgram() { | 
|  | 89 | if (!isProgramLoaded()) return; | 
|  | 90 | killProgram(); | 
|  | 91 | delete Program; | 
|  | 92 | Program = 0; | 
|  | 93 | } | 
|  | 94 |  | 
|  | 95 |  | 
|  | 96 | /// createProgram - Create an instance of the currently loaded program, | 
|  | 97 | /// killing off any existing one.  This creates the program and stops it at | 
|  | 98 | /// the first possible moment.  If there is no program loaded or if there is a | 
|  | 99 | /// problem starting the program, this method throws an exception. | 
|  | 100 | void Debugger::createProgram() { | 
|  | 101 | if (!isProgramLoaded()) | 
|  | 102 | throw "Cannot start program: none is loaded."; | 
|  | 103 |  | 
|  | 104 | // Kill any existing program. | 
|  | 105 | killProgram(); | 
|  | 106 |  | 
|  | 107 | // Add argv[0] to the arguments vector.. | 
|  | 108 | std::vector<std::string> Args(ProgramArguments); | 
|  | 109 | Args.insert(Args.begin(), getProgramPath()); | 
|  | 110 |  | 
|  | 111 | // Start the new program... this could throw if the program cannot be started. | 
|  | 112 | Process = InferiorProcess::create(Program, Args, Environment); | 
|  | 113 | } | 
|  | 114 |  | 
|  | 115 | /// killProgram - If the program is currently executing, kill off the | 
|  | 116 | /// process and free up any state related to the currently running program.  If | 
|  | 117 | /// there is no program currently running, this just silently succeeds. | 
|  | 118 | void Debugger::killProgram() { | 
|  | 119 | // The destructor takes care of the dirty work. | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 120 | try { | 
|  | 121 | delete Process; | 
|  | 122 | } catch (...) { | 
|  | 123 | Process = 0; | 
|  | 124 | throw; | 
|  | 125 | } | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 126 | Process = 0; | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | /// stepProgram - Implement the 'step' command, continuing execution until | 
|  | 130 | /// the next possible stop point. | 
|  | 131 | void Debugger::stepProgram() { | 
|  | 132 | assert(isProgramRunning() && "Cannot step if the program isn't running!"); | 
|  | 133 | try { | 
|  | 134 | Process->stepProgram(); | 
|  | 135 | } catch (InferiorProcessDead &IPD) { | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 136 | killProgram(); | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 137 | throw NonErrorException("The program stopped with exit code " + | 
|  | 138 | itostr(IPD.getExitCode())); | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 139 | } catch (...) { | 
|  | 140 | killProgram(); | 
|  | 141 | throw; | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 142 | } | 
|  | 143 | } | 
|  | 144 |  | 
|  | 145 | /// nextProgram - Implement the 'next' command, continuing execution until | 
|  | 146 | /// the next possible stop point that is in the current function. | 
|  | 147 | void Debugger::nextProgram() { | 
|  | 148 | assert(isProgramRunning() && "Cannot next if the program isn't running!"); | 
|  | 149 | try { | 
|  | 150 | // This should step the process.  If the process enters a function, then it | 
|  | 151 | // should 'finish' it.  However, figuring this out is tricky.  In | 
|  | 152 | // particular, the program can do any of: | 
|  | 153 | //  0. Not change current frame. | 
|  | 154 | //  1. Entering or exiting a region within the current function | 
|  | 155 | //     (which changes the frame ID, but which we shouldn't 'finish') | 
|  | 156 | //  2. Exiting the current function (which changes the frame ID) | 
|  | 157 | //  3. Entering a function (which should be 'finish'ed) | 
|  | 158 | // For this reason, we have to be very careful about when we decide to do | 
|  | 159 | // the 'finish'. | 
|  | 160 |  | 
|  | 161 | // Get the current frame, but don't trust it.  It could change... | 
|  | 162 | void *CurrentFrame = Process->getPreviousFrame(0); | 
|  | 163 |  | 
|  | 164 | // Don't trust the current frame: get the caller frame. | 
|  | 165 | void *ParentFrame  = Process->getPreviousFrame(CurrentFrame); | 
| Misha Brukman | edf128a | 2005-04-21 22:36:52 +0000 | [diff] [blame^] | 166 |  | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 167 | // Ok, we have some information, run the program one step. | 
|  | 168 | Process->stepProgram(); | 
|  | 169 |  | 
|  | 170 | // Where is the new frame?  The most common case, by far is that it has not | 
|  | 171 | // been modified (Case #0), in which case we don't need to do anything more. | 
|  | 172 | void *NewFrame = Process->getPreviousFrame(0); | 
|  | 173 | if (NewFrame != CurrentFrame) { | 
|  | 174 | // Ok, the frame changed.  If we are case #1, then the parent frame will | 
|  | 175 | // be identical. | 
|  | 176 | void *NewParentFrame = Process->getPreviousFrame(NewFrame); | 
|  | 177 | if (ParentFrame != NewParentFrame) { | 
|  | 178 | // Ok, now we know we aren't case #0 or #1.  Check to see if we entered | 
|  | 179 | // a new function.  If so, the parent frame will be "CurrentFrame". | 
|  | 180 | if (CurrentFrame == NewParentFrame) | 
|  | 181 | Process->finishProgram(NewFrame); | 
|  | 182 | } | 
|  | 183 | } | 
|  | 184 |  | 
|  | 185 | } catch (InferiorProcessDead &IPD) { | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 186 | killProgram(); | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 187 | throw NonErrorException("The program stopped with exit code " + | 
|  | 188 | itostr(IPD.getExitCode())); | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 189 | } catch (...) { | 
|  | 190 | killProgram(); | 
|  | 191 | throw; | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 192 | } | 
|  | 193 | } | 
|  | 194 |  | 
|  | 195 | /// finishProgram - Implement the 'finish' command, continuing execution | 
|  | 196 | /// until the specified frame ID returns. | 
|  | 197 | void Debugger::finishProgram(void *Frame) { | 
|  | 198 | assert(isProgramRunning() && "Cannot cont if the program isn't running!"); | 
|  | 199 | try { | 
|  | 200 | Process->finishProgram(Frame); | 
|  | 201 | } catch (InferiorProcessDead &IPD) { | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 202 | killProgram(); | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 203 | throw NonErrorException("The program stopped with exit code " + | 
|  | 204 | itostr(IPD.getExitCode())); | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 205 | } catch (...) { | 
|  | 206 | killProgram(); | 
|  | 207 | throw; | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 208 | } | 
|  | 209 | } | 
|  | 210 |  | 
|  | 211 | /// contProgram - Implement the 'cont' command, continuing execution until | 
|  | 212 | /// the next breakpoint is encountered. | 
|  | 213 | void Debugger::contProgram() { | 
|  | 214 | assert(isProgramRunning() && "Cannot cont if the program isn't running!"); | 
|  | 215 | try { | 
|  | 216 | Process->contProgram(); | 
|  | 217 | } catch (InferiorProcessDead &IPD) { | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 218 | killProgram(); | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 219 | throw NonErrorException("The program stopped with exit code " + | 
|  | 220 | itostr(IPD.getExitCode())); | 
| Chris Lattner | de31b76 | 2004-01-14 20:58:17 +0000 | [diff] [blame] | 221 | } catch (...) { | 
|  | 222 | killProgram(); | 
|  | 223 | throw; | 
| Chris Lattner | 2eacf26 | 2004-01-05 05:25:10 +0000 | [diff] [blame] | 224 | } | 
|  | 225 | } |