set struct-convention
modestruct
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
struct
s
from functions.
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
pointerset mpx bound
pointer,
lbound,
uboundWhen 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.