blob: fd11f23b37ba57f8c1c5a2c65179db82d20eb3fb [file] [log] [blame]
Chris Lattner2eacf262004-01-05 05:25:10 +00001//===-- Debugger.cpp - LLVM debugger library implementation ---------------===//
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 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"
19#include "Support/StringExtras.h"
20using namespace llvm;
21
22/// Debugger constructor - Initialize the debugger to its initial, empty, state.
23///
24Debugger::Debugger() : Environment(0), Program(0), Process(0) {
25}
26
27Debugger::~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 }
35
36 unloadProgram();
37}
38
39/// getProgramPath - Get the path of the currently loaded program, or an
40/// empty string if none is loaded.
41std::string Debugger::getProgramPath() const {
42 return Program ? Program->getModuleIdentifier() : "";
43}
44
45static Module *
46getMaterializedModuleProvider(const std::string &Filename) {
47 try {
48 std::auto_ptr<ModuleProvider> Result(getBytecodeModuleProvider(Filename));
49 if (!Result.get()) return 0;
50
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.
62void 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.
88void 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.
100void 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.
118void Debugger::killProgram() {
119 // The destructor takes care of the dirty work.
120 delete Process;
121 Process = 0;
122}
123
124/// stepProgram - Implement the 'step' command, continuing execution until
125/// the next possible stop point.
126void Debugger::stepProgram() {
127 assert(isProgramRunning() && "Cannot step if the program isn't running!");
128 try {
129 Process->stepProgram();
130 } catch (InferiorProcessDead &IPD) {
131 delete Process;
132 Process = 0;
133 throw NonErrorException("The program stopped with exit code " +
134 itostr(IPD.getExitCode()));
135 }
136}
137
138/// nextProgram - Implement the 'next' command, continuing execution until
139/// the next possible stop point that is in the current function.
140void Debugger::nextProgram() {
141 assert(isProgramRunning() && "Cannot next if the program isn't running!");
142 try {
143 // This should step the process. If the process enters a function, then it
144 // should 'finish' it. However, figuring this out is tricky. In
145 // particular, the program can do any of:
146 // 0. Not change current frame.
147 // 1. Entering or exiting a region within the current function
148 // (which changes the frame ID, but which we shouldn't 'finish')
149 // 2. Exiting the current function (which changes the frame ID)
150 // 3. Entering a function (which should be 'finish'ed)
151 // For this reason, we have to be very careful about when we decide to do
152 // the 'finish'.
153
154 // Get the current frame, but don't trust it. It could change...
155 void *CurrentFrame = Process->getPreviousFrame(0);
156
157 // Don't trust the current frame: get the caller frame.
158 void *ParentFrame = Process->getPreviousFrame(CurrentFrame);
159
160 // Ok, we have some information, run the program one step.
161 Process->stepProgram();
162
163 // Where is the new frame? The most common case, by far is that it has not
164 // been modified (Case #0), in which case we don't need to do anything more.
165 void *NewFrame = Process->getPreviousFrame(0);
166 if (NewFrame != CurrentFrame) {
167 // Ok, the frame changed. If we are case #1, then the parent frame will
168 // be identical.
169 void *NewParentFrame = Process->getPreviousFrame(NewFrame);
170 if (ParentFrame != NewParentFrame) {
171 // Ok, now we know we aren't case #0 or #1. Check to see if we entered
172 // a new function. If so, the parent frame will be "CurrentFrame".
173 if (CurrentFrame == NewParentFrame)
174 Process->finishProgram(NewFrame);
175 }
176 }
177
178 } catch (InferiorProcessDead &IPD) {
179 delete Process;
180 Process = 0;
181 throw NonErrorException("The program stopped with exit code " +
182 itostr(IPD.getExitCode()));
183 }
184}
185
186/// finishProgram - Implement the 'finish' command, continuing execution
187/// until the specified frame ID returns.
188void Debugger::finishProgram(void *Frame) {
189 assert(isProgramRunning() && "Cannot cont if the program isn't running!");
190 try {
191 Process->finishProgram(Frame);
192 } catch (InferiorProcessDead &IPD) {
193 delete Process;
194 Process = 0;
195 throw NonErrorException("The program stopped with exit code " +
196 itostr(IPD.getExitCode()));
197 }
198}
199
200/// contProgram - Implement the 'cont' command, continuing execution until
201/// the next breakpoint is encountered.
202void Debugger::contProgram() {
203 assert(isProgramRunning() && "Cannot cont if the program isn't running!");
204 try {
205 Process->contProgram();
206 } catch (InferiorProcessDead &IPD) {
207 delete Process;
208 Process = 0;
209 throw NonErrorException("The program stopped with exit code " +
210 itostr(IPD.getExitCode()));
211 }
212}