mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 21:40:12 +00:00
cheri: stdio-common: add support for printing CHERI capabilities
This adds a new modifier %#p for printing capability information according to the CHERI C Programming guide: https://github.com/CTSRD-CHERI/cheri-c-programming/wiki/Displaying-Capabilities A %#p option in printf will display: <address> [<permissions>,<base>-<top>] (<attr>) * address: Virtual address of capability displayed as a hexadecimal value with a 0x 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) * base: Lower bound of capability displayed as a hexadecimal value with a 0x prefix. * top: Upper bound of capability plus 1 displayed as a hexadecimal value with a 0x 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. A %p option in printf will display the capability value (address) normally.
This commit is contained in:
parent
cec148df6f
commit
3be82efc58
@ -80,6 +80,7 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn,
|
||||
spec->info.pad = ' ';
|
||||
spec->info.wide = sizeof (UCHAR_T) > 1;
|
||||
spec->info.is_binary128 = 0;
|
||||
spec->info.is_cap = 0;
|
||||
|
||||
/* Test for positional argument. */
|
||||
if (ISDIGIT (*format))
|
||||
@ -371,6 +372,10 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn,
|
||||
break;
|
||||
case L'p':
|
||||
spec->data_arg_type = PA_POINTER;
|
||||
#ifdef __CHERI_PURE_CAPABILITY__
|
||||
if (spec->info.alt)
|
||||
spec->info.is_cap = 1;
|
||||
#endif
|
||||
break;
|
||||
case L'n':
|
||||
spec->data_arg_type = PA_INT|PA_FLAG_PTR;
|
||||
|
@ -50,7 +50,8 @@ struct printf_info
|
||||
unsigned int i18n:1; /* I flag. */
|
||||
unsigned int is_binary128:1; /* Floating-point argument is ABI-compatible
|
||||
with IEC 60559 binary128. */
|
||||
unsigned int __pad:3; /* Unused so far. */
|
||||
unsigned int is_cap:1; /* CHERI capability. */
|
||||
unsigned int __pad:2; /* Unused so far. */
|
||||
unsigned short int user; /* Bits for user-installed modifiers. */
|
||||
wchar_t pad; /* Padding character. */
|
||||
};
|
||||
|
@ -116,6 +116,10 @@
|
||||
while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __CHERI_PURE_CAPABILITY__
|
||||
# include <cheri_perms.h>
|
||||
#endif
|
||||
|
||||
/* Add LENGTH to DONE. Return the new value of DONE, or -1 on
|
||||
overflow (and set errno accordingly). */
|
||||
static inline int
|
||||
@ -792,6 +796,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
|
||||
int base;
|
||||
union printf_arg the_arg;
|
||||
CHAR_T *string; /* Pointer to argument string. */
|
||||
#ifdef __CHERI_PURE_CAPABILITY__
|
||||
const void *cap = 0;
|
||||
#endif
|
||||
int alt = 0; /* Alternate format. */
|
||||
int space = 0; /* Use space prefix if no sign is needed. */
|
||||
int left = 0; /* Left-justify output. */
|
||||
@ -805,6 +812,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
|
||||
int is_char = 0; /* Argument is promoted (unsigned) char. */
|
||||
int width = 0; /* Width of output; 0 means none specified. */
|
||||
int prec = -1; /* Precision of output; -1 means none specified. */
|
||||
int is_cap = 0; /* Argument is a capability. */
|
||||
|
||||
/* This flag is set by the 'I' modifier and selects the use of the
|
||||
`outdigits' as determined by the current locale. */
|
||||
int use_outdigits = 0;
|
||||
@ -1324,6 +1333,9 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
|
||||
} number;
|
||||
int base;
|
||||
CHAR_T *string; /* Pointer to argument string. */
|
||||
#ifdef __CHERI_PURE_CAPABILITY__
|
||||
const void *cap = 0;
|
||||
#endif
|
||||
|
||||
/* Fill variables from values in struct. */
|
||||
int alt = specs[nspecs_done].info.alt;
|
||||
@ -1338,6 +1350,7 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
|
||||
int is_long = specs[nspecs_done].info.is_long;
|
||||
int width = specs[nspecs_done].info.width;
|
||||
int prec = specs[nspecs_done].info.prec;
|
||||
int is_cap = specs[nspecs_done].info.is_cap;
|
||||
int use_outdigits = specs[nspecs_done].info.i18n;
|
||||
char pad = specs[nspecs_done].info.pad;
|
||||
CHAR_T spec = specs[nspecs_done].info.spec;
|
||||
|
@ -25,6 +25,115 @@
|
||||
{
|
||||
/* Start real work. We know about all flags and modifiers and
|
||||
now process the wanted format specifier. */
|
||||
|
||||
/* Process capability information according to the CHERI C Programming guide:
|
||||
https://github.com/CTSRD-CHERI/cheri-c-programming/wiki/Displaying-Capabilities */
|
||||
#ifdef __CHERI_PURE_CAPABILITY__
|
||||
LABEL (capability):
|
||||
/* CHERI capability. */
|
||||
{
|
||||
uint64_t cap_perm = 0;
|
||||
uint64_t cap_base = 0;
|
||||
uint64_t cap_limit = 0;
|
||||
uint64_t cap_tag = 0;
|
||||
uint64_t cap_type = 0;
|
||||
outchar (L_(' '));
|
||||
outchar (L_('['));
|
||||
cap_perm = __builtin_cheri_perms_get (cap);
|
||||
if (cap_perm & CAP_PERM_LOAD)
|
||||
outchar (L_('r'));
|
||||
if (cap_perm & CAP_PERM_STORE)
|
||||
outchar (L_('w'));
|
||||
if (cap_perm & CAP_PERM_EXECUTE)
|
||||
outchar (L_('x'));
|
||||
if (cap_perm & CAP_PERM_LOAD_CAP)
|
||||
outchar (L_('R'));
|
||||
if (cap_perm & CAP_PERM_STORE_CAP)
|
||||
outchar (L_('W'));
|
||||
if (cap_perm & CAP_PERM_EXECUTIVE)
|
||||
outchar (L_('E'));
|
||||
outchar (L_(','));
|
||||
cap_base = __builtin_cheri_base_get (cap);
|
||||
number.word = (unsigned long int) cap_base;
|
||||
if (prec < 0)
|
||||
prec = 1;
|
||||
else
|
||||
pad = L_(' ');
|
||||
string = _itoa_word (number.word, workend, base, spec == L_('X'));
|
||||
prec = MAX (0, prec - (workend - string));
|
||||
width -= workend - string + prec;
|
||||
if (number.word != 0)
|
||||
width -= 2;
|
||||
if (pad == L_(' '))
|
||||
{
|
||||
PAD (L_(' '));
|
||||
width = 0;
|
||||
}
|
||||
if (number.word != 0)
|
||||
{
|
||||
outchar (L_('0'));
|
||||
outchar (spec);
|
||||
}
|
||||
width += prec;
|
||||
PAD (L_('0'));
|
||||
outstring (string, workend - string);
|
||||
outchar (L_('-'));
|
||||
cap_limit = __builtin_cheri_length_get (cap) + cap_base;
|
||||
number.word = (unsigned long int) cap_limit;
|
||||
if (prec < 0)
|
||||
prec = 1;
|
||||
else
|
||||
pad = L_(' ');
|
||||
string = _itoa_word (number.word, workend, base, spec == L_('X'));
|
||||
prec = MAX (0, prec - (workend - string));
|
||||
width -= workend - string + prec;
|
||||
if (number.word != 0)
|
||||
width -= 2;
|
||||
if (pad == L_(' '))
|
||||
{
|
||||
PAD (L_(' '));
|
||||
width = 0;
|
||||
}
|
||||
if (number.word != 0)
|
||||
{
|
||||
outchar (L_('0'));
|
||||
outchar (spec);
|
||||
}
|
||||
width += prec;
|
||||
PAD (L_('0'));
|
||||
outstring (string, workend - string);
|
||||
outchar (L_(']'));
|
||||
cap_tag = __builtin_cheri_tag_get (cap);
|
||||
if (!cap_tag)
|
||||
{
|
||||
outchar (L_(' '));
|
||||
outchar (L_('('));
|
||||
outstring ("invalid", 8);
|
||||
outchar (L_(')'));
|
||||
break;
|
||||
}
|
||||
cap_type = __builtin_cheri_type_get (cap);
|
||||
if (cap_type != 0)
|
||||
{
|
||||
if (cap_type == 1)
|
||||
{
|
||||
outchar (L_(' '));
|
||||
outchar (L_('('));
|
||||
outstring ("sentry", 7);
|
||||
outchar (L_(')'));
|
||||
}
|
||||
else
|
||||
{
|
||||
outchar (L_(' '));
|
||||
outchar (L_('('));
|
||||
outstring ("sealed", 7);
|
||||
outchar (L_(')'));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
LABEL (form_percent):
|
||||
/* Write a literal "%". */
|
||||
outchar (L_('%'));
|
||||
@ -212,6 +321,11 @@ LABEL (unsigned_number): /* Unsigned number of base BASE. */
|
||||
|
||||
outstring (string, workend - string);
|
||||
|
||||
#ifdef __CHERI_PURE_CAPABILITY__
|
||||
if (is_cap == 1)
|
||||
goto LABEL(capability);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -265,6 +379,13 @@ LABEL (form_pointer):
|
||||
base = 16;
|
||||
number.word = (unsigned long int) ptr;
|
||||
is_negative = 0;
|
||||
#ifdef __CHERI_PURE_CAPABILITY__
|
||||
if (alt == 1)
|
||||
{
|
||||
cap = ptr;
|
||||
is_cap = 1;
|
||||
}
|
||||
#endif
|
||||
alt = 1;
|
||||
group = 0;
|
||||
spec = L_('x');
|
||||
|
Loading…
Reference in New Issue
Block a user