2
* This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3
* http://www.gnu.org/licenses/lgpl-3.0.html
6
* $Id: debuggermanager.cpp 10695 2016-01-23 19:02:44Z mortenmacfly $
7
* $HeadURL: http://svn.code.sf.net/p/codeblocks/code/branches/release-16.xx/src/sdk/debuggermanager.cpp $
10
#include "sdk_precomp.h"
12
#include <wx/artprov.h>
13
#include <wx/bmpbuttn.h>
14
#include <wx/combobox.h>
15
#include <wx/filedlg.h>
18
#include <wx/settings.h>
20
#include <wx/stattext.h>
24
#include "cbexception.h"
26
#include "cbproject.h"
27
#include "compilerfactory.h"
28
#include "configmanager.h"
29
#include "editormanager.h"
30
#include "logmanager.h"
31
#include "projectmanager.h"
36
#include <wx/toolbar.h>
38
#include "debuggermanager.h"
40
#include "annoyingdialog.h"
41
#include "cbdebugger_interfaces.h"
58
void cbWatch::AddChild(cb::shared_ptr<cbWatch> parent, cb::shared_ptr<cbWatch> watch)
60
watch->m_parent = parent;
61
parent->m_children.push_back(watch);
64
void cbWatch::RemoveChild(int index)
66
std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin();
67
std::advance(it, index);
71
inline bool TestIfMarkedForRemoval(cb::shared_ptr<cbWatch> watch)
73
if(watch->IsRemoved())
77
watch->RemoveMarkedChildren();
82
bool cbWatch::RemoveMarkedChildren()
84
size_t start_size = m_children.size();
85
std::vector<cb::shared_ptr<cbWatch> >::iterator new_last;
86
new_last = std::remove_if(m_children.begin(), m_children.end(), &TestIfMarkedForRemoval);
87
m_children.erase(new_last, m_children.end());
89
return start_size != m_children.size();
92
void cbWatch::RemoveChildren()
97
int cbWatch::GetChildCount() const
99
return m_children.size();
102
cb::shared_ptr<cbWatch> cbWatch::GetChild(int index)
104
std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin();
105
std::advance(it, index);
109
cb::shared_ptr<const cbWatch> cbWatch::GetChild(int index) const
111
std::vector<cb::shared_ptr<cbWatch> >::const_iterator it = m_children.begin();
112
std::advance(it, index);
116
cb::shared_ptr<cbWatch> cbWatch::FindChild(const wxString& symbol)
118
for (std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin(); it != m_children.end(); ++it)
125
return cb::shared_ptr<cbWatch>();
128
int cbWatch::FindChildIndex(const wxString& symbol) const
131
for (std::vector<cb::shared_ptr<cbWatch> >::const_iterator it = m_children.begin();
132
it != m_children.end();
143
cb::shared_ptr<const cbWatch> cbWatch::GetParent() const
145
return m_parent.lock();
148
cb::shared_ptr<cbWatch> cbWatch::GetParent()
150
return m_parent.lock();
153
bool cbWatch::IsRemoved() const
158
bool cbWatch::IsChanged() const
163
void cbWatch::MarkAsRemoved(bool flag)
168
void cbWatch::MarkChildsAsRemoved()
170
for(std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin(); it != m_children.end(); ++it)
171
(*it)->MarkAsRemoved(true);
173
void cbWatch::MarkAsChanged(bool flag)
178
void cbWatch::MarkAsChangedRecursive(bool flag)
181
for(std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin(); it != m_children.end(); ++it)
182
(*it)->MarkAsChangedRecursive(flag);
185
bool cbWatch::IsExpanded() const
190
void cbWatch::Expand(bool expand)
195
bool cbWatch::IsAutoUpdateEnabled() const
200
void cbWatch::AutoUpdate(bool enabled)
202
m_autoUpdate = enabled;
205
cb::shared_ptr<cbWatch> DLLIMPORT cbGetRootWatch(cb::shared_ptr<cbWatch> watch)
207
cb::shared_ptr<cbWatch> root = watch;
210
cb::shared_ptr<cbWatch> parent = root->GetParent();
218
cbStackFrame::cbStackFrame() :
223
void cbStackFrame::SetNumber(int number)
228
void cbStackFrame::SetAddress(uint64_t address)
233
void cbStackFrame::SetSymbol(const wxString& symbol)
238
void cbStackFrame::SetFile(const wxString& filename, const wxString &line)
244
void cbStackFrame::MakeValid(bool flag)
249
int cbStackFrame::GetNumber() const
254
uint64_t cbStackFrame::GetAddress() const
259
wxString cbStackFrame::GetAddressAsString() const
262
return cbDebuggerAddressToString(m_address);
264
return wxEmptyString;
267
const wxString& cbStackFrame::GetSymbol() const
272
const wxString& cbStackFrame::GetFilename() const
277
const wxString& cbStackFrame::GetLine() const
282
bool cbStackFrame::IsValid() const
291
cbThread::cbThread(bool active, int number, const wxString& info)
298
bool cbThread::IsActive() const
303
int cbThread::GetNumber() const
308
const wxString& cbThread::GetInfo() const
313
cbDebuggerConfiguration::cbDebuggerConfiguration(const ConfigManagerWrapper &config) :
319
cbDebuggerConfiguration::cbDebuggerConfiguration(const cbDebuggerConfiguration &o) :
320
m_config(o.m_config),
325
void cbDebuggerConfiguration::SetName(const wxString &name)
329
const wxString& cbDebuggerConfiguration::GetName() const
334
const ConfigManagerWrapper& cbDebuggerConfiguration::GetConfig() const
339
void cbDebuggerConfiguration::SetConfig(const ConfigManagerWrapper &config)
344
void cbDebuggerConfiguration::SetMenuId(long id)
349
long cbDebuggerConfiguration::GetMenuId() const
354
bool cbDebuggerCommonConfig::GetFlag(Flags flag)
356
ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
360
return c->ReadBool(wxT("/common/auto_build"), true);
361
case AutoSwitchFrame:
362
return c->ReadBool(wxT("/common/auto_switch_frame"), true);
363
case ShowDebuggersLog:
364
return c->ReadBool(wxT("/common/debug_log"), false);
365
case JumpOnDoubleClick:
366
return c->ReadBool(wxT("/common/jump_on_double_click"), false);
367
case RequireCtrlForTooltips:
368
return c->ReadBool(wxT("/common/require_ctrl_for_tooltips"), false);
369
case ShowTemporaryBreakpoints:
370
return c->ReadBool(wxT("/common/show_temporary_breakpoints"), false);
376
void cbDebuggerCommonConfig::SetFlag(Flags flag, bool value)
378
ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
382
c->Write(wxT("/common/auto_build"), value);
384
case AutoSwitchFrame:
385
c->Write(wxT("/common/auto_switch_frame"), value);
387
case ShowDebuggersLog:
388
c->Write(wxT("/common/debug_log"), value);
390
case JumpOnDoubleClick:
391
c->Write(wxT("/common/jump_on_double_click"), value);
393
case RequireCtrlForTooltips:
394
c->Write(wxT("/common/require_ctrl_for_tooltips"), value);
396
case ShowTemporaryBreakpoints:
397
c->Write(wxT("/common/show_temporary_breakpoints"), value);
403
wxString cbDebuggerCommonConfig::GetValueTooltipFont()
405
wxFont system = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
406
system.SetPointSize(std::max(system.GetPointSize() - 3, 7));
407
wxString defaultFont = system.GetNativeFontInfo()->ToString();
409
ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
410
wxString configFont = c->Read(wxT("/common/tooltip_font"));
412
return configFont.empty() ? defaultFont : configFont;
415
void cbDebuggerCommonConfig::SetValueTooltipFont(const wxString &font)
417
const wxString &oldFont = GetValueTooltipFont();
419
if (font != oldFont && !font.empty())
421
ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
422
c->Write(wxT("/common/tooltip_font"), font);
426
cbDebuggerCommonConfig::Perspective cbDebuggerCommonConfig::GetPerspective()
428
ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
429
int v = c->ReadInt(wxT("/common/perspective"), static_cast<int>(OnePerDebuggerConfig));
430
if (v < OnlyOne || v > OnePerDebuggerConfig)
431
return OnePerDebuggerConfig;
432
return static_cast<Perspective>(v);
435
void cbDebuggerCommonConfig::SetPerspective(int perspective)
437
ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
438
if (perspective < OnlyOne || perspective > OnePerDebuggerConfig)
439
perspective = OnePerDebuggerConfig;
440
c->Write(wxT("/common/perspective"), perspective);
443
wxString cbDetectDebuggerExecutable(const wxString &exeName)
445
wxString exeExt(platform::windows ? wxT(".exe") : wxEmptyString);
446
wxString exePath = cbFindFileInPATH(exeName);
447
wxChar sep = wxFileName::GetPathSeparator();
451
if (!platform::windows)
452
exePath = wxT("/usr/bin/") + exeName + exeExt;
455
const wxString &cbInstallFolder = ConfigManager::GetExecutableFolder();
456
if (wxFileExists(cbInstallFolder + sep + wxT("MINGW") + sep + wxT("bin") + sep + exeName + exeExt))
457
exePath = cbInstallFolder + sep + wxT("MINGW") + sep + wxT("bin");
460
exePath = wxT("C:\\MinGW\\bin");
461
if (!wxDirExists(exePath))
462
exePath = wxT("C:\\MinGW32\\bin");
466
if (!wxDirExists(exePath))
467
return wxEmptyString;
468
return exePath + wxFileName::GetPathSeparator() + exeName + exeExt;
471
uint64_t cbDebuggerStringToAddress(const wxString &address)
475
std::istringstream s(address.utf8_str().data());
477
s >> std::hex >> result;
478
return (s.fail() ? 0 : result);
481
wxString cbDebuggerAddressToString(uint64_t address)
484
s << "0x" << std::hex << address;
485
return wxString(s.str().c_str(), wxConvUTF8);
488
class DebugTextCtrlLogger : public TextCtrlLogger
491
DebugTextCtrlLogger(bool fixedPitchFont, bool debugLog) :
492
TextCtrlLogger(fixedPitchFont),
498
wxWindow* CreateTextCtrl(wxWindow *parent)
500
return TextCtrlLogger::CreateControl(parent);
503
virtual wxWindow* CreateControl(wxWindow* parent);
510
class DebugLogPanel : public wxPanel
513
DebugLogPanel(wxWindow *parent, DebugTextCtrlLogger *text_control_logger, bool debug_log) :
515
m_text_control_logger(text_control_logger),
516
m_debug_log(debug_log)
518
int idDebug_LogEntryControl = wxNewId();
519
int idDebug_ExecuteButton = wxNewId();
520
int idDebug_ClearButton = wxNewId();
521
int idDebug_LoadButton = wxNewId();
523
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
524
wxBoxSizer *control_sizer = new wxBoxSizer(wxHORIZONTAL);
526
wxWindow *text_control = text_control_logger->CreateTextCtrl(this);
527
sizer->Add(text_control, wxEXPAND, wxEXPAND | wxALL , 0);
528
sizer->Add(control_sizer, 0, wxEXPAND | wxALL, 0);
530
wxStaticText *label = new wxStaticText(this, wxID_ANY, _T("Command:"),
531
wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
533
m_command_entry = new wxComboBox(this, idDebug_LogEntryControl, wxEmptyString,
534
wxDefaultPosition, wxDefaultSize, 0, nullptr,
535
wxCB_DROPDOWN | wxTE_PROCESS_ENTER);
537
wxBitmap execute_bitmap = wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_EXECUTABLE_FILE")),
539
wxBitmap clear_bitmap = wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_DELETE")),wxART_BUTTON);
540
wxBitmap file_open_bitmap =wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_FILE_OPEN")),
543
wxBitmapButton *button_execute;
544
button_execute = new wxBitmapButton(this, idDebug_ExecuteButton, execute_bitmap, wxDefaultPosition,
545
wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator,
546
_T("idDebug_ExecuteButton"));
547
button_execute->SetToolTip(_("Execute current command"));
549
wxBitmapButton *button_load = new wxBitmapButton(this, idDebug_LoadButton, file_open_bitmap, wxDefaultPosition,
550
wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator,
551
_T("idDebug_LoadButton"));
552
button_load->SetDefault();
553
button_load->SetToolTip(_("Load from file"));
555
wxBitmapButton *button_clear = new wxBitmapButton(this, idDebug_ClearButton, clear_bitmap, wxDefaultPosition,
556
wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator,
557
_T("idDebug_ClearButton"));
558
button_clear->SetDefault();
559
button_clear->SetToolTip(_("Clear output window"));
561
control_sizer->Add(label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 2);
562
control_sizer->Add(m_command_entry, wxEXPAND, wxEXPAND | wxALL, 2);
563
control_sizer->Add(button_execute, 0, wxEXPAND | wxALL, 0);
564
control_sizer->Add(button_load, 0, wxALL|wxALIGN_CENTER_VERTICAL, 0);
565
control_sizer->Add(button_clear, 0, wxALL|wxALIGN_CENTER_VERTICAL, 0);
569
Connect(idDebug_LogEntryControl,
570
wxEVT_COMMAND_TEXT_ENTER,
571
wxObjectEventFunction(&DebugLogPanel::OnEntryCommand));
572
Connect(idDebug_ExecuteButton,
573
wxEVT_COMMAND_BUTTON_CLICKED,
574
wxObjectEventFunction(&DebugLogPanel::OnEntryCommand));
575
Connect(idDebug_ClearButton,
576
wxEVT_COMMAND_BUTTON_CLICKED,
577
wxObjectEventFunction(&DebugLogPanel::OnClearLog));
578
Connect(idDebug_LoadButton,
579
wxEVT_COMMAND_BUTTON_CLICKED,
580
wxObjectEventFunction(&DebugLogPanel::OnLoadFile));
583
Connect(idDebug_ExecuteButton,
585
wxObjectEventFunction(&DebugLogPanel::OnUpdateUI));
586
Connect(idDebug_LoadButton,
588
wxObjectEventFunction(&DebugLogPanel::OnUpdateUI));
589
Connect(idDebug_LogEntryControl,
591
wxObjectEventFunction(&DebugLogPanel::OnUpdateUI));
594
void OnEntryCommand(cb_unused wxCommandEvent& event)
596
assert(m_command_entry);
597
wxString cmd = m_command_entry->GetValue();
603
cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
606
plugin->SendCommand(cmd, m_debug_log);
608
//If it already exists in the list, remove it and add it back at the end
609
int index = m_command_entry->FindString(cmd);
610
if (index != wxNOT_FOUND)
611
m_command_entry->Delete(index);
612
m_command_entry->Append(cmd);
614
m_command_entry->SetValue(wxEmptyString);
618
void OnClearLog(cb_unused wxCommandEvent& event)
620
assert(m_command_entry);
621
assert(m_text_control_logger);
622
m_text_control_logger->Clear();
623
m_command_entry->SetFocus();
626
void OnLoadFile(cb_unused wxCommandEvent& event)
628
cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
632
ConfigManager* manager = Manager::Get()->GetConfigManager(_T("app"));
633
wxString path = manager->Read(_T("/file_dialogs/file_run_dbg_script/directory"), wxEmptyString);
635
wxFileDialog dialog(this, _("Load script"), path, wxEmptyString,
636
_T("Debugger script files (*.gdb)|*.gdb"), wxFD_OPEN | compatibility::wxHideReadonly);
638
if (dialog.ShowModal() == wxID_OK)
640
manager->Write(_T("/file_dialogs/file_run_dbg_script/directory"), dialog.GetDirectory());
642
plugin->SendCommand(_T("source ") + dialog.GetPath(), m_debug_log);
646
void OnUpdateUI(wxUpdateUIEvent &event)
648
cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
649
event.Enable(plugin && plugin->IsRunning() && plugin->IsStopped());
652
DebugTextCtrlLogger *m_text_control_logger;
653
wxComboBox *m_command_entry;
657
wxWindow* DebugTextCtrlLogger::CreateControl(wxWindow* parent)
660
m_panel = new DebugLogPanel(parent, this, m_debugLog);
665
template<> DebuggerManager* Mgr<DebuggerManager>::instance = nullptr;
666
template<> bool Mgr<DebuggerManager>::isShutdown = false;
668
inline void ReadActiveDebuggerConfig(wxString &name, int &configIndex)
670
ConfigManager &config = *Manager::Get()->GetConfigManager(_T("debugger_common"));
671
name = config.Read(wxT("active_debugger"), wxEmptyString);
675
configIndex = std::max(0, config.ReadInt(wxT("active_debugger_config"), 0));
678
inline void WriteActiveDebuggerConfig(const wxString &name, int configIndex)
680
ConfigManager &configMgr = *Manager::Get()->GetConfigManager(_T("debugger_common"));
681
configMgr.Write(wxT("active_debugger"), name);
682
configMgr.Write(wxT("active_debugger_config"), configIndex);
685
cbDebuggerConfiguration* DebuggerManager::PluginData::GetConfiguration(int index)
687
if (m_configurations.empty())
689
if (index >= static_cast<int>(m_configurations.size()))
692
return m_configurations[index];
695
DebuggerManager::DebuggerManager() :
696
m_interfaceFactory(nullptr),
697
m_activeDebugger(nullptr),
698
m_menuHandler(nullptr),
699
m_backtraceDialog(nullptr),
700
m_breakPointsDialog(nullptr),
701
m_cpuRegistersDialog(nullptr),
702
m_disassemblyDialog(nullptr),
703
m_examineMemoryDialog(nullptr),
704
m_threadsDialog(nullptr),
705
m_watchesDialog(nullptr),
708
m_isDisassemblyMixedMode(false),
709
m_useTargetsDefault(false)
711
typedef cbEventFunctor<DebuggerManager, CodeBlocksEvent> Event;
712
Manager::Get()->RegisterEventSink(cbEVT_PROJECT_ACTIVATE, new Event(this, &DebuggerManager::OnProjectActivated));
713
// connect with cbEVT_PROJECT_OPEN, too (see here: http://forums.codeblocks.org/index.php/topic,17260.msg118431.html#msg118431)
714
Manager::Get()->RegisterEventSink(cbEVT_PROJECT_OPEN, new Event(this, &DebuggerManager::OnProjectActivated));
715
Manager::Get()->RegisterEventSink(cbEVT_BUILDTARGET_SELECTED, new Event(this, &DebuggerManager::OnTargetSelected));
716
Manager::Get()->RegisterEventSink(cbEVT_SETTINGS_CHANGED, new Event(this, &DebuggerManager::OnSettingsChanged));
717
Manager::Get()->RegisterEventSink(cbEVT_PLUGIN_LOADING_COMPLETE, new Event(this, &DebuggerManager::OnPluginLoadingComplete));
719
wxString activeDebuggerName;
721
ReadActiveDebuggerConfig(activeDebuggerName, activeConfig);
722
if (activeDebuggerName.empty() && activeConfig == -1)
723
m_useTargetsDefault = true;
726
DebuggerManager::~DebuggerManager()
728
for (RegisteredPlugins::iterator it = m_registered.begin(); it != m_registered.end(); ++it)
729
it->second.ClearConfigurations();
731
Manager::Get()->RemoveAllEventSinksFor(this);
732
delete m_interfaceFactory;
735
bool DebuggerManager::RegisterDebugger(cbDebuggerPlugin *plugin)
737
RegisteredPlugins::iterator it = m_registered.find(plugin);
738
if (it != m_registered.end())
740
const wxString &guiName=plugin->GetGUIName();
741
const wxString &settingsName=plugin->GetSettingsName();
743
wxRegEx regExSettingsName(wxT("^[a-z_][a-z0-9_]+$"));
744
if (!regExSettingsName.Matches(settingsName))
747
s = wxString::Format(_("The settings name for the debugger plugin \"%s\" - \"%s\" contains invalid characters"),
748
guiName.c_str(), settingsName.c_str());
749
Manager::Get()->GetLogManager()->LogError(s);
753
int normalIndex = -1;
754
GetLogger(normalIndex);
755
plugin->SetupLog(normalIndex);
759
m_registered[plugin] = data;
760
it = m_registered.find(plugin);
763
// There should be at least one configuration for every plugin.
764
// If this is not the case, something is wrong and should be fixed.
765
cbAssert(!it->second.GetConfigurations().empty());
767
wxString activeDebuggerName;
769
ReadActiveDebuggerConfig(activeDebuggerName, activeConfig);
771
if (activeDebuggerName == settingsName)
773
if (activeConfig > static_cast<int>(it->second.GetConfigurations().size()))
776
m_activeDebugger = plugin;
777
m_activeDebugger->SetActiveConfig(activeConfig);
779
m_menuHandler->SetActiveDebugger(m_activeDebugger);
783
m_menuHandler->RebuildMenus();
788
bool DebuggerManager::UnregisterDebugger(cbDebuggerPlugin *plugin)
790
RegisteredPlugins::iterator it = m_registered.find(plugin);
791
if(it == m_registered.end())
794
it->second.ClearConfigurations();
795
m_registered.erase(it);
796
if (plugin == m_activeDebugger)
798
if (m_registered.empty())
799
m_activeDebugger = nullptr;
801
m_activeDebugger = m_registered.begin()->first;
802
m_menuHandler->SetActiveDebugger(m_activeDebugger);
804
if (!Manager::IsAppShuttingDown())
806
m_menuHandler->RebuildMenus();
810
if (m_registered.empty())
814
if (Manager::Get()->GetLogManager())
815
Manager::Get()->GetDebuggerManager()->HideLogger();
821
void DebuggerManager::ProcessSettings(RegisteredPlugins::iterator it)
823
cbDebuggerPlugin *plugin = it->first;
824
PluginData &data = it->second;
825
ConfigManager *config = Manager::Get()->GetConfigManager(wxT("debugger_common"));
826
wxString path = wxT("/sets/") + plugin->GetSettingsName();
827
wxArrayString configs = config->EnumerateSubPaths(path);
832
config->Write(path + wxT("/conf1/name"), wxString(wxT("Default")));
833
configs = config->EnumerateSubPaths(path);
837
data.ClearConfigurations();
838
data.m_lastConfigID = -1;
840
for (size_t jj = 0; jj < configs.Count(); ++jj)
842
wxString configPath = path + wxT("/") + configs[jj];
843
wxString name = config->Read(configPath + wxT("/name"));
845
cbDebuggerConfiguration *pluginConfig;
846
pluginConfig = plugin->LoadConfig(ConfigManagerWrapper(wxT("debugger_common"), configPath + wxT("/values")));
849
pluginConfig->SetName(name);
850
data.GetConfigurations().push_back(pluginConfig);
855
ConfigManagerWrapper DebuggerManager::NewConfig(cbDebuggerPlugin *plugin, cb_unused const wxString& name)
857
RegisteredPlugins::iterator it = m_registered.find(plugin);
858
if (it == m_registered.end())
859
return ConfigManagerWrapper();
861
wxString path = wxT("/sets/") + it->first->GetSettingsName();
863
if (it->second.m_lastConfigID == -1)
865
ConfigManager *config = Manager::Get()->GetConfigManager(wxT("debugger_common"));
866
wxArrayString configs = config->EnumerateSubPaths(path);
867
for (size_t ii = 0; ii < configs.GetCount(); ++ii)
870
if (configs[ii].Remove(0, 4).ToLong(&id))
871
it->second.m_lastConfigID = std::max<long>(it->second.m_lastConfigID, id);
875
path << wxT("/conf") << ++it->second.m_lastConfigID;
877
return ConfigManagerWrapper(wxT("debugger_common"), path + wxT("/values"));
880
void DebuggerManager::RebuildAllConfigs()
882
for (RegisteredPlugins::iterator it = m_registered.begin(); it != m_registered.end(); ++it)
884
m_menuHandler->RebuildMenus();
887
wxMenu* DebuggerManager::GetMenu()
889
wxMenuBar *menuBar = Manager::Get()->GetAppFrame()->GetMenuBar();
893
int menu_pos = menuBar->FindMenu(_("&Debug"));
895
if(menu_pos != wxNOT_FOUND)
896
menu = menuBar->GetMenu(menu_pos);
900
menu = Manager::Get()->LoadMenu(_T("debugger_menu"),true);
902
// ok, now, where do we insert?
903
// three possibilities here:
904
// a) locate "Compile" menu and insert after it
905
// b) locate "Project" menu and insert after it
906
// c) if not found (?), insert at pos 5
908
int projcompMenuPos = menuBar->FindMenu(_("&Build"));
909
if (projcompMenuPos == wxNOT_FOUND)
910
projcompMenuPos = menuBar->FindMenu(_("&Compile"));
912
if (projcompMenuPos != wxNOT_FOUND)
913
finalPos = projcompMenuPos + 1;
916
projcompMenuPos = menuBar->FindMenu(_("&Project"));
917
if (projcompMenuPos != wxNOT_FOUND)
918
finalPos = projcompMenuPos + 1;
920
menuBar->Insert(finalPos, menu, _("&Debug"));
922
m_menuHandler->RebuildMenus();
927
bool DebuggerManager::HasMenu() const
929
wxMenuBar *menuBar = Manager::Get()->GetAppFrame()->GetMenuBar();
931
int menu_pos = menuBar->FindMenu(_("&Debug"));
932
return menu_pos != wxNOT_FOUND;
935
void DebuggerManager::BuildContextMenu(wxMenu &menu, const wxString& word_at_caret, bool is_running)
937
m_menuHandler->BuildContextMenu(menu, word_at_caret, is_running);
940
TextCtrlLogger* DebuggerManager::GetLogger(int &index)
942
LogManager* msgMan = Manager::Get()->GetLogManager();
946
m_logger = new DebugTextCtrlLogger(true, false);
947
m_loggerIndex = msgMan->SetLog(m_logger);
948
LogSlot &slot = msgMan->Slot(m_loggerIndex);
949
slot.title = _("Debugger");
951
wxString prefix = ConfigManager::GetDataFolder() + _T("/images/");
952
wxBitmap* bmp = new wxBitmap(cbLoadBitmap(prefix + _T("misc_16x16.png"), wxBITMAP_TYPE_PNG));
955
CodeBlocksLogEvent evtAdd(cbEVT_ADD_LOG_WINDOW, m_logger, slot.title, slot.icon);
956
Manager::Get()->ProcessEvent(evtAdd);
959
index = m_loggerIndex;
963
TextCtrlLogger* DebuggerManager::GetLogger()
966
return GetLogger(index);
969
void DebuggerManager::HideLogger()
972
CodeBlocksLogEvent evt(cbEVT_REMOVE_LOG_WINDOW, m_logger);
973
Manager::Get()->ProcessEvent(evt);
978
void DebuggerManager::SetInterfaceFactory(cbDebugInterfaceFactory *factory)
980
cbAssert(!m_interfaceFactory);
981
m_interfaceFactory = factory;
985
m_backtraceDialog->EnableWindow(false);
986
m_cpuRegistersDialog->EnableWindow(false);
987
m_disassemblyDialog->EnableWindow(false);
988
m_examineMemoryDialog->EnableWindow(false);
989
m_threadsDialog->EnableWindow(false);
992
void DebuggerManager::CreateWindows()
994
if (!m_backtraceDialog)
995
m_backtraceDialog = m_interfaceFactory->CreateBacktrace();
996
if (!m_breakPointsDialog)
997
m_breakPointsDialog = m_interfaceFactory->CreateBreapoints();
998
if (!m_cpuRegistersDialog)
999
m_cpuRegistersDialog = m_interfaceFactory->CreateCPURegisters();
1000
if (!m_disassemblyDialog)
1001
m_disassemblyDialog = m_interfaceFactory->CreateDisassembly();
1002
if (!m_examineMemoryDialog)
1003
m_examineMemoryDialog = m_interfaceFactory->CreateMemory();
1004
if (!m_threadsDialog)
1005
m_threadsDialog = m_interfaceFactory->CreateThreads();
1006
if (!m_watchesDialog)
1007
m_watchesDialog = m_interfaceFactory->CreateWatches();
1010
void DebuggerManager::DestoryWindows()
1012
m_interfaceFactory->DeleteBacktrace(m_backtraceDialog);
1013
m_backtraceDialog = nullptr;
1015
m_interfaceFactory->DeleteBreakpoints(m_breakPointsDialog);
1016
m_breakPointsDialog = nullptr;
1018
m_interfaceFactory->DeleteCPURegisters(m_cpuRegistersDialog);
1019
m_cpuRegistersDialog = nullptr;
1021
m_interfaceFactory->DeleteDisassembly(m_disassemblyDialog);
1022
m_disassemblyDialog = nullptr;
1024
m_interfaceFactory->DeleteMemory(m_examineMemoryDialog);
1025
m_examineMemoryDialog = nullptr;
1027
m_interfaceFactory->DeleteThreads(m_threadsDialog);
1028
m_threadsDialog = nullptr;
1030
m_interfaceFactory->DeleteWatches(m_watchesDialog);
1031
m_watchesDialog = nullptr;
1034
cbDebugInterfaceFactory* DebuggerManager::GetInterfaceFactory()
1036
return m_interfaceFactory;
1039
void DebuggerManager::SetMenuHandler(cbDebuggerMenuHandler *handler)
1041
m_menuHandler = handler;
1044
cbDebuggerMenuHandler* DebuggerManager::GetMenuHandler()
1046
return m_menuHandler;
1049
cbBacktraceDlg* DebuggerManager::GetBacktraceDialog()
1051
return m_backtraceDialog;
1054
cbBreakpointsDlg* DebuggerManager::GetBreakpointDialog()
1056
return m_breakPointsDialog;
1059
cbCPURegistersDlg* DebuggerManager::GetCPURegistersDialog()
1061
return m_cpuRegistersDialog;
1064
cbDisassemblyDlg* DebuggerManager::GetDisassemblyDialog()
1066
return m_disassemblyDialog;
1069
cbExamineMemoryDlg* DebuggerManager::GetExamineMemoryDialog()
1071
return m_examineMemoryDialog;
1074
cbThreadsDlg* DebuggerManager::GetThreadsDialog()
1076
return m_threadsDialog;
1079
cbWatchesDlg* DebuggerManager::GetWatchesDialog()
1081
return m_watchesDialog;
1084
bool DebuggerManager::ShowBacktraceDialog()
1086
cbBacktraceDlg *dialog = GetBacktraceDialog();
1088
if (!IsWindowReallyShown(dialog->GetWindow()))
1090
// show the backtrace window
1091
CodeBlocksDockEvent evt(cbEVT_SHOW_DOCK_WINDOW);
1092
evt.pWindow = dialog->GetWindow();
1093
Manager::Get()->ProcessEvent(evt);
1100
bool DebuggerManager::UpdateBacktrace()
1102
return m_backtraceDialog && IsWindowReallyShown(m_backtraceDialog->GetWindow());
1105
bool DebuggerManager::UpdateCPURegisters()
1107
return m_cpuRegistersDialog && IsWindowReallyShown(m_cpuRegistersDialog->GetWindow());
1110
bool DebuggerManager::UpdateDisassembly()
1112
return m_disassemblyDialog && IsWindowReallyShown(m_disassemblyDialog->GetWindow());
1115
bool DebuggerManager::UpdateExamineMemory()
1117
return m_examineMemoryDialog && IsWindowReallyShown(m_examineMemoryDialog->GetWindow());
1120
bool DebuggerManager::UpdateThreads()
1122
return m_threadsDialog && IsWindowReallyShown(m_threadsDialog->GetWindow());
1125
cbDebuggerPlugin* DebuggerManager::GetDebuggerHavingWatch(cb::shared_ptr<cbWatch> watch)
1127
watch = cbGetRootWatch(watch);
1128
for (RegisteredPlugins::iterator it = m_registered.begin(); it != m_registered.end(); ++it)
1130
if (it->first->HasWatch(watch))
1136
bool DebuggerManager::ShowValueTooltip(const cb::shared_ptr<cbWatch> &watch, const wxRect &rect)
1138
return m_interfaceFactory->ShowValueTooltip(watch, rect);
1141
DebuggerManager::RegisteredPlugins const & DebuggerManager::GetAllDebuggers() const
1143
return m_registered;
1145
DebuggerManager::RegisteredPlugins & DebuggerManager::GetAllDebuggers()
1147
return m_registered;
1149
cbDebuggerPlugin* DebuggerManager::GetActiveDebugger()
1151
return m_activeDebugger;
1154
inline void RefreshBreakpoints(cb_unused const cbDebuggerPlugin* plugin)
1156
EditorManager *editorManager = Manager::Get()->GetEditorManager();
1157
int count = editorManager->GetEditorsCount();
1158
for (int ii = 0; ii < count; ++ii)
1160
EditorBase *editor = editorManager->GetEditor(ii);
1161
if (!editor->IsBuiltinEditor())
1163
editor->RefreshBreakpointMarkers();
1167
void DebuggerManager::SetActiveDebugger(cbDebuggerPlugin* activeDebugger, ConfigurationVector::const_iterator config)
1169
RegisteredPlugins::const_iterator it = m_registered.find(activeDebugger);
1170
cbAssert(it != m_registered.end());
1172
m_useTargetsDefault = false;
1173
m_activeDebugger = activeDebugger;
1174
int index = std::distance(it->second.GetConfigurations().begin(), config);
1175
m_activeDebugger->SetActiveConfig(index);
1177
WriteActiveDebuggerConfig(it->first->GetSettingsName(), index);
1181
void DebuggerManager::RefreshUI()
1183
m_menuHandler->SetActiveDebugger(m_activeDebugger);
1184
m_menuHandler->RebuildMenus();
1185
RefreshBreakpoints(m_activeDebugger);
1187
if (m_activeDebugger)
1189
if (m_backtraceDialog)
1190
m_backtraceDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::Callstack));
1191
if (m_cpuRegistersDialog)
1192
m_cpuRegistersDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::CPURegisters));
1193
if (m_disassemblyDialog)
1194
m_disassemblyDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::Disassembly));
1195
if (m_examineMemoryDialog)
1196
m_examineMemoryDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::ExamineMemory));
1197
if (m_threadsDialog)
1198
m_threadsDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::Threads));
1200
if (m_watchesDialog)
1201
m_watchesDialog->RefreshUI();
1202
if (m_breakPointsDialog)
1203
m_breakPointsDialog->Reload();
1206
bool DebuggerManager::IsActiveDebuggerTargetsDefault() const
1208
return m_activeDebugger && m_useTargetsDefault;
1211
void DebuggerManager::SetTargetsDefaultAsActiveDebugger()
1213
m_activeDebugger = nullptr;
1214
m_menuHandler->SetActiveDebugger(nullptr);
1215
FindTargetsDebugger();
1218
void DebuggerManager::FindTargetsDebugger()
1220
if (Manager::Get()->GetProjectManager()->IsLoadingOrClosing())
1223
m_activeDebugger = nullptr;
1224
m_menuHandler->SetActiveDebugger(nullptr);
1226
if (m_registered.empty())
1228
m_menuHandler->MarkActiveTargetAsValid(false);
1232
ProjectManager* projectMgr = Manager::Get()->GetProjectManager();
1233
LogManager* log = Manager::Get()->GetLogManager();
1234
cbProject* project = projectMgr->GetActiveProject();
1235
ProjectBuildTarget *target = nullptr;
1238
const wxString &targetName = project->GetActiveBuildTarget();
1239
if (project->BuildTargetValid(targetName))
1240
target = project->GetBuildTarget(targetName);
1244
Compiler *compiler = nullptr;
1248
compiler = CompilerFactory::GetCompiler(project->GetCompilerID());
1250
compiler = CompilerFactory::GetDefaultCompiler();
1253
log->LogError(_("Can't get the compiler for the active target, nor the project, nor the default one!"));
1254
m_menuHandler->MarkActiveTargetAsValid(false);
1260
compiler = CompilerFactory::GetCompiler(target->GetCompilerID());
1263
log->LogError(wxString::Format(_("Current target '%s' doesn't have valid compiler!"),
1264
target->GetTitle().c_str()));
1265
m_menuHandler->MarkActiveTargetAsValid(false);
1269
wxString dbgString = compiler->GetPrograms().DBGconfig;
1270
wxString::size_type pos = dbgString.find(wxT(':'));
1272
wxString name, config;
1273
if (pos != wxString::npos)
1275
name = dbgString.substr(0, pos);
1276
config = dbgString.substr(pos + 1, dbgString.length() - pos - 1);
1279
if (name.empty() || config.empty())
1281
log->LogError(wxString::Format(_("Current compiler '%s' doesn't have correctly defined debugger!"),
1282
compiler->GetName().c_str()));
1283
m_menuHandler->MarkActiveTargetAsValid(false);
1287
for (RegisteredPlugins::iterator it = m_registered.begin(); it != m_registered.end(); ++it)
1289
PluginData &data = it->second;
1290
if (it->first->GetSettingsName() == name)
1292
ConfigurationVector &configs = data.GetConfigurations();
1294
for (ConfigurationVector::iterator itConf = configs.begin(); itConf != configs.end(); ++itConf, ++index)
1296
if ((*itConf)->GetName() == config)
1298
m_activeDebugger = it->first;
1299
m_activeDebugger->SetActiveConfig(index);
1300
m_useTargetsDefault = true;
1302
WriteActiveDebuggerConfig(wxEmptyString, -1);
1304
m_menuHandler->MarkActiveTargetAsValid(true);
1311
wxString targetTitle(target ? target->GetTitle() : wxT("<nullptr>"));
1312
log->LogError(wxString::Format(_("Can't find the debugger config: '%s:%s' for the current target '%s'!"),
1313
name.c_str(), config.c_str(),
1314
targetTitle.c_str()));
1315
m_menuHandler->MarkActiveTargetAsValid(false);
1318
bool DebuggerManager::IsDisassemblyMixedMode()
1320
return m_isDisassemblyMixedMode;
1323
void DebuggerManager::SetDisassemblyMixedMode(bool mixed)
1325
m_isDisassemblyMixedMode = mixed;
1328
void DebuggerManager::OnProjectActivated(cb_unused CodeBlocksEvent& event)
1330
if (m_useTargetsDefault)
1331
FindTargetsDebugger();
1334
void DebuggerManager::OnTargetSelected(cb_unused CodeBlocksEvent& event)
1336
if (m_useTargetsDefault)
1337
FindTargetsDebugger();
1340
void DebuggerManager::OnSettingsChanged(CodeBlocksEvent& event)
1342
if (event.GetInt() == cbSettingsType::Compiler || event.GetInt() == cbSettingsType::Debugger)
1344
if (m_useTargetsDefault)
1345
FindTargetsDebugger();
1349
void DebuggerManager::OnPluginLoadingComplete(cb_unused CodeBlocksEvent& event)
1352
if (!m_activeDebugger)
1354
m_useTargetsDefault = true;
1355
FindTargetsDebugger();