gdb: i386
21.4.2 x86 Architecture-specific Issues
---------------------------------------
'set struct-convention MODE'
Set the convention used by the inferior to return 'struct's and
'union's from functions to MODE. Possible values of MODE are
'"pcc"', '"reg"', and '"default"' (the default). '"default"' or
'"pcc"' means that 'struct's are returned on the stack, while
'"reg"' means that a 'struct' or a 'union' whose size is 1, 2, 4,
or 8 bytes will be returned in a register.
'show struct-convention'
Show the current setting of the convention to return 'struct's from
functions.
21.4.2.1 Intel "Memory Protection Extensions" (MPX).
....................................................
Memory Protection Extension (MPX) adds the bound registers 'BND0' (1)
through 'BND3'. Bound registers store a pair of 64-bit values which are
the lower bound and upper bound. Bounds are effective addresses or
memory locations. The upper bounds are architecturally represented in
1's complement form. A bound having lower bound = 0, and upper bound =
0 (1's complement of all bits set) will allow access to the entire
address space.
'BND0' through 'BND3' are represented in GDB as 'bnd0raw' through
'bnd3raw'. Pseudo registers 'bnd0' through 'bnd3' display the upper
bound performing the complement of one operation on the upper bound
value, i.e. when upper bound in 'bnd0raw' is 0 in the GDB 'bnd0' it will
be '0xfff...'. In this sense it can also be noted that the upper bounds
are inclusive.
As an example, assume that the register BND0 holds bounds for a
pointer having access allowed for the range between 0x32 and 0x71. The
values present on bnd0raw and bnd registers are presented as follows:
bnd0raw = {0x32, 0xffffffff8e}
bnd0 = {lbound = 0x32, ubound = 0x71} : size 64
This way the raw value can be accessed via bnd0raw...bnd3raw. Any
change on bnd0...bnd3 or bnd0raw...bnd3raw is reflect on its
counterpart. When the bnd0...bnd3 registers are displayed via Python,
the display includes the memory size, in bits, accessible to the
pointer.
Bounds can also be stored in bounds tables, which are stored in
application memory. These tables store bounds for pointers by
specifying the bounds pointer's value along with its bounds. Evaluating
and changing bounds located in bound tables is therefore interesting
while investigating bugs on MPX context. GDB provides commands for this
purpose:
'show mpx bound POINTER'
Display bounds of the given POINTER.
'set mpx bound POINTER, LBOUND, UBOUND'
Set the bounds of a pointer in the bound table. This command takes
three parameters: POINTER is the pointers whose bounds are to be
changed, LBOUND and UBOUND are new values for lower and upper
bounds respectively.
When you call an inferior function on an Intel MPX enabled program,
GDB sets the inferior's bound registers to the init (disabled) state
before calling the function. As a consequence, bounds checks for the
pointer arguments passed to the function will always pass.
This is necessary because when you call an inferior function, the
program is usually in the middle of the execution of other function.
Since at that point bound registers are in an arbitrary state, not
clearing them would lead to random bound violations in the called
function.
You can still examine the influence of the bound registers on the
execution of the called function by stopping the execution of the called
function at its prologue, setting bound registers, and continuing the
execution. For example:
$ break *upper
Breakpoint 2 at 0x4009de: file i386-mpx-call.c, line 47.
$ print upper (a, b, c, d, 1)
Breakpoint 2, upper (a=0x0, b=0x6e0000005b, c=0x0, d=0x0, len=48)....
$ print $bnd0
{lbound = 0x0, ubound = ffffffff} : size -1
At this last step the value of bnd0 can be changed for investigation
of bound violations caused along the execution of the call. In order to
know how to set the bound registers or bound table for the call consult
the ABI.
---------- Footnotes ----------
(1) The register named with capital letters represent the
architecture registers.