Gem #119 : GDB Scripting— Part 1

by Jean-Charles Delay —AdaCore

Let's get started...

The GDB configuration file is located in the user's home directory:

${HOME}/.gdbinit.

When GDB starts, it sources this file -- if it exists -- meaning that it evaluates all the commands in the file, which can be any of the available CLI commands. At a basic level, this file can be used for simple configuration commands, such as selecting the default assembler format desired or changing the default input/output radix display style.

But GDB offers more: it can also read a macro-coding language that allows more powerful customizations.

This language follows the following format:

define _command_
  _code_
end
document _command_
_help text_
end

Commands defined like this are known as user commands. You can use and combine any standard GDB CLI commands in your user-defined macros.

The document section is important, since it is used by GDB to produce the output for the help command when associated with user-defined commands.

The GDB language also offers you a set of flow-control instructions and allows parameters. However, parameter manipulation is limited, because GDB only offers the following variables:

$argc
$arg0
$arg1
$arg2
...

However, note that GDB does not provide an array such as $argv.

Flow-control Instructions

GDB provides the "survival kit" for any language, meaning:

  • The set statement
  • The if control structure for conditions
  • The while control structure for loops

The Set Statement

You can assign the result of an expression to an environment variable with set, for example:

set $VAR = 0
set $byte = *(unsigned char *)$arg0

The If Statement

if _expression_
  _statements_
else
  _statements_
end

The While Statement

while _expression_
  _statements_
end

Controlled Output

During the execution of a command file or a user-defined command, normal GDB output is suppressed; the only output that appears is what is explicitly printed by the commands in the definition.

GDB provides three commands for generating any desired output:

echo _text_

This command prints _text_ including any nonprintable character escaped in a C-style string. No newline is printed unless you specify one using the ` ' character. You can also use escape sequences to output colors for a color terminal. For example, `\033[01;31' prints the following characters in red, whereas `\033[0m' resets the colored output to default.

output _expression_

This prints the value of _expression_ and nothing but that value (no newline, no `$nn = ').

printf _string_, _expressions_...

This prints the values of the _expressions_ under control of the format string _string_. The _expressions_ may be either numbers or pointers.

For example, you can print two values in hex like this:

printf "foo, bar-foo = 0x%x, 0x%x
", foo, bar-foo

Invoking the Shell

You can invoke a shell through the GDB command shell. If it exists, GDB uses the $SHELL environment variable to determine which shell to run. Otherwise it uses the default shell (`/bin/sh' on Unix systems, `COMMAND.COM' on MS-DOS, etc.).

Invoking make

Let's say that you compile your project using a Makefile and the make program. You may then want to use the GDB shell command to run make. GDB generally provides you with a make command of its own that executes the make program. For GNAT Pro Ada users though, the build program is gprbuild, which doesn't natively exist in GDB. However, you can define a command that will invoke it, for example:

define gprbuild
  if $argc == 0
      shell gprbuild
  end
  if $argc == 1
      shell gprbuild $arg0
  end
  if $argc > 1
      help gprbuild
  end
end
document gprbuild
Run the gprbuild program, optionally specifying the project name as parameter.
Usage: gprbuild [project_name]
end

Radix Display Style

GDB allows you to change the default radix display style -- for both input and output -- allowing the following formats: octal, decimal, and hexadecimal.

You can always enter numbers in octal, decimal, or hexadecimal in GDB by the usual conventions: octal numbers begin with `0', decimal numbers end with `.', and hexadecimal numbers begin with `0x'.

However, numbers that begin with none of these are, by default, entered in base 10.

The radix commands are the following:

set input-radix _base_
set output-radix _base_

Caution: base must itself be specified either unambiguously or using the current default radix.

Therefore, you can select the hexadecimal style by default through the following commands:

set input-radix 0x10 
set output-radix 0x10 

Prompt Look

Changing the prompt look is also possible, and similar to changing your shell prompt. The following example makes your gdb prompt `gdb$' display in red:

set prompt \033[01;31mgdb$ \033[0m

Preventing GDB from Pausing during Long Output

You might have already experienced that when GDB needs to print more lines than your terminal height can display, it pauses each time the console is full. To prevent that and make GDB display all information at once, use the following settings:

set height 0
set width 0

Changing the Assembler Code Format

GDB supports different kinds of instruction set formats when disassembling a program via the disassemble or x/i commands.

You can set GDB to use either intel or att format. However, this command is only defined for the Intel x86 family:

set disassembly-flavor intel
set disassembly-flavor att

The default instruction set is att (the AT&T flavor used by default by Unix assemblers for x86-based targets).

Optional Messages

By default, GDB is cautious, and asks what sometimes seem to be a lot of questions to confirm certain commands. If you are willing to unflinchingly face the consequences of your own commands, you can disable this "feature":

set confirm off

Going Further

For a full list of GDB capabilities, see the GDB manual.

In a future Gem we will provide examples of GDB's more sophisticated scripting capabilities.