Jessica Clarke wrote:
> I can see in your patches that you're using __CHERI__ as your ABI
> detection macro. Unfortunately, this currently isn't quite right.
> ...
> we also have a hybrid ABI, which is
> binary-compatible with non-CHERI code, treating all pointers as
> traditional integer addresses, but with the ability to qualify them with
> __capability to opt into them being capabilities (and (u)intcap_t for
> the (u)intptr_t case).
> ...
> the
> __CHERI__ macro is for detecting this latter case, i.e. just that you
> have CHERI ISA features available (cc -march=morello -mabi=aapcs for
> Morello)
> ...
> What you instead want is the (rather
> cumbersome) __CHERI_PURE_CAPABILITY__ macro, which is specifically
> testing for the pure-capability ABI, so hybrid code where pointers are
> plain integer addresses continues to use the old code paths rather than
> the new capability ones.

Thanks for the advice. Indeed, I can see 3 ABIs on cfarm240:

(1) "clang" — the traditional aarch64 ABI.
(2) "clang -march=morello" == "clang -march=morello -mabi=aapcs"
    — what you call "hybrid" mode.
(3) "clang -march=morello -mabi=purecap" == "cc"

Predefined symbol differences between (1) and (2):

$ diff <(:|clang -E -dM -|LC_ALL=C sort) <(:|clang -march=morello -E -dM 
-|LC_ALL=C sort) | grep '^[<>]'
> #define __ARM_CAP_PERMISSION_BRANCH_SEALED_PAIR__ 256
> #define __ARM_CAP_PERMISSION_COMPARTMENT_ID__ 128
> #define __ARM_CAP_PERMISSION_EXECUTIVE__ 2
> #define __ARM_CAP_PERMISSION_MUTABLE_LOAD__ 64
> #define __ARM_FEATURE_ATOMICS 1
> #define __ARM_FEATURE_CRC32 1
> #define __ARM_FEATURE_DOTPROD 1
> #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
> #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
> #define __ARM_FEATURE_QRDMX 1
> #define __CHERI_ADDRESS_BITS__ 64
> #define __CHERI_CAPABILITY_WIDTH__ 128
> #define __CHERI_CAP_PERMISSION_ACCESS_SYSTEM_REGISTERS__ 512
> #define __CHERI_CAP_PERMISSION_GLOBAL__ 1
> #define __CHERI_CAP_PERMISSION_PERMIT_EXECUTE__ 32768
> #define __CHERI_CAP_PERMISSION_PERMIT_LOAD_CAPABILITY__ 16384
> #define __CHERI_CAP_PERMISSION_PERMIT_LOAD__ 131072
> #define __CHERI_CAP_PERMISSION_PERMIT_SEAL__ 2048
> #define __CHERI_CAP_PERMISSION_PERMIT_STORE_CAPABILITY__ 8192
> #define __CHERI_CAP_PERMISSION_PERMIT_STORE_LOCAL__ 4096
> #define __CHERI_CAP_PERMISSION_PERMIT_STORE__ 65536
> #define __CHERI_CAP_PERMISSION_PERMIT_UNSEAL__ 1024
> #define __CHERI__ 1
> #define __INTCAP_MAX__ 9223372036854775807L
> #define __SIZEOF_CHERI_CAPABILITY__ 16
> #define __SIZEOF_INTCAP__ 16
> #define __SIZEOF_UINTCAP__ 16
> #define __UINTCAP_MAX__ 18446744073709551615UL

Predefined symbol differences between (2) and (3):

$ diff <(:|clang -march=morello -E -dM -|LC_ALL=C sort) <(:|clang 
-march=morello -mabi=purecap -E -dM -|LC_ALL=C sort) | grep '^[<>]'
> #define __ARM_FEATURE_C64 1
> #define __CHERI_CAPABILITY_TABLE__ 3
> #define __CHERI_CAPABILITY_TLS__ 1
> #define __CHERI_PURE_CAPABILITY__ 2
> #define __CHERI_SANDBOX__ 4
< #define __INTPTR_FMTd__ "ld"
< #define __INTPTR_FMTi__ "li"
> #define __INTPTR_FMTd__ "Pd"
> #define __INTPTR_FMTi__ "Pi"
< #define __INTPTR_TYPE__ long int
< #define __INTPTR_WIDTH__ 64
> #define __INTPTR_TYPE__ __intcap
> #define __INTPTR_WIDTH__ 128
< #define __POINTER_WIDTH__ 64
> #define __PIC__ 1
> #define __POINTER_WIDTH__ 128
< #define __SIZEOF_POINTER__ 8
> #define __SIZEOF_POINTER__ 16
< #define __UINTPTR_FMTX__ "lX"
< #define __UINTPTR_FMTo__ "lo"
< #define __UINTPTR_FMTu__ "lu"
< #define __UINTPTR_FMTx__ "lx"
> #define __UINTPTR_FMTX__ "PX"
> #define __UINTPTR_FMTo__ "Po"
> #define __UINTPTR_FMTu__ "Pu"
> #define __UINTPTR_FMTx__ "Px"
< #define __UINTPTR_TYPE__ long unsigned int
< #define __UINTPTR_WIDTH__ 64
> #define __UINTPTR_TYPE__ unsigned __intcap
> #define __UINTPTR_WIDTH__ 128
> #define __pic__ 1

So, if I understood it correctly, in hybrid mode (2), programs (especially
memory allocators) _can_ use <cheri.h> and its functions, but it's not
necessary since the programs will also work without it?

Bruno




Reply via email to