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
8b8bf42f
Commit
8b8bf42f
authored
Jul 24, 2009
by
Friedemann Kleint
Browse files
CDB: Fixed thread handling, added dumping of string types in case of crashes.
parent
403c344c
Changes
9
Hide whitespace changes
Inline
Side-by-side
dist/changes-1.3.0
View file @
8b8bf42f
...
...
@@ -15,6 +15,8 @@ Debugging
* CDB: Added more types to the dumpers (QSharedPointer, QVector, common
* QMap/QSet types), dereference reference parameters
* CDB: Simplified display of STL types in the locals window
* CDB: Fixed thread handling
* CDB: Added internal dumpers for string types for debuggee crashes
* Improved QObject dumping, print out QRect/QSize, enumerations and flags
General:
...
...
@@ -39,3 +41,4 @@ Wizards
* Added version control checkout wizards
* Added a license header template setting
* Added a wizard for Qt Designer custom widgets
* Added a gitorious clone wizard
src/plugins/debugger/cdb/cdbdebugengine.cpp
View file @
8b8bf42f
...
...
@@ -1177,8 +1177,11 @@ void CdbDebugEngine::selectThread(int index)
ThreadsHandler
*
threadsHandler
=
m_d
->
m_debuggerManagerAccess
->
threadsHandler
();
threadsHandler
->
setCurrentThread
(
index
);
m_d
->
m_currentThreadId
=
index
;
m_d
->
updateStackTrace
();
const
int
newThreadId
=
threadsHandler
->
threads
().
at
(
index
).
id
;
if
(
newThreadId
!=
m_d
->
m_currentThreadId
)
{
m_d
->
m_currentThreadId
=
threadsHandler
->
threads
().
at
(
index
).
id
;
m_d
->
updateStackTrace
();
}
}
void
CdbDebugEngine
::
attemptBreakpointSynchronization
()
...
...
@@ -1223,7 +1226,7 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
m_cif
.
debugSymbols
,
m_debuggerManagerAccess
->
breakHandler
(),
errorMessage
,
&
warnings
);
if
(
const
int
warningsCount
=
warnings
.
size
())
if
(
const
int
warningsCount
=
warnings
.
size
())
for
(
int
w
=
0
;
w
<
warningsCount
;
w
++
)
m_engine
->
warning
(
warnings
.
at
(
w
));
return
ok
;
...
...
@@ -1390,6 +1393,16 @@ void CdbDebugEnginePrivate::notifyCrashed()
m_dumper
->
disable
();
}
static
int
threadIndexById
(
const
ThreadsHandler
*
threadsHandler
,
int
id
)
{
const
QList
<
ThreadData
>
threads
=
threadsHandler
->
threads
();
const
int
count
=
threads
.
count
();
for
(
int
i
=
0
;
i
<
count
;
i
++
)
if
(
threads
.
at
(
i
).
id
==
id
)
return
i
;
return
-
1
;
}
void
CdbDebugEnginePrivate
::
handleDebugEvent
()
{
if
(
debugCDB
)
...
...
@@ -1401,10 +1414,15 @@ void CdbDebugEnginePrivate::handleDebugEvent()
m_breakEventMode
=
BreakEventHandle
;
switch
(
mode
)
{
case
BreakEventHandle
:
case
BreakEventHandle
:
{
m_debuggerManagerAccess
->
notifyInferiorStopped
();
updateThreadList
();
m_currentThreadId
=
updateThreadList
();
ThreadsHandler
*
threadsHandler
=
m_debuggerManagerAccess
->
threadsHandler
();
const
int
threadIndex
=
threadIndexById
(
threadsHandler
,
m_currentThreadId
);
if
(
threadIndex
!=
-
1
)
threadsHandler
->
setCurrentThread
(
threadIndex
);
updateStackTrace
();
}
break
;
case
BreakEventIgnoreOnce
:
m_engine
->
startWatchTimer
();
...
...
@@ -1430,7 +1448,7 @@ void CdbDebugEnginePrivate::setDebuggeeHandles(HANDLE hDebuggeeProcess, HANDLE
m_hDebuggeeThread
=
hDebuggeeThread
;
}
void
CdbDebugEnginePrivate
::
updateThreadList
()
ULONG
CdbDebugEnginePrivate
::
updateThreadList
()
{
if
(
debugCDB
)
qDebug
()
<<
Q_FUNC_INFO
<<
m_hDebuggeeProcess
;
...
...
@@ -1439,25 +1457,25 @@ void CdbDebugEnginePrivate::updateThreadList()
QList
<
ThreadData
>
threads
;
bool
success
=
false
;
QString
errorMessage
;
ULONG
currentThreadId
=
0
;
do
{
ULONG
numberOfThreads
;
HRESULT
hr
=
m_cif
.
debugSystemObjects
->
GetNumberThreads
(
&
numberOfThreads
);
ULONG
threadCount
;
HRESULT
hr
=
m_cif
.
debugSystemObjects
->
GetNumberThreads
(
&
threadCount
);
if
(
FAILED
(
hr
))
{
errorMessage
=
msgComFailed
(
"GetNumberThreads"
,
hr
);
break
;
}
const
ULONG
maxThreadIds
=
256
;
ULONG
threadIds
[
maxThreadIds
];
ULONG
biggestThreadId
=
qMin
(
maxThreadIds
,
numberOfThreads
-
1
);
hr
=
m_cif
.
debugSystemObjects
->
GetThreadIdsByIndex
(
0
,
biggestThreadId
,
threadIds
,
0
);
if
(
FAILED
(
hr
))
{
errorMessage
=
msgComFailed
(
"GetThreadIdsByIndex"
,
hr
);
break
;
}
for
(
ULONG
threadId
=
0
;
threadId
<=
biggestThreadId
;
++
threadId
)
{
ThreadData
thread
;
thread
.
id
=
threadId
;
threads
.
append
(
thread
);
// Get ids and index of current
if
(
threadCount
)
{
m_cif
.
debugSystemObjects
->
GetCurrentThreadId
(
&
currentThreadId
);
QVector
<
ULONG
>
threadIds
(
threadCount
);
hr
=
m_cif
.
debugSystemObjects
->
GetThreadIdsByIndex
(
0
,
threadCount
,
&
(
*
threadIds
.
begin
()),
0
);
if
(
FAILED
(
hr
))
{
errorMessage
=
msgComFailed
(
"GetThreadIdsByIndex"
,
hr
);
break
;
}
for
(
ULONG
i
=
0
;
i
<
threadCount
;
i
++
)
threads
.
push_back
(
ThreadData
(
threadIds
.
at
(
i
)));
}
th
->
setThreads
(
threads
);
...
...
@@ -1465,6 +1483,7 @@ void CdbDebugEnginePrivate::updateThreadList()
}
while
(
false
);
if
(
!
success
)
m_engine
->
warning
(
msgFunctionFailed
(
Q_FUNC_INFO
,
errorMessage
));
return
currentThreadId
;
}
void
CdbDebugEnginePrivate
::
updateStackTrace
()
...
...
src/plugins/debugger/cdb/cdbdebugengine_p.h
View file @
8b8bf42f
...
...
@@ -115,7 +115,7 @@ struct CdbDebugEnginePrivate
bool
isDebuggeeRunning
()
const
{
return
m_watchTimer
!=
-
1
;
}
void
handleDebugEvent
();
void
updateThreadList
();
ULONG
updateThreadList
();
void
updateStackTrace
();
void
updateModules
();
...
...
src/plugins/debugger/cdb/cdbstackframecontext.cpp
View file @
8b8bf42f
...
...
@@ -40,7 +40,7 @@
namespace
Debugger
{
namespace
Internal
{
enum
{
OwnerNewItem
,
OwnerSymbolGroup
,
OwnerDumper
};
enum
{
OwnerNewItem
,
OwnerSymbolGroup
,
OwnerSymbolGroupDumper
,
OwnerDumper
};
typedef
QSharedPointer
<
CdbDumperHelper
>
SharedPointerCdbDumperHelper
;
typedef
QList
<
WatchData
>
WatchDataList
;
...
...
@@ -216,6 +216,12 @@ WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
wd
.
source
=
OwnerDumper
;
return
*
this
;
}
// Expanded by internal dumper? : ok
if
(
wd
.
source
==
OwnerSymbolGroupDumper
)
{
m_wh
->
insertData
(
wd
);
return
*
this
;
}
// Try library dumpers.
switch
(
m_dumper
->
dumpType
(
wd
,
true
,
OwnerDumper
,
&
m_dumperResult
,
&
errorMessage
))
{
case
CdbDumperHelper
::
DumpOk
:
if
(
debugCDBWatchHandling
)
...
...
@@ -258,13 +264,15 @@ bool CdbStackFrameContext::populateModelInitially(WatchHandler *wh, QString *err
qDebug
()
<<
"populateModelInitially dumpers="
<<
m_useDumpers
;
// Recurse down items that are initially expanded in the view, stop processing for
// dumper items.
const
CdbSymbolGroupRecursionContext
rctx
(
m_symbolContext
,
OwnerSymbolGroupDumper
,
m_dumper
->
comInterfaces
()
->
debugDataSpaces
);
const
bool
rc
=
m_useDumpers
?
CdbSymbolGroupContext
::
populateModelInitially
(
m_symbolContext
,
CdbSymbolGroupContext
::
populateModelInitially
(
rctx
,
WatchHandleDumperInserter
(
wh
,
m_dumper
),
WatchHandlerExpandedPredicate
(
wh
),
isDumperPredicate
,
errorMessage
)
:
CdbSymbolGroupContext
::
populateModelInitially
(
m_symbolContext
,
CdbSymbolGroupContext
::
populateModelInitially
(
rctx
,
WatchHandlerModelInserter
(
wh
),
WatchHandlerExpandedPredicate
(
wh
),
falsePredicate
,
...
...
@@ -279,9 +287,11 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
if
(
debugCDBWatchHandling
)
qDebug
()
<<
">completeData src="
<<
incompleteLocal
.
source
<<
incompleteLocal
.
toString
();
const
CdbSymbolGroupRecursionContext
rctx
(
m_symbolContext
,
OwnerSymbolGroupDumper
,
m_dumper
->
comInterfaces
()
->
debugDataSpaces
);
// Expand symbol group items, recurse one level from desired item
if
(
!
m_useDumpers
)
{
return
CdbSymbolGroupContext
::
completeData
(
m_symbolContext
,
incompleteLocal
,
return
CdbSymbolGroupContext
::
completeData
(
rctx
,
incompleteLocal
,
WatchHandlerModelInserter
(
wh
),
MatchINamePredicate
(
incompleteLocal
.
iname
),
falsePredicate
,
...
...
@@ -311,7 +321,7 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
}
// Expand symbol group items, recurse one level from desired item
return
CdbSymbolGroupContext
::
completeData
(
m_symbolContext
,
incompleteLocal
,
return
CdbSymbolGroupContext
::
completeData
(
rctx
,
incompleteLocal
,
WatchHandleDumperInserter
(
wh
,
m_dumper
),
MatchINamePredicate
(
incompleteLocal
.
iname
),
isDumperPredicate
,
...
...
src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
View file @
8b8bf42f
...
...
@@ -33,15 +33,22 @@
#include "watchutils.h"
#include <QtCore/QTextStream>
#include <QtCore/QCoreApplication>
#include <QtCore/QRegExp>
enum
{
debug
=
0
};
enum
{
debugInternalDumpers
=
0
};
static
inline
QString
msgSymbolNotFound
(
const
QString
&
s
)
{
return
QString
::
fromLatin1
(
"The symbol '%1' could not be found."
).
arg
(
s
);
}
static
inline
QString
msgOutOfScope
()
{
return
QCoreApplication
::
translate
(
"SymbolGroup"
,
"Out of scope"
);
}
static
inline
bool
isTopLevelSymbol
(
const
DEBUG_SYMBOL_PARAMETERS
&
p
)
{
return
p
.
ParentSymbol
==
DEBUG_ANY_ID
;
...
...
@@ -102,6 +109,16 @@ static inline QString getSymbolString(IDebugSymbolGroup2 *sg,
namespace
Debugger
{
namespace
Internal
{
CdbSymbolGroupRecursionContext
::
CdbSymbolGroupRecursionContext
(
CdbSymbolGroupContext
*
ctx
,
int
ido
,
CIDebugDataSpaces
*
ds
)
:
context
(
ctx
),
internalDumperOwner
(
ido
),
dataspaces
(
ds
)
{
}
static
inline
CdbSymbolGroupContext
::
SymbolState
getSymbolState
(
const
DEBUG_SYMBOL_PARAMETERS
&
p
)
{
if
(
p
.
SubElements
==
0u
)
...
...
@@ -419,6 +436,13 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
return
wd
;
}
WatchData
CdbSymbolGroupContext
::
dumpSymbolAt
(
CIDebugDataSpaces
*
ds
,
unsigned
long
index
)
{
WatchData
rc
=
symbolAt
(
index
);
dump
(
ds
,
&
rc
);
return
rc
;
}
bool
CdbSymbolGroupContext
::
assignValue
(
const
QString
&
iname
,
const
QString
&
value
,
QString
*
newValue
,
QString
*
errorMessage
)
{
...
...
@@ -561,5 +585,189 @@ bool CdbSymbolGroupContext::debugValueToInteger(const DEBUG_VALUE &dv, qint64 *v
return
false
;
}
/* The special type dumpers have an integer return code meaning:
* 0: ok
* 1: Dereferencing or retrieving memory failed, this is out of scope,
* do not try to query further.
* > 1: A structural error was encountered, that is, the implementation
* of the class changed (Qt or say, a different STL implementation).
* Visibly warn about it.
* To add further types, have a look at the toString() output of the
* symbol group. */
static
QString
msgStructuralError
(
const
QString
&
type
,
int
code
)
{
return
QString
::
fromLatin1
(
"Warning: Internal dumper for '%1' failed with %2."
).
arg
(
type
).
arg
(
code
);
}
static
inline
bool
isStdStringOrPointer
(
const
QString
&
type
)
{
#define STD_WSTRING "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >"
#define STD_STRING "std::basic_string<char,std::char_traits<char>,std::allocator<char> >"
return
type
.
endsWith
(
QLatin1String
(
STD_STRING
))
||
type
.
endsWith
(
QLatin1String
(
STD_STRING
" *"
))
||
type
.
endsWith
(
QLatin1String
(
STD_WSTRING
))
||
type
.
endsWith
(
QLatin1String
(
STD_WSTRING
" *"
));
#undef STD_WSTRING
#undef STD_STRING
}
CdbSymbolGroupContext
::
DumperResult
CdbSymbolGroupContext
::
dump
(
CIDebugDataSpaces
*
ds
,
WatchData
*
wd
)
{
DumperResult
rc
=
DumperNotHandled
;
do
{
// Is this a previously detected Null-Pointer?
if
(
wd
->
isHasChildrenKnown
()
&&
!
wd
->
hasChildren
)
break
;
// QString
if
(
wd
->
type
.
endsWith
(
QLatin1String
(
"QString"
))
||
wd
->
type
.
endsWith
(
QLatin1String
(
"QString *"
)))
{
const
int
drc
=
dumpQString
(
ds
,
wd
);
switch
(
drc
)
{
case
0
:
rc
=
DumperOk
;
break
;
case
1
:
rc
=
DumperError
;
break
;
default:
qWarning
(
"%s
\n
"
,
qPrintable
(
msgStructuralError
(
wd
->
type
,
drc
)));
rc
=
DumperNotHandled
;
break
;
}
}
// StdString
if
(
isStdStringOrPointer
(
wd
->
type
))
{
const
int
drc
=
dumpStdString
(
wd
);
switch
(
drc
)
{
case
0
:
rc
=
DumperOk
;
break
;
case
1
:
rc
=
DumperError
;
break
;
default:
qWarning
(
"%s
\n
"
,
qPrintable
(
msgStructuralError
(
wd
->
type
,
drc
)));
rc
=
DumperNotHandled
;
break
;
}
}
}
while
(
false
);
if
(
debugInternalDumpers
)
qDebug
()
<<
"CdbSymbolGroupContext::dump"
<<
rc
<<
wd
->
toString
();
return
rc
;
}
// Get integer value of symbol group
static
inline
bool
getIntValue
(
CIDebugSymbolGroup
*
sg
,
int
index
,
int
*
value
)
{
const
QString
valueS
=
getSymbolString
(
sg
,
&
IDebugSymbolGroup2
::
GetSymbolValueTextWide
,
index
);
bool
ok
;
*
value
=
valueS
.
toInt
(
&
ok
);
return
ok
;
}
// Get pointer value of symbol group ("0xAAB")
static
inline
bool
getPointerValue
(
CIDebugSymbolGroup
*
sg
,
int
index
,
quint64
*
value
)
{
*
value
=
0
;
QString
valueS
=
getSymbolString
(
sg
,
&
IDebugSymbolGroup2
::
GetSymbolValueTextWide
,
index
);
if
(
!
valueS
.
startsWith
(
QLatin1String
(
"0x"
)))
return
false
;
valueS
.
remove
(
0
,
2
);
bool
ok
;
*
value
=
valueS
.
toULongLong
(
&
ok
,
16
);
return
ok
;
}
int
CdbSymbolGroupContext
::
dumpQString
(
CIDebugDataSpaces
*
ds
,
WatchData
*
wd
)
{
const
int
maxLength
=
40
;
QString
errorMessage
;
unsigned
long
stringIndex
;
if
(
!
lookupPrefix
(
wd
->
iname
,
&
stringIndex
))
return
1
;
// Expand string and it's "d" (step over 'static null')
if
(
!
expandSymbol
(
wd
->
iname
,
stringIndex
,
&
errorMessage
))
return
2
;
const
unsigned
long
dIndex
=
stringIndex
+
4
;
if
(
!
expandSymbol
(
wd
->
iname
,
dIndex
,
&
errorMessage
))
return
3
;
const
unsigned
long
sizeIndex
=
dIndex
+
3
;
const
unsigned
long
arrayIndex
=
dIndex
+
4
;
// Get size and pointer
int
size
;
if
(
!
getIntValue
(
m_symbolGroup
,
sizeIndex
,
&
size
))
return
4
;
quint64
array
;
if
(
!
getPointerValue
(
m_symbolGroup
,
arrayIndex
,
&
array
))
return
5
;
// Fetch
const
bool
truncated
=
size
>
maxLength
;
if
(
truncated
)
size
=
maxLength
;
const
QChar
doubleQuote
=
QLatin1Char
(
'"'
);
QString
value
(
doubleQuote
);
if
(
size
)
{
// Should this ever be a remote debugger, need to check byte order.
unsigned
short
*
buf
=
new
unsigned
short
[
size
+
1
];
unsigned
long
bytesRead
;
const
HRESULT
hr
=
ds
->
ReadVirtual
(
array
,
buf
,
size
*
sizeof
(
unsigned
short
),
&
bytesRead
);
if
(
FAILED
(
hr
))
{
delete
[]
buf
;
return
1
;
}
buf
[
bytesRead
/
sizeof
(
unsigned
short
)]
=
0
;
value
+=
QString
::
fromUtf16
(
buf
);
delete
[]
buf
;
if
(
truncated
)
value
+=
QLatin1String
(
"..."
);
}
value
+=
doubleQuote
;
wd
->
setValue
(
value
);
wd
->
setHasChildren
(
false
);
return
0
;
}
int
CdbSymbolGroupContext
::
dumpStdString
(
WatchData
*
wd
)
{
const
int
maxLength
=
40
;
QString
errorMessage
;
unsigned
long
stringIndex
;
if
(
!
lookupPrefix
(
wd
->
iname
,
&
stringIndex
))
return
1
;
// Expand string ->string_val->_bx.
if
(
!
expandSymbol
(
wd
->
iname
,
stringIndex
,
&
errorMessage
))
return
1
;
const
unsigned
long
bxIndex
=
stringIndex
+
3
;
if
(
!
expandSymbol
(
wd
->
iname
,
bxIndex
,
&
errorMessage
))
return
2
;
// Check if size is something sane
const
int
sizeIndex
=
stringIndex
+
6
;
int
size
;
if
(
!
getIntValue
(
m_symbolGroup
,
sizeIndex
,
&
size
))
return
3
;
if
(
size
<
0
)
return
1
;
// Just copy over the value of the buf[]-array, which should be the string
const
QChar
doubleQuote
=
QLatin1Char
(
'"'
);
const
int
bufIndex
=
stringIndex
+
4
;
QString
bufValue
=
getSymbolString
(
m_symbolGroup
,
&
IDebugSymbolGroup2
::
GetSymbolValueTextWide
,
bufIndex
);
const
int
quotePos
=
bufValue
.
indexOf
(
doubleQuote
);
if
(
quotePos
==
-
1
)
return
1
;
bufValue
.
remove
(
0
,
quotePos
);
if
(
bufValue
.
size
()
>
maxLength
)
{
bufValue
.
truncate
(
maxLength
);
bufValue
+=
QLatin1String
(
"...
\"
"
);
}
wd
->
setValue
(
bufValue
);
wd
->
setHasChildren
(
false
);
return
0
;
}
}
// namespace Internal
}
// namespace Debugger
src/plugins/debugger/cdb/cdbsymbolgroupcontext.h
View file @
8b8bf42f
...
...
@@ -46,6 +46,7 @@ namespace Internal {
class
WatchData
;
class
WatchHandler
;
struct
CdbSymbolGroupRecursionContext
;
/* A thin wrapper around the IDebugSymbolGroup2 interface which represents
* a flat list of symbols using an index (for example, belonging to a stack
...
...
@@ -73,7 +74,7 @@ class CdbSymbolGroupContext
public:
~
CdbSymbolGroupContext
();
static
CdbSymbolGroupContext
*
create
(
const
QString
&
prefix
,
CIDebugSymbolGroup
*
symbolGroup
,
CIDebugSymbolGroup
*
symbolGroup
,
QString
*
errorMessage
);
QString
prefix
()
const
{
return
m_prefix
;
}
...
...
@@ -87,7 +88,7 @@ public:
// to terminate processing after insertion of an item (if the calling
// routine wants to insert another subtree).
template
<
class
OutputIterator
,
class
RecursionPredicate
,
class
IgnorePredicate
>
static
bool
populateModelInitially
(
CdbSymbolGroupContext
*
sg
,
static
bool
populateModelInitially
(
const
CdbSymbolGroup
Recursion
Context
&
ctx
,
OutputIterator
it
,
RecursionPredicate
recursionPredicate
,
IgnorePredicate
ignorePredicate
,
...
...
@@ -99,7 +100,7 @@ public:
// to terminate processing after insertion of an item (if the calling
// routine wants to insert another subtree).
template
<
class
OutputIterator
,
class
RecursionPredicate
,
class
IgnorePredicate
>
static
bool
completeData
(
CdbSymbolGroupContext
*
sg
,
static
bool
completeData
(
const
CdbSymbolGroup
Recursion
Context
&
ctx
,
WatchData
incompleteLocal
,
OutputIterator
it
,
RecursionPredicate
recursionPredicate
,
...
...
@@ -108,9 +109,19 @@ public:
// Retrieve child symbols of prefix as a sequence of WatchData.
template
<
class
OutputIterator
>
bool
getChildSymbols
(
const
QString
&
prefix
,
OutputIterator
it
,
QString
*
errorMessage
);
bool
getChildSymbols
(
const
QString
&
prefix
,
OutputIterator
it
,
QString
*
errorMessage
)
{
return
getDumpChildSymbols
(
0
,
prefix
,
0
,
it
,
errorMessage
);
}
// Retrieve child symbols of prefix as a sequence of WatchData.
// Is CIDebugDataSpaces is != 0, try internal dumper and set owner
template
<
class
OutputIterator
>
bool
getDumpChildSymbols
(
CIDebugDataSpaces
*
ds
,
const
QString
&
prefix
,
int
dumpedOwner
,
OutputIterator
it
,
QString
*
errorMessage
);
WatchData
symbolAt
(
unsigned
long
index
)
const
;
// Run the internal dumpers on the symbol
WatchData
dumpSymbolAt
(
CIDebugDataSpaces
*
ds
,
unsigned
long
index
);
bool
lookupPrefix
(
const
QString
&
prefix
,
unsigned
long
*
index
)
const
;
enum
SymbolState
{
LeafSymbol
,
ExpandedSymbol
,
CollapsedSymbol
};
...
...
@@ -127,6 +138,10 @@ public:
// format an array of unsigned longs as "0x323, 0x2322, ..."
static
QString
hexFormatArray
(
const
unsigned
short
*
array
,
int
size
);
// Dump
enum
DumperResult
{
DumperOk
,
DumperError
,
DumperNotHandled
};
DumperResult
dump
(
CIDebugDataSpaces
*
ds
,
WatchData
*
wd
);
private:
typedef
QMap
<
QString
,
unsigned
long
>
NameIndexMap
;
...
...
@@ -140,8 +155,11 @@ private:
unsigned
long
*
parentId
,
QString
*
errorMessage
);
bool
expandSymbol
(
const
QString
&
prefix
,
unsigned
long
index
,
QString
*
errorMessage
);
void
populateINameIndexMap
(
const
QString
&
prefix
,
unsigned
long
parentId
,
unsigned
long
start
,
unsigned
long
count
);
QString
symbolINameAt
(
unsigned
long
index
)
const
;
void
populateINameIndexMap
(
const
QString
&
prefix
,
unsigned
long
parentId
,
unsigned
long
start
,
unsigned
long
count
);
QString
symbolINameAt
(
unsigned
long
index
)
const
;
int
dumpQString
(
CIDebugDataSpaces
*
ds
,
WatchData
*
wd
);
int
dumpStdString
(
WatchData
*
wd
);
inline
DEBUG_SYMBOL_PARAMETERS
*
symbolParameters
()
{
return
&
(
*
m_symbolParameters
.
begin
());
}
inline
const
DEBUG_SYMBOL_PARAMETERS
*
symbolParameters
()
const
{
return
&
(
*
m_symbolParameters
.
constBegin
());
}
...
...
@@ -155,6 +173,16 @@ private:
int
m_unnamedSymbolNumber
;
};
// A convenience struct to save parameters for the model recursion.
struct
CdbSymbolGroupRecursionContext
{
explicit
CdbSymbolGroupRecursionContext
(
CdbSymbolGroupContext
*
ctx
,
int
internalDumperOwner
,
CIDebugDataSpaces
*
ds
);
CdbSymbolGroupContext
*
context
;
int
internalDumperOwner
;
CIDebugDataSpaces
*
dataspaces
;
};
// Helper to a sequence of WatchData into a list.
class
WatchDataBackInserter
{
...
...
src/plugins/debugger/cdb/cdbsymbolgroupcontext_tpl.h
View file @
8b8bf42f
...
...
@@ -48,18 +48,32 @@ enum { debugSgRecursion = 0 };
}
template
<
class
OutputIterator
>
bool
CdbSymbolGroupContext
::
getChildSymbols
(
const
QString
&
prefix
,
OutputIterator
it
,
QString
*
errorMessage
)
bool
CdbSymbolGroupContext
::
getDumpChildSymbols
(
CIDebugDataSpaces
*
ds
,
const
QString
&
prefix
,
int
dumpedOwner
,
OutputIterator
it
,
QString
*
errorMessage
)
{
unsigned
long
start
;
unsigned
long
parentId
;
if
(
!
getChildSymbolsPosition
(
prefix
,
&
start
,
&
parentId
,
errorMessage
))
return
false
;
// Skip over expanded children
const
unsigned
long
end
=
m_symbolParameters
.
size
();
for
(
unsigned
long
s
=
start
;
s
<
end
;
++
s
)
{
// Skip over expanded children
. Internal dumping might expand
// children, so, re-evaluate size in end condition.
for
(
int
s
=
start
;
s
<
m_symbolParameters
.
size
()
;
++
s
)
{
const
DEBUG_SYMBOL_PARAMETERS
&
p
=
m_symbolParameters
.
at
(
s
);
if
(
p
.
ParentSymbol
==
parentId
&&
isSymbolDisplayable
(
p
))
{
*
it
=
symbolAt
(
s
);
WatchData
wd
=
symbolAt
(
s
);
// Run internal dumper, mark ownership
if
(
ds
)
{
switch
(
dump
(
ds
,
&
wd
))
{
case
DumperOk
:
case
DumperError
:
// Not initialized yet, do not run other dumpers
wd
.
source
=
dumpedOwner
;
break
;
case
DumperNotHandled
:
break
;
}
}
*
it
=
wd
;
++
it
;
}
}
...
...
@@ -73,7 +87,7 @@ bool CdbSymbolGroupContext::getChildSymbols(const QString &prefix, OutputIterato
// (expand icon), though (ignore for simplicity).
template
<
class
OutputIterator
,
class
RecursionPredicate
,
class
IgnorePredicate
>
bool
insertSymbolRecursion
(
WatchData
wd
,
CdbSymbolGroupContext
*
sg
,
const
CdbSymbolGroup
Recursion
Context
&
ctx
,
OutputIterator
it
,
RecursionPredicate
recursionPredicate
,
IgnorePredicate
ignorePredicate
,
...
...
@@ -110,13 +124,16 @@ bool insertSymbolRecursion(WatchData wd,
return
true
;
QList
<
WatchData
>
watchList
;
// This implicitly enforces expansion
if
(
!
sg
->
getChildSymbols
(
wd
.
iname
,
WatchDataBackInserter
(
watchList
),
errorMessage
))
if
(
!
ctx
.
context
->
getDumpChildSymbols
(
ctx
.
dataspaces
,
wd
.
iname
,
ctx
.
internalDumperOwner
,
WatchDataBackInserter
(
watchList
),
errorMessage
))
return
false
;