Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
5139f513
Commit
5139f513
authored
Jul 07, 2009
by
dt
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline
parents
660b210e
8f02d4da
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
286 additions
and
57 deletions
+286
-57
share/qtcreator/gdbmacros/gdbmacros.cpp
share/qtcreator/gdbmacros/gdbmacros.cpp
+128
-17
share/qtcreator/gdbmacros/test/main.cpp
share/qtcreator/gdbmacros/test/main.cpp
+30
-0
src/plugins/debugger/cdb/cdbdumperhelper.cpp
src/plugins/debugger/cdb/cdbdumperhelper.cpp
+13
-8
src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
+4
-2
src/plugins/debugger/gdb/gdbengine.cpp
src/plugins/debugger/gdb/gdbengine.cpp
+37
-11
src/plugins/debugger/watchutils.cpp
src/plugins/debugger/watchutils.cpp
+56
-15
src/plugins/debugger/watchutils.h
src/plugins/debugger/watchutils.h
+18
-4
No files found.
share/qtcreator/gdbmacros/gdbmacros.cpp
View file @
5139f513
...
...
@@ -174,6 +174,9 @@ QT_BEGIN_NAMESPACE
struct
Sender
{
QObject
*
sender
;
int
signal
;
int
ref
;
};
const
char
*
stdStringTypeC
=
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >"
;
const
char
*
stdWideStringTypeUShortC
=
"std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >"
;
#if QT_VERSION < 0x040600
struct
Connection
{
...
...
@@ -905,7 +908,8 @@ static inline void dumpChildNumChildren(QDumper &d, InnerValueResult innerValueR
}
}
static
InnerValueResult
qDumpInnerValueHelper
(
QDumper
&
d
,
const
char
*
type
,
const
void
*
addr
,
// Called by templates, so, not static.
InnerValueResult
qDumpInnerValueHelper
(
QDumper
&
d
,
const
char
*
type
,
const
void
*
addr
,
const
char
*
field
=
"value"
)
{
char
buf
[
30
];
...
...
@@ -1017,13 +1021,13 @@ static InnerValueResult qDumpInnerValueHelper(QDumper &d, const char *type, cons
return
InnerValueNotHandled
;
case
't'
:
if
(
isEqual
(
type
,
"std::string"
)
||
isEqual
(
type
,
"
std
::basic_string<char,std::char_traits<char>,std::allocator<char> >"
))
{
||
isEqual
(
type
,
std
StringTypeC
))
{
d
.
putCommaIfNeeded
();
dumpStdStringValue
(
d
,
*
reinterpret_cast
<
const
std
::
string
*>
(
addr
));
return
InnerValueNoFurtherChildren
;
}
if
(
isEqual
(
type
,
"std::wstring"
)
||
isEqual
(
type
,
"
std
::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >"
))
{
||
isEqual
(
type
,
std
WideStringTypeUShortC
))
{
dumpStdWStringValue
(
d
,
*
reinterpret_cast
<
const
std
::
wstring
*>
(
addr
));
return
InnerValueNoFurtherChildren
;
}
...
...
@@ -2905,9 +2909,16 @@ static void qDumpStdList(QDumper &d)
d
.
disarm
();
}
static
void
qDumpStdMap
(
QDumper
&
d
)
/* Dump out an arbitrary map. To iterate the map,
* it is cast to a map of <KeyType,Value>. 'int' can be used for both
* for all types if the implementation does not depend on the types
* which is the case for GNU STL. The implementation used by MS VC, however,
* does depend on the key/value type, so, special cases need to be hardcoded. */
template
<
class
KeyType
,
class
ValueType
>
static
void
qDumpStdMapHelper
(
QDumper
&
d
)
{
typedef
std
::
map
<
int
,
int
>
DummyType
;
typedef
std
::
map
<
KeyType
,
ValueType
>
DummyType
;
const
DummyType
&
map
=
*
reinterpret_cast
<
const
DummyType
*>
(
d
.
data
);
const
char
*
keyType
=
d
.
templateParameters
[
0
];
const
char
*
valueType
=
d
.
templateParameters
[
1
];
...
...
@@ -2915,14 +2926,15 @@ static void qDumpStdMap(QDumper &d)
qCheckAccess
(
p
);
p
=
deref
(
p
);
int
nn
=
map
.
size
();
const
int
nn
=
map
.
size
();
if
(
nn
<
0
)
return
;
DummyType
::
const_iterator
it
=
map
.
begin
();
for
(
int
i
=
0
;
i
<
nn
&&
i
<
10
&&
it
!=
map
.
end
();
++
i
,
++
it
)
Q_TYPENAME
DummyType
::
const_iterator
it
=
map
.
begin
();
const
Q_TYPENAME
DummyType
::
const_iterator
cend
=
map
.
end
();
for
(
int
i
=
0
;
i
<
nn
&&
i
<
10
&&
it
!=
cend
;
++
i
,
++
it
)
qCheckAccess
(
it
.
operator
->
());
QByteArray
strippedInnerType
=
stripPointerType
(
d
.
innertype
);
const
QByteArray
strippedInnerType
=
stripPointerType
(
d
.
innertype
);
d
.
putItem
(
"numchild"
,
nn
);
d
.
putItemCount
(
"value"
,
nn
);
d
.
putItem
(
"valuedisabled"
,
"true"
);
...
...
@@ -2937,6 +2949,7 @@ static void qDumpStdMap(QDumper &d)
pairType
[
strlen
(
pairType
)
-
2
]
=
0
;
d
.
putItem
(
"pairtype"
,
pairType
);
InnerValueResult
innerValueResult
=
InnerValueChildrenSpecified
;
if
(
d
.
dumpChildren
)
{
bool
isSimpleKey
=
isSimpleType
(
keyType
);
bool
isSimpleValue
=
isSimpleType
(
valueType
);
...
...
@@ -2951,12 +2964,12 @@ static void qDumpStdMap(QDumper &d)
d
.
beginChildren
();
it
=
map
.
begin
();
for
(
int
i
=
0
;
i
<
1000
&&
it
!=
map
.
end
()
;
++
i
,
++
it
)
{
for
(
int
i
=
0
;
i
<
1000
&&
it
!=
c
end
;
++
i
,
++
it
)
{
d
.
beginHash
();
const
void
*
node
=
it
.
operator
->
();
d
.
putItem
(
"name"
,
i
);
qDumpInnerValueHelper
(
d
,
keyType
,
node
,
"key"
);
qDumpInnerValueHelper
(
d
,
valueType
,
addOffset
(
node
,
valueOffset
));
innerValueResult
=
qDumpInnerValueHelper
(
d
,
valueType
,
addOffset
(
node
,
valueOffset
));
if
(
isSimpleKey
&&
isSimpleValue
)
{
d
.
putItem
(
"type"
,
valueType
);
d
.
putItem
(
"addr"
,
addOffset
(
node
,
valueOffset
));
...
...
@@ -2972,22 +2985,61 @@ static void qDumpStdMap(QDumper &d)
d
.
putEllipsis
();
d
.
endChildren
();
}
dumpChildNumChildren
(
d
,
innerValueResult
);
d
.
disarm
();
}
static
void
qDumpStdSet
(
QDumper
&
d
)
static
void
qDumpStdMap
(
QDumper
&
d
)
{
#ifdef Q_CC_MSVC
// As the map implementation inherits from a base class
// depending on the key, use something equivalent to iterate it.
const
int
keySize
=
d
.
extraInt
[
0
];
const
int
valueSize
=
d
.
extraInt
[
1
];
if
(
keySize
==
valueSize
)
{
if
(
keySize
==
sizeof
(
int
))
{
qDumpStdMapHelper
<
int
,
int
>
(
d
);
return
;
}
if
(
keySize
==
sizeof
(
std
::
string
))
{
qDumpStdMapHelper
<
std
::
string
,
std
::
string
>
(
d
);
return
;
}
return
;
}
if
(
keySize
==
sizeof
(
int
)
&&
valueSize
==
sizeof
(
std
::
string
))
{
qDumpStdMapHelper
<
int
,
std
::
string
>
(
d
);
return
;
}
if
(
keySize
==
sizeof
(
std
::
string
)
&&
valueSize
==
sizeof
(
int
))
{
qDumpStdMapHelper
<
std
::
string
,
int
>
(
d
);
return
;
}
#else
qDumpStdMapHelper
<
int
,
int
>
(
d
);
#endif
}
/* Dump out an arbitrary set. To iterate the set,
* it is cast to a set of <KeyType>. 'int' can be used
* for all types if the implementation does not depend on the key type
* which is the case for GNU STL. The implementation used by MS VC, however,
* does depend on the key type, so, special cases need to be hardcoded. */
template
<
class
KeyType
>
static
void
qDumpStdSetHelper
(
QDumper
&
d
)
{
typedef
std
::
set
<
int
>
DummyType
;
typedef
std
::
set
<
KeyType
>
DummyType
;
const
DummyType
&
set
=
*
reinterpret_cast
<
const
DummyType
*>
(
d
.
data
);
const
void
*
p
=
d
.
data
;
qCheckAccess
(
p
);
p
=
deref
(
p
);
int
nn
=
set
.
size
();
const
int
nn
=
set
.
size
();
if
(
nn
<
0
)
return
;
DummyType
::
const_iterator
it
=
set
.
begin
();
const
DummyType
::
const_iterator
cend
=
set
.
end
();
Q_TYPENAME
DummyType
::
const_iterator
it
=
set
.
begin
();
const
Q_TYPENAME
DummyType
::
const_iterator
cend
=
set
.
end
();
for
(
int
i
=
0
;
i
<
nn
&&
i
<
10
&&
it
!=
cend
;
++
i
,
++
it
)
qCheckAccess
(
it
.
operator
->
());
...
...
@@ -3024,6 +3076,29 @@ static void qDumpStdSet(QDumper &d)
d
.
disarm
();
}
static
void
qDumpStdSet
(
QDumper
&
d
)
{
#ifdef Q_CC_MSVC
// As the set implementation inherits from a base class
// depending on the key, use something equivalent to iterate it.
const
int
innerSize
=
d
.
extraInt
[
0
];
if
(
innerSize
==
sizeof
(
int
))
{
qDumpStdSetHelper
<
int
>
(
d
);
return
;
}
if
(
innerSize
==
sizeof
(
std
::
string
))
{
qDumpStdSetHelper
<
std
::
string
>
(
d
);
return
;
}
if
(
innerSize
==
sizeof
(
std
::
wstring
))
{
qDumpStdSetHelper
<
std
::
wstring
>
(
d
);
return
;
}
#else
qDumpStdSetHelper
<
int
>
(
d
);
#endif
}
static
void
qDumpStdString
(
QDumper
&
d
)
{
const
std
::
string
&
str
=
*
reinterpret_cast
<
const
std
::
string
*>
(
d
.
data
);
...
...
@@ -3329,12 +3404,37 @@ template <class Key, class Value>
d
.
put
(
keyType
);
d
.
put
(
','
);
d
.
put
(
valueType
);
if
(
valueType
[
qstrlen
(
valueType
)
-
1
]
==
'>'
)
d
.
put
(
' '
);
d
.
put
(
">'*)0)->value=
\"
"
);
d
.
put
(
valueOffset
);
d
.
put
(
'"'
);
return
d
;
}
// Helper to write out common expression values for CDB:
// Offsets of a std::pair for dumping std::map node value which look like
// "(size_t)&(('std::pair<int const ,unsigned int>'*)0)->second"
template
<
class
Key
,
class
Value
>
inline
QDumper
&
putStdPairValueOffsetExpression
(
const
char
*
keyType
,
const
char
*
valueType
,
QDumper
&
d
)
{
std
::
pair
<
Key
,
Value
>
*
p
=
0
;
const
int
valueOffset
=
(
char
*
)
&
(
p
->
second
)
-
(
char
*
)
p
;
d
.
put
(
"(size_t)&(('std::pair<"
);
d
.
put
(
keyType
);
d
.
put
(
" const ,"
);
d
.
put
(
valueType
);
if
(
valueType
[
qstrlen
(
valueType
)
-
1
]
==
'>'
)
d
.
put
(
' '
);
d
.
put
(
">'*)0)->second=
\"
"
);
d
.
put
(
valueOffset
);
d
.
put
(
'"'
);
return
d
;
}
extern
"C"
Q_DECL_EXPORT
void
*
qDumpObjectData440
(
int
protocolVersion
,
...
...
@@ -3461,7 +3561,18 @@ void *qDumpObjectData440(
putQMapNodeOffsetExpression
<
int
,
QVariant
>
(
"int"
,
NS
"QVariant"
,
d
).
put
(
','
);
putQMapNodeOffsetExpression
<
QString
,
int
>
(
NS
"QString"
,
"int"
,
d
).
put
(
','
);
putQMapNodeOffsetExpression
<
QString
,
QString
>
(
NS
"QString"
,
NS
"QString"
,
d
).
put
(
','
);
putQMapNodeOffsetExpression
<
QString
,
QVariant
>
(
NS
"QString"
,
NS
"QVariant"
,
d
);
putQMapNodeOffsetExpression
<
QString
,
QVariant
>
(
NS
"QString"
,
NS
"QVariant"
,
d
).
put
(
','
);
// Std Pairs
putStdPairValueOffsetExpression
<
int
,
int
>
(
"int"
,
"int"
,
d
).
put
(
','
);
putStdPairValueOffsetExpression
<
QString
,
QString
>
(
NS
"QString"
,
NS
"QString"
,
d
).
put
(
','
);
putStdPairValueOffsetExpression
<
int
,
QString
>
(
"int"
,
NS
"QString"
,
d
).
put
(
','
);
putStdPairValueOffsetExpression
<
QString
,
int
>
(
NS
"QString"
,
"int"
,
d
).
put
(
','
);
putStdPairValueOffsetExpression
<
std
::
string
,
std
::
string
>
(
stdStringTypeC
,
stdStringTypeC
,
d
).
put
(
','
);
putStdPairValueOffsetExpression
<
int
,
std
::
string
>
(
"int"
,
stdStringTypeC
,
d
).
put
(
','
);
putStdPairValueOffsetExpression
<
std
::
string
,
int
>
(
stdStringTypeC
,
"int"
,
d
.
put
(
','
));
putStdPairValueOffsetExpression
<
std
::
wstring
,
std
::
wstring
>
(
stdWideStringTypeUShortC
,
stdWideStringTypeUShortC
,
d
).
put
(
','
);
putStdPairValueOffsetExpression
<
int
,
std
::
wstring
>
(
"int"
,
stdWideStringTypeUShortC
,
d
).
put
(
','
);
putStdPairValueOffsetExpression
<
std
::
wstring
,
int
>
(
stdWideStringTypeUShortC
,
"int"
,
d
);
d
.
put
(
'}'
);
d
.
disarm
();
}
...
...
share/qtcreator/gdbmacros/test/main.cpp
View file @
5139f513
...
...
@@ -308,6 +308,18 @@ static int dumpStdStringSet()
return
0
;
}
static
int
dumpStdQStringSet
()
{
std
::
set
<
QString
>
test
;
test
.
insert
(
QLatin1String
(
"item1"
));
test
.
insert
(
QLatin1String
(
"item2"
));
prepareInBuffer
(
"std::set"
,
"local.stringset"
,
"local.stringset"
,
"QString"
);
qDumpObjectData440
(
2
,
42
,
testAddress
(
&
test
),
1
,
sizeof
(
QString
),
sizeof
(
std
::
list
<
int
>::
allocator_type
),
0
,
0
);
fputs
(
qDumpOutBuffer
,
stdout
);
fputc
(
'\n'
,
stdout
);
return
0
;
}
static
int
dumpStdMapIntString
()
{
std
::
map
<
int
,
std
::
string
>
test
;
...
...
@@ -322,6 +334,22 @@ static int dumpStdMapIntString()
return
0
;
}
static
int
dumpStdMapStringString
()
{
typedef
std
::
map
<
std
::
string
,
std
::
string
>
TestType
;
TestType
test
;
const
TestType
::
value_type
entry
(
"K"
,
"V"
);
test
.
insert
(
entry
);
const
int
valueOffset
=
(
char
*
)
&
(
entry
.
second
)
-
(
char
*
)
&
entry
;
prepareInBuffer
(
"std::map"
,
"local.stdmapstringstring"
,
"local.stdmapstringstring"
,
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::less<int>@std::allocator<std::pair<const std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >"
);
qDumpObjectData440
(
2
,
42
,
testAddress
(
&
test
),
1
,
sizeof
(
std
::
string
),
sizeof
(
std
::
string
),
valueOffset
,
0
);
fputs
(
qDumpOutBuffer
,
stdout
);
fputc
(
'\n'
,
stdout
);
return
0
;
}
static
int
dumpQObject
()
{
// Requires the childOffset to be know, but that is not critical
...
...
@@ -398,7 +426,9 @@ static TypeDumpFunctionMap registerTypes()
rc
.
insert
(
"vector<wstring>"
,
dumpStdWStringVector
);
rc
.
insert
(
"set<int>"
,
dumpStdIntSet
);
rc
.
insert
(
"set<string>"
,
dumpStdStringSet
);
rc
.
insert
(
"set<QString>"
,
dumpStdQStringSet
);
rc
.
insert
(
"map<int,string>"
,
dumpStdMapIntString
);
rc
.
insert
(
"map<string,string>"
,
dumpStdMapStringString
);
rc
.
insert
(
"QObject"
,
dumpQObject
);
rc
.
insert
(
"QObjectList"
,
dumpQObjectList
);
rc
.
insert
(
"QVariant"
,
dumpQVariant
);
...
...
src/plugins/debugger/cdb/cdbdumperhelper.cpp
View file @
5139f513
...
...
@@ -100,7 +100,7 @@ static bool allocDebuggeeMemory(CdbComInterfaces *cif,
OutputRedirector
redir
(
cif
->
debugClient
,
&
stringHandler
);
if
(
!
CdbDebugEnginePrivate
::
executeDebuggerCommand
(
cif
->
debugControl
,
allocCmd
,
errorMessage
))
return
false
;
// "Allocated 1000 bytes starting at 003a0000" .. hopefully never localized
// "Allocated 1000 bytes starting at 003a0000" .. hopefully never localized
bool
ok
=
false
;
const
QString
output
=
stringHandler
.
result
();
const
int
lastBlank
=
output
.
lastIndexOf
(
QLatin1Char
(
' '
));
...
...
@@ -176,7 +176,7 @@ static bool debuggeeLoadLibrary(IDebuggerManagerAccessForEngines *access,
return
false
;
// This will hit a breakpoint.
if
(
!
CdbDebugEnginePrivate
::
executeDebuggerCommand
(
cif
->
debugControl
,
QString
(
QLatin1Char
(
'g'
)),
errorMessage
))
return
false
;
return
false
;
const
HRESULT
hr
=
cif
->
debugControl
->
WaitForEvent
(
0
,
waitTimeOutMS
);
if
(
FAILED
(
hr
))
{
*
errorMessage
=
msgComFailed
(
"WaitForEvent"
,
hr
);
...
...
@@ -280,7 +280,7 @@ void CdbDumperHelper::moduleLoadHook(const QString &module, HANDLE debuggeeHandl
if
(
m_tryInjectLoad
&&
module
.
contains
(
QLatin1String
(
"Qt"
),
Qt
::
CaseInsensitive
))
{
// Also shows up in the log window.
m_manager
->
showStatusMessage
(
msgLoading
(
m_library
,
true
),
10000
);
QString
errorMessage
;
QString
errorMessage
;
SharedLibraryInjector
sh
(
GetProcessId
(
debuggeeHandle
));
if
(
sh
.
remoteInject
(
m_library
,
false
,
&
errorMessage
))
{
m_state
=
InjectLoading
;
...
...
@@ -408,7 +408,7 @@ static inline bool getSymbolAddress(CIDebugSymbols *sg,
}
bool
CdbDumperHelper
::
initResolveSymbols
(
QString
*
errorMessage
)
{
{
// Resolve the symbols we need (potentially namespaced).
// There is a 'qDumpInBuffer' in QtCore as well.
m_dumpObjectSymbol
=
QLatin1String
(
"*qDumpObjectData440"
);
...
...
@@ -437,6 +437,7 @@ bool CdbDumperHelper::initResolveSymbols(QString *errorMessage)
// Call query protocol to retrieve known types and sizes
bool
CdbDumperHelper
::
initKnownTypes
(
QString
*
errorMessage
)
{
const
double
dumperVersionRequired
=
1.3
;
QByteArray
output
;
QString
callCmd
;
QTextStream
(
&
callCmd
)
<<
".call "
<<
m_dumpObjectSymbol
<<
"(1,0,0,0,0,0,0,0)"
;
...
...
@@ -447,6 +448,10 @@ bool CdbDumperHelper::initKnownTypes(QString *errorMessage)
if
(
!
m_helper
.
parseQuery
(
outData
,
QtDumperHelper
::
CdbDebugger
))
{
*
errorMessage
=
QString
::
fromLatin1
(
"Unable to parse the dumper output: '%1'"
).
arg
(
QString
::
fromAscii
(
output
));
}
if
(
m_helper
.
dumperVersion
()
<
dumperVersionRequired
)
{
*
errorMessage
=
QtDumperHelper
::
msgDumperOutdated
(
dumperVersionRequired
,
m_helper
.
dumperVersion
());
return
false
;
}
if
(
loadDebug
)
qDebug
()
<<
Q_FUNC_INFO
<<
m_helper
.
toString
(
true
);
return
true
;
...
...
@@ -521,7 +526,7 @@ bool CdbDumperHelper::callDumper(const QString &callCmd, const QByteArray &inBuf
return
false
;
}
// see QDumper implementation
const
char
result
=
m_buffer
[
0
];
const
char
result
=
m_buffer
[
0
];
switch
(
result
)
{
case
't'
:
break
;
...
...
@@ -574,7 +579,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
}
// Known type?
const
QtDumperHelper
::
TypeData
td
=
m_helper
.
typeData
(
wd
.
type
);
const
QtDumperHelper
::
TypeData
td
=
m_helper
.
typeData
(
wd
.
type
);
if
(
loadDebug
)
qDebug
()
<<
"dumpType"
<<
wd
.
type
<<
td
;
if
(
td
.
type
==
QtDumperHelper
::
UnknownType
)
{
...
...
@@ -596,7 +601,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
// yet initialized in a particular breakpoint. That should be ignored.
// Also fail for complex expression that were not cached/replaced by the helper.
if
(
der
==
DumpExecuteSizeFailed
||
der
==
DumpComplexExpressionEncountered
)
m_failedTypes
.
push_back
(
wd
.
type
);
m_failedTypes
.
push_back
(
wd
.
type
);
// log error
*
errorMessage
=
msgDumpFailed
(
wd
,
errorMessage
);
m_access
->
showDebuggerOutput
(
LogWarning
,
*
errorMessage
);
...
...
@@ -609,7 +614,7 @@ CdbDumperHelper::DumpExecuteResult
QList
<
WatchData
>
*
result
,
QString
*
errorMessage
)
{
QByteArray
inBuffer
;
QStringList
extraParameters
;
QStringList
extraParameters
;
// Build parameter list.
m_helper
.
evaluationParameters
(
wd
,
td
,
QtDumperHelper
::
CdbDebugger
,
&
inBuffer
,
&
extraParameters
);
// If the parameter list contains sizeof-expressions, execute them separately
...
...
src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
View file @
5139f513
...
...
@@ -86,10 +86,12 @@ static inline QString getSymbolString(IDebugSymbolGroup2 *sg,
WideStringRetrievalFunction
wsf
,
unsigned
long
index
)
{
static
WCHAR
nameBuffer
[
MAX_PATH
+
1
];
// Template type names can get quite long....
enum
{
BufSize
=
1024
};
static
WCHAR
nameBuffer
[
BufSize
+
1
];
// Name
ULONG
nameLength
;
const
HRESULT
hr
=
(
sg
->*
wsf
)(
index
,
nameBuffer
,
MAX_PATH
,
&
nameLength
);
const
HRESULT
hr
=
(
sg
->*
wsf
)(
index
,
nameBuffer
,
BufSize
,
&
nameLength
);
if
(
SUCCEEDED
(
hr
))
{
nameBuffer
[
nameLength
]
=
0
;
return
QString
::
fromUtf16
(
reinterpret_cast
<
const
ushort
*>
(
nameBuffer
));
...
...
src/plugins/debugger/gdb/gdbengine.cpp
View file @
5139f513
...
...
@@ -246,7 +246,7 @@ void GdbEngine::initializeVariables()
m_address
.
clear
();
m_currentFunctionArgs
.
clear
();
m_currentFrame
.
clear
();
m_dumperHelper
=
QtDumperHelpe
r
();
m_dumperHelper
.
clea
r
();
// FIXME: unhandled:
//m_outputCodecState = QTextCodec::ConverterState();
...
...
@@ -3144,8 +3144,33 @@ void GdbEngine::rebuildModel()
showToolTip
();
}
static
inline
double
getDumperVersion
(
const
GdbMi
&
contents
)
{
const
GdbMi
dumperVersionG
=
contents
.
findChild
(
"dumperversion"
);
if
(
dumperVersionG
.
type
()
!=
GdbMi
::
Invalid
)
{
bool
ok
;
const
double
v
=
QString
::
fromAscii
(
dumperVersionG
.
data
()).
toDouble
(
&
ok
);
if
(
ok
)
return
v
;
}
return
1.0
;
}
static
void
parseSizeCache
(
const
GdbMi
&
contents
,
QtDumperHelper
*
dumperHelper
)
{
const
GdbMi
sizesList
=
contents
.
findChild
(
"sizes"
);
if
(
sizesList
.
type
()
==
GdbMi
::
Invalid
)
return
;
foreach
(
const
GdbMi
&
c
,
sizesList
.
children
())
{
const
QString
name
=
QString
::
fromAscii
(
c
.
name
());
if
(
const
int
size
=
QString
::
fromAscii
(
c
.
data
()).
toInt
())
dumperHelper
->
addSize
(
name
,
size
);
}
}
void
GdbEngine
::
handleQueryDebuggingHelper
(
const
GdbResultRecord
&
record
,
const
QVariant
&
)
{
const
double
dumperVersionRequired
=
1.0
;
m_dumperHelper
.
clear
();
//qDebug() << "DATA DUMPER TRIAL:" << record.toString();
...
...
@@ -3163,7 +3188,6 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
//qDebug() << "FOUND QT VERSION:" << qtversion.toString() << m_qtVersion;
}
m_dumperHelper
.
setQtVersion
(
qtv
);
//qDebug() << "CONTENTS:" << contents.toString();
//qDebug() << "SIMPLE DUMPERS:" << simple.toString();
...
...
@@ -3176,17 +3200,19 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
if
(
!
m_dumperInjectionLoad
)
// Retry if thread has not terminated yet.
m_debuggingHelperState
=
DebuggingHelperUnavailable
;
q
->
showStatusMessage
(
tr
(
"Debugging helpers not found."
));
//QMessageBox::warning(q->mainWindow(),
// tr("Cannot find special data dumpers"),
// tr("The debugged binary does not contain information needed for "
// "nice display of Qt data types.\n\n"
// "You might want to try including the file\n\n"
// ".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n"
// "into your project directly.")
// );
}
else
{
// Get version and sizes from dumpers. Expression cache
// currently causes errors.
const
double
dumperVersion
=
getDumperVersion
(
contents
);
if
(
dumperVersion
<
dumperVersionRequired
)
{
qq
->
showQtDumperLibraryWarning
(
QtDumperHelper
::
msgDumperOutdated
(
dumperVersionRequired
,
dumperVersion
));
m_debuggingHelperState
=
DebuggingHelperUnavailable
;
return
;
}
parseSizeCache
(
contents
,
&
m_dumperHelper
);
m_debuggingHelperState
=
DebuggingHelperAvailable
;
q
->
showStatusMessage
(
tr
(
"%n custom dumpers found."
,
0
,
m_dumperHelper
.
typeCount
()));
const
QString
successMsg
=
tr
(
"Dumper version %1, %n custom dumpers found."
,
0
,
m_dumperHelper
.
typeCount
()).
arg
(
dumperVersion
);
q
->
showStatusMessage
(
successMsg
);
}
//qDebug() << m_dumperHelper.toString(true);
//qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
...
...
src/plugins/debugger/watchutils.cpp
View file @
5139f513
...
...
@@ -638,20 +638,30 @@ void QtDumperHelper::TypeData::clear()
// ----------------- QtDumperHelper
QtDumperHelper
::
QtDumperHelper
()
:
m_qtVersion
(
0
)
m_qtVersion
(
0
),
m_dumperVersion
(
1.0
)
{
qFill
(
m_specialSizes
,
m_specialSizes
+
SpecialSizeCount
,
0
);
setQClassPrefixes
(
QString
());
}
void
QtDumperHelper
::
clear
()
{
m_nameTypeMap
.
clear
();
m_qtVersion
=
0
;
m_dumperVersion
=
1.0
;
m_qtNamespace
.
clear
();
m_sizeCache
.
clear
();
qFill
(
m_specialSizes
,
m_specialSizes
+
SpecialSizeCount
,
0
);
m_expressionCache
.
clear
();
m_dumperVersion
.
clear
();
setQClassPrefixes
(
QString
());
}
QString
QtDumperHelper
::
msgDumperOutdated
(
double
requiredVersion
,
double
currentVersion
)
{
return
QCoreApplication
::
translate
(
"QtDumperHelper"
,
"Found a too-old version of the debugging helper library (%1); version %2 is required."
).
arg
(
currentVersion
).
arg
(
requiredVersion
);
}
static
inline
void
formatQtVersion
(
int
v
,
QTextStream
&
str
)
...
...
@@ -685,7 +695,7 @@ QString QtDumperHelper::toString(bool debug) const
return
QCoreApplication
::
translate
(
"QtDumperHelper"
,
"%n known types, Qt version: %1, Qt namespace: %2 Dumper version: %3"
,
0
,
QCoreApplication
::
CodecForTr
,
m_nameTypeMap
.
size
()).
arg
(
qtVersionString
(),
nameSpace
,
m_dumperVersion
);
m_nameTypeMap
.
size
()).
arg
(
qtVersionString
(),
nameSpace
).
arg
(
m_dumperVersion
);
}
QtDumperHelper
::
Type
QtDumperHelper
::
simpleType
(
const
QString
&
simpleType
)
const
...
...
@@ -774,11 +784,11 @@ QtDumperHelper::ExpressionRequirement QtDumperHelper::expressionRequirements(Typ
switch
(
t
)
{
case
QAbstractItemType
:
case
QVectorType
:
case
StdMapType
:
return
NeedsComplexExpression
;
case
QMapType
:
case
QMultiMapType
:
case
QMapNodeType
:
case
StdMapType
:
return
NeedsCachedExpression
;
default:
// QObjectSlotType, QObjectSignalType need the signal number, which is numeric
...
...
@@ -1130,6 +1140,25 @@ bool QueryDumperParser::handleValue(const char *k, int size)
return
true
;
}
static
inline
QString
qClassName
(
const
QString
&
qtNamespace
,
const
char
*
className
)
{
if
(
qtNamespace
.
isEmpty
())
return
QString
::
fromAscii
(
className
);
QString
rc
=
qtNamespace
;
rc
+=
QLatin1String
(
"::"
);
rc
+=
QString
::
fromAscii
(
className
);
return
rc
;
}
void
QtDumperHelper
::
setQClassPrefixes
(
const
QString
&
qNamespace
)
{
// Prefixes with namespaces
m_qPointerPrefix
=
qClassName
(
qNamespace
,
"QPointer"
);
m_qSharedPointerPrefix
=
qClassName
(
qNamespace
,
"QSharedPointer"
);
m_qSharedDataPointerPrefix
=
qClassName
(
qNamespace
,
"QSharedDataPointer"
);
m_qWeakPointerPrefix
=
qClassName
(
qNamespace
,
"QWeakPointer"
);
}
// parse a query
bool
QtDumperHelper
::
parseQuery
(
const
char
*
data
,
Debugger
debugger
)
{
...
...
@@ -1139,14 +1168,27 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
clear
();
m_qtNamespace
=
parser
.
data
().
qtNameSpace
;
setQtVersion
(
parser
.
data
().
qtVersion
);
setQClassPrefixes
(
m_qtNamespace
);
parseQueryTypes
(
parser
.
data
().
types
,
debugger
);
foreach
(
const
QueryDumperParser
::
SizeEntry
&
se
,
parser
.
data
().
sizes
)
addSize
(
se
.
first
,
se
.
second
);
m_expressionCache
=
parser
.
data
().
expressionCache
;
m_dumperVersion
=
parser
.
data
().
dumperVersion
;
// Version
if
(
!
parser
.
data
().
dumperVersion
.
isEmpty
())
{
double
dumperVersion
;
bool
ok
;
dumperVersion
=
parser
.
data
().
dumperVersion
.
toDouble
(
&
ok
);
if
(
ok
)
m_dumperVersion
=
dumperVersion
;
}
return
true
;
}
void
QtDumperHelper
::
addExpression
(
const
QString
&
expression
,
const
QString
&
value
)
{
m_expressionCache
.
insert
(
expression
,
value
);
}
void
QtDumperHelper
::
addSize
(
const
QString
&
name
,
int
size
)
{
// Special interest cases
...
...
@@ -1219,27 +1261,23 @@ QString QtDumperHelper::evaluationSizeofTypeExpression(const QString &typeName,
return
sizeofTypeExpression
(
typeName
);
}