public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
* [glibc/arm/morello/main] cheri: stdio-common: add support for printing CHERI capabilities
@ 2022-08-05 19:37 Szabolcs Nagy
  0 siblings, 0 replies; 4+ messages in thread
From: Szabolcs Nagy @ 2022-08-05 19:37 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=3be82efc58a7089039c4e8ae442c8baa78a99d1b

commit 3be82efc58a7089039c4e8ae442c8baa78a99d1b
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    |  13 ++++
 stdio-common/vfprintf-process-arg.c | 121 ++++++++++++++++++++++++++++++++++++
 4 files changed, 141 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..6bda3a2b27 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,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;
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');


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [glibc/arm/morello/main] cheri: stdio-common: add support for printing CHERI capabilities
@ 2022-11-23 14:49 Szabolcs Nagy
  0 siblings, 0 replies; 4+ messages in thread
From: Szabolcs Nagy @ 2022-11-23 14:49 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=36d565f7e3ac9e1d73ef9921c24bbcd0cfd1ade4

commit 36d565f7e3ac9e1d73ef9921c24bbcd0cfd1ade4
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');

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [glibc/arm/morello/main] cheri: stdio-common: add support for printing CHERI capabilities
@ 2022-10-27 13:59 Szabolcs Nagy
  0 siblings, 0 replies; 4+ messages in thread
From: Szabolcs Nagy @ 2022-10-27 13:59 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=cfa623ce10c5d1319f3a8345930a5044b3471e57

commit cfa623ce10c5d1319f3a8345930a5044b3471e57
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');

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [glibc/arm/morello/main] cheri: stdio-common: add support for printing CHERI capabilities
@ 2022-10-26 15:21 Szabolcs Nagy
  0 siblings, 0 replies; 4+ messages in thread
From: Szabolcs Nagy @ 2022-10-26 15:21 UTC (permalink / raw)
  To: glibc-cvs

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');

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-11-23 14:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-05 19:37 [glibc/arm/morello/main] cheri: stdio-common: add support for printing CHERI capabilities Szabolcs Nagy
2022-10-26 15:21 Szabolcs Nagy
2022-10-27 13:59 Szabolcs Nagy
2022-11-23 14:49 Szabolcs Nagy

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).