20 #include "pedigree/kernel/debugger/commands/TraceCommand.h" 21 #include "pedigree/kernel/debugger/DebuggerIO.h" 22 #include "pedigree/kernel/linker/KernelElf.h" 23 #include "pedigree/kernel/processor/Disassembler.h" 24 #include "pedigree/kernel/processor/Processor.h" 25 #include "pedigree/kernel/processor/state.h" 26 #include "pedigree/kernel/utilities/demangle.h" 41 void TraceCommand::setInterface(
int nInterface)
43 m_nInterface = nInterface;
52 pScreen->disableCli();
56 int nCols = pScreen->
getWidth() - 25;
58 int nLines = ((pScreen->getHeight() - 2) * 3) / 4;
61 disassembly.move(0, 1);
62 disassembly.resize(nCols, nLines);
63 disassembly.setScrollKeys(
'o',
'p');
66 registers.move(nCols + 1, 1);
67 registers.resize(24, nLines);
68 registers.setScrollKeys(
'j',
'k');
71 stacktrace.move(0, nLines + 2);
72 stacktrace.resize(pScreen->
getWidth(), pScreen->getHeight() - nLines - 3);
73 stacktrace.setScrollKeys(
'n',
'm');
75 size_t nInstruction = 0;
78 uintptr_t nIp = state.getInstructionPointer();
79 uintptr_t nSymStart = 0;
90 while (nInstruction < disassembly.getLineCount())
96 if (nLocation == state.getInstructionPointer())
100 disassembly.centreOn(nInstruction);
102 pScreen->disableRefreshes();
103 drawBackground(nCols, nLines, pScreen);
104 registers.refresh(pScreen);
105 disassembly.refresh(pScreen);
106 stacktrace.refresh(pScreen);
110 bool bContinue =
true;
114 while ((c = pScreen->
getChar()) == 0)
126 disassembly.scroll(-1);
127 disassembly.refresh(pScreen);
131 disassembly.scroll(1);
132 disassembly.refresh(pScreen);
136 registers.scroll(-1);
137 registers.refresh(pScreen);
142 registers.refresh(pScreen);
146 stacktrace.scroll(-1);
147 stacktrace.refresh(pScreen);
151 stacktrace.scroll(1);
152 stacktrace.refresh(pScreen);
161 void TraceCommand::drawBackground(
162 size_t nCols,
size_t nLines,
DebuggerIO *pScreen)
169 ' ', 0, 0, pScreen->
getWidth() - 1, DebuggerIO::White,
172 ' ', pScreen->getHeight() - 1, 0, pScreen->
getWidth() - 1,
173 DebuggerIO::White, DebuggerIO::Green);
176 "Pedigree debugger - Execution Tracer", 0, 0, DebuggerIO::White,
180 "s: Step. c: Continue. q: Quit. ?: Current instruction. ?: Breakpoint.",
181 pScreen->getHeight() - 1, 0, DebuggerIO::White, DebuggerIO::Green);
183 "s", pScreen->getHeight() - 1, 0, DebuggerIO::Yellow,
186 "c", pScreen->getHeight() - 1, 9, DebuggerIO::Yellow,
189 "q", pScreen->getHeight() - 1, 22, DebuggerIO::Yellow,
192 " ", pScreen->getHeight() - 1, 31, DebuggerIO::Yellow,
195 " ", pScreen->getHeight() - 1, 55, DebuggerIO::Yellow, DebuggerIO::Red);
198 '-', nLines + 1, 0, pScreen->
getWidth(), DebuggerIO::DarkGrey,
200 pScreen->drawVerticalLine(
201 '|', nCols, 1, nLines, DebuggerIO::DarkGrey, DebuggerIO::Black);
204 TraceCommand::Disassembly::Disassembly(InterruptState &state)
205 : m_nInstructions(0), m_nFirstInstruction(0), m_nIp(0),
206 m_LastLine(0xFFFFFFFF), m_LastInstructionLocation(0)
209 m_nIp = state.getInstructionPointer();
210 uintptr_t nSymStart = 0;
219 m_nFirstInstruction = nSymStart;
220 uintptr_t nLocation = 0;
229 if (nSym == nLocation && nSym != nSymStart)
235 const char *TraceCommand::Disassembly::getLine1(
242 colour = DebuggerIO::Yellow;
245 m_nFirstInstruction, &nSym);
253 size_t nInstruction = 0;
260 uintptr_t nLocation = 0;
263 if (index > 0 && m_LastLine == index - 1)
265 disassembler.
setLocation(m_LastInstructionLocation);
277 while (nInstruction <= index)
286 m_LastInstructionLocation = nLocation;
290 if (nLocation == m_nIp)
291 bgColour = DebuggerIO::Blue;
294 colour = DebuggerIO::DarkGrey;
298 sym.append(nLocation, 16,
sizeof(uintptr_t) * 2,
'0');
303 const char *TraceCommand::Disassembly::getLine2(
315 size_t nInstruction = 0;
322 uintptr_t nLocation = 0;
324 if (index == m_LastLine)
326 disassembler.
setLocation(m_LastInstructionLocation);
327 nLocation = m_LastInstructionLocation;
333 while (nInstruction <= index)
344 if (nLocation == m_nIp)
345 bgColour = DebuggerIO::Blue;
348 colour = DebuggerIO::White;
351 colOffset =
sizeof(uintptr_t) * 2 + 1;
356 uint32_t nLen = sym.length() + colOffset;
357 while (nLen++ < width())
362 size_t TraceCommand::Disassembly::getLineCount()
364 return m_nInstructions + 1;
367 TraceCommand::Registers::Registers(InterruptState &state) : m_State(state)
371 const char *TraceCommand::Registers::getLine1(
375 colour = DebuggerIO::Yellow;
380 if (m_State.kernelMode())
388 int nRegister = index - 1;
390 str = m_State.getRegisterName(nRegister);
395 const char *TraceCommand::Registers::getLine2(
407 int nRegister = index - 1;
409 uintptr_t nValue = m_State.getRegister(nRegister);
411 str.append(nValue, 16,
sizeof(uintptr_t) * 2,
'0');
412 colOffset = width() - 2 *
sizeof(uintptr_t) - 2;
417 size_t TraceCommand::Registers::getLineCount()
419 return m_State.getRegisterCount() + 1;
422 TraceCommand::Stacktrace::Stacktrace(InterruptState &state) : m_Bt()
424 m_Bt.performBacktrace(state);
427 const char *TraceCommand::Stacktrace::getLine1(
432 m_Bt.prettyPrint(str, 1, index);
434 str = str.left(str.length() - 1);
438 const char *TraceCommand::Stacktrace::getLine2(
445 size_t TraceCommand::Stacktrace::getLineCount()
447 return m_Bt.numStackFrames();
virtual size_t getWidth()=0
virtual void enableCli()=0
void autocomplete(const HugeStaticString &input, HugeStaticString &output)
static KernelElf & instance()
virtual void enableRefreshes()=0
static void setSingleStep(bool bEnable, InterruptState &state)
void setMode(size_t nMode)
uintptr_t globalLookupSymbol(const char *pName)
virtual void drawString(const char *str, size_t row, size_t col, Colour foreColour, Colour backColour)=0
bool execute(const HugeStaticString &input, HugeStaticString &output, InterruptState &state, DebuggerIO *screen)
void setLocation(uintptr_t nLocation)
void disassemble(LargeStaticString &text)
virtual void drawHorizontalLine(char c, size_t row, size_t colStart, size_t colEnd, Colour foreColour, Colour backColour)=0