vuvova / gdb-tools Goto Github PK
View Code? Open in Web Editor NEWVarious tools to improve the gdb experience
License: BSD 3-Clause "New" or "Revised" License
Various tools to improve the gdb experience
License: BSD 3-Clause "New" or "Revised" License
currently a function name must be an identifier,
(foo,bar)(1)
will not work. it's a bug.
In this example:
struct S
{
int _i;
long _l;
};
struct S s[] = {{4, 5}, {94, 34}, {83, 95}};
int main()
{
return s[0]._i + s[2]._l;
}
When trying to print only the _i
member:
(gdb) dl s[..3]._i
Expected '#' or '.' or '->' or '-->' or '@' or '[' or '[[' or '(' or '/' or '*' or '%' or '-' or '+' or '<<' or '>>' or '..' or '<=?' or '>=?' or '<?' or '>?' o
r '<=' or '>=' or '<' or '>' or '==?' or '!=?' or '==' or '!=' or '&' or '^' or '|' or '&&' or '||' or '?' or ',' or '=>' or ';' or EOF at position (1, 9) => 's
[..3]._*i'.
With this possible fix ...:
--- a/duel/parser.py
+++ b/duel/parser.py
@@ -57,7 +57,7 @@ def char(): return RegExMatch(r"'([^'\\]|"+escapes+")'")
def string(): return RegExMatch(r'"([^\\"]|'+escapes+')*"')
def ident(): return RegExMatch(r'[A-Za-z_]\w*')
def gdbvar(): return RegExMatch(r'\$\w+')
-def underscores(): return RegExMatch(r'_+')
+def underscores(): return RegExMatch(r'_+\b')
def parens(): return [('(', expression, ')'), ('{', expression, '}')]
def term21(): return [real, hexadecimal, decimal, octal, char, string,
underscores, ident, gdbvar]
... it looks better:
(gdb) dl s[..3]._i
s[0]._i = 4
s[1]._i = 94
s[2]._i = 83
(gdb) set variable $i = 0
(gdb) p $i
$1 = 0
(gdb) dl $i
Expected 'if' or ident or '&&/' or '||/' or '#/' or '+/' or '-' or '*' or '&' or '!' or '~' or '(cast)' or real or hexadecimal or decimal or octal or char or string or underscores or ident or '(' or '{' or '..' at position (1, 1) => '*$i'
is it possible to fix this?)
It would be very useful to have this package on PyPI.
Just a quick tip for those who might encounter this error when having both python 2.7 and 3.7 installed. GDB uses python 3 while your pip
might be from python 2. So before importing duel
in your .gdbinit.py you might want to add:
sys.path.append("/usr/local/lib/python2.7/dist-packages")
Just find out where it was installed:
$ pip show gdb-tools
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.
Name: gdb-tools
Version: 1.3
Summary: Various tools to improve the gdb experience
Home-page: https://github.com/vuvova/gdb-tools
Author: Sergei Golubchik
Author-email: [email protected]
License: BSD-3-clause
Location: /usr/local/lib/python2.7/dist-packages
Requires: arpeggio
Required-by:
But probably it's a good idea to discard 2.7 like disclaimer says... :)
The help.md
fails to load with Python 3.6 because of ...
.. the fourth \xe2\x80\x94 boolean OR. Just like in C, AND and OR
The error is:
Traceback (most recent call last):
File "<string>", line 7, in <module>
File "/opt/work/chris/gdb/duel/__init__.py", line 5, in <module>
from duel.help import *
File "/opt/work/chris/gdb/duel/help.py", line 15, in <module>
with open(__file__.rstrip("pyc") + "md") as f: LONGHELP = ''.join(f)
File "/usr/local/lib/python3.6/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
Within the code I'm debugging, I have an array of pointers to a struct. I'd like to be able to print all the structs in from this array. However, when I attempt a simple print, gdb works, but duel does not. Sample session:
(gdb) print *(HOST *)hosts->entry[9]->key
$22 = {scheme = 0x7ffff7bbbb4b "http", host = 0x5555557b4af2 "example.com", robot_job = 0x0, robots = 0x0, queue = 0x0, host_docs = 0x7fffec000b20,
tree_docs = 0x7fffec005c90, root = 0x7fffec005d70, robot = 0x0, retry_ts = 0, qsize = 0, failures = 0, port = 80, blocked = false}
(gdb) dl *(HOST *)hosts->entry[9]->key
'*'
(gdb) dl (HOST *)hosts->entry[9]->key
(HOST *)hosts->entry[9]->key = 0x5555557b1e90
(gdb)
As can be seen, the hosts->entry
is an array of HOST *
pointers. With gdb, a print statement is able to dereference the pointer correctly, however with duel, it doesn't seem to work, Is this a bug, or am I using duel wrong?
IMO, there is a fundamental printing behavior missing here, the support of print format:
FMT is a repeat count followed by a format letter and a size letter.
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
t(binary), f(float), a(address), i(instruction), c(char), s(string)
and z(hex, zero padded on the left).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
The specified number of objects of the specified size are printed
according to the format.
Anyway, I can't wait the next bug to really test DUEL, thanks!
>> uname -a
Linux archlinux 6.3.9-zen1-1-zen
>> python --version
Python 3.11.3
>> pacs -nl python-re
python-regex 2023.6.3-1
>> cat ~/.gdbinit
py import duel
>> gdb -q -x ~/.gdbinit
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/chz/.local/lib/python3.11/site-packages/duel/__init__.py", line 5, in <module>
from duel.help import *
File "/home/chz/.local/lib/python3.11/site-packages/duel/help.py", line 38, in <module>
OPERATORS = re.sub(r'^(?s).*\nOperators\n---------\n\n*(.*?\n)[^\n]+\n-----+\n.*$', r'\1', LONGHELP)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/__init__.py", line 185, in sub
return _compile(pattern, flags).sub(repl, string, count)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/__init__.py", line 294, in _compile
p = _compiler.compile(pattern, flags)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_compiler.py", line 743, in compile
p = _parser.parse(p, flags)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 980, in parse
p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 455, in _parse_sub
itemsappend(_parse(source, state, verbose, nested + 1,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 841, in _parse
raise source.error('global flags not at the start '
re.error: global flags not at the start of the expression at position 1
/home/chz/.gdbinit:1: Error in sourced command file:
Error while executing Python code.
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/chz/.local/lib/python3.11/site-packages/duel/__init__.py", line 5, in <module>
from duel.help import *
File "/home/chz/.local/lib/python3.11/site-packages/duel/help.py", line 38, in <module>
OPERATORS = re.sub(r'^(?s).*\nOperators\n---------\n\n*(.*?\n)[^\n]+\n-----+\n.*$', r'\1', LONGHELP)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/__init__.py", line 185, in sub
return _compile(pattern, flags).sub(repl, string, count)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/__init__.py", line 294, in _compile
p = _compiler.compile(pattern, flags)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_compiler.py", line 743, in compile
p = _parser.parse(p, flags)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 980, in parse
p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 455, in _parse_sub
itemsappend(_parse(source, state, verbose, nested + 1,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 841, in _parse
raise source.error('global flags not at the start '
re.error: global flags not at the start of the expression at position 1
/home/chz/.gdbinit:1: Error in sourced command file:
Error while executing Python code.
(gdb)
>> gdb -q -n
(gdb) py import duel
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/chz/.local/lib/python3.11/site-packages/duel/__init__.py", line 5, in <module>
from duel.help import *
File "/home/chz/.local/lib/python3.11/site-packages/duel/help.py", line 38, in <module>
OPERATORS = re.sub(r'^(?s).*\nOperators\n---------\n\n*(.*?\n)[^\n]+\n-----+\n.*$', r'\1', LONGHELP)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/__init__.py", line 185, in sub
return _compile(pattern, flags).sub(repl, string, count)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/__init__.py", line 294, in _compile
p = _compiler.compile(pattern, flags)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_compiler.py", line 743, in compile
p = _parser.parse(p, flags)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 980, in parse
p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 455, in _parse_sub
itemsappend(_parse(source, state, verbose, nested + 1,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/re/_parser.py", line 841, in _parse
raise source.error('global flags not at the start '
re.error: global flags not at the start of the expression at position 1
Error while executing Python code.
(gdb)
Considering the example from the help text:
..100 => if(emp[_].code>400) emp[_].code,emp[_].name
I'm trying something similar, with this code:
struct Struct
{
int i;
int j;
};
struct Struct num[10] = { {5, 43}, {10, 94}, {94, 74}, {14, 85} };
int main()
{
return num[0].i;
}
The output of this command is not what I expect:
(gdb) dl ..10 => if(num[_].i >= 11) _
if(num[2].i >= 11) {i = 94, j = 74} = {i = 94, j = 74}
if(num[3].i >= 11) {i = 14, j = 85} = {i = 14, j = 85}
If I use"__" instead, it shows the result I would expect with "_":
(gdb) dl ..10 => if(num[_].i >= 11) __
if(num[2].i >= 11) 2 = 2
if(num[3].i >= 11) 3 = 3
What I really want to do is use "_" as the index again, to print another member, but here I have the same issue:
(gdb) dl ..10 => if(num[_].i >= 11) num[_].j
Cannot convert value to int.
(gdb) dl ..10 => if(num[_].i >= 11) num[__].j
if(num[2].i >= 11) num[2].j = 74
if(num[3].i >= 11) num[3].j = 85
It gets even weirder if I add another condition:
(gdb) dl ..10 => if(num[_].i >= 11 && num[_].i <= 50) _
Cannot convert value to int.
(gdb) dl ..10 => if(num[_].i >= 11 && num[__].i <= 50) _
if(num[3].i >= 11 && num[3].i <= 50) {i = 14, j = 85} = {i = 14, j = 85}
(gdb) dl ..10 => if(num[_].i >= 11 && num[__].i <= 50) __
if(num[3].i >= 11 && num[3].i <= 50) {i = 14, j = 85} = {i = 14, j = 85}
(gdb) dl ..10 => if(num[_].i >= 11 && num[__].i <= 50) ___
if(num[3].i >= 11 && num[3].i <= 50) 3 = 3
Am I misunderstanding how "_" is supposed to work?
F.ex. I do:
dl dbug_print_fk((FK_info *)el->share->foreign_keys->first-->(next!=?0x21052a8)->info)
and get this output:
dbug_print_fk((FK_info *)el->share->foreign_keys->first->info) = 0x2133a50 <dbug_item_print_buf> "foreign_id: fk_ch1; foreign_db: test; foreign_table: ch1; referenced_db: test; referenced_table: t1; referenced_key_name: fk_ch1; update_method: ???; delete_method: ???; foreign_fields: [0]: xid; referenced_fields: [0]: id"
dbug_print_fk((FK_info *)el->share->foreign_keys->first->(next !=? 0x21052a8)->info) = 0x2133a50 <dbug_item_print_buf> "foreign_id: fk_ch1_2; foreign_db: test; foreign_table: ch1; referenced_db: test; referenced_table: t2; referenced_key_name: fk_ch1_2; update_method: ???; delete_method: ???; foreign_fields: [0]: xid2; referenced_fields: [0]: id"
dbug_print_fk((FK_info *)el->share->foreign_keys->first-->(next !=? 0x21052a8)[[2]]->info) = 0x2133a50 <dbug_item_print_buf> "foreign_id: fk_ch1_3; foreign_db: test; foreign_table: ch1; referenced_db: test; referenced_table: t3; referenced_key_name: fk_ch1_3; update_method: ???; delete_method: ???; foreign_fields: [0]: xid; referenced_fields: [0]: id"
I'd really benefit from shorter output, like this:
0x2133a50 <dbug_item_print_buf> "foreign_id: fk_ch1; foreign_db: test; foreign_table: ch1; referenced_db: test; referenced_table: t1; referenced_key_name: fk_ch1; update_method: ???; delete_method: ???; foreign_fields: [0]: xid; referenced_fields: [0]: id"
0x2133a50 <dbug_item_print_buf> "foreign_id: fk_ch1_2; foreign_db: test; foreign_table: ch1; referenced_db: test; referenced_table: t2; referenced_key_name: fk_ch1_2; update_method: ???; delete_method: ???; foreign_fields: [0]: xid2; referenced_fields: [0]: id"
0x2133a50 <dbug_item_print_buf> "foreign_id: fk_ch1_3; foreign_db: test; foreign_table: ch1; referenced_db: test; referenced_table: t3; referenced_key_name: fk_ch1_3; update_method: ???; delete_method: ???; foreign_fields: [0]: xid; referenced_fields: [0]: id"
Is there such an option?
If a function returns a pointer to a struct, you can't access the members with ->.
Basically I want that this test succeeds:
diff --git a/tests/test.cc b/tests/test.cc
index f3952f8..3c02623 100644
--- a/tests/test.cc
+++ b/tests/test.cc
@@ -19,7 +19,7 @@ struct t t0={ 0, 0, 0}, t1={ 1, 0, 0}, t2={ 2, 0, 0}, t3={ 3, 0, 0},
t4={ 4, 0, 0}, t5={ 5, 0, 0}, t6={ 6, 0, 0}, t7={ 7, 0, 0},
t8={ 8,&t0,&t1}, t9={ 9,&t2,&t3}, ta={10,&t4,&t5}, tb={11,&t6,&t7},
tc={12,&t8,&t9}, td={13,&ta,&tb}, te={14,&tc,&td}, *tree = &te;
-
+struct t *struct_pointer(void) { return &t8; }
int main()
{
diff --git a/tests/test.gdb b/tests/test.gdb
index 2bdaa0a..28be273 100644
--- a/tests/test.gdb
+++ b/tests/test.gdb
@@ -462,3 +462,5 @@ $a + $1 = 10
$_strlen(s) = 2
(gdb) dl $_regex(s, ".*[0-9]")
$_regex(s,".*[0-9]") = true
+(gdb) dl struct_pointer()->v
+struct_pointer()->v = 8
But currently I get this error:
@@ -298,4 +298,4 @@
*(char *)s = 115 's'
$_strlen(s) = 2
$_regex(s,".*[0-9]") = true
-struct_pointer()->v = 8
+Expected '&&/' or '||/' or '#/' or '+/' or '-' or '*' or '&' or '!' or '~' or '(cast)' or real or hexadecimal or decimal or octal or char or string or underscores or ident or gdbvar or '(' or '{' at position (1, 18) => 'pointer()-*>v'.
The pip package is not working on debian stretch/ubuntu 14.04,
It appears the gdb is packaged with python 3.x (3.5), whereas gdb-tools is still 2.7.
Can this package made available for python 3 as well ?
support lldb
Basically, when in [[x]]
the x value is negative, add the sequence count to it, so e.g. [[-1]]
would get you the last value in the sequence.
Then you wouldn't need the #/
operator where you have to duplicate the full expression, just to get the final value.
This would give you the final 3 values:
(gdb) dl (100..199)[[-3..-1]]
(100..199)[[-3]] = 197
(100..199)[[-2]] = 198
(100..199)[[-1]] = 199
My implementation looks like this now:
--- a/duel/expr.py
+++ b/duel/expr.py
@@ -143,7 +143,14 @@ class StructWalk(BinaryBase):
class TakeNth(BinaryBase):
name_ = '{0}[[{1}]]'
def eval(self):
+ l = None
for n2,v2 in self.arg2_.eval():
+ if v2 < 0:
+ if l is None:
+ l = sum(1 for i in self.arg1_.eval())
+ v2 += l
+ if v2 < 0:
+ continue
val = self.arg1_.eval()
for i in xrange(0,v2): next(val)
n1, v1 = next(val)
What do you think?
Btw, duel is awesome.
I'm very excited about duel (I remember using the non-python version back in the 90's). I wonder if it's possible to call functions the same way that the print command does. Currently:
(gdb) dl head-->next->getKey()
Value is not callable (not TYPE_CODE_FUNC).
(gdb) p head->next->getKey()
$68 = "foobar"
At my company we often have containers filled with pointers to a base classes. I'd like to call a virtual function to get more info about the object. I could do it in two steps (get the address in duel and call the function manually) but that won't work in a loop.
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.