public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Szabolcs Nagy <nsz@sourceware.org>
To: glibc-cvs@sourceware.org
Subject: [glibc/arm/morello/main] cheri: stdio-common: add support for printing CHERI capabilities
Date: Wed, 26 Oct 2022 15:21:20 +0000 (GMT) [thread overview]
Message-ID: <20221026152120.EC129382DE10@sourceware.org> (raw)
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=d1bb6dcbf353d46f0029eafb97d95bbb669882a2
commit d1bb6dcbf353d46f0029eafb97d95bbb669882a2
Author: Carlos Eduardo Seo <carlos.seo@arm.com>
Date: Thu Jul 7 18:46:43 2022 +0000
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.
Diff:
---
stdio-common/printf-parsemb.c | 5 ++
stdio-common/printf.h | 3 +-
stdio-common/vfprintf-internal.c | 15 +++++
stdio-common/vfprintf-process-arg.c | 121 ++++++++++++++++++++++++++++++++++++
4 files changed, 143 insertions(+), 1 deletion(-)
diff --git a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c
index 386e2a27bb..e9e395c2de 100644
--- a/stdio-common/printf-parsemb.c
+++ b/stdio-common/printf-parsemb.c
@@ -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;
diff --git a/stdio-common/printf.h b/stdio-common/printf.h
index 46993e031e..815dc95779 100644
--- a/stdio-common/printf.h
+++ b/stdio-common/printf.h
@@ -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. */
};
diff --git a/stdio-common/vfprintf-internal.c b/stdio-common/vfprintf-internal.c
index fb94961f37..c2f1904b7d 100644
--- a/stdio-common/vfprintf-internal.c
+++ b/stdio-common/vfprintf-internal.c
@@ -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,9 @@ 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. */
+ __attribute__((unused))
+ 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 +1334,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 +1351,8 @@ 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;
+ __attribute__((unused))
+ 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;
diff --git a/stdio-common/vfprintf-process-arg.c b/stdio-common/vfprintf-process-arg.c
index 4fe369e111..709d2c7db7 100644
--- a/stdio-common/vfprintf-process-arg.c
+++ b/stdio-common/vfprintf-process-arg.c
@@ -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');
next reply other threads:[~2022-10-26 15:21 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-26 15:21 Szabolcs Nagy [this message]
-- strict thread matches above, loose matches on Subject: below --
2022-11-23 14:49 Szabolcs Nagy
2022-10-27 13:59 Szabolcs Nagy
2022-08-05 19:37 Szabolcs Nagy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221026152120.EC129382DE10@sourceware.org \
--to=nsz@sourceware.org \
--cc=glibc-cvs@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).