A Dive into GDB Scripting Hidden Gems with Albert Lee

GDB Scripting – Hidden Gems
Albert Lee
2018-11-15
Print people
Put_Line (“IN CONNECT...”);
Put_Line (“   credentials: “ & Image (Credentials));
if Check_Credentials (Session, Credentials) then
   Put_Line (“   credentials accepted”);
   Session.Authenticated := True;
end if;
Put_Line (“<--”);
2
Debugger people
$ gdb ./test_connect
(gdb) break connect
(gdb) run
(gdb) print credentials
(gdb) next
(gdb) next
3
GDB Tour
GDB lets you inspect the program as it runs
Low-level aspects (registers, assembly, …)
Source-level aspects (source locations, variables, …)
4
GDB Tour: low-level view (1/3): registers
(gdb)
 info registers
rax        
 
0x1             
 
1
rbx        
 
0x0             
 
0
rcx        
 
0xfbad0087      
 
4222419079
rdx        
 
0x0             
 
0
rsi        
 
0x7ffff7f8e710  
 
140737353672464
[…]
r15        
 
0x0             
 
0
rip        
 
0x403d01        
 
0x403d01
<main+9>
eflags     
 
0x206           
 
[ PF IF ]
5
GDB Tour: low-level view (2/3): ASM code
(gdb)
 disassemble
Dump of assembler code for function _ada_main:
   0x0000000000403cf8 <+0>: 
 
push   %rbp
   0x0000000000403cf9 <+1>: 
 
mov
 
%rsp,%rbp
   0x0000000000403cfc <+4>: 
 
push   %rbx
   0x0000000000403cfd <+5>: 
 
sub
 
$0x8,%rsp
=> 0x0000000000403d01 <+9>: 
 
mov
 
$0x428248,%eax
   0x0000000000403d06 <+14>:
 
mov
 
$0x428258,%edx
   0x0000000000403d0b <+19>:
 
mov
 
%rax,%rcx
   0x0000000000403d0e <+22>:
 
mov
 
%rdx,%rbx
[…]
6
GDB Tour: low-level view (3/3): memory
(gdb)
 x/3gx $rax
0x428248:   
 
0x77202c6f6c6c6548  
 
0x00000021646c726f
0x428258:   
 
0x0000000d00000001
(gdb)
 x/14bo $rax
0x428248:   0110
 
0145
 
0154
 
0154
 
0157
 
054 
 
040
 
0167
0x428250:   0157
 
0162
 
0154
 
0144
 
041 
 
0
(gdb)
 x/1s $rax
0x428248:   "Hello, world!["00"]"
7
GDB Tour: source-level view
(gdb)
 list
8
9      
 
procedure Initialize
10       
 
(R : out Record_Type;
11          I : Integer; C : Character) is
12     
 
begin
13        
 
R.A := I;
14        
 
R.B := 2 * I;
15        
 
R.C := C;
16     
 
end Initialize;
Corresponding location in sources:
8
GDB Tour: source-level view
(gdb)
 info args
r = (a => -8864, b => 32767, c => 84 'T')
i = 10
c = 65 'A'
(gdb)
 info local
b = 75
(gdb)
 print r.b
$1 = 32767
Inspection of arguments and local variables, evaluation of arbitrary expression:
9
GDB Tour: source-level view
(gdb)
 info local
b = 75
(gdb)
 backtrace
#0  main.initialize (r=..., i=10, c=65 'A') at main.adb:17
#1  0x0000000000403dd3 in main () at main.adb:23
(gdb)
 up
#1  0x0000000000403dd3 in main () at main.adb:23
23     
 
Initialize (R, 10, 'A');
(gdb)
 info local
r = (a => -8864, b => 32767, c => 100 'd')
Inspection of the call stack:
10
GDB Tour: source-level view
(gdb)
 catch exception
(gdb)
 break engine.adb:549
(gdb)
 break Display.Text.Show_Line
(gdb)
 run
Breakpoint 3, display.text.show_line (line=...)
   at display-text.adb:123
123   Line_Length : constant Natural := Line’Length;
Pause on interesting events: when specific code is executed
11
GDB Tour: source-level view
(gdb)
 watch Display.Text.Current_Line
(gdb)
 continue
Hardware watchpoint 4: Display.Text.Current_Line
Old value = 56
New value = 57
display.text.show_line (line=...)
   at display-text.adb:130
130   Current_Line := Current_Line + 1;
Pause on interesting events: when data changes
12
GDB Scripting (finally)
GDB makes the state of your program available via a programming interface
You can extend GDB with scripts!
Programmatic access to program state
Custom breakpoints, custom commands
Pretty-printers
Auto-loading extensions
You can also run Python code directly inside GDB:
(gdb) python-interactive ‘Hello, {}!’.format(‘world’)
‘Hello, world!’
(gdb) pi import antigravity
(gdb) source my_gdb_extensions.py
13
GDB Scripting: programmatic inspection
(gdb)
 pi frame = gdb.selected_frame()
(gdb)
 pi {symbol.name: str(symbol.value(frame))
          
for
 symbol 
in
 frame.block()
          
if
 symbol.is_variable}
{'r': "(a => 10, b => 75, c => 65 'A')"}
For instance, a Python re-implementation of the “info local” command:
14
GDB Scripting: custom breakpoints
(gdb)
 break buggy_function if the caller is some_function
Have you ever wanted to do something like this?
i.e. put a breakpoint on “buggy_function” but don’t stop unless “some_function” is
the caller.
Using the Python API, you can implement this feature.
15
GDB Scripting: custom breakpoints
class BreakIfCaller(gdb.Breakpoint):
    def __init__(self, spec, caller_name):
        super(BreakIfCaller, self).__init__(spec)
        self.caller_name = caller_name
    def stop(self):
        try:
            caller_name = (gdb.selected_frame()
                           .older().function().name)
        except gdb.error:
            return False
        return caller_name == self.caller_name
# And then in GDB:
(gdb)
 pi BreakIfCaller(‘buggy_function’, ‘other_function’)
16
GDB Scripting: custom commands
(gdb)
 break-if-caller buggy_function some_function
The Python API lets you create new commands
Subclass 
gdb.Command
 and override 
.invoke
The previous example could be exposed as:
17
GDB Scripting: pretty-printers
--  In your Ada source code…
package Int_Vectors is new Ada.Containers.Vectors
  (Index_Type => Positive, Element_Type => Integer);
V : Int_Vectors.Vector;
# … then in GDB:
(gdb)
 print v
$1 = (elements => 0x459260, last => 3, tc => (busy => 0,
lock => 0))
# Whereas we want:
(gdb)
 print v
$1 = break.int_vectors.vector of length 3 = {1, 2, 3}
Have you ever tried to inspect the content of a vector?
18
GDB Scripting: pretty-printers
GDB pretty-printers are Python objects
Register them to GDB and override their methods to:
make them match objects to pretty-print
yield text to display
They automatically compose (e.g. nested containers)
Pretty-printers for standard containers in GNAT Pro
(
https://github.com/AdaCore/gnat-gdb-scripts
)
19
GDB Scripting: auto-loading extensions
Writing extensions is cool
Have GDB automatically load them is even better:
my_program
-gdb.py
 OR 
my_shared_lib
-gdb.py
.debug_gdb_script
 section in executables
Requires some “safe path” tuning for security
20
GDB Scripting
The Python API offers much more
API reference in GDB’s documentation
The sky’s the limit!
21
Slide Note
Embed
Share

Delve into the world of GDB scripting hidden gems with Albert Lee on November 15, 2018. Explore essential features like debugging, register inspection, low-level memory views, and source-level code analysis. Understand techniques to enhance your debugging skills through the exploration of assembly code and program memory.

  • GDB scripting
  • Debugging techniques
  • Low-level inspection
  • Source-level analysis
  • Assembly code exploration

Uploaded on Sep 11, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. GDB Scripting Hidden Gems Albert Lee 2018-11-15

  2. Print people Put_Line ( IN CONNECT... ); Put_Line ( credentials: & Image (Credentials)); if Check_Credentials (Session, Credentials) then Put_Line ( credentials accepted ); Session.Authenticated := True; end if; Put_Line ( <-- ); 2

  3. Debugger people $ gdb ./test_connect (gdb) break connect (gdb) run (gdb) print credentials (gdb) next (gdb) next 3

  4. GDB Tour GDB lets you inspect the program as it runs Low-level aspects (registers, assembly, ) Source-level aspects (source locations, variables, ) 4

  5. GDB Tour: low-level view (1/3): registers (gdb) (gdb) info registers rax rbx rcx rdx rsi [ ] r15 rip <main+9> eflags 0x1 0x0 0xfbad0087 0x0 0x7ffff7f8e710 1 0 4222419079 0 140737353672464 0x0 0x403d01 0 0x403d01 0x206 [ PF IF ] 5

  6. GDB Tour: low-level view (2/3): ASM code (gdb) (gdb) disassemble Dump of assembler code for function _ada_main: 0x0000000000403cf8 <+0>: 0x0000000000403cf9 <+1>: 0x0000000000403cfc <+4>: 0x0000000000403cfd <+5>: => 0x0000000000403d01 <+9>: $0x428248,%eax 0x0000000000403d06 <+14>: $0x428258,%edx 0x0000000000403d0b <+19>: 0x0000000000403d0e <+22>: [ ] push %rbp mov push %rbx sub mov %rsp,%rbp $0x8,%rsp mov mov mov %rax,%rcx %rdx,%rbx 6

  7. GDB Tour: low-level view (3/3): memory (gdb) (gdb) x/3gx $rax 0x428248: 0x428258: 0x77202c6f6c6c6548 0x0000000d00000001 0x00000021646c726f (gdb) (gdb) x/14bo $rax 0x428248: 0110 0167 0x428250: 0157 0145 0154 0154 0157 054 040 0162 0154 0144 041 0 (gdb) (gdb) x/1s $rax 0x428248: "Hello, world!["00"]" 7

  8. GDB Tour: source-level view Corresponding location in sources: (gdb) (gdb) list 8 9 procedure Initialize 10 11 I : Integer; C : Character) is 12 begin 13 R.A := I; 14 R.B := 2 * I; 15 R.C := C; 16 end Initialize; (R : out Record_Type; 8

  9. GDB Tour: source-level view Inspection of arguments and local variables, evaluation of arbitrary expression: (gdb) (gdb) info args r = (a => -8864, b => 32767, c => 84 'T') i = 10 c = 65 'A' (gdb) (gdb) info local b = 75 (gdb) (gdb) print r.b $1 = 32767 9

  10. GDB Tour: source-level view Inspection of the call stack: (gdb) (gdb) info local b = 75 (gdb) (gdb) backtrace #0 main.initialize (r=..., i=10, c=65 'A') at main.adb:17 #1 0x0000000000403dd3 in main () at main.adb:23 (gdb) (gdb) up #1 0x0000000000403dd3 in main () at main.adb:23 23 Initialize (R, 10, 'A'); (gdb) (gdb) info local r = (a => -8864, b => 32767, c => 100 'd') 10

  11. GDB Tour: source-level view Pause on interesting events: when specific code is executed (gdb) (gdb) catch exception (gdb) (gdb) break engine.adb:549 (gdb) (gdb) break Display.Text.Show_Line (gdb) (gdb) run Breakpoint 3, display.text.show_line (line=...) at display-text.adb:123 123 Line_Length : constant Natural := Line Length; 11

  12. GDB Tour: source-level view Pause on interesting events: when data changes (gdb) (gdb) watch Display.Text.Current_Line (gdb) (gdb) continue Hardware watchpoint 4: Display.Text.Current_Line Old value = 56 New value = 57 display.text.show_line (line=...) at display-text.adb:130 130 Current_Line := Current_Line + 1; 12

  13. GDB Scripting (finally) GDB makes the state of your program available via a programming interface You can extend GDB with scripts! Programmatic access to program state Custom breakpoints, custom commands Pretty-printers Auto-loading extensions You can also run Python code directly inside GDB: (gdb) python-interactive Hello, {}! .format( world ) Hello, world! (gdb) pi import antigravity (gdb) source my_gdb_extensions.py 13

  14. GDB Scripting: programmatic inspection For instance, a Python re-implementation of the info local command: (gdb) (gdb) pi frame = gdb.selected_frame() (gdb) (gdb) pi {symbol.name: str(symbol.value(frame)) for for symbol in in frame.block() if if symbol.is_variable} {'r': "(a => 10, b => 75, c => 65 'A')"} 14

  15. GDB Scripting: custom breakpoints Have you ever wanted to do something like this? (gdb) (gdb) break buggy_function if the caller is some_function i.e. put a breakpoint on buggy_function but don t stop unless some_function is the caller. Using the Python API, you can implement this feature. 15

  16. GDB Scripting: custom breakpoints class BreakIfCaller(gdb.Breakpoint): def __init__(self, spec, caller_name): super(BreakIfCaller, self).__init__(spec) self.caller_name = caller_name def stop(self): try: caller_name = (gdb.selected_frame() .older().function().name) except gdb.error: return False return caller_name == self.caller_name # And then in GDB: (gdb) (gdb) pi BreakIfCaller( buggy_function , other_function ) 16

  17. GDB Scripting: custom commands The Python API lets you create new commands Subclass gdb.Command and override .invoke The previous example could be exposed as: (gdb) (gdb) break-if-caller buggy_function some_function 17

  18. GDB Scripting: pretty-printers Have you ever tried to inspect the content of a vector? -- package Int_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Integer); V : Int_Vectors.Vector; In your Ada source code # then in GDB: (gdb) (gdb) print v $1 = (elements => 0x459260, last => 3, tc => (busy => 0, lock => 0)) # Whereas we want: (gdb) (gdb) print v $1 = break.int_vectors.vector of length 3 = {1, 2, 3} 18

  19. GDB Scripting: pretty-printers GDB pretty-printers are Python objects Register them to GDB and override their methods to: make them match objects to pretty-print yield text to display They automatically compose (e.g. nested containers) Pretty-printers for standard containers in GNAT Pro (https://github.com/AdaCore/gnat-gdb-scripts) 19

  20. GDB Scripting: auto-loading extensions Writing extensions is cool Have GDB automatically load them is even better: my_program-gdb.py OR my_shared_lib-gdb.py .debug_gdb_script section in executables Requires some safe path tuning for security 20

  21. GDB Scripting The Python API offers much more API reference in GDB s documentation The sky s the limit! 21

Related


More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#