Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
72a18377
Commit
72a18377
authored
Apr 29, 2009
by
Friedemann Kleint
Browse files
Initial work on dumpers for CDB.
Add dumper calls, parser etc. Catch crashes in the dumper functions.
parent
3cb783f7
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
share/qtcreator/gdbmacros/gdbmacros.cpp
View file @
72a18377
...
...
@@ -60,6 +60,10 @@ int qtGhVersion = QT_VERSION;
# include <QtGui/QImage>
#endif
#ifdef Q_OS_WIN
# include <windows.h>
#endif
#include <list>
#include <map>
#include <string>
...
...
@@ -231,11 +235,17 @@ static QByteArray stripPointerType(QByteArray type)
}
// This is used to abort evaluation of custom data dumpers in a "coordinated"
// way. Abortion will happen a
nyway
when we try to access a non-initialized
// way. Abortion will happen a
t the latest
when we try to access a non-initialized
// non-trivial object, so there is no way to prevent this from occuring at all
// conceptionally. Gdb will catch SIGSEGV and return to the calling frame.
// This is just fine provided we only _read_ memory in the custom handlers
// below.
// conceptionally. Ideally, if there is API to check memory access, it should
// be used to terminate nicely, especially with CDB.
// 1) Gdb will catch SIGSEGV and return to the calling frame.
// This is just fine provided we only _read_ memory in the custom handlers
// below.
// 2) For MSVC/CDB, exceptions must be handled in the dumper, which is
// achieved using __try/__except. The exception will be reported in the
// debugger, which will then execute a 'gN' command, passing handling back
// to the __except clause.
volatile
int
qProvokeSegFaultHelper
;
...
...
@@ -269,11 +279,16 @@ static bool startsWith(const char *s, const char *t)
return
qstrncmp
(
s
,
t
,
qstrlen
(
t
))
==
0
;
}
// provoke segfault when address is not readable
#define qCheckAccess(d) do { qProvokeSegFaultHelper = *(char*)d; } while (0)
#define qCheckPointer(d) do { if (d) qProvokeSegFaultHelper = *(char*)d; } while (0)
// provoke segfault unconditionally
#define qCheck(b) do { if (!(b)) qProvokeSegFaultHelper = *(char*)0; } while (0)
// Check memory for read access and provoke segfault if nothing else helps.
// On Windows, try to be less crash-prone by checking memory using WinAPI
#ifdef Q_OS_WIN
# define qCheckAccess(d) if (IsBadReadPtr(d, 1)) return false; do { qProvokeSegFaultHelper = *(char*)d; } while (0)
# define qCheckPointer(d) if (d && IsBadReadPtr(d, 1)) return false; do { if (d) qProvokeSegFaultHelper = *(char*)d; } while (0)
#else
# define qCheckAccess(d) do { qProvokeSegFaultHelper = *(char*)d; } while (0)
# define qCheckPointer(d) do { if (d) qProvokeSegFaultHelper = *(char*)d; } while (0)
#endif
const
char
*
stripNamespace
(
const
char
*
type
)
{
...
...
@@ -692,11 +707,14 @@ void QDumper::putEllipsis()
#define TT(type, value) \
"<tr><td>" << type << "</td><td> : </td><td>" << value << "</td></tr>"
static
void
qDumpUnknown
(
QDumper
&
d
)
#define DUMPUNKNOWN_MESSAGE "<internal error>"
static
void
qDumpUnknown
(
QDumper
&
d
,
const
char
*
why
=
0
)
{
P
(
d
,
"iname"
,
d
.
iname
);
P
(
d
,
"addr"
,
d
.
data
);
P
(
d
,
"value"
,
"<internal error>"
);
if
(
!
why
)
why
=
DUMPUNKNOWN_MESSAGE
;
P
(
d
,
"value"
,
why
);
P
(
d
,
"type"
,
d
.
outertype
);
P
(
d
,
"numchild"
,
"0"
);
d
.
disarm
();
...
...
@@ -815,7 +833,7 @@ static void qDumpInnerValueOrPointer(QDumper &d,
//////////////////////////////////////////////////////////////////////////////
static
void
qDumpQByteArray
(
QDumper
&
d
)
static
bool
qDumpQByteArray
(
QDumper
&
d
)
{
const
QByteArray
&
ba
=
*
reinterpret_cast
<
const
QByteArray
*>
(
d
.
data
);
...
...
@@ -848,6 +866,7 @@ static void qDumpQByteArray(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpQDateTime
(
QDumper
&
d
)
...
...
@@ -1063,7 +1082,7 @@ int hashOffset(bool optimizedIntKey, bool forKey, unsigned keySize, unsigned val
}
static
void
qDumpQHash
(
QDumper
&
d
)
static
bool
qDumpQHash
(
QDumper
&
d
)
{
QHashData
*
h
=
*
reinterpret_cast
<
QHashData
*
const
*>
(
d
.
data
);
const
char
*
keyType
=
d
.
templateParameters
[
0
];
...
...
@@ -1078,7 +1097,7 @@ static void qDumpQHash(QDumper &d)
int
n
=
h
->
size
;
if
(
n
<
0
)
qCheck
(
false
)
;
return
false
;
if
(
n
>
0
)
{
qCheckPointer
(
h
->
fakeNext
);
qCheckPointer
(
*
h
->
buckets
);
...
...
@@ -1127,6 +1146,7 @@ static void qDumpQHash(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpQHashNode
(
QDumper
&
d
)
...
...
@@ -1177,23 +1197,25 @@ static void qDumpQImage(QDumper &d)
#endif
}
static
void
qDumpQList
(
QDumper
&
d
)
static
bool
qDumpQList
(
QDumper
&
d
)
{
// This uses the knowledge that QList<T> has only a single member
// of type union { QListData p; QListData::Data *d; };
const
QListData
&
ldata
=
*
reinterpret_cast
<
const
QListData
*>
(
d
.
data
);
const
QListData
::
Data
*
pdata
=
*
reinterpret_cast
<
const
QListData
::
Data
*
const
*>
(
d
.
data
);
qCheckAccess
(
pdata
);
int
nn
=
ldata
.
size
();
if
(
nn
<
0
)
qCheck
(
false
)
;
return
false
;
if
(
nn
>
0
)
{
qCheckAccess
(
ldata
.
d
->
array
);
//qCheckAccess(ldata.d->array[0]);
//qCheckAccess(ldata.d->array[nn - 1]);
#if QT_VERSION >= 0x040400
if
(
ldata
.
d
->
ref
.
_q_value
<=
0
)
qCheck
(
false
)
;
return
false
;
#endif
}
...
...
@@ -1252,9 +1274,10 @@ static void qDumpQList(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpQLinkedList
(
QDumper
&
d
)
static
bool
qDumpQLinkedList
(
QDumper
&
d
)
{
// This uses the knowledge that QLinkedList<T> has only a single member
// of type union { QLinkedListData *d; QLinkedListNode<T> *e; };
...
...
@@ -1262,7 +1285,7 @@ static void qDumpQLinkedList(QDumper &d)
reinterpret_cast
<
const
QLinkedListData
*>
(
deref
(
d
.
data
));
int
nn
=
ldata
->
size
;
if
(
nn
<
0
)
qCheck
(
false
)
;
return
false
;
int
n
=
nn
;
P
(
d
,
"value"
,
"<"
<<
n
<<
" items>"
);
...
...
@@ -1294,6 +1317,7 @@ static void qDumpQLinkedList(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpQLocale
(
QDumper
&
d
)
...
...
@@ -1341,7 +1365,7 @@ static void qDumpQLocale(QDumper &d)
d
.
disarm
();
}
static
void
qDumpQMapNode
(
QDumper
&
d
)
static
bool
qDumpQMapNode
(
QDumper
&
d
)
{
const
QMapData
*
h
=
reinterpret_cast
<
const
QMapData
*>
(
d
.
data
);
const
char
*
keyType
=
d
.
templateParameters
[
0
];
...
...
@@ -1375,9 +1399,10 @@ static void qDumpQMapNode(QDumper &d)
}
d
.
disarm
();
return
true
;
}
static
void
qDumpQMap
(
QDumper
&
d
)
static
bool
qDumpQMap
(
QDumper
&
d
)
{
QMapData
*
h
=
*
reinterpret_cast
<
QMapData
*
const
*>
(
d
.
data
);
const
char
*
keyType
=
d
.
templateParameters
[
0
];
...
...
@@ -1386,7 +1411,7 @@ static void qDumpQMap(QDumper &d)
int
n
=
h
->
size
;
if
(
n
<
0
)
qCheck
(
false
)
;
return
false
;
if
(
n
>
0
)
{
qCheckAccess
(
h
->
backward
);
qCheckAccess
(
h
->
forward
[
0
]);
...
...
@@ -1455,11 +1480,12 @@ static void qDumpQMap(QDumper &d)
}
d
.
disarm
();
return
true
;
}
static
void
qDumpQMultiMap
(
QDumper
&
d
)
static
bool
qDumpQMultiMap
(
QDumper
&
d
)
{
qDumpQMap
(
d
);
return
qDumpQMap
(
d
);
}
static
void
qDumpQModelIndex
(
QDumper
&
d
)
...
...
@@ -1890,7 +1916,7 @@ static void qDumpQPixmap(QDumper &d)
#endif
}
static
void
qDumpQSet
(
QDumper
&
d
)
static
bool
qDumpQSet
(
QDumper
&
d
)
{
// This uses the knowledge that QHash<T> has only a single member
// of union { QHashData *d; QHashNode<Key, T> *e; };
...
...
@@ -1899,7 +1925,7 @@ static void qDumpQSet(QDumper &d)
int
n
=
hd
->
size
;
if
(
n
<
0
)
qCheck
(
false
)
;
return
false
;
if
(
n
>
0
)
{
qCheckAccess
(
node
);
qCheckPointer
(
node
->
next
);
...
...
@@ -1933,6 +1959,7 @@ static void qDumpQSet(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpQSharedPointer
(
QDumper
&
d
)
...
...
@@ -1959,7 +1986,7 @@ static void qDumpQSharedPointer(QDumper &d)
d
.
disarm
();
}
static
void
qDumpQString
(
QDumper
&
d
)
static
bool
qDumpQString
(
QDumper
&
d
)
{
const
QString
&
str
=
*
reinterpret_cast
<
const
QString
*>
(
d
.
data
);
...
...
@@ -1975,14 +2002,15 @@ static void qDumpQString(QDumper &d)
P
(
d
,
"numchild"
,
"0"
);
d
.
disarm
();
return
true
;
}
static
void
qDumpQStringList
(
QDumper
&
d
)
static
bool
qDumpQStringList
(
QDumper
&
d
)
{
const
QStringList
&
list
=
*
reinterpret_cast
<
const
QStringList
*>
(
d
.
data
);
int
n
=
list
.
size
();
if
(
n
<
0
)
qCheck
(
false
)
;
return
false
;
if
(
n
>
0
)
{
qCheckAccess
(
&
list
.
front
());
qCheckAccess
(
&
list
.
back
());
...
...
@@ -2009,6 +2037,7 @@ static void qDumpQStringList(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpQTextCodec
(
QDumper
&
d
)
...
...
@@ -2109,7 +2138,7 @@ static void qDumpQVariant(QDumper &d)
d
.
disarm
();
}
static
void
qDumpQVector
(
QDumper
&
d
)
static
bool
qDumpQVector
(
QDumper
&
d
)
{
QVectorData
*
v
=
*
reinterpret_cast
<
QVectorData
*
const
*>
(
d
.
data
);
...
...
@@ -2117,7 +2146,7 @@ static void qDumpQVector(QDumper &d)
// from asking for unavailable child details
int
nn
=
v
->
size
;
if
(
nn
<
0
)
qCheck
(
false
)
;
return
false
;
if
(
nn
>
0
)
{
//qCheckAccess(&vec.front());
//qCheckAccess(&vec.back());
...
...
@@ -2149,9 +2178,10 @@ static void qDumpQVector(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpStdList
(
QDumper
&
d
)
static
bool
qDumpStdList
(
QDumper
&
d
)
{
const
std
::
list
<
int
>
&
list
=
*
reinterpret_cast
<
const
std
::
list
<
int
>
*>
(
d
.
data
);
const
void
*
p
=
d
.
data
;
...
...
@@ -2196,9 +2226,10 @@ static void qDumpStdList(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpStdMap
(
QDumper
&
d
)
static
bool
qDumpStdMap
(
QDumper
&
d
)
{
typedef
std
::
map
<
int
,
int
>
DummyType
;
const
DummyType
&
map
=
*
reinterpret_cast
<
const
DummyType
*>
(
d
.
data
);
...
...
@@ -2209,7 +2240,8 @@ static void qDumpStdMap(QDumper &d)
p
=
deref
(
p
);
int
nn
=
map
.
size
();
qCheck
(
nn
>=
0
);
if
(
nn
<
0
)
return
false
;
DummyType
::
const_iterator
it
=
map
.
begin
();
for
(
int
i
=
0
;
i
<
nn
&&
i
<
10
&&
it
!=
map
.
end
();
++
i
,
++
it
)
qCheckAccess
(
it
.
operator
->
());
...
...
@@ -2263,9 +2295,10 @@ static void qDumpStdMap(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpStdSet
(
QDumper
&
d
)
static
bool
qDumpStdSet
(
QDumper
&
d
)
{
typedef
std
::
set
<
int
>
DummyType
;
const
DummyType
&
set
=
*
reinterpret_cast
<
const
DummyType
*>
(
d
.
data
);
...
...
@@ -2274,7 +2307,8 @@ static void qDumpStdSet(QDumper &d)
p
=
deref
(
p
);
int
nn
=
set
.
size
();
qCheck
(
nn
>=
0
);
if
(
nn
<
0
)
return
false
;
DummyType
::
const_iterator
it
=
set
.
begin
();
for
(
int
i
=
0
;
i
<
nn
&&
i
<
10
&&
it
!=
set
.
end
();
++
i
,
++
it
)
qCheckAccess
(
it
.
operator
->
());
...
...
@@ -2306,9 +2340,10 @@ static void qDumpStdSet(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpStdString
(
QDumper
&
d
)
static
bool
qDumpStdString
(
QDumper
&
d
)
{
const
std
::
string
&
str
=
*
reinterpret_cast
<
const
std
::
string
*>
(
d
.
data
);
...
...
@@ -2325,9 +2360,10 @@ static void qDumpStdString(QDumper &d)
P
(
d
,
"numchild"
,
"0"
);
d
.
disarm
();
return
true
;
}
static
void
qDumpStdWString
(
QDumper
&
d
)
static
bool
qDumpStdWString
(
QDumper
&
d
)
{
const
std
::
wstring
&
str
=
*
reinterpret_cast
<
const
std
::
wstring
*>
(
d
.
data
);
...
...
@@ -2344,9 +2380,10 @@ static void qDumpStdWString(QDumper &d)
P
(
d
,
"numchild"
,
"0"
);
d
.
disarm
();
return
true
;
}
static
void
qDumpStdVector
(
QDumper
&
d
)
static
bool
qDumpStdVector
(
QDumper
&
d
)
{
// Correct type would be something like:
// std::_Vector_base<int,std::allocator<int, std::allocator<int> >>::_Vector_impl
...
...
@@ -2361,7 +2398,7 @@ static void qDumpStdVector(QDumper &d)
// from asking for unavailable child details
int
nn
=
(
v
->
finish
-
v
->
start
)
/
d
.
extraInt
[
0
];
if
(
nn
<
0
)
qCheck
(
false
)
;
return
false
;
if
(
nn
>
0
)
{
qCheckAccess
(
v
->
start
);
qCheckAccess
(
v
->
finish
);
...
...
@@ -2392,9 +2429,10 @@ static void qDumpStdVector(QDumper &d)
d
<<
"]"
;
}
d
.
disarm
();
return
true
;
}
static
void
qDumpStdVectorBool
(
QDumper
&
d
)
static
bool
qDumpStdVectorBool
(
QDumper
&
d
)
{
// FIXME
return
qDumpStdVector
(
d
);
...
...
@@ -2402,10 +2440,14 @@ static void qDumpStdVectorBool(QDumper &d)
static
void
handleProtocolVersion2and3
(
QDumper
&
d
)
{
if
(
!
d
.
outertype
[
0
])
{
qDumpUnknown
(
d
);
return
;
}
#ifdef Q_CC_MSVC // Catch exceptions with MSVC/CDB
__try
{
#endif
d
.
setupTemplateParameters
();
P
(
d
,
"iname"
,
d
.
iname
);
...
...
@@ -2551,6 +2593,12 @@ static void handleProtocolVersion2and3(QDumper & d)
if
(
!
d
.
success
)
qDumpUnknown
(
d
);
#ifdef Q_CC_MSVC // Catch exceptions with MSVC/CDB
}
__except
(
EXCEPTION_EXECUTE_HANDLER
)
{
qDumpUnknown
(
d
,
DUMPUNKNOWN_MESSAGE
" <exception>"
);
}
#endif
}
}
// anonymous namespace
...
...
src/plugins/debugger/cdb/cdb.pri
View file @
72a18377
...
...
@@ -34,6 +34,7 @@ HEADERS += \
$$PWD/cdbdebugoutput.h \
$$PWD/cdbsymbolgroupcontext.h \
$$PWD/cdbstacktracecontext.h \
$$PWD/cdbstackframecontext.h \
$$PWD/cdbbreakpoint.h \
$$PWD/cdbmodules.h \
$$PWD/cdbassembler.h \
...
...
@@ -46,6 +47,7 @@ SOURCES += \
$$PWD/cdbdebugeventcallback.cpp \
$$PWD/cdbdebugoutput.cpp \
$$PWD/cdbsymbolgroupcontext.cpp \
$$PWD/cdbstackframecontext.cpp \
$$PWD/cdbstacktracecontext.cpp \
$$PWD/cdbbreakpoint.cpp \
$$PWD/cdbmodules.cpp \
...
...
src/plugins/debugger/cdb/cdbdebugengine.cpp
View file @
72a18377
...
...
@@ -29,8 +29,9 @@
#include "cdbdebugengine.h"
#include "cdbdebugengine_p.h"
#include "cdbsymbolgroupcontext.h"
#include "cdbstacktracecontext.h"
#include "cdbstackframecontext.h"
#include "cdbsymbolgroupcontext.h"
#include "cdbbreakpoint.h"
#include "cdbmodules.h"
#include "cdbassembler.h"
...
...
@@ -274,7 +275,7 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent,
m_hDebuggeeProcess
(
0
),
m_hDebuggeeThread
(
0
),
m_breakEventMode
(
BreakEventHandle
),
m_dumper
(
&
m_cif
),
m_dumper
(
new
CdbDumperHelper
(
parent
,
&
m_cif
)
)
,
m_watchTimer
(
-
1
),
m_debugEventCallBack
(
engine
),
m_engine
(
engine
),
...
...
@@ -464,7 +465,7 @@ bool CdbDebugEngine::startDebugger()
dumperEnabled
=
false
;
}
}
m_d
->
m_dumper
.
reset
(
dumperLibName
,
dumperEnabled
);
m_d
->
m_dumper
->
reset
(
dumperLibName
,
dumperEnabled
);
m_d
->
m_debuggerManager
->
showStatusMessage
(
"Starting Debugger"
,
-
1
);
QString
errorMessage
;
bool
rc
=
false
;
...
...
@@ -590,19 +591,20 @@ void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG6
}
else
{
m_currentThreadId
=
0
;
}
// Set initial breakpoints
// Clear any saved breakpoints and set initial breakpoints
m_engine
->
executeDebuggerCommand
(
QLatin1String
(
"bc"
));
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
(
m_dumper
->
state
()
==
CdbDumperHelper
::
NotLoaded
)
{
if
(
!
hasBreakPointAtMain
(
m_debuggerManagerAccess
->
breakHandler
()))
{
QString
errorMessage
;
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
);
}
...
...
@@ -675,13 +677,13 @@ void CdbDebugEngine::exitDebugger()
killWatchTimer
();
}
CdbS
ymbolGroup
Context
*
CdbDebugEnginePrivate
::
getStackFrame
SymbolGroup
Context
(
int
frameIndex
,
QString
*
errorMessage
)
const
CdbS
tackFrame
Context
*
CdbDebugEnginePrivate
::
getStackFrameContext
(
int
frameIndex
,
QString
*
errorMessage
)
const
{
if
(
!
m_currentStackTrace
)
{
*
errorMessage
=
QLatin1String
(
msgNoStackTraceC
);
return
0
;
}
if
(
CdbS
ymbolGroup
Context
*
sg
=
m_currentStackTrace
->
symbolGroup
ContextAt
(
frameIndex
,
errorMessage
))
if
(
CdbS
tackFrame
Context
*
sg
=
m_currentStackTrace
->
frame
ContextAt
(
frameIndex
,
errorMessage
))
return
sg
;
return
0
;
}
...
...
@@ -718,8 +720,8 @@ bool CdbDebugEnginePrivate::updateLocals(int frameIndex,
}
bool
success
=
false
;
if
(
CdbS
ymbolGroup
Context
*
sgc
=
getStackFrame
SymbolGroup
Context
(
frameIndex
,
errorMessage
))
success
=
CdbSymbolGroupContext
::
populateModelInitially
(
sgc
,
wh
,
errorMessage
);
if
(
CdbS
tackFrame
Context
*
sgc
=
getStackFrameContext
(
frameIndex
,
errorMessage
))
success
=
sgc
->
populateModelInitially
(
wh
,
errorMessage
);
wh
->
rebuildModel
();
return
success
;
...
...
@@ -800,8 +802,8 @@ void CdbDebugEngine::updateWatchModel()
filterEvaluateWatchers
(
&
incomplete
,
watchHandler
);
// Do locals. We might get called while running when someone enters watchers
if
(
!
incomplete
.
empty
())
{
CdbS
ymbolGroup
Context
*
sg
=
m_d
->
m_currentStackTrace
->
symbolGroup
ContextAt
(
frameIndex
,
&
errorMessage
);
if
(
!
sg
||
!
CdbSymbolGroupContext
::
completeModel
(
sg
,
incomplete
,
watchHandler
,
&
errorMessage
))
CdbS
tackFrame
Context
*
sg
=
m_d
->
m_currentStackTrace
->
frame
ContextAt
(
frameIndex
,
&
errorMessage
);
if
(
!
sg
||
!
sg
->
completeModel
(
incomplete
,
watchHandler
,
&
errorMessage
))
break
;
}
watchHandler
->
rebuildModel
();
...
...
@@ -1016,7 +1018,7 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v
bool
success
=
false
;
do
{
QString
newValue
;
CdbS
ymbolGroup
Context
*
sg
=
m_d
->
getStackFrame
SymbolGroup
Context
(
frameIndex
,
&
errorMessage
);
CdbS
tackFrame
Context
*
sg
=
m_d
->
getStackFrameContext
(
frameIndex
,
&
errorMessage
);
if
(
!
sg
)
break
;
if
(
!
sg
->
assignValue
(
expr
,
value
,
&
newValue
,
&
errorMessage
))
...
...
@@ -1061,17 +1063,30 @@ bool CdbDebugEngine::evaluateExpression(const QString &expression,
QString
*
value
,
QString
*
type
,
QString
*
errorMessage
)
{
DEBUG_VALUE
debugValue
;
if
(
!
m_d
->
evaluateExpression
(
m_d
->
m_cif
.
debugControl
,
expression
,
&
debugValue
,
errorMessage
))
return
false
;
*
value
=
CdbSymbolGroupContext
::
debugValueToString
(
debugValue
,
m_d
->
m_cif
.
debugControl
,
type
);
return
true
;
}
bool
CdbDebugEnginePrivate
::
evaluateExpression
(
CIDebugControl
*
ctrl
,
const
QString
&
expression
,
DEBUG_VALUE
*
debugValue
,
QString
*
errorMessage
)
{
if
(
debugCDB
>
1
)
qDebug
()
<<
Q_FUNC_INFO
<<
expression
;
DEBUG_VALUE
debugValue
;
memset
(
&
debugValue
,
0
,
sizeof
(
DEBUG_VALUE
));
memset
(
debugValue
,
0
,
sizeof
(
DEBUG_VALUE
));
// Original syntax must be restored, else setting breakpoints will fail.
SyntaxSetter
syntaxSetter
(
m_d
->
m_cif
.
debugCon
tr
o
l
,
DEBUG_EXPR_CPLUSPLUS
);
SyntaxSetter
syntaxSetter
(
c
trl
,
DEBUG_EXPR_CPLUSPLUS
);
ULONG
errorPosition
=
0
;
const
HRESULT
hr
=
m_d
->
m_cif
.
debugControl
->
EvaluateWide
(
expression
.
utf16
(),
DEBUG_VALUE_INVALID
,
&
debugValue
,
&
errorPosition
);
if
(
FAILED
(
hr
))
{
const
HRESULT
hr
=
ctrl
->
EvaluateWide
(
expression
.
utf16
(),
DEBUG_VALUE_INVALID
,
debugValue
,
&
errorPosition
);
if
(
FAILED
(
hr
))
{
if
(
HRESULT_CODE
(
hr
)
==
517
)
{
*
errorMessage
=
QString
::
fromLatin1
(
"Unable to evaluate '%1': Expression out of scope."
).
arg
(
expression
);
...
...
@@ -1081,7 +1096,6 @@ bool CdbDebugEngine::evaluateExpression(const QString &expression,
}
return
false
;
}
*
value
=
CdbSymbolGroupContext
::
debugValueToString
(
debugValue
,
m_d
->
m_cif
.
debugControl
,
type
);
return
true
;
}
...
...
@@ -1355,14 +1369,14 @@ void CdbDebugEnginePrivate::handleDebugEvent()
case
BreakEventHandle
:
case
BreakEventMain
:
if
(
mode
==
BreakEventMain
)
m_dumper
.
load
(
m_debuggerManager
,
m_debuggerManagerAccess
);
m_dumper
->
load
(
m_debuggerManager
);
m_debuggerManagerAccess
->
notifyInferiorStopped
();
updateThreadList
();
updateStackTrace
();
break
;
case
BreakEventMainLoadDumpers
:
// Temp stop to load dumpers
m_dumper
.
load
(
m_debuggerManager
,
m_debuggerManagerAccess
);
m_dumper
->
load
(
m_debuggerManager
);
m_engine
->
startWatchTimer
();
continueInferiorProcess
();
break
;
...
...
@@ -1436,7 +1450,7 @@ void CdbDebugEnginePrivate::updateStackTrace()
QString
errorMessage
;
m_engine
->
reloadRegisters
();
m_currentStackTrace
=
CdbStackTraceContext
::
create
(
&
m_
cif
,
m_currentThreadId
,
&
errorMessage
);
CdbStackTraceContext
::
create
(
m_
dumper
,
m_currentThreadId
,
&
errorMessage
);
if
(
!
m_currentStackTrace
)
{
qWarning
(
"%s: failed to create trace context: %s"
,
Q_FUNC_INFO
,
qPrintable
(
errorMessage
));
return
;
...
...
src/plugins/debugger/cdb/cdbdebugengine_p.h
View file @
72a18377
...
...
@@ -46,7 +46,7 @@ namespace Internal {
class
DebuggerManager
;
class
IDebuggerManagerAccessForEngines
;
class
WatchHandler
;
class
CdbS
ymbolGroup
Context
;
class
CdbS
tackFrame
Context
;
class
CdbStackTraceContext
;