📄 debuggergdb.cpp
字号:
break;
case CMD_DISASSEMBLE:
{
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, "Disassembling...");
if (m_pDisassembly)
m_pDisassembly->ClearRegisters();
for (int i = 0; i < 16; ++i)
{
long int val = ReadRegisterValue(i);
if (m_pDisassembly)
m_pDisassembly->AddRegisterValue(i, val);
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, "%s: '%s' (%d)", DisassemblyDlg::Registers[i].c_str(), token.c_str(), val);
}
SendCommand(_T("disassemble"));
break;
}
default: break;
}
}
long int DebuggerGDB::ReadRegisterValue(int idx)
{
SendCommand(_T("info registers ") + DisassemblyDlg::Registers[idx]);
wxString line;
do
{
line = GetNextOutputLineClean();
} while (!line.IsEmpty() && line.StartsWith(GDB_PROMPT));
if (line.IsEmpty())
return 0;
// break up the string in its parts
wxStringTokenizer tkz(line, wxT("\t"));
wxString token;
while (tkz.HasMoreTokens())
{
token = tkz.GetNextToken();
}
long int val;
if (token.StartsWith(_T("0x")))
token.ToLong(&val, 16);
else
token.ToLong(&val, 10);
return val;
}
void DebuggerGDB::CmdDisassemble()
{
if (!m_pDisassembly)
m_pDisassembly = new DisassemblyDlg(Manager::Get()->GetAppWindow(), this);
m_pDisassembly->Show();
RunCommand(CMD_DISASSEMBLE);
}
void DebuggerGDB::CmdBacktrace()
{
if (!m_pBacktrace)
m_pBacktrace = new BacktraceDlg(Manager::Get()->GetAppWindow(), this);
m_pBacktrace->Clear();
m_pBacktrace->Show();
RunCommand(CMD_BACKTRACE);
}
void DebuggerGDB::CmdContinue()
{
SetBreakpoints();
if (!m_Tbreak.IsEmpty())
{
SendCommand(m_Tbreak);
m_Tbreak.Clear();
}
RunCommand(CMD_CONTINUE);
}
void DebuggerGDB::CmdNext()
{
RunCommand(CMD_STEP);
}
void DebuggerGDB::CmdStep()
{
RunCommand(CMD_STEPIN);
}
bool DebuggerGDB::Validate(const wxString& line, const char cb)
{
bool bResult = false;
int bep = line.Find(cb)+1;
int scs = line.Find(_T('\''))+1;
int sce = line.Find(_T('\''),true)+1;
int dcs = line.Find(_T('"'))+1;
int dce = line.Find(_T('"'),true)+1;
//No single and double quote
if(!scs && !sce && !dcs && !dce) bResult = true;
//No single/double quote in pair
if(!(sce-scs) && !(dce-dcs)) bResult = true;
//Outside of single quote
if((sce-scs) && ((bep < scs)||(bep >sce))) bResult = true;
//Outside of double quote
if((dce-dcs) && ((bep < dcs)||(bep >dce))) bResult = true;
return bResult;
}
void DebuggerGDB::CmdStepOut()
{
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
if (!ed) return;
ProjectFile* pf = ed->GetProjectFile();
if (!pf) return;
wxString filename = pf->file.GetFullName(), lineBuf, cmd;
cbStyledTextCtrl* stc = ed->GetControl();
int line = m_HaltAtLine;
lineBuf = stc->GetLine(line);
unsigned int nLevel = 1;
while(nLevel){
if ((lineBuf.Find(_T('{'))+1) && Validate(lineBuf, _T('{')) &&
(line > m_HaltAtLine)) nLevel++;
if ((lineBuf.Find(_T('}'))+1) && Validate(lineBuf, _T('}'))) nLevel--;
if (nLevel) lineBuf = stc->GetLine(++line);
}
if (line == stc->GetCurrentLine())
CmdNext();
else {
cmd << _T("tbreak ") << filename << _T(":") << line+1;
m_Tbreak = cmd;
CmdContinue();
}
}
void DebuggerGDB::CmdRunToCursor()
{
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
if (!ed)
return;
ProjectFile* pf = ed->GetProjectFile();
if (!pf)
return;
wxString cmd, filename = pf->file.GetFullName();
cmd << _T("tbreak ") << filename << _T(":") << ed->GetControl()->GetCurrentLine()+1;
m_Tbreak = cmd;
if (m_pProcess)
{
CmdContinue();
}
else
{
Debug();
}
}
void DebuggerGDB::CmdToggleBreakpoint()
{
ClearActiveMarkFromAllEditors();
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
if (!ed)
return;
ed->MarkerToggle(BREAKPOINT_MARKER);
// SetBreakpoints();
}
void DebuggerGDB::CmdStop()
{
if (m_pProcess && m_Pid)
{
if (m_ProgramIsStopped)
{
RunCommand(CMD_STOP);
m_pProcess->CloseOutput();
}
else
{
m_pProcess->CloseOutput();
wxKillError err = m_pProcess->Kill(m_Pid, wxSIGKILL);
if (err == wxKILL_OK){
/*
wxMessageBox(_("Debug session terminated!"),
_("Debug"), wxOK | wxICON_EXCLAMATION);
*/
}
m_ProgramIsStopped = true;
}
}
}
void DebuggerGDB::ParseOutput(const wxString& output)
{
wxString buffer = output;
if (buffer.StartsWith(g_EscapeChars)) // ->->
{
buffer.Remove(0, 2); // remove ->->
if (m_HasDebugLog)
m_pDbgLog->AddLog(buffer); // write it in the full debugger log
// Is the program running?
if (buffer.Matches(_T("starting")))
m_ProgramIsStopped = false;
// Is the program stopped?
else if (buffer.Matches(_T("stopped")))
{
bool already = m_ProgramIsStopped;
m_ProgramIsStopped = true;
if (!already)
{
DoWatches();
// if stopped with a signal, force a backtrace
if (m_StoppedOnSignal)
{
CmdBacktrace();
m_StoppedOnSignal = false; // reset for next time
}
}
}
// Is the program exited?
else if (buffer.StartsWith(_T("exited ")))
{
m_ProgramIsStopped = true;
Manager::Get()->GetMessageManager()->Log(m_PageIndex, buffer);
CmdStop();
}
// error
else if (buffer.Matches(_T("error")))
{
Manager::Get()->GetMessageManager()->Log(m_PageIndex, buffer);
//CmdStop();
}
else if (buffer.StartsWith(_T("error-begin")))
{
wxString error = GetNextOutputLineClean(true);
Manager::Get()->GetMessageManager()->Log(m_PageIndex, error);
if (error.StartsWith(_T("No symbol table is loaded.")))
m_NoDebugInfo = true;
//CmdStop();
}
// signal
else if (buffer.Matches(_T("signal-name")))
{
BringAppToFront();
wxString sig = GetNextOutputLineClean();
Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("Program received signal (%s)"), sig.c_str());
m_StoppedOnSignal = true;
}
else if (buffer.Matches(_T("signal-string")))
{
wxString sig = GetNextOutputLineClean();
Manager::Get()->GetMessageManager()->Log(m_PageIndex, sig);
}
// Stack-frame info
else if (buffer.Matches(_T("frames-invalid")))
m_CurrentFrame.Clear();
else if (buffer.StartsWith(_T("frame-begin ")))
{
m_CurrentFrame.Clear();
sscanf(buffer.mb_str(), "frame-begin %d %x", &m_CurrentFrame.number, &m_CurrentFrame.address);
m_CurrentFrame.valid = true;
}
else if (buffer.Matches(_T("frame-function-name")))
{
m_CurrentFrame.function = GetNextOutputLineClean();
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, "m_FrameFunction=%s", m_FrameFunction.c_str());
}
else if (buffer.Matches(_T("frame-source-file")))
m_CurrentFrame.file = GetNextOutputLineClean();
else if (buffer.Matches(_T("frame-source-line")))
m_CurrentFrame.line = GetNextOutputLineClean();
else if (buffer.Matches(_T("frame-end")) && m_CurrentFrame.valid)
{
if (m_pBacktrace)
m_pBacktrace->AddFrame(m_CurrentFrame);
// Manager::Get()->GetMessageManager()->Log(m_PageIndex,
// _("Frame #%-2d [0x%8.8x]: %s (%s:%s)"),
// m_CurrentFrame.number,
// m_CurrentFrame.address,
// m_CurrentFrame.valid ? m_CurrentFrame.function.c_str() : "??",
// m_CurrentFrame.valid && !m_CurrentFrame.file.IsEmpty() ? m_CurrentFrame.file.c_str() : "??",
// m_CurrentFrame.valid && !m_CurrentFrame.line.IsEmpty() ? m_CurrentFrame.line.c_str() : "??");
}
// source d:/wx2.4/samples/exec/exec.cpp:753:22811:beg:0x403e39
else if (buffer.StartsWith(_T("source ")))
{
Manager::Get()->GetMessageManager()->DebugLog(buffer);
buffer.Remove(0, 7); // remove "source "
if (!reSource.IsValid())
#ifdef __WXMSW__
reSource.Compile(_T("([A-Za-z]:)([ A-Za-z0-9_/\\.~-]*):([0-9]*):[0-9]*:beg:(0x[0-9A-Za-z]*)"));
#else
reSource.Compile(_T("([ A-Za-z0-9_/\\.~-]*):([0-9]*):[0-9]*:beg:(0x[0-9A-Za-z]*)"));
#endif
if ( reSource.Matches(buffer) )
{
#ifdef __WXMSW__
wxString file = reSource.GetMatch(buffer, 1) + reSource.GetMatch(buffer, 2);
wxString lineStr = reSource.GetMatch(buffer, 3);
wxString addr = reSource.GetMatch(buffer, 4);
#else
wxString file = reSource.GetMatch(buffer, 1);
wxString lineStr = reSource.GetMatch(buffer, 2);
wxString addr = reSource.GetMatch(buffer, 3);
#endif
if (m_pDisassembly)
{
long int val;
addr.ToLong(&val, 16);
m_pDisassembly->SetActiveAddress(val);
// update CPU registers
// NOTE: this hangs; another solution must be found...
// for (int i = 0; i < 16; ++i)
// {
// val = ReadRegisterValue(i);
// m_pDisassembly->SetRegisterValue(i, val);
// }
}
long int line;
lineStr.ToLong(&line);
// Manager::Get()->GetMessageManager()->DebugLog("file %s, line %ld", file.c_str(), line);
SyncEditor(file, line);
m_HaltAtLine = line-1;
BringAppToFront();
}
}
}
else
{
if (buffer.StartsWith(_T("Dump of assembler code")))
{
// Manager::Get()->GetMessageManager()->Log(m_PageIndex,
// "Starting disassembly of %s (starting address: 0x%8.8x)",
// m_CurrentFrame.valid ? m_CurrentFrame.function.c_str() : "??",
// m_CurrentFrame.valid ? m_CurrentFrame.address : 0);
if (m_pDisassembly)
m_pDisassembly->Clear(m_CurrentFrame);
//0x00403977 <_ZN7MyFrame11OnLocalTestER14wxCommandEvent+521>: ret
wxRegEx re(_T("(0x[0-9A-Za-z]+)[ \t]+<.*>:[ \t]+(.*)"));
wxString tmp;
do
{
tmp = GetNextOutputLine();
if (tmp.Matches(_T("End of assembler dump.")))
{
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, "Disassembly end");
break;
}
if (re.Matches(tmp) && m_pDisassembly)
{
long int val;
wxString addr = re.GetMatch(tmp, 1);
addr.ToLong(&val, 16);
m_pDisassembly->AddAssemblerLine(val, re.GetMatch(tmp, 2));
}
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, "%s: %s", re.GetMatch(tmp, 1).c_str(), re.GetMatch(tmp, 2).c_str());
}
while (!tmp.IsEmpty());
if (m_pDisassembly)
m_pDisassembly->Show(true);
}
}
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, buffer);
}
void DebuggerGDB::BringAppToFront()
{
wxWindow* app = Manager::Get()->GetAppWindow();
if (app)
app->Raise();
}
void DebuggerGDB::ClearActiveMarkFromAllEditors()
{
EditorManager* edMan = Manager::Get()->GetEditorManager();
if (!edMan)
return;
for (int i = 0; i < edMan->GetEditorsCount(); ++i)
{
cbEditor* ed = edMan->GetBuiltinEditor(i);
if (ed)
ed->MarkLine(ACTIVE_LINE, -1);
}
}
void DebuggerGDB::SyncEditor(const wxString& filename, int line)
{
ClearActiveMarkFromAllEditors();
cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
if (project)
{
wxFileName fname(filename);
ProjectFile* f = project->GetFileByFilename(fname.GetFullPath(), false, true);
if (f)
{
cbEditor* ed = Manager::Get()->GetEditorManager()->Open(f->file.GetFullPath());
if (ed)
{
ed->SetProjectFile(f);
ed->Show(true);
ed->GetControl()->GotoLine(line - 10); // make sure we can see some context...
ed->GetControl()->GotoLine(line - 1);
ed->MarkLine(ACTIVE_LINE, line - 1);
}
}
else
{
// no such file in project; maybe in another open project?
cbEditor* ed = Manager::Get()->GetEditorManager()->Open(fname.GetFullPath());
if (ed)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -