Author Topic: Some thoughts on doing breakpoints persistent  (Read 42952 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #15 on: June 16, 2009, 06:16:33 pm »
We talk about data per project.
If a plugin needs some global configuration, the core can(must) still provide an interface for storing settings.

Yes, There are many *.ini files  for plugin global settings in APPDATA folder.

Edit:
Some global settings were using XML format, such as "default.conf"
Others use INI file format.


For example the BrowseTracker.ini
Code
BrowseMarksEnabled=1
BrowseMarksStyle=0
BrowseMarksToggleKey=0
LeftMouseDelay=400
BrowseMarksClearAllMethod=0

I'm not sure the core supply method to access these ini files.


Edit2

I found in cbproject.cpp, there are some code do the "your_project_name.layout" file IO.

Code
bool cbProject::SaveLayout()
{
    if (m_Filename.IsEmpty())
        return false;

    wxFileName fname(m_Filename);
    fname.SetExt(_T("layout"));
    ProjectLayoutLoader loader(this);
    return loader.Save(fname.GetFullPath());
}

bool cbProject::LoadLayout()
{
   if (m_Filename.IsEmpty())
        return false;
    int openmode = Manager::Get()->GetConfigManager(_T("project_manager"))->ReadInt(_T("/open_files"), (long int)1);
    bool result = false;

    if(openmode==2)
    {
        // Do not open any files
        result = true;
    }
    else
    {
        Manager::Get()->GetEditorManager()->HideNotebook();
        if(openmode == 0) // Open all files
        {
            FilesList::Node* node = m_Files.GetFirst();
            while(node)
            {
                ProjectFile* f = node->GetData();
                Manager::Get()->GetEditorManager()->Open(f->file.GetFullPath(),0,f);
                node = node->GetNext();
            }
            result = true;
        }
        else if(openmode == 1)// Open last open files
        {
            wxFileName fname(m_Filename);
            fname.SetExt(_T("layout"));
            ProjectLayoutLoader loader(this);
            if (loader.Open(fname.GetFullPath()))
            {
                typedef std::map<int, ProjectFile*> open_files_map;
                open_files_map open_files;

                // Get all files to open and sort them according to their tab-position:
                FilesList::Node* node = m_Files.GetFirst();
                while(node)
                {
                    ProjectFile* f = node->GetData();
                    if (f->editorOpen)
                        open_files[f->editorTabPos] = f;
                    node = node->GetNext();
                }

                // Load all requested files
                std::vector<LoaderBase*> filesInMemory;
                for (open_files_map::iterator it = open_files.begin(); it != open_files.end(); ++it)
                {
                    filesInMemory.push_back(Manager::Get()->GetFileManager()->Load((*it).second->file.GetFullPath()));
                }
                // Open all requested files:
                size_t i = 0;
                for (open_files_map::iterator it = open_files.begin(); it != open_files.end(); ++it)
                {
                    cbEditor* ed = Manager::Get()->GetEditorManager()->Open(filesInMemory[i], (*it).second->file.GetFullPath(),0,(*it).second);
                    if (ed)
                        ed->SetProjectFile((*it).second);
                    ++i;
                }

                ProjectFile* f = loader.GetTopProjectFile();
                if (f)
                {
                    Manager::Get()->GetLogManager()->DebugLog(_T("Top Editor: ") + f->file.GetFullPath());
                    EditorBase* eb = Manager::Get()->GetEditorManager()->Open(f->file.GetFullPath());
                    if(eb)
                        eb->Activate();
                }
//                Manager::Get()->GetAppWindow()->Thaw();
            }
            result = true;
        }
        else
            result = false;
        Manager::Get()->GetEditorManager()->ShowNotebook();
    }
    return result;
}
« Last Edit: June 16, 2009, 06:31:05 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #16 on: June 17, 2009, 10:48:19 am »
Hi, I'm doing a simple test.
Here is a breakpoints layout file
Code
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<BreakPoints_layout_file>
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="58" />
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="74" />
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="71" />
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="68" />
<BreakPoint file="C:/test/test_for_cb_forum/main.cpp" position="66" />
</BreakPoints_layout_file>

My question is:
Is there any way I can change the absolute file name to relative file name?

Since my code is like this:

Code
// ----------------------------------------------------------------------------
bool BreakPointsLayout::Save(const wxString& filename, BreakpointsList &breakPointsList)
// ----------------------------------------------------------------------------
{
    const char* ROOT_TAG = "BreakPoints_layout_file";

    TiXmlDocument doc;
    doc.SetCondenseWhiteSpace(false);
    doc.InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
    TiXmlElement* rootnode = static_cast<TiXmlElement*>(doc.InsertEndChild(TiXmlElement(ROOT_TAG)));
    if (!rootnode)
        return false;


    for (int i = breakPointsList.GetCount() - 1; i >= 0; --i)
    {
        DebuggerBreakpoint* bp = breakPointsList[i];
        //Only save the breakpoints belong to the current project
        if (bp->userData == m_pProject)
        {
            Manager::Get()->GetLogManager()->DebugLog(F(_T("Got one")));
            TiXmlElement* node = static_cast<TiXmlElement*>(rootnode->InsertEndChild(TiXmlElement("BreakPoint")));
            node->SetAttribute("file", cbU2C(bp->filename));
            node->SetAttribute("position", bp->line);
            //RemoveBreakpoint(i, true);
        }
    }


    return cbSaveTinyXMLDocument(&doc, filename);
}

bp->filename is a full name.

But in debugger_def.h

Code
struct DebuggerBreakpoint
{
enum BreakpointType
{
bptCode = 0, ///< Normal file/line breakpoint
bptFunction, ///< Function signature breakpoint
bptData ///< Data breakpoint
};

    /** Constructor.
      * Sets default values for members.
      */
    DebuggerBreakpoint()
        : type(bptCode),
        line(0),
        index(-1),
        temporary(false),
        enabled(true),
        active(true),
        useIgnoreCount(false),
        ignoreCount(0),
        useCondition(false),
        wantsCondition(false),
        address(0),
        alreadySet(false),
        breakOnRead(false),
        breakOnWrite(true),
        userData(0)
    {}
    BreakpointType type; ///< The type of this breakpoint.
    wxString filename; ///< The filename for the breakpoint (kept as relative).

It said the file name should  keep as relative. :(


Any Comments?

Thanks
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: Some thoughts on doing breakpoints persistant
« Reply #17 on: June 17, 2009, 12:12:01 pm »
You can use the MakeRelativeTo-function of wxFileName.

The code below is not tested !

Code
    wxFileName fname;

    for (int i = breakPointsList.GetCount() - 1; i >= 0; --i)
    {
        DebuggerBreakpoint* bp = breakPointsList[i];
        //Only save the breakpoints belong to the current project
        if (bp->userData == m_pProject)
        {
            Manager::Get()->GetLogManager()->DebugLog(F(_T("Got one")));
            TiXmlElement* node = static_cast<TiXmlElement*>(rootnode->InsertEndChild(TiXmlElement("BreakPoint")));
            fname.Assign(bp->filename);
            if (fname.IsAbsolute())
            {
                fname.MakeRelativeTo(m_pProject->GetBasePath());
            }
            node->SetAttribute("file", cbU2C(fname.GetFullPath()));
            node->SetAttribute("position", bp->line);
            //RemoveBreakpoint(i, true);
        }
    }

Instead of m_pProject->GetBasePath() it might also make sense to use m_pProject->GetCommonTopLevelPath().
Depends on what the debugger-plugin wants.

No time to look into it at themoment.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #18 on: June 17, 2009, 01:13:46 pm »
Thanks for your help. Now, using the MakeRelativeTo() function ,I can save and load the saved breakpoints( simple position based breakpoints)

There is only one thing left. Since when I load the project, the BreakpointsList were successfully loaded from a projectname.bps file. But the UI has not notified. See the image below:


Breakpoints on Line 77 73 and 71 were loaded, but they were not shown on the editor. Even I add another breakpoint on line 59.

Then only way to show the breakpoints icon in the editor is "reopen the main.cpp file", see below:



So, I need a way to "notify the editor" after all the breakpoints were loaded.

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: Some thoughts on doing breakpoints persistant
« Reply #19 on: June 17, 2009, 01:23:10 pm »
Do you use AddBreakpoint from debugger-plugin or from editor ?

You can use the function from cbEditor, if the source-file is already opened and set notifyDebugger to true or use the function from debugger-plugin, if the file is not (yet) opened.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #20 on: June 17, 2009, 01:26:57 pm »
Do you use AddBreakpoint from debugger-plugin or from editor ?

You can use the function from cbEditor, if the source-file is already opened and set notifyDebugger to true or use the function from debugger-plugin, if the file is not (yet) opened.

I totally use the function AddBreakpoint from debuggergdb plugin  debuggerstate.

I will try it now, Thanks very much!
« Last Edit: June 17, 2009, 01:40:51 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #21 on: June 17, 2009, 02:10:49 pm »
Sorry, I can't figure how to check if the current file was opened in cbEditor. Can someone help me?

here is the patch.( The patch has include some patches from oBFusCATed adding a command entry)


http://sites.google.com/site/studycodeblocks/imagescb/breakpoints.patch This patch has been updated in

https://developer.berlios.de/patch/index.php?func=detailpatch&patch_id=2775&group_id=5358


Here is some explanation about this patch:

1, I add two files: breakpointslayout.cpp and breakpointslayout.h(They are similar with code in BrowserTracker plugin)

2, I add some code in doing DebuggerGDB::OnProjectOpened and DebuggerGDB::OnProjectClosed

3, When a project is opened, I will use Addbreakpoints function in debuggerstate structure.

4, when a project is closed, I just read the breakpointsList in debuggerstate, then save them to a xml file.

5, I still can't find a way to notify cbEditor, so, the breakpoints add silently. :(



By the way, I can't upload an attachment any more(upload folder is FULL), can someone help me?  :(

Thanks

Edit:

Here are some ideas:

Code
class ProjectFile  : public BlockAllocated<ProjectFile, 1000>
{
......
        /** If true, the file is open inside an editor. */
        bool editorOpen; // layout info


Can we use "ProjectFile" related method?
« Last Edit: June 20, 2009, 03:22:00 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: Some thoughts on doing breakpoints persistant
« Reply #22 on: June 17, 2009, 02:35:41 pm »
You can try:
Code
EditorBase* eb = Manager::Get()->GetEditorManager()->IsOpen(filename);
or
Code
cbEditor* ed = Manager::Get()->GetEditorManager()->IsBuiltinOpen( filename );

Both return NULL if not opened.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #23 on: June 17, 2009, 02:40:34 pm »
@jens
Thanks very much! I will try it....So excited!!!

Edit:

Problem solved!!!! Works perfectly! Just change this function to:

Code
// ----------------------------------------------------------------------------
bool BreakpointsLayout::Load(const wxString& filename, DebuggerState * pDebuggerState)
// ----------------------------------------------------------------------------
{
    TiXmlDocument doc;
    if (!TinyXML::LoadDocument(filename, &doc))
        return false;

    TiXmlElement* root;
    TiXmlElement* elem;
    wxString fname;
    ProjectFile* pf;


    root = doc.FirstChildElement("Breakpoints_layout_file");
    if (!root)
    {
        return false;
    }

    elem = root->FirstChildElement("Breakpoint");

    while (elem)
    {
        wxString fname = cbC2U(elem->Attribute("file"));
        ProjectFile* pf;
        if (fname.IsEmpty())
        {
            break;
        }
        else
            pf = m_pProject->GetFileByFilename(fname);

        wxString filenamePath = pf->file.GetFullPath();

        int line = 0;
        if (not elem->QueryIntAttribute("position", &line) == TIXML_SUCCESS)
            break;

        //Manager::Get()->GetLogManager()->DebugLog(F(_T("file='%s', line='%d'"), filenamePath.c_str(), line));


        cbEditor* ed = Manager::Get()->GetEditorManager()->IsBuiltinOpen( filenamePath );
        if (ed==NULL){
            pDebuggerState->AddBreakpoint(filenamePath,line); //add breakpoints silently
            Manager::Get()->GetLogManager()->DebugLog(F(_T("silently add bp file='%s', line='%d'"), filenamePath.c_str(), line));
        }
        else{
            ed->AddBreakpoint(line);
            Manager::Get()->GetLogManager()->DebugLog(F(_T("add bp from editor file='%s', line='%d'"), filenamePath.c_str(), line));

        }
        elem = elem->NextSiblingElement();
    }
    return true;
}//Load



« Last Edit: June 17, 2009, 02:57:17 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #24 on: June 20, 2009, 03:17:16 pm »
Hi, every one.
I have finished the finally patch.

Both watches and breakpoints can be persistent with the current project.

I add the patch here:

https://developer.berlios.de/patch/index.php?func=detailpatch&patch_id=2775&group_id=5358

Here is the example of a projectname.bps file

Code
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Debugger_layout_file>
<BreakpointsList>
<Breakpoint file="main.cpp" position="67" />
<Breakpoint file="main.cpp" position="69" />
<Breakpoint file="main.cpp" position="62" />
<Breakpoint file="main.cpp" position="58" />
</BreakpointsList>
<WatchesList>
<Watch variable="abcdefg" />
<Watch variable="llll" />
</WatchesList>
</Debugger_layout_file>


Any comments and enhancements are welcome!!

Thanks. :D
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: Some thoughts on doing breakpoints persistant
« Reply #25 on: June 20, 2009, 03:44:53 pm »
I did not (yet)test it, but what came in my mind:

what about the other attributes of the breakpoints and watches ?

The breakpoints might be data, function or conditional breakpoints (might be more possibilities, I don't know at the moment).
The same is for watches: might be watches as character, hex ..., or as array with begin and count.


Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #26 on: June 20, 2009, 03:53:29 pm »
hehe, this is the first step.

I only add codes in debuggerGDB.cpp. For "watches types" and "breakpoints types", things will be more complicated, so, they should be added to the separate cpp and h files.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Some thoughts on doing breakpoints persistant
« Reply #27 on: June 22, 2009, 06:55:10 am »
The same is for watches: might be watches as character, hex ..., or as array with begin and count.
Notice that watches can already be saved / loaded (including this info).
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistant
« Reply #28 on: June 22, 2009, 08:11:33 am »
The same is for watches: might be watches as character, hex ..., or as array with begin and count.
Notice that watches can already be saved / loaded (including this info).

Where can I find the code? (save watches with other info?)

The only code I can find is:

Code
void DebuggerTree::OnSaveWatchFile(wxCommandEvent& event)
{
    // Verify that there ARE watches to save
    size_t wc = m_Watches.GetCount();
    if (wc<1)
    {
        cbMessageBox(_("There are no watches in the list to save."),
                     _("Save Watches"), wxICON_ERROR);
        return;
    }

    wxString fname;
    wxFileDialog dlg (Manager::Get()->GetAppWindow(),
                    _T("Save debugger watch file"),
                    _T(""),
                    _T(""),
                    _T("Watch files (*.watch)|*.watch|Any file (*)|*"),
                    wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
    PlaceWindow(&dlg);
    if (dlg.ShowModal() != wxID_OK)
        return;

    wxTextFile tf(dlg.GetPath());
    bool bSuccess = false;

    // Create() will fail if the file exist -> must use Open() if file exist
    if (tf.Exists())
    {
        bSuccess = tf.Open();
        if (bSuccess) tf.Clear(); // remove old content (if any)
    }
    else
    {
        bSuccess = tf.Create();
    }

    if (bSuccess)
    {
        // iterate over each watch and write them to the file buffer
        for (size_t i = 0; i < wc; ++i)
        {
            Watch& w = m_Watches[i];
            tf.AddLine(w.keyword);
        }
        tf.Write(); // Write buffer to file
        tf.Close(); // release file handle
    }
    else
        Manager::Get()->GetLogManager()->DebugLog(_T("Error opening debugger watch file: ") + fname);
}

Seems no other info was saved :(
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5916
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Some thoughts on doing breakpoints persistent
« Reply #29 on: December 15, 2012, 07:05:51 am »
Active this thread :)
What should we do if we want to save all the user setting information in one file, those include:
The setting should be one file for each c::b project.
1, project layout (which file of the project should be opened/shown after loading the project), caret position
2, breakpoints
3, watches
4, bookmarks
5, other user setting dedicated to the project file.

We should unify the interface, but I have no idea how to implement this.

The user setting file should be saved/loaded as the same time as "bool cbProject::SaveLayout() and bool cbProject::LoadLayout()".
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.