Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
flatpak-qt-creator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
52915776
Commit
52915776
authored
Apr 22, 2009
by
Friedemann Kleint
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make CDB load custom dumpers.
Load in a 'well-defined' (temporary) breakpoint at main().
parent
ef8e69d9
Changes
14
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
593 additions
and
156 deletions
+593
-156
share/qtcreator/gdbmacros/gdbmacros.cpp
share/qtcreator/gdbmacros/gdbmacros.cpp
+4
-0
src/plugins/debugger/cdb/cdbbreakpoint.cpp
src/plugins/debugger/cdb/cdbbreakpoint.cpp
+20
-4
src/plugins/debugger/cdb/cdbbreakpoint.h
src/plugins/debugger/cdb/cdbbreakpoint.h
+1
-0
src/plugins/debugger/cdb/cdbdebugengine.cpp
src/plugins/debugger/cdb/cdbdebugengine.cpp
+83
-21
src/plugins/debugger/cdb/cdbdebugengine_p.h
src/plugins/debugger/cdb/cdbdebugengine_p.h
+6
-1
src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
+6
-14
src/plugins/debugger/cdb/cdbdumperhelper.cpp
src/plugins/debugger/cdb/cdbdumperhelper.cpp
+273
-69
src/plugins/debugger/cdb/cdbdumperhelper.h
src/plugins/debugger/cdb/cdbdumperhelper.h
+41
-19
src/plugins/debugger/cdb/cdbmodules.cpp
src/plugins/debugger/cdb/cdbmodules.cpp
+83
-18
src/plugins/debugger/cdb/cdbmodules.h
src/plugins/debugger/cdb/cdbmodules.h
+7
-3
src/plugins/debugger/debuggermanager.h
src/plugins/debugger/debuggermanager.h
+10
-4
src/plugins/debugger/gdbengine.cpp
src/plugins/debugger/gdbengine.cpp
+3
-3
src/plugins/debugger/watchutils.cpp
src/plugins/debugger/watchutils.cpp
+53
-0
src/plugins/debugger/watchutils.h
src/plugins/debugger/watchutils.h
+3
-0
No files found.
share/qtcreator/gdbmacros/gdbmacros.cpp
View file @
52915776
...
...
@@ -2529,7 +2529,11 @@ void *qDumpObjectData440(
int
protocolVersion
,
int
token
,
void
*
data
,
#ifdef Q_CC_MSVC // CDB cannot handle boolean parameters
int
dumpChildren
,
#else
bool
dumpChildren
,
#endif
int
extraInt0
,
int
extraInt1
,
int
extraInt2
,
...
...
src/plugins/debugger/cdb/cdbbreakpoint.cpp
View file @
52915776
...
...
@@ -48,7 +48,8 @@ static const char sourceFileQuoteC = '`';
CDBBreakPoint
::
CDBBreakPoint
()
:
ignoreCount
(
0
),
lineNumber
(
-
1
)
lineNumber
(
-
1
),
oneShot
(
false
)
{
}
...
...
@@ -57,7 +58,8 @@ CDBBreakPoint::CDBBreakPoint(const BreakpointData &bpd) :
condition
(
bpd
.
condition
),
ignoreCount
(
0
),
funcName
(
bpd
.
funcName
),
lineNumber
(
-
1
)
lineNumber
(
-
1
),
oneShot
(
false
)
{
if
(
!
bpd
.
ignoreCount
.
isEmpty
())
ignoreCount
=
bpd
.
ignoreCount
.
toInt
();
...
...
@@ -75,6 +77,10 @@ int CDBBreakPoint::compare(const CDBBreakPoint& rhs) const
return
1
;
if
(
lineNumber
<
rhs
.
lineNumber
)
return
-
1
;
if
(
oneShot
&&
!
rhs
.
oneShot
)
return
1
;
if
(
!
oneShot
&&
rhs
.
oneShot
)
return
-
1
;
if
(
const
int
fileCmp
=
fileName
.
compare
(
rhs
.
fileName
))
return
fileCmp
;
if
(
const
int
funcCmp
=
funcName
.
compare
(
rhs
.
funcName
))
...
...
@@ -87,6 +93,7 @@ int CDBBreakPoint::compare(const CDBBreakPoint& rhs) const
void
CDBBreakPoint
::
clear
()
{
ignoreCount
=
0
;
oneShot
=
false
;
clearExpressionData
();
}
...
...
@@ -110,6 +117,8 @@ QDebug operator<<(QDebug dbg, const CDBBreakPoint &bp)
nsp
<<
" condition='"
<<
bp
.
condition
<<
'\''
;
if
(
bp
.
ignoreCount
)
nsp
<<
" ignoreCount="
<<
bp
.
ignoreCount
;
if
(
bp
.
oneShot
)
nsp
<<
" oneShot"
;
return
dbg
;
}
...
...
@@ -144,7 +153,10 @@ bool CDBBreakPoint::apply(CIDebugBreakpoint *ibp, QString *errorMessage) const
}
// Pass Count is ignoreCount + 1
ibp
->
SetPassCount
(
ignoreCount
+
1u
);
ibp
->
AddFlags
(
DEBUG_BREAKPOINT_ENABLED
);
ULONG
flags
=
DEBUG_BREAKPOINT_ENABLED
;
if
(
oneShot
)
flags
|=
DEBUG_BREAKPOINT_ONE_SHOT
;
ibp
->
AddFlags
(
flags
);
return
true
;
}
...
...
@@ -190,6 +202,10 @@ bool CDBBreakPoint::retrieve(CIDebugBreakpoint *ibp, QString *errorMessage)
ibp
->
GetPassCount
(
&
ignoreCount
);
if
(
ignoreCount
)
ignoreCount
--
;
ULONG
flags
=
0
;
ibp
->
GetFlags
(
&
flags
);
if
(
flags
&
DEBUG_BREAKPOINT_ONE_SHOT
)
oneShot
=
true
;
const
QString
expr
=
QString
::
fromUtf16
(
wszBuf
);
if
(
!
parseExpression
(
expr
))
{
*
errorMessage
=
QString
::
fromLatin1
(
"Parsing of '%1' failed."
).
arg
(
expr
);
...
...
src/plugins/debugger/cdb/cdbbreakpoint.h
View file @
52915776
...
...
@@ -83,6 +83,7 @@ struct CDBBreakPoint
unsigned
long
ignoreCount
;
// ignore count associated with breakpoint
int
lineNumber
;
// line in source file
QString
funcName
;
// name of containing function
bool
oneShot
;
};
QDebug
operator
<<
(
QDebug
,
const
CDBBreakPoint
&
bp
);
...
...
src/plugins/debugger/cdb/cdbdebugengine.cpp
View file @
52915776
...
...
@@ -53,6 +53,7 @@
#include <utils/consoleprocess.h>
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QTimerEvent>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
...
...
@@ -102,7 +103,7 @@ QString msgDebugEngineComResult(HRESULT hr)
return
QLatin1String
(
"ERROR_ACCESS_DENIED"
);;
if
(
hr
==
HRESULT_FROM_NT
(
STATUS_CONTROL_C_EXIT
))
return
QLatin1String
(
"STATUS_CONTROL_C_EXIT"
);
return
Core
::
Utils
::
winErrorMessage
(
HRESULT_CODE
(
hr
));
return
QLatin1String
(
"E_FAIL "
)
+
Core
::
Utils
::
winErrorMessage
(
HRESULT_CODE
(
hr
));
}
static
QString
msgStackIndexOutOfRange
(
int
idx
,
int
size
)
...
...
@@ -450,14 +451,16 @@ void CdbDebugEnginePrivate::clearDisplay()
bool
CdbDebugEngine
::
startDebugger
()
{
m_d
->
clearDisplay
();
const
DebuggerStartMode
mode
=
m_d
->
m_debuggerManager
->
startMode
();
// Figure out dumper. @TODO: same in gdb...
bool
dumperEnabled
=
false
&&
m_d
->
m_debuggerManager
->
qtDumperLibraryEnabled
();
const
QString
dumperLibName
=
QDir
::
toNativeSeparators
(
m_d
->
m_debuggerManager
->
qtDumperLibraryName
());
const
QString
dumperLibName
=
QDir
::
toNativeSeparators
(
m_d
->
m_debuggerManagerAccess
->
qtDumperLibraryName
());
bool
dumperEnabled
=
mode
!=
AttachCore
&&
!
dumperLibName
.
isEmpty
()
&&
m_d
->
m_debuggerManagerAccess
->
qtDumperLibraryEnabled
();
if
(
dumperEnabled
)
{
const
QFileInfo
fi
(
dumperLibName
);
if
(
!
fi
.
isFile
())
{
const
QString
msg
=
tr
(
"The dumper library '%1' does not exist."
).
arg
(
dumperLibName
);
m_d
->
m_debuggerManager
->
showQtDumperLibraryWarning
(
msg
);
m_d
->
m_debuggerManager
Access
->
showQtDumperLibraryWarning
(
msg
);
dumperEnabled
=
false
;
}
}
...
...
@@ -466,7 +469,6 @@ bool CdbDebugEngine::startDebugger()
QString
errorMessage
;
bool
rc
=
false
;
m_d
->
clearForRun
();
const
DebuggerStartMode
mode
=
m_d
->
m_debuggerManager
->
startMode
();
switch
(
mode
)
{
case
AttachExternal
:
rc
=
startAttachDebugger
(
m_d
->
m_debuggerManager
->
m_attachedPID
,
&
errorMessage
);
...
...
@@ -561,6 +563,52 @@ bool CdbDebugEngine::startDebuggerWithExecutable(DebuggerStartMode sm, QString *
return
true
;
}
// check for a breakpoint at 'main()'
static
inline
bool
hasBreakPointAtMain
(
const
BreakHandler
*
bp
)
{
if
(
const
int
count
=
bp
->
size
())
{
// check all variations, resolved or not
const
QString
main
=
QLatin1String
(
"main"
);
const
QString
qMain
=
QLatin1String
(
"qMain"
);
const
QString
moduleMainPattern
=
QLatin1String
(
"!main"
);
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
const
QString
&
function
=
bp
->
at
(
i
)
->
funcName
;
if
(
function
==
main
||
function
==
qMain
||
function
.
endsWith
(
moduleMainPattern
))
return
true
;
}
}
return
false
;
}
void
CdbDebugEnginePrivate
::
processCreatedAttached
(
ULONG64
processHandle
,
ULONG64
initialThreadHandle
)
{
setDebuggeeHandles
(
reinterpret_cast
<
HANDLE
>
(
processHandle
),
reinterpret_cast
<
HANDLE
>
(
initialThreadHandle
));
m_debuggerManagerAccess
->
notifyInferiorRunning
();
ULONG
currentThreadId
;
if
(
SUCCEEDED
(
m_cif
.
debugSystemObjects
->
GetThreadIdByHandle
(
initialThreadHandle
,
&
currentThreadId
)))
{
m_currentThreadId
=
currentThreadId
;
}
else
{
m_currentThreadId
=
0
;
}
// Set initial breakpoints
if
(
m_debuggerManagerAccess
->
breakHandler
()
->
hasPendingBreakpoints
())
m_engine
->
attemptBreakpointSynchronization
();
// At any event, we want a temporary breakpoint at main() to load
// the dumpers.
if
(
m_dumper
.
state
()
==
CdbDumperHelper
::
NotLoaded
)
{
if
(
!
hasBreakPointAtMain
(
m_debuggerManagerAccess
->
breakHandler
()))
{
CDBBreakPoint
mainBP
;
// Do not resolve at this point in the rare event someone
// has main in a module
mainBP
.
funcName
=
QLatin1String
(
"main"
);
mainBP
.
oneShot
=
true
;
QString
errorMessage
;
if
(
!
mainBP
.
add
(
m_cif
.
debugControl
,
&
errorMessage
))
m_debuggerManagerAccess
->
showQtDumperLibraryWarning
(
errorMessage
);
}
}
}
void
CdbDebugEngine
::
processTerminated
(
unsigned
long
exitCode
)
{
if
(
debugCDB
)
...
...
@@ -859,13 +907,18 @@ void CdbDebugEngine::continueInferior()
}
// Continue process without notifications
bool
CdbDebugEnginePrivate
::
continueInferiorProcess
(
QString
*
errorMessage
)
bool
CdbDebugEnginePrivate
::
continueInferiorProcess
(
QString
*
errorMessage
Ptr
/* = 0 */
)
{
if
(
debugCDB
)
qDebug
()
<<
Q_FUNC_INFO
;
const
HRESULT
hr
=
m_cif
.
debugControl
->
SetExecutionStatus
(
DEBUG_STATUS_GO
);
if
(
FAILED
(
hr
))
{
*
errorMessage
=
msgComFailed
(
"SetExecutionStatus"
,
hr
);
const
QString
errorMessage
=
msgComFailed
(
"SetExecutionStatus"
,
hr
);
if
(
errorMessagePtr
)
{
*
errorMessagePtr
=
errorMessage
;
}
else
{
qWarning
(
"continueInferiorProcess: %s
\n
"
,
qPrintable
(
errorMessage
));
}
return
false
;
}
return
true
;
...
...
@@ -992,10 +1045,10 @@ void CdbDebugEngine::executeDebuggerCommand(const QString &command)
bool
CdbDebugEnginePrivate
::
executeDebuggerCommand
(
CIDebugControl
*
ctrl
,
const
QString
&
command
,
QString
*
errorMessage
)
{
if
(
debugCDB
)
qDebug
()
<<
Q_FUNC_INFO
<<
command
;
// output to all clients, else we do not see anything
const
HRESULT
hr
=
ctrl
->
ExecuteWide
(
DEBUG_OUTCTL_ALL_CLIENTS
,
command
.
utf16
(),
0
);
if
(
debugCDB
)
qDebug
()
<<
"executeDebuggerCommand"
<<
command
<<
SUCCEEDED
(
hr
);
if
(
FAILED
(
hr
))
{
*
errorMessage
=
QString
::
fromLatin1
(
"Unable to execute '%1': %2"
).
arg
(
command
,
msgDebugEngineComResult
(
hr
));
...
...
@@ -1300,10 +1353,19 @@ void CdbDebugEnginePrivate::handleDebugEvent()
switch
(
mode
)
{
case
BreakEventHandle
:
case
BreakEventMain
:
if
(
mode
==
BreakEventMain
)
m_dumper
.
load
(
m_debuggerManager
,
m_debuggerManagerAccess
);
m_debuggerManagerAccess
->
notifyInferiorStopped
();
updateThreadList
();
updateStackTrace
();
break
;
case
BreakEventMainLoadDumpers
:
// Temp stop to load dumpers
m_dumper
.
load
(
m_debuggerManager
,
m_debuggerManagerAccess
);
m_engine
->
startWatchTimer
();
continueInferiorProcess
();
break
;
case
BreakEventIgnoreOnce
:
m_engine
->
startWatchTimer
();
break
;
...
...
@@ -1417,17 +1479,6 @@ void CdbDebugEnginePrivate::handleModuleLoad(const QString &name)
if
(
debugCDB
>
2
)
qDebug
()
<<
Q_FUNC_INFO
<<
"
\n
"
<<
name
;
updateModules
();
// Call the dumper helper hook and notify about progress.
bool
ignoreNextBreakPoint
;
if
(
m_dumper
.
moduleLoadHook
(
name
,
&
ignoreNextBreakPoint
))
{
if
(
m_dumper
.
state
()
==
CdbDumperHelper
::
Loaded
)
m_debuggerManagerAccess
->
showDebuggerOutput
(
QLatin1String
(
dumperPrefixC
),
QString
::
fromLatin1
(
"Dumpers loaded: %1"
).
arg
(
m_dumper
.
library
()));
}
else
{
m_debuggerManager
->
showQtDumperLibraryWarning
(
m_dumper
.
errorMessage
());
m_debuggerManagerAccess
->
showDebuggerOutput
(
QLatin1String
(
dumperPrefixC
),
QString
::
fromLatin1
(
"Unable to load dumpers: %1"
).
arg
(
m_dumper
.
errorMessage
()));
}
if
(
ignoreNextBreakPoint
)
m_breakEventMode
=
BreakEventIgnoreOnce
;
}
void
CdbDebugEnginePrivate
::
handleBreakpointEvent
(
PDEBUG_BREAKPOINT2
pBP
)
...
...
@@ -1435,6 +1486,17 @@ void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP)
Q_UNUSED
(
pBP
)
if
(
debugCDB
)
qDebug
()
<<
Q_FUNC_INFO
;
// Did we hit main() and did the user want that or is that just
// our internal BP to load the dumpers?
QString
errorMessage
;
CDBBreakPoint
bp
;
if
(
bp
.
retrieve
(
pBP
,
&
errorMessage
)
&&
!
bp
.
funcName
.
isEmpty
())
{
if
(
bp
.
funcName
==
QLatin1String
(
"main"
)
||
bp
.
funcName
.
endsWith
(
QLatin1String
(
"!main"
)))
{
m_breakEventMode
=
bp
.
oneShot
?
BreakEventMainLoadDumpers
:
BreakEventMain
;
}
if
(
debugCDB
)
qDebug
()
<<
bp
<<
" b-mode="
<<
m_breakEventMode
;
}
}
void
CdbDebugEngine
::
reloadSourceFiles
()
...
...
src/plugins/debugger/cdb/cdbdebugengine_p.h
View file @
52915776
...
...
@@ -98,6 +98,10 @@ struct CdbDebugEnginePrivate
enum
HandleBreakEventMode
{
// Special modes for break event handler.
BreakEventHandle
,
BreakEventIgnoreOnce
,
// We hit main (and the user intended it)
BreakEventMain
,
// We hit main (and the user did not intend it, just load dumpers)
BreakEventMainLoadDumpers
,
BreakEventSyncBreakPoints
,
};
...
...
@@ -107,6 +111,7 @@ struct CdbDebugEnginePrivate
bool
init
(
QString
*
errorMessage
);
~
CdbDebugEnginePrivate
();
void
processCreatedAttached
(
ULONG64
processHandle
,
ULONG64
initialThreadHandle
);
void
setDebuggeeHandles
(
HANDLE
hDebuggeeProcess
,
HANDLE
hDebuggeeThread
);
bool
isDebuggeeRunning
()
const
{
return
m_watchTimer
!=
-
1
;
}
...
...
@@ -125,7 +130,7 @@ struct CdbDebugEnginePrivate
bool
interruptInterferiorProcess
(
QString
*
errorMessage
);
bool
continueInferiorProcess
(
QString
*
errorMessage
);
bool
continueInferiorProcess
(
QString
*
errorMessage
=
0
);
bool
continueInferior
(
QString
*
errorMessage
);
bool
attemptBreakpointSynchronization
(
QString
*
errorMessage
);
...
...
src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
View file @
52915776
...
...
@@ -247,7 +247,8 @@ void formatException(const EXCEPTION_RECORD64 *e, QTextStream &str)
break
;
case
EXCEPTION_ACCESS_VIOLATION
:
{
const
bool
writeOperation
=
e
->
ExceptionInformation
[
0
];
str
<<
(
writeOperation
?
"write access violation"
:
"read access violation"
);
str
<<
(
writeOperation
?
"write"
:
"read"
)
<<
" access violation at: 0x"
<<
e
->
ExceptionInformation
[
1
];
}
break
;
case
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
...
...
@@ -344,6 +345,8 @@ STDMETHODIMP CdbDebugEventCallback::Exception(
QTextStream
str
(
&
msg
);
formatException
(
Exception
,
m_pEngine
->
m_d
->
m_cif
,
str
);
}
if
(
debugCDB
)
qDebug
()
<<
Q_FUNC_INFO
<<
'\n'
<<
msg
;
m_pEngine
->
m_d
->
m_debuggerManagerAccess
->
showApplicationOutput
(
msg
);
return
S_OK
;
}
...
...
@@ -402,18 +405,7 @@ STDMETHODIMP CdbDebugEventCallback::CreateProcess(
Q_UNUSED
(
StartOffset
)
if
(
debugCDB
)
qDebug
()
<<
Q_FUNC_INFO
<<
ModuleName
;
m_pEngine
->
m_d
->
setDebuggeeHandles
(
reinterpret_cast
<
HANDLE
>
(
Handle
),
reinterpret_cast
<
HANDLE
>
(
InitialThreadHandle
));
m_pEngine
->
m_d
->
m_debuggerManagerAccess
->
notifyInferiorRunning
();
ULONG
currentThreadId
;
if
(
SUCCEEDED
(
m_pEngine
->
m_d
->
m_cif
.
debugSystemObjects
->
GetThreadIdByHandle
(
InitialThreadHandle
,
&
currentThreadId
)))
m_pEngine
->
m_d
->
m_currentThreadId
=
currentThreadId
;
else
m_pEngine
->
m_d
->
m_currentThreadId
=
0
;
// Set initial breakpoints
if
(
m_pEngine
->
m_d
->
m_debuggerManagerAccess
->
breakHandler
()
->
hasPendingBreakpoints
())
m_pEngine
->
attemptBreakpointSynchronization
();
m_pEngine
->
m_d
->
processCreatedAttached
(
Handle
,
InitialThreadHandle
);
return
S_OK
;
}
...
...
src/plugins/debugger/cdb/cdbdumperhelper.cpp
View file @
52915776
This diff is collapsed.
Click to expand it.
src/plugins/debugger/cdb/cdbdumperhelper.h
View file @
52915776
...
...
@@ -30,55 +30,77 @@
#ifndef CDBDUMPERHELPER_H
#define CDBDUMPERHELPER_H
#include <QtCore/QString>
#include <QtCore/QString
List
>
namespace
Debugger
{
namespace
Internal
{
struct
CdbComInterfaces
;
// For code clarity, all the stuff related to custom dumpers
// goes here.
// "Custom dumper" is a library compiled against the current
// Qt containing functions to evaluate values of Qt classes
// (such as QString, taking pointers to their addresses).
// The library must be loaded into the debuggee.
class
IDebuggerManagerAccessForEngines
;
class
DebuggerManager
;
/* For code clarity, all the stuff related to custom dumpers
* goes here.
* "Custom dumper" is a library compiled against the current
* Qt containing functions to evaluate values of Qt classes
* (such as QString, taking pointers to their addresses).
* The library must be loaded into the debuggee.
* Loading the dumpers requires making the debuggee call functions
* (LoadLibrary() and the dumper functions). This only works if the
* debuggee is in a 'well-defined' breakpoint state (such as at 'main()').
* Calling the load functions from an IDebugEvent callback causes
* WaitForEvent() to fail with unknown errors. Calling the load functions from an
* non 'well-defined' (arbitrary) breakpoint state will cause LoadLibrary
* to trigger an access violations.
* Currently, we call the load function when stopping at 'main()' for which
* we set a temporary break point if the user does not want to stop there. */
class
CdbDumperHelper
{
Q_DISABLE_COPY
(
CdbDumperHelper
)
public:
enum
State
{
Disabled
,
NotLoaded
,
Loading
,
Loaded
,
Failed
};
explicit
CdbDumperHelper
(
CdbComInterfaces
*
cif
);
~
CdbDumperHelper
();
State
state
()
const
{
return
m_state
;
}
operator
bool
()
const
{
return
m_state
==
Loaded
;
}
// Call before starting the debugger
void
reset
(
const
QString
&
library
,
bool
enabled
);
// Call from the module loaded event handler.
// It will load the dumper library and resolve the required symbols
// when appropriate.
bool
moduleLoadHook
(
const
QString
&
name
,
bool
*
ignoreNextBreakPoint
);
State
state
()
const
{
return
m_state
;
}
QString
errorMessage
()
const
{
return
m_errorMessage
;
}
QString
library
()
const
{
return
m_library
;
}
// Call in a temporary breakpoint state to actually load.
void
load
(
DebuggerManager
*
manager
,
IDebuggerManagerAccessForEngines
*
access
);
private:
struct
DumperInputParameters
;
void
clearBuffer
();
bool
resolveSymbols
(
QString
*
errorMessage
);
bool
getKnownTypes
(
QString
*
errorMessage
);
bool
callDumper
(
const
DumperInputParameters
&
p
,
QByteArray
*
output
,
QString
*
errorMessage
);
inline
QString
statusMessage
()
const
;
State
m_state
;
CdbComInterfaces
*
m_cif
;
QString
m_library
;
QString
m_dumpObjectSymbol
;
QString
m_errorMessage
;
QStringList
m_knownTypes
;
QString
m_qtVersion
;
QString
m_qtNamespace
;
quint64
m_inBufferAddress
;
unsigned
long
m_inBufferSize
;
quint64
m_outBufferAddress
;
unsigned
long
m_outBufferSize
;
char
*
m_buffer
;
};
}
// namespace Internal
...
...
src/plugins/debugger/cdb/cdbmodules.cpp
View file @
52915776
...
...
@@ -32,25 +32,47 @@
#include "cdbdebugengine_p.h"
#include <QtCore/QFileInfo>
#include <QtCore/QRegExp>
namespace
Debugger
{
namespace
Internal
{
bool
getModuleList
(
CIDebugSymbols
*
syms
,
QList
<
Module
>
*
modules
,
QString
*
errorMessage
)
static
inline
bool
getModuleCount
(
CIDebugSymbols
*
syms
,
ULONG
*
count
,
QString
*
errorMessage
)
{
modules
->
clear
()
;
*
count
=
0
;
ULONG
loadedCount
,
unloadedCount
;
HRESULT
hr
=
syms
->
GetNumberModules
(
&
loadedCount
,
&
unloadedCount
);
const
HRESULT
hr
=
syms
->
GetNumberModules
(
&
loadedCount
,
&
unloadedCount
);
if
(
FAILED
(
hr
))
{
*
errorMessage
=
msgComFailed
(
"GetNumberModules"
,
hr
);
return
false
;
}
// retrieve array of parameters
const
ULONG
count
=
loadedCount
+
unloadedCount
;
*
count
=
loadedCount
+
unloadedCount
;
return
true
;
}
bool
getModuleNameList
(
CIDebugSymbols
*
syms
,
QStringList
*
modules
,
QString
*
errorMessage
)
{
ULONG
count
;
modules
->
clear
();
if
(
!
getModuleCount
(
syms
,
&
count
,
errorMessage
))
return
false
;
WCHAR
wszBuf
[
MAX_PATH
];
for
(
ULONG
m
=
0
;
m
<
count
;
m
++
)
if
(
SUCCEEDED
(
syms
->
GetModuleNameStringWide
(
DEBUG_MODNAME_IMAGE
,
m
,
0
,
wszBuf
,
MAX_PATH
-
1
,
0
)))
modules
->
push_back
(
QString
::
fromUtf16
(
wszBuf
));
return
true
;
}
bool
getModuleList
(
CIDebugSymbols
*
syms
,
QList
<
Module
>
*
modules
,
QString
*
errorMessage
)
{
ULONG
count
;
modules
->
clear
();
if
(
!
getModuleCount
(
syms
,
&
count
,
errorMessage
))
return
false
;
QVector
<
DEBUG_MODULE_PARAMETERS
>
parameters
(
count
);
DEBUG_MODULE_PARAMETERS
*
parmPtr
=
&
(
*
parameters
.
begin
());
memset
(
parmPtr
,
0
,
sizeof
(
DEBUG_MODULE_PARAMETERS
)
*
count
);
hr
=
syms
->
GetModuleParameters
(
count
,
0
,
0u
,
parmPtr
);
HRESULT
hr
=
syms
->
GetModuleParameters
(
count
,
0
,
0u
,
parmPtr
);
// E_INVALIDARG indicates 'Partial results' according to docu
if
(
FAILED
(
hr
)
&&
hr
!=
E_INVALIDARG
)
{
*
errorMessage
=
msgComFailed
(
"GetModuleParameters"
,
hr
);
...
...
@@ -67,7 +89,7 @@ bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorM
&&
(
p
.
SymbolType
!=
DEBUG_SYMTYPE_NONE
);
module
.
startAddress
=
hexPrefix
+
QString
::
number
(
p
.
Base
,
16
);
module
.
endAddress
=
hexPrefix
+
QString
::
number
((
p
.
Base
+
p
.
Size
),
16
);
hr
=
syms
->
GetModuleNameStringWide
(
DEBUG_MODNAME_IMAGE
,
m
,
0
,
wszBuf
,
MAX_PATH
-
1
,
0
);
hr
=
syms
->
GetModuleNameStringWide
(
DEBUG_MODNAME_IMAGE
,
m
,
0
,
wszBuf
,
MAX_PATH
-
1
,
0
);
if
(
FAILED
(
hr
)
&&
hr
!=
E_INVALIDARG
)
{
*
errorMessage
=
msgComFailed
(
"GetModuleNameStringWide"
,
hr
);
return
false
;
...
...
@@ -111,9 +133,9 @@ bool searchSymbols(CIDebugSymbols *syms, const QString &pattern,
return
true
;
}
//
Add missing the module specifier: "main" -> "project!main"
ResolveSymbolResult
resolveSymbol
(
CIDebugSymbols
*
syms
,
QString
*
symbol
,
//
Helper for the resolveSymbol overloads.
static
ResolveSymbolResult
resolveSymbol
(
CIDebugSymbols
*
syms
,
QString
*
symbol
,
QStringList
*
matches
,
QString
*
errorMessage
)
{
// Is it an incomplete symbol?
...
...
@@ -123,20 +145,63 @@ ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, QString *symbol,
if
(
*
symbol
==
QLatin1String
(
"qMain"
))
*
symbol
=
QLatin1String
(
"main"
);
// resolve
QStringList
matches
;
if
(
!
searchSymbols
(
syms
,
*
symbol
,
&
matches
,
errorMessage
))
if
(
!
searchSymbols
(
syms
,
*
symbol
,
matches
,
errorMessage
))
return
ResolveSymbolError
;
if
(
matches
.
empty
())
if
(
matches
->
empty
())
return
ResolveSymbolNotFound
;
*
symbol
=
matches
.
front
();
if
(
matches
.
size
()
>
1
)
{
*
symbol
=
matches
->
front
();
if
(
matches
->
size
()
>
1
)
{
*
errorMessage
=
QString
::
fromLatin1
(
"Ambiguous symbol '%1': %2"
).
arg
(
*
symbol
,
matches
.
join
(
QString
(
QLatin1Char
(
' '
))));
arg
(
*
symbol
,
matches
->
join
(
QString
(
QLatin1Char
(
' '
))));
return
ResolveSymbolAmbiguous
;
}
return
ResolveSymbolOk
;
}
// Add missing the module specifier: "main" -> "project!main"
ResolveSymbolResult
resolveSymbol
(
CIDebugSymbols
*
syms
,
QString
*
symbol
,
QString
*
errorMessage
)
{
QStringList
matches
;
return
resolveSymbol
(
syms
,
symbol
,
&
matches
,
errorMessage
);
}
ResolveSymbolResult
resolveSymbol
(
CIDebugSymbols
*
syms
,
const
QString
&
pattern
,
QString
*
symbol
,
QString
*
errorMessage
)
{
QStringList
matches
;
const
ResolveSymbolResult
r1
=
resolveSymbol
(
syms
,
symbol
,
&
matches
,
errorMessage
);
switch
(
r1
)
{
case
ResolveSymbolOk
:
case
ResolveSymbolNotFound
:
case
ResolveSymbolError
:
return
r1
;
case
ResolveSymbolAmbiguous
:
break
;
}
// Filter out
errorMessage
->
clear
();
const
QRegExp
re
(
pattern
);
if
(
!
re
.
isValid
())
{
*
errorMessage
=
QString
::
fromLatin1
(
"Internal error: Invalid pattern '%1'."
).
arg
(
pattern
);
return
ResolveSymbolError
;
}
const
QStringList
filteredMatches
=
matches
.
filter
(
re
);
if
(
filteredMatches
.
size
()
==
1
)
{
*
symbol
=
filteredMatches
.
front
();
return
ResolveSymbolOk
;
}
// something went wrong
const
QString
matchesString
=
matches
.
join
(
QString
(
QLatin1Char
(
','
)));
if
(
filteredMatches
.
empty
())
{
*
errorMessage
=
QString
::
fromLatin1
(
"None of symbols '%1' found for '%2' matches '%3'."
).
arg
(
matchesString
,
*
symbol
,
pattern
);
return
ResolveSymbolNotFound
;
}
*
errorMessage
=
QString
::
fromLatin1
(
"Ambiguous match of symbols '%1' found for '%2' (%3)"
).
arg
(
matchesString
,
*
symbol
,
pattern
);
return
ResolveSymbolAmbiguous
;
}
// List symbols of a module
bool
getModuleSymbols
(
CIDebugSymbols
*
syms
,
const
QString
&
moduleName
,
QList
<
Symbol
>
*
symbols
,
QString
*
errorMessage
)
...
...
src/plugins/debugger/cdb/cdbmodules.h
View file @
52915776
...
...
@@ -30,8 +30,7 @@
#ifndef CDBMODULES_H
#define CDBMODULES_H
#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include "cdbcom.h"
...
...
@@ -42,7 +41,8 @@ class Module;
class
Symbol
;
bool
getModuleList
(
CIDebugSymbols
*
syms
,
QList
<
Module
>
*
modules
,
QString
*
errorMessage
);
// Search symbols matching a pattern
bool
getModuleNameList
(
CIDebugSymbols
*
syms
,
QStringList
*
modules
,
QString
*
errorMessage
);
// Search symbols matching a pattern. Does not filter on module names.
bool
searchSymbols
(
CIDebugSymbols
*
syms
,
const
QString
&
pattern
,
QStringList
*
matches
,
QString
*
errorMessage
);
...
...
@@ -52,8 +52,12 @@ bool searchSymbols(CIDebugSymbols *syms, const QString &pattern,
enum
ResolveSymbolResult
{
ResolveSymbolOk
,
ResolveSymbolAmbiguous
,
ResolveSymbolNotFound
,
ResolveSymbolError
};
// Resolve a symbol that is unique to all modules
ResolveSymbolResult
resolveSymbol
(
CIDebugSymbols
*
syms
,
QString
*
symbol
,
QString
*
errorMessage
);
// Resolve symbol overload with an additional regexp pattern to filter on modules.
ResolveSymbolResult
resolveSymbol
(
CIDebugSymbols
*
syms
,
const
QString
&
pattern
,
QString
*
symbol
,
QString
*
errorMessage
);
// List symbols of a module
bool
getModuleSymbols
(
CIDebugSymbols
*
syms
,
const
QString
&
moduleName
,
QList
<
Symbol
>
*
symbols
,
QString
*
errorMessage
);
...
...
src/plugins/debugger/debuggermanager.h
View file @
52915776
...
...
@@ -145,6 +145,7 @@ private:
friend
class
CdbDebugEventCallback
;
friend
class
ScriptEngine
;
friend
struct
CdbDebugEnginePrivate
;
friend
class
CdbDumperHelper
;
// called from the engines after successful startup