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
Tobias Hunger
qt-creator
Commits
dd118df7
Commit
dd118df7
authored
Jan 14, 2010
by
hjk
Browse files
debugger: workaround failing 'info locals' on gdb 6.8-symbianelf
parent
0cadbd85
Changes
3
Hide whitespace changes
Inline
Side-by-side
share/qtcreator/gdbmacros/dumper.py
View file @
dd118df7
...
...
@@ -32,8 +32,8 @@ def isGoodGdb():
return
'parse_and_eval'
in
dir
(
gdb
)
def
cleanAddress
(
addr
):
#
w
e cannot use str(addr) as it yields rubbish for char pointers
# that might trigger Unicode encoding errors
#
W
e cannot use str(addr) as it yields rubbish for char pointers
# that might trigger Unicode encoding errors
.
return
addr
.
cast
(
gdb
.
lookup_type
(
"void"
).
pointer
())
def
parseAndEvaluate
(
exp
):
...
...
@@ -50,17 +50,27 @@ def parseAndEvaluate(exp):
gdb
.
execute
(
"set logging off"
)
return
gdb
.
history
(
0
)
def
listOfLocals
():
def
listOfLocals
(
varList
):
try
:
frame
=
gdb
.
selected_frame
()
#warn("FRAME %s: " % frame)
except
RuntimeError
:
warn
(
"FRAME NOT ACCESSIBLE"
)
return
[]
# gdb-6.8-symbianelf fails here
hasBlock
=
'block'
in
dir
(
frame
)
items
=
[]
if
isGoodGdb
():
# archer-tromey-python
block
=
frame
.
block
()
if
hasBlock
and
isGoodGdb
():
warn
(
"IS GOOD: %s "
%
varList
)
try
:
block
=
frame
.
block
()
#warn("BLOCK: %s " % block)
except
:
warn
(
"BLOCK NOT ACCESSIBLE"
)
return
items
while
True
:
if
block
is
None
:
warn
(
"UNEXPECTED 'None' BLOCK"
)
...
...
@@ -94,31 +104,55 @@ def listOfLocals():
# Assuming gdb 7.0 release or 6.8-symbianelf.
file
=
tempfile
.
mkstemp
(
prefix
=
"gdbpy_"
)
filename
=
file
[
1
]
#warn("VARLIST: %s " % varList)
#warn("VARLIST: %s " % len(varList))
gdb
.
execute
(
"set logging off"
)
gdb
.
execute
(
"set logging redirect off"
)
gdb
.
execute
(
"set logging file %s"
%
filename
)
gdb
.
execute
(
"set logging redirect on"
)
gdb
.
execute
(
"set logging on"
)
gdb
.
execute
(
"info locals"
)
gdb
.
execute
(
"info args"
)
try
:
gdb
.
execute
(
"info args"
)
# We cannot use "info locals" as at least 6.8-symbianelf
# aborts as soon as we hit unreadable memory.
# gdb.execute("interpreter mi '-stack-list-locals 0'")
# results in &"Recursive internal problem.\n", so we have
# the frontend pass us the list of locals.
# There are two cases, either varList is empty, so we have
# to fetch the list here, or it is not empty with the
# first entry being a dummy.
if
len
(
varList
)
==
0
:
gdb
.
execute
(
"info locals"
)
else
:
varList
=
varList
[
1
:]
except
:
pass
gdb
.
execute
(
"set logging off"
)
gdb
.
execute
(
"set logging redirect off"
)
file
=
open
(
filename
,
"r"
)
for
line
in
file
:
if
len
(
line
)
==
0
or
line
.
startswith
(
" "
):
continue
# The function parameters
pos
=
line
.
find
(
" = "
)
if
pos
<
0
:
continue
name
=
line
[
0
:
pos
]
varList
.
append
(
line
[
0
:
pos
])
file
.
close
()
os
.
remove
(
filename
)
#warn("VARLIST: %s " % varList)
for
name
in
varList
:
#warn("NAME %s " % name)
item
=
Item
(
0
,
"local"
,
name
,
name
)
try
:
item
.
value
=
frame
.
read_var
(
name
)
# this is a gdb value
except
RuntimeError
:
continue
pass
#continue
items
.
append
(
item
)
file
.
close
()
os
.
remove
(
filename
)
return
items
...
...
@@ -155,8 +189,8 @@ def isStringType(d, typeobj):
or
type
==
"wstring"
def
warn
(
message
):
if
verbosity
>
0
:
print
"XXX: %s
"
%
message
.
encode
(
"latin1"
)
if
True
or
verbosity
>
0
:
print
"XXX: %s
\n
"
%
message
.
encode
(
"latin1"
)
pass
def
check
(
exp
):
...
...
@@ -317,13 +351,24 @@ class FrameCommand(gdb.Command):
def
invoke
(
self
,
arg
,
from_tty
):
args
=
arg
.
split
(
' '
)
#warn("ARG: %s" % arg)
#warn("ARGS: %s" % args)
options
=
args
[
0
].
split
(
","
)
varList
=
args
[
1
][
1
:]
if
len
(
varList
)
==
0
:
varList
=
[]
else
:
varList
=
varList
.
split
(
","
)
expandedINames
=
set
(
args
[
2
].
split
(
","
))
watchers
=
""
if
len
(
args
)
>
3
:
watchers
=
base64
.
b16decode
(
args
[
3
],
True
)
#warn("WATCHERS: %s" % watchers)
useFancy
=
"fancy"
in
options
expandedINames
=
set
()
if
len
(
args
)
>
1
:
expandedINames
=
set
(
args
[
1
].
split
(
","
))
#warn("VARIABLES: %s" % varList)
#warn("EXPANDED INAMES: %s" % expandedINames)
module
=
sys
.
modules
[
__name__
]
self
.
dumpers
=
{}
...
...
@@ -337,7 +382,7 @@ class FrameCommand(gdb.Command):
output
+=
'"'
+
key
[
7
:]
+
'"'
output
+=
"],"
#output += "qtversion=[%d,%d,%d]"
output
+=
"qtversion=[4,6,0],"
#
output += "qtversion=[4,6,0],"
output
+=
"namespace=
\"
%s
\"
,"
%
qtNamespace
()
output
+=
"dumperversion=
\"
2.0
\"
,"
output
+=
"sizes=[],"
...
...
@@ -349,7 +394,6 @@ class FrameCommand(gdb.Command):
if
useFancy
:
for
key
,
value
in
module
.
__dict__
.
items
():
#if callable(value):
if
key
.
startswith
(
"qdump__"
):
self
.
dumpers
[
key
[
7
:]]
=
value
...
...
@@ -365,14 +409,28 @@ class FrameCommand(gdb.Command):
#
# Locals
#
for
item
in
listOfLocals
():
for
item
in
listOfLocals
(
varList
):
#warn("ITEM NAME %s: " % item.name)
#warn("ITEM VALUE %s: " % item.value)
try
:
#warn("ITEM VALUE %s: " % item.value)
# Throw on funny stuff, catch below.
dummy
=
str
(
item
.
value
)
except
:
# Locals with failing memory access.
d
.
beginHash
()
d
.
put
(
'iname="%s",'
%
item
.
iname
)
d
.
put
(
'name="%s",'
%
item
.
name
)
d
.
put
(
'addr="<not accessible>",'
)
d
.
put
(
'value="<not accessible>",'
)
d
.
put
(
'type="%s",'
%
item
.
value
.
type
)
d
.
put
(
'numchild="0"'
);
d
.
endHash
()
continue
type
=
item
.
value
.
type
if
type
.
code
==
gdb
.
TYPE_CODE_PTR
\
and
item
.
name
==
"argv"
and
str
(
type
)
==
"char **"
:
# Special handling for char** argv
:
# Special handling for char** argv
.
n
=
0
p
=
item
.
value
while
not
isNull
(
p
.
dereference
())
and
n
<=
100
:
...
...
@@ -398,7 +456,7 @@ class FrameCommand(gdb.Command):
d
.
endHash
()
else
:
# A "normal" local variable or parameter
# A "normal" local variable or parameter
.
try
:
addr
=
cleanAddress
(
item
.
value
.
address
)
d
.
beginHash
()
...
...
@@ -407,9 +465,8 @@ class FrameCommand(gdb.Command):
d
.
safePutItemHelper
(
item
)
d
.
endHash
()
except
AttributeError
:
# thrown by cleanAddreas with message
# "'NoneType' object has no attribute 'cast'"
# for optimized-out values
# Thrown by cleanAddress with message "'NoneType' object
# has no attribute 'cast'" for optimized-out values.
d
.
beginHash
()
d
.
put
(
'iname="%s",'
%
item
.
iname
)
d
.
put
(
'name="%s",'
%
item
.
name
)
...
...
@@ -426,9 +483,6 @@ class FrameCommand(gdb.Command):
# Watchers
#
d
.
safeoutput
=
""
watchers
=
""
if
len
(
args
)
>
2
:
watchers
=
base64
.
b16decode
(
args
[
2
],
True
)
if
len
(
watchers
)
>
0
:
for
watcher
in
watchers
.
split
(
"##"
):
(
exp
,
iname
)
=
watcher
.
split
(
"#"
)
...
...
@@ -764,7 +818,8 @@ class Dumper:
#warn("REAL VALUE: %s " % item.value)
#try:
# warn("REAL VALUE: %s " % item.value)
#except UnicodeEncodeError:
#except:
# #UnicodeEncodeError:
# warn("REAL VALUE: <unprintable>")
value
=
item
.
value
...
...
src/plugins/debugger/gdb/gdbengine.cpp
View file @
dd118df7
...
...
@@ -743,7 +743,7 @@ void GdbEngine::postCommand(const QByteArray &command, GdbCommandFlags flags,
void
GdbEngine
::
postCommandHelper
(
const
GdbCommand
&
cmd
)
{
if
(
!
stateAcceptsGdbCommands
(
state
()))
{
PENDING_DEBUG
(
_
(
"NO GDB PROCESS RUNNING, CMD IGNORED: "
)
+
cmd
.
command
);
PENDING_DEBUG
(
_
(
"NO GDB PROCESS RUNNING, CMD IGNORED: "
+
cmd
.
command
)
)
;
debugMessage
(
_
(
"NO GDB PROCESS RUNNING, CMD IGNORED: %1 %2"
)
.
arg
(
_
(
cmd
.
command
)).
arg
(
state
()));
return
;
...
...
@@ -1019,6 +1019,7 @@ void GdbEngine::executeDebuggerCommand(const QString &command)
// Called from CoreAdapter and AttachAdapter
void
GdbEngine
::
updateAll
()
{
PENDING_DEBUG
(
"UPDATING ALL
\n
"
);
QTC_ASSERT
(
state
()
==
InferiorUnrunnable
||
state
()
==
InferiorStopped
,
/**/
);
tryLoadDebuggingHelpers
();
reloadModulesInternal
();
...
...
@@ -2469,12 +2470,14 @@ void GdbEngine::handleStackSelectThread(const GdbResponse &)
void
GdbEngine
::
reloadFullStack
()
{
PENDING_DEBUG
(
"RELOAD FULL STACK"
);
postCommand
(
"-stack-list-frames"
,
WatchUpdate
,
CB
(
handleStackListFrames
),
QVariant
::
fromValue
<
StackCookie
>
(
StackCookie
(
true
,
true
)));
}
void
GdbEngine
::
reloadStack
(
bool
forceGotoLocation
)
{
PENDING_DEBUG
(
"RELOAD STACK"
);
QByteArray
cmd
=
"-stack-list-frames"
;
int
stackDepth
=
theDebuggerAction
(
MaximalStackDepth
)
->
value
().
toInt
();
if
(
stackDepth
&&
!
m_gdbAdapter
->
isTrkAdapter
())
...
...
@@ -2485,6 +2488,7 @@ void GdbEngine::reloadStack(bool forceGotoLocation)
// access the memory belonging to the lower frames. But as we know
// this sometimes happens, ask the second time immediately instead
// of waiting for the first request to fail.
// FIXME: Seems to work with 6.8.
if
(
m_gdbAdapter
->
isTrkAdapter
())
postCommand
(
cmd
,
WatchUpdate
);
postCommand
(
cmd
,
WatchUpdate
,
CB
(
handleStackListFrames
),
...
...
@@ -3640,52 +3644,12 @@ void GdbEngine::updateLocals(const QVariant &cookie)
{
m_pendingRequests
=
0
;
if
(
isSynchroneous
())
{
m_processedNames
.
clear
();
manager
()
->
watchHandler
()
->
beginCycle
();
//m_toolTipExpression.clear();
WatchHandler
*
handler
=
m_manager
->
watchHandler
();
QByteArray
expanded
;
QSet
<
QByteArray
>
expandedINames
=
handler
->
expandedINames
();
QSetIterator
<
QByteArray
>
jt
(
expandedINames
);
while
(
jt
.
hasNext
())
{
expanded
.
append
(
jt
.
next
());
expanded
.
append
(
','
);
}
if
(
expanded
.
isEmpty
())
expanded
.
append
(
"defaults,"
);
expanded
.
chop
(
1
);
QByteArray
watchers
;
if
(
!
m_toolTipExpression
.
isEmpty
())
watchers
+=
m_toolTipExpression
.
toLatin1
()
+
"#"
+
tooltipINameForExpression
(
m_toolTipExpression
.
toLatin1
());
QHash
<
QByteArray
,
int
>
watcherNames
=
handler
->
watcherNames
();
QHashIterator
<
QByteArray
,
int
>
it
(
watcherNames
);
while
(
it
.
hasNext
())
{
it
.
next
();
if
(
!
watchers
.
isEmpty
())
watchers
+=
"##"
;
if
(
it
.
key
()
==
WatchHandler
::
watcherEditPlaceHolder
().
toLatin1
())
watchers
+=
"<Edit>#watch."
+
QByteArray
::
number
(
it
.
value
());
else
watchers
+=
it
.
key
()
+
"#watch."
+
QByteArray
::
number
(
it
.
value
());
if
(
m_gdbAdapter
->
isTrkAdapter
())
{
postCommand
(
"-stack-list-locals 0"
,
WatchUpdate
,
CB
(
handleStackListLocals0
));
}
else
{
updateLocalsSync
(
QByteArray
());
}
QByteArray
options
;
if
(
theDebuggerBoolSetting
(
UseDebuggingHelpers
))
options
+=
"fancy,"
;
if
(
theDebuggerBoolSetting
(
AutoDerefPointers
))
options
+=
"autoderef,"
;
if
(
options
.
isEmpty
())
options
+=
"defaults,"
;
options
.
chop
(
1
);
postCommand
(
"-interpreter-exec console
\"
bb "
+
options
+
' '
+
expanded
+
' '
+
watchers
.
toHex
()
+
'"'
,
Discardable
,
CB
(
handleStackFrame
));
}
else
{
m_processedNames
.
clear
();
...
...
@@ -3710,6 +3674,69 @@ void GdbEngine::updateLocals(const QVariant &cookie)
}
}
void
GdbEngine
::
handleStackListLocals0
(
const
GdbResponse
&
response
)
{
if
(
response
.
resultClass
==
GdbResultDone
)
{
// 44^done,data={locals=[name="model",name="backString",...]}
QByteArray
varList
=
"vars"
;
// Dummy entry, will be stripped by dumper.
foreach
(
const
GdbMi
&
child
,
response
.
data
.
findChild
(
"locals"
).
children
())
{
varList
.
append
(
','
);
varList
.
append
(
child
.
data
());
}
updateLocalsSync
(
varList
);
}
}
void
GdbEngine
::
updateLocalsSync
(
const
QByteArray
&
varList
)
{
m_processedNames
.
clear
();
manager
()
->
watchHandler
()
->
beginCycle
();
//m_toolTipExpression.clear();
WatchHandler
*
handler
=
m_manager
->
watchHandler
();
QByteArray
expanded
;
QSet
<
QByteArray
>
expandedINames
=
handler
->
expandedINames
();
QSetIterator
<
QByteArray
>
jt
(
expandedINames
);
while
(
jt
.
hasNext
())
{
expanded
.
append
(
jt
.
next
());
expanded
.
append
(
','
);
}
if
(
expanded
.
isEmpty
())
expanded
.
append
(
"defaults,"
);
expanded
.
chop
(
1
);
QByteArray
watchers
;
if
(
!
m_toolTipExpression
.
isEmpty
())
watchers
+=
m_toolTipExpression
.
toLatin1
()
+
"#"
+
tooltipINameForExpression
(
m_toolTipExpression
.
toLatin1
());
QHash
<
QByteArray
,
int
>
watcherNames
=
handler
->
watcherNames
();
QHashIterator
<
QByteArray
,
int
>
it
(
watcherNames
);
while
(
it
.
hasNext
())
{
it
.
next
();
if
(
!
watchers
.
isEmpty
())
watchers
+=
"##"
;
if
(
it
.
key
()
==
WatchHandler
::
watcherEditPlaceHolder
().
toLatin1
())
watchers
+=
"<Edit>#watch."
+
QByteArray
::
number
(
it
.
value
());
else
watchers
+=
it
.
key
()
+
"#watch."
+
QByteArray
::
number
(
it
.
value
());
}
QByteArray
options
;
if
(
theDebuggerBoolSetting
(
UseDebuggingHelpers
))
options
+=
"fancy,"
;
if
(
theDebuggerBoolSetting
(
AutoDerefPointers
))
options
+=
"autoderef,"
;
if
(
options
.
isEmpty
())
options
+=
"defaults,"
;
options
.
chop
(
1
);
postCommand
(
"bb "
+
options
+
" @"
+
varList
+
' '
+
expanded
+
' '
+
watchers
.
toHex
(),
WatchUpdate
,
CB
(
handleStackFrame
));
}
void
GdbEngine
::
handleStackFrame
(
const
GdbResponse
&
response
)
{
if
(
response
.
resultClass
==
GdbResultDone
)
{
...
...
src/plugins/debugger/gdb/gdbengine.h
View file @
dd118df7
...
...
@@ -450,6 +450,7 @@ private: ////////// View & Data Stuff //////////
void
updateLocals
(
const
QVariant
&
cookie
=
QVariant
());
void
handleStackListLocals
(
const
GdbResponse
&
response
);
void
handleStackListLocals0
(
const
GdbResponse
&
response
);
WatchData
localVariable
(
const
GdbMi
&
item
,
const
QStringList
&
uninitializedVariables
,
QMap
<
QByteArray
,
int
>
*
seen
);
...
...
@@ -484,6 +485,8 @@ private: ////////// Convenience Functions //////////
int
buttons
=
0
);
void
debugMessage
(
const
QString
&
msg
);
QMainWindow
*
mainWindow
()
const
;
void
updateLocalsSync
(
const
QByteArray
&
varList
);
};
}
// namespace Internal
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment