Hi, I'm opening this old topic because I would like to implement some functionality of DDD to Code::Blocks. As I noticed, new features to debugger are added by editing the code in plugins/debuggergdb/ directory. But I try add new functionality by pure new plugin. This is my test code:void DDDLikeWatches::OnAttach()
{
cbDebuggerPlugin *debugger = reinterpret_cast<cbDebuggerPlugin *>(
Manager::Get()->GetPluginManager()->FindPluginByName(wxT("Debugger"))
);
DebuggerGDB *gdb = reinterpret_cast<DebuggerGDB *>(debugger);
DebuggerDriver *driver = gdb->GetState().GetDriver();
}
When I try compile this, I get undefined reference to `DebuggerState::GetDriver()'. My question is: Where is the problem? Can I access debugger's functions from debugger.dll from other plugin or must modify original debugger plugin's code to add this functionality to debugger? I link debugger.dll to my project.
Thanks for your replies and sorry for my inattention. I use debugger_branch (/branches/wxpropgrid_debugger/) now.
I'm still implementing this feature to C::B and have one question. I try to add functionality that after double click on pointer element in structure dereferences pointer and join nodes of graph by edge. Here is relevant part of my event handler for that:cbDebuggerPlugin* debugger = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
wxString watchString; watch->GetFullWatchString(watchString);
watch = debugger->AddWatch(wxT("(*") + watchString + wxT(')'));
if(!watch) { return; }
ViewNode* node = new ViewNode(
this->GetParent(),
watch,
this->GetPosition() + wxPoint(this->GetSize().GetWidth() + 20, 0) // TODO (m.29##): automatic graph layouts
);
this->GetParent()->AddChild(node);
ViewNode::JoinNodes(this, node);
But in ViewNode's constructor I get uninitialized watch (e.g. watch->GetChildCount() == 0 if watch is structure type). I know it is because watch is parsed in parallel to my code. I don't know how to wait for end of parsing. Or how can I find out that watch was parsed yet? I tried find answer in C::B codes but it seems nothing special is done after calling cbDebuggerPlugin::AddWatch() there.
Thanks, it helps. I'm implementing "index out of bounds" checking now. I noticed some things during exploring C::B sources:
1) Function ParseCDBWatchValue has some strange (for me) condition if (tokens[0] == wxT("class") || tokens[0] == wxT("class"))
I think it should be if (tokens[0] == wxT("struct") || tokens[0] == wxT("class"))
as it is a few rows below.
2) I edited GDBWatch::GetFullWatchString function 'cause for arrays it always gave me ArrayName.[index].
3) Because I would like to check indexing out of bounds I added size to array watches in GdbCmd_Watch class.
4) In GdbCmd_FindWatchType class there was "whatis &" instead of "whatis " string used to finding type of watch and then tmp.substr(0, tmp.length() - 1); used to removing last "*". But this was bad for arrays or functions:
- int (*)[4] -> int (*)[4
- int (*)(int) -> int (*)(int
- ...
I made the patch (http://dl.dropbox.com/u/22120595/array_dbg001.patch) for this things, but if I done something wrong someone explain me what and why, please.
1) I didn't test it, but that condition is really weird. Why there is test for the same thing twice? Here is the test case:TEST(CDBSingleLineStructPointer)
{
GDBWatch w(wxT("t"));
CHECK(ParseCDBWatchValue(w, wxT("struct t * 0x123456"));
CHECK_EQUAL(wxT("t*=0x123456"), w);
}
TEST(CDBSingleLineClassPointer)
{
GDBWatch w(wxT("t"));
CHECK(ParseCDBWatchValue(w, wxT("class t * 0x123456"));
CHECK_EQUAL(wxT("t*=0x123456"), w);
}
2) In my code there is functionality that dereferences pointer (http://dl.dropbox.com/u/22120595/array_of_structs_deref.png) on double click on variable. There is array of structures struct s {
payload_t payload;
struct s* next;
} item1, item2, ...;
struct s array[] = {
item1,
item2,
...
};
Then I try dereference pointer next in structure on index 0 I get (*array.[0].next) instead of (*array[0].next). This expression is not valid and gdb can't return right result.
3) I don't override user's choice because there is a condition that allows set parameters only 1st time. If my code overrides user's choice there is watch->SetArray(true); what also overrides user's choice. But no. As I tested if I change properties of watch everything stay set according to my new choice. Only if watch format is Undefined and it is array with size (int array[29];) but GDBWatch::IsArray returns false everything is set to default. I hope it is understandable - my English and speech aren't good :-(
I changed GDBWatch::GetFullWatchString into test if parent is array - hope it's OK now.
4) For me it is good. Can you provide some example when it is not watchable? Or it is issue of any specific platform?
I graphical representation of watches programmer can see actual indexed item of array in bold (http://dl.dropbox.com/u/22120595/array_autoindexing.png). My idea is, if i know index and size of array I can check if index is not bigger than size of array. Then C::B warns programmer about it. There is some complications now and I want to do on automatic graph layout of oriented graphs so I return to this later, but I think is not good if size of array will be available anyway.
In my code, there is many changes, but these seem to be bugs and useful changes that affect functionality of C::B. But I want to find out if some of them is not intention (like "whatis &" issue) because there is no explanation in comments. That's why I put them here.
So I did the most of my TODOs and tried the patch on Ubuntu. On Ubuntu I found modifications like this one in patch:
@@ -232,7 +232,7 @@
</Linker>
</Target>
<Target title="Compiler depslib">
- <Option output="plugins/compilergcc/depslib/depslib" prefix_auto="1" extension_auto="1" />
+ <Option output="plugins/compilergcc/depslib/libdepslib" prefix_auto="1" extension_auto="1" />
<Option working_dir="" />
<Option type="2" />
<Option compiler="gcc" />
I don't know what is it and why is there. Because of this there are not included modifications in "CodeBlocks-unix.cbp" file so on linux you need to add 10 files to project.
src/include/arraypanel.h
src/include/viewnode.h
src/include/viewvector.h
src/include/visualwatchesdlg.h
src/include/visualobject.h
src/sdk/arraypanel.cpp
src/sdk/viewnode.cpp
src/sdk/viewvector.cpp
src/sdk/visualwatchesdlg.cpp
src/sdk/visualobject.cpp
Hope it is not complication for you. I'm waiting for your feedback :-)
This change:
Index: src/plugins/debuggergdb/parsewatchvalue.cpp
===================================================================
--- src/plugins/debuggergdb/parsewatchvalue.cpp (revision 7112)
+++ src/plugins/debuggergdb/parsewatchvalue.cpp (working copy)
@@ -258,6 +258,8 @@
bool ParseGDBWatchValue(GDBWatch &watch, wxString const &value, int &start, int length)
{
watch.SetDebugValue(value);
+ // erase possible "Cannot access memory at address" at structural types
+ watch.SetValue(wxEmptyString);
watch.MarkChildsAsRemoved();
int position = start;
requires a unittest, explanation and steps to reproduce.
Also you're using C++, not C# or any other "modern" language, so "this->" is not required (99.99% of the time), when accessing members of the class.
Please don't do it.
I've not tried the patch yet, will do so tomorrow...
I tried this unittest with others and all tests passed:// dereferenced pointer from invalid to valid address
TEST(DereferencedStructPointer)
{
GDBWatch w(wxT("*s"));
CHECK(ParseGDBWatchValue(w, wxT("Cannot access memory at address 0x0")));
CHECK(ParseGDBWatchValue(w, wxT("{\n number = 29,\n real = 36\n}")));
CHECK_EQUAL(wxT("*s= {number=29,real=36}"), w);
}
Without my patch I get *s=Cannot access memory at address 0x0 {number=29,real=36}. You can reproduce this with this C code:#include <stdlib.h>
struct structure {
int number;
float real;
};
int main(void) {
struct structure *s = NULL;
struct structure S = {
.number = 29,
.real = 36,
};
s = &S;
return EXIT_SUCCESS;
}
You set breakpoint at line struct structure *s = NULL; and then stop at line return EXIT_SUCCESS; As you can see at picture, old value is displayed.
In my code I hide edges of graph which are invalid. I find out this case (watch is invalid) by parsing watch value, but in some cases value of watch was invalid even if watch was was valid. Typically if dereferenced pointer was NULL and then not NULL.
Sorry for the "this->" issue. I'll remove it.
[attachment deleted by admin]