User forums > Using Code::Blocks

c::b's macro replace map sometime doe not work correctly

<< < (2/3) > >>

ollydbg:

--- Quote from: oBFusCATed on August 29, 2012, 08:42:41 am ---So if this issue is repeatable, you can start C::B under gdb and wait.

--- End quote ---
I'm going to debug it. It looks there are some extra error like:


--- Quote ---Starting debugger: bin\gdb.exe -nx -fullname  -quiet  -args E:/code/cb/cb_trunk/src/devel/codeblocks.exe
done

--- End quote ---

I put the line "$(TARGET_COMPILER_DIR)bin\gdb.exe" as the gdb's patch, but it looks like this variable was replaced to empty string.
The luck thing is the path "E:\code\gcc\PCXMinGW463" was in PATH(I'm not sure why it was in PATH), so gdb.exe can still be found.

ollydbg:
For those would like to reproduce this bug, do the following:
1, disable CC(I think this is not CC related)
2, open the file "CodeBlocks.workspace"
3, Set the gdb executable as "$(TARGET_COMPILER_DIR)bin\gdb.exe" (no double quotes)
4, Set the "wxsmith" as the active c::b project
4a, You should check off the option "Auto-build the project if it is not up-to-date". (I suppose you have already build this target)
5, start the debugging. (you can select the option "Do *not" run the debugee", as this bug appeared in the initialization of the debugging session)
6, then read the debugger log. This is mine:

--- Quote ---Selecting target:
wxSmith
Adding source dir: E:\code\cb\cleantrunk\src\plugins\contrib\wxSmith\
Adding source dir: E:\code\cb\cleantrunk\src\plugins\contrib\wxSmith\
Adding file: ..\..\..\devel\codeblocks.exe
Changing directory to: E:/code/cb/cleantrunk/src/plugins/contrib/wxSmith/.

[debug]PATH=.;E:\code\cb\wx\wxWidgets-2.8.12\lib\gcc_dll;E:\code\cb\wx\wxWidgets-2.8.12\lib\gcc_dll\mswu;E:\code\cb\cleantrunk\src\devel;E:\code\cb\cleantrunk\src\base\tinyxml;E:\code\gcc\PCXMinGW463\bin;E:\code\gcc\PCXMinGW463;.;C:\Program Files\Intel\WiFi\bin;E:\code\common_bin;E:\code\shortcut
[debug]Command-line: bin\gdb.exe -nx -fullname  -quiet  -args ../../../devel/codeblocks.exe
[debug]Working dir : E:\code\cb\cleantrunk\src\plugins\contrib\wxSmith

Starting debugger: bin\gdb.exe -nx -fullname  -quiet  -args ../../../devel/codeblocks.exe
done

[debug]> set prompt >>>>>>cb_gdb:

Registered new type: wxString
Registered new type: STL String
Registered new type: STL Vector
Setting breakpoints

[debug]Reading symbols from E:\code\cb\cleantrunk\src\devel\codeblocks.exe...done.
[debug](gdb) >>>>>>cb_gdb:
[debug]> show version
[debug]GNU gdb (GDB) 7.5.50.20120823-cvs
[debug]Copyright (C) 2012 Free Software Foundation, Inc.
[debug]License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
[debug]This is free software: you are free to change and redistribute it.
[debug]There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
[debug]and "show warranty" for details.
[debug]This GDB was configured as "mingw32".
[debug]For bug reporting instructions, please see:
[debug]<http://www.gnu.org/software/gdb/bugs/>.
[debug]>>>>>>cb_gdb:
[debug]> set confirm off

Debugger name and version: GNU gdb (GDB) 7.5.50.20120823-cvs

[debug]>>>>>>cb_gdb:
[debug]> set width 0
[debug]>>>>>>cb_gdb:
[debug]> set height 0
[debug]>>>>>>cb_gdb:
[debug]> set breakpoint pending on
[debug]>>>>>>cb_gdb:
[debug]> set print asm-demangle on
[debug]>>>>>>cb_gdb:
[debug]> set unwindonsignal on
[debug]>>>>>>cb_gdb:
[debug]> set print elements 0
[debug]>>>>>>cb_gdb:
[debug]> set disassembly-flavor att
[debug]>>>>>>cb_gdb:
[debug]> catch throw
[debug]Catchpoint 1 (throw)
[debug]>>>>>>cb_gdb:
[debug]> source E:\code\cb\cb_trunk\src\devel\share\codeblocks/scripts/stl-views-1.0.3.gdb
[debug]>>>>>>cb_gdb:
[debug]> source bin\my.gdb
[debug]bin\my.gdb: No such file or directory.
[debug]>>>>>>cb_gdb:
[debug]> directory E:/code/cb/cleantrunk/src/plugins/contrib/wxSmith/
[debug]Source directories searched: E:/code/cb/cleantrunk/src/plugins/contrib/wxSmith;$cdir;$cwd
[debug]>>>>>>cb_gdb:
[debug]> set args --debug-log --multiple-instance -na -ns -nd -p=debugCC
[debug]>>>>>>cb_gdb:

--- End quote ---

Look:

--- Quote ---bin\gdb.exe

--- End quote ---

It looks like if I set the active project as "Code::Blocks wx2.8.x", I don't have such issue. So, I guess this is caused by something related to "switch the project".

EDIT:
When debugging, I found that in the code:

--- Code: ---void MacrosManager::ReplaceMacros(wxString& buffer, ProjectBuildTarget* target, bool subrequest)
{
    if (buffer.IsEmpty())
        return;

    static const wxString delim(_T("$%["));
    if ( buffer.find_first_of(delim) == wxString::npos )
        return;

    cbProject* project = target
                        ? target->GetParentProject()
                        : Manager::Get()->GetProjectManager()->GetActiveProject();
    EditorBase* editor = Manager::Get()->GetEditorManager()->GetActiveEditor();

    if (!target)
    {
        if (project)
        {
            // use the currently compiling target
            target = project->GetCurrentlyCompilingTarget();
            // if none,
            if (!target)
                // use the last known active target
                target = project->GetBuildTarget(project->GetActiveBuildTarget());
        }
    }
    if (project != m_LastProject || target != m_LastTarget || (editor && (editor->GetFilename() != m_ActiveEditorFilename)) )
        RecalcVars(project, editor, target);

--- End code ---
The "target" value is 0. This may cause the issue.

Because the variable $(TARGET_COMPILER_DIR) is only set when "target" is valid, see below:

--- Code: ---    if (target)
    {
        const StringHash& v = target->GetAllVars();
        for (StringHash::const_iterator it = v.begin(); it != v.end(); ++it)
            m_Macros[it->first.Upper()] = it->second;

        if (Compiler* c = CompilerFactory::GetCompiler(target->GetCompilerID()))
        {
            m_Macros[_T("TARGET_CC")]           = c->GetPrograms().C;
            m_Macros[_T("TARGET_CPP")]          = c->GetPrograms().CPP;
            m_Macros[_T("TARGET_LD")]           = c->GetPrograms().LD;
            m_Macros[_T("TARGET_LIB")]          = c->GetPrograms().LIB;
            wxFileName MasterPath;
            MasterPath.SetPath(c->GetMasterPath(), wxPATH_NATIVE);
            m_Macros[_T("TARGET_COMPILER_DIR")] = MasterPath.GetPathWithSep(wxPATH_NATIVE);
        }
        m_Macros[_T("TARGET_OBJECT_DIR")] = target->GetObjectOutput();
    }

--- End code ---

ollydbg:
Look at the code:

--- Code: ---void MacrosManager::ReplaceMacros(wxString& buffer, ProjectBuildTarget* target, bool subrequest)
{
    if (buffer.IsEmpty())
        return;

    static const wxString delim(_T("$%["));
    if ( buffer.find_first_of(delim) == wxString::npos )
        return;

    cbProject* project = target
                        ? target->GetParentProject()
                        : Manager::Get()->GetProjectManager()->GetActiveProject();
    EditorBase* editor = Manager::Get()->GetEditorManager()->GetActiveEditor();

    if (!target)
    {
        if (project)
        {
            // use the currently compiling target
            target = project->GetCurrentlyCompilingTarget();
            // if none,
            if (!target)
                // use the last known active target
                target = project->GetBuildTarget(project->GetActiveBuildTarget());
        }
    }
    if (project != m_LastProject || target != m_LastTarget || (editor && (editor->GetFilename() != m_ActiveEditorFilename)) )
        RecalcVars(project, editor, target);

    wxString search;
    wxString replace;

--- End code ---

When I debug this code, I found that

--- Code: ---target = project->GetBuildTarget(project->GetActiveBuildTarget());
--- End code ---
will still set the target to 0.

Internally, it call

--- Code: ---int cbProject::IndexOfBuildTargetName(const wxString& targetName) const
{
    for (unsigned int i = 0; i < m_Targets.GetCount(); ++i)
    {
        ProjectBuildTarget* target = m_Targets[i];
        if (target->GetTitle().Matches(targetName))
            return i;
    }
    return -1;
}
--- End code ---
But the "targetName" passed in is "All", and it does not match any target name of wxsmith.cbp, so it return -1, and the final "target" is still 0.

Now, we go to the line:

--- Code: ---    if (project != m_LastProject || target != m_LastTarget || (editor && (editor->GetFilename() != m_ActiveEditorFilename)) )
        RecalcVars(project, editor, target);

--- End code ---
But unluckily, this if condition is false. m_LastTarget is 0, and m_LastProject is the same as project, so there is no chance to call RecalcVars().

This cause the issue.

MortenMacFly:
...but then precisely it is the correct thing to do. As targets can be assigned to different compilers and therefore different debuggers, virtual targets have no specified value.

The only thing you could do is to record when the active target has changes and issue the RecalcVars then.

ollydbg:

--- Quote from: MortenMacFly on August 29, 2012, 02:26:37 pm ---...but then precisely it is the correct thing to do. As targets can be assigned to different compilers and therefore different debuggers, virtual targets have no specified value.

The only thing you could do is to record when the active target has changes and issue the RecalcVars then.

--- End quote ---
I review the code a little, and I see that if the active target name is "All", which is not a valid build target, the debugger will open a dialog to let the user select one, see the code:

--- Code: ---int DebuggerGDB::DoDebug(bool breakOnEntry)
{
    // set this to true before every error exit point in this function
    m_Canceled = false;
    ProjectManager* prjMan = Manager::Get()->GetProjectManager();

    // select the build target to debug
    ProjectBuildTarget* target = 0;
    Compiler* actualCompiler = 0;
    if (m_PidToAttach == 0)
    {
        Log(_("Selecting target: "));
        if (!m_pProject->BuildTargetValid(m_ActiveBuildTarget, false))
        {
            int tgtIdx = m_pProject->SelectTarget();
            if (tgtIdx == -1)
            {
                Log(_("canceled"));
                m_Canceled = true;
                return 3;
            }
            target = m_pProject->GetBuildTarget(tgtIdx);
            m_ActiveBuildTarget = target->GetTitle();
        }
        else
            target = m_pProject->GetBuildTarget(m_ActiveBuildTarget);

--- End code ---
So, the debugger plugin know which target it will going to debug.

But what about Macromanager? it was just blind. E.g.:

--- Code: ---wxString DebuggerConfiguration::GetDebuggerExecutable(bool expandMacro)
{
    wxString result = m_config.Read(wxT("executable_path"), wxEmptyString);
    if (expandMacro)
        Manager::Get()->GetMacrosManager()->ReplaceEnvVars(result);
    return !result.empty() ? result : cbDetectDebuggerExecutable(wxT("gdb"));
}

--- End code ---
This code, the debugger plugin try to prepare the full path of gdb.exe, it directly call ReplaceEnvVars(result), which is:

--- Code: ---void ReplaceEnvVars(wxString& buffer) { ReplaceMacros(buffer); }

--- End code ---

Then:

--- Code: ---void MacrosManager::ReplaceMacros(wxString& buffer, ProjectBuildTarget* target, bool subrequest)
{
    if (buffer.IsEmpty())
        return;

    static const wxString delim(_T("$%["));
    if ( buffer.find_first_of(delim) == wxString::npos )
        return;

    cbProject* project = target
                        ? target->GetParentProject()
                        : Manager::Get()->GetProjectManager()->GetActiveProject();
    EditorBase* editor = Manager::Get()->GetEditorManager()->GetActiveEditor();

    if (!target)
    {
        if (project)
        {
            // use the currently compiling target
            target = project->GetCurrentlyCompilingTarget();
            // if none,
            if (!target)
                // use the last known active target
                target = project->GetBuildTarget(project->GetActiveBuildTarget());
        }
    }
    if (project != m_LastProject || target != m_LastTarget || (editor && (editor->GetFilename() != m_ActiveEditorFilename)) )
        RecalcVars(project, editor, target);

--- End code ---

NOTE: when call the function: ReplaceMacros(), the default argument target = 0 is used, which try to use the "GetActiveBuildTarget()", but as we know, currently, the activeTarget name is "All", which is not a valid build target, so the variable "target" is still ZERO.

Thus, even the function RecalcVars() is called, the piece of code in the function body still has no chance to run.

--- Code: ---    if (target)
    {
        const StringHash& v = target->GetAllVars();
        for (StringHash::const_iterator it = v.begin(); it != v.end(); ++it)
            m_Macros[it->first.Upper()] = it->second;

        if (Compiler* c = CompilerFactory::GetCompiler(target->GetCompilerID()))
        {
            m_Macros[_T("TARGET_CC")]           = c->GetPrograms().C;
            m_Macros[_T("TARGET_CPP")]          = c->GetPrograms().CPP;
            m_Macros[_T("TARGET_LD")]           = c->GetPrograms().LD;
            m_Macros[_T("TARGET_LIB")]          = c->GetPrograms().LIB;
            wxFileName MasterPath;
            MasterPath.SetPath(c->GetMasterPath(), wxPATH_NATIVE);
            m_Macros[_T("TARGET_COMPILER_DIR")] = MasterPath.GetPathWithSep(wxPATH_NATIVE);
        }
        m_Macros[_T("TARGET_OBJECT_DIR")] = target->GetObjectOutput();
    }

--- End code ---
So: ("TARGET_OBJECT_DIR") is still empty string.

The simple solution I thought is:
1, when the debugger plugin started debugging, it can temporary switch the target to a real valid target name, e.g. Switch "All" to "src".
2, when it finish debugging, do switching back.

This way, the ReplaceMacros() function can get the real valid target, and it should solve the bug.

What's you comments about this?

EDIT:
Maybe, we can let the debugger plugin to temporary to select this one, and select to none after debugging......

--- Code: ---void cbProject::SetCurrentlyCompilingTarget(ProjectBuildTarget* bt)
{
    m_CurrentlyCompilingTarget = bt;
}

--- End code ---
In the case that I open a workspace, and I don't want to build anything, and just start debugging.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version