-
Notifications
You must be signed in to change notification settings - Fork 3
Displaying Capabilities
When CHERI capabilities are used in pointers in C, it is helpful for developers to provide a human-friendly format for properties of pointers beyond the address such as bounds and permissions. This document defines a few different formats for displaying capabilities as well as contexts for displaying them.
Different contexts may use different formats.
The simplest format for displaying a capability is to display the raw contents of the capability as a hexadecimal value. This may or may not include the tag (TBD?).
An example use of this format is p/x
of a capability in CHERI GDB.
Format:
<capability>
Fields:
-
capability
: Hex value of capability bytes.
Another simple format for displaying a capability is to display the address of a capability as a hexadecimal value. This should generally match the existing format used with integer pointers.
An example use of this format is the printf(3) %p
format when used in pure-capability CHERI C.
Format:
<address>
Fields:
-
address
: Virtual address of capability.
Initially, CHERI projects used a verbose format which displayed all possible fields of capabilities as separate hex values. However, this format had a couple of disadvantages. First, it was quite broad (over 80 characters for a single pointer). Secondly, it still required manual decoding of fields such as permission bits and object types. The simplified format aims to provide a more concise format which provides details that are generally applicable to most developers using CHERI C such as basic permissions. It does omit some details such as more obscure permissions and most object types. In addition, for null-derived capabilities (capabilities where the tag and upper attribute word are all zero), only the address is displayed (the Basic Format).
An example use of this format is the printf(3) %#p
format when used in pure-capability CHERI C.
Format:
<address> [<permissions>,<base>-<top>] (<attr>)
-
address
: Virtual address of capability displayed as a hexadecimal value with a0x
prefix. -
permissions
: Zero or more of the following characters:-
r
: LOAD permission -
w
: STORE permission -
x
: EXECUTE permission -
R
: LOAD_CAP permission -
W
: STORE_CAP permission -
E
: EXECUTIVE permission (Morello only)- Could be
X
instead so we haverwxRWX
, though we may wantX
for ASR instead
- Could be
-
-
base
: Lower bound of capability displayed as a hexadecimal value with a0x
prefix. -
top
: Upper bound of capability plus 1 displayed as a hexadecimal value with a0x
prefix. -
attr
: Zero or more of the following comma-separated attributes. If none of the attributes are present, this field is omitted (along with the enclosing parentheses/brackets).-
invalid
: Capability's tag is clear. -
sentry
: Capability is a sealed entry. -
sealed
: Capability is sealed with a type other than the sealed entry object type.
-
In some cases, all of the details of a capability may be desired (for example, when working with code that uses sealed capabilities). For these cases, a verbose (but readable) format should be defined. Ideally such a format would retain human-friendly display of fields such as permissions when possible while providing details of all of the fields of a capability.
Ideally, displaying capabilities in this format would be provided in debuggers.
Format:
TBD
Both pure-capability and hybrid CHERI C implementations should permit the display of capabilities via printf(3) via the p
format specifier.
By default, the p
specifier should print the address of the capability (the Basic Format) matching the format used for integer pointers in plain C for the given platform. Different environments display pointers differently (for example BSD kernels and C libraries display integer pointers as hexadecimal values with a 0x
prefix, whereas the Linux kernel displays integer pointers as hexadecimal without a 0x
prefix), and p
should match a platform's existing format.
In addition, the following additional format specifiers are defined in CHERI C:
-
The
l
modifier can be used with thep
specifier to indicate that the argument is avoid * __capability
rather than avoid *
.For hybrid CHERI C,
p
accepts integer pointer arguments by default (void *
). This modifier allows a capability to be passed instead. To ease portability between hybrid and pure-capability CHERI C, pure-capability CHERI C also accepts (but ignores) this modifier. In pure-capability CHERI C,void *
is already a capability. -
The
#
modifier can be used with thep
specifier to request that a capability be displayed using the Simplified Format.To ease portability, this modifier is ignored if it is used with an integer pointer in hybrid CHERI C.
-
An optional precision can be used with the
p
specifier.If given, the precision is used to determine the width of addresses (address, base, and top) displayed in the Simplified Format. Each address should be zero-padded if necessary to meet the desired precision. Note that the precision applies to the hexadecimal digits displayed for each address and does not include the
0x
prefix.
If a field width is provided for the p
specifier, that field width should be applied to the result of the entire output string generated by the Simplified Format when used with the #
modifier.
-
E
vsX
permission (see above) - Should absent permissions be denoted by a
-
similar tols -l
output? When used with precision, this would provide a fixed-width format which is nice for dumping tables of registers. - Other permissions? ASR could be useful and is likely to stick around. S and U are useful but in an otype-less world with just sentries those would no longer be needed.
- ASR may make sense as
X
: just as LOAD_CAP gates access to specific types of loads, ASR gates access to specific types of instructions. - We may also want to show flags (e.g. cap mode for risc-v)