Compare commits

...
Author SHA1 Message Date
Carlos Eduardo Seo 2f3bf4cf63 TODO(drop): aarch64: morello: CPU feature detection for Morello
Initial detection of Arm Morello architecture from the HWCAP2 bit and CPU
identification from MIDR_EL0.

TODO: not needed?
- lp64 does not have to detect
- purecap can assume morello
2022-08-05 19:45:19 +01:00
Szabolcs Nagy ccce788403 TODO(gprof): aarch64: morello: add gprof profiling support to asm
Assembly prologue code with mcount call for gprof instrumentation.

TODO: untested, likely needs further runtime updates too.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 5ef98a9900 TODO(sprof): cheri: disable profiling shared libraries
This is needed now to avoid referencing abort in ld.so.

TODO: Fixing shared library profiling for capabilities requires
type fixes so capabilities are not stored into shared memory
(maybe purecap layout can match the lp64 one and then no file format
and external tooling change is required.)
TODO: Proper fix also depends on _dl_runtime_profile plt entry
2022-08-05 19:45:19 +01:00
Szabolcs Nagy a8989aef06 TODO(audit): aarch64: morello: add _dl_runtime_profile entry
Required for LD_AUDIT PLT hooks and shared library profiling.

incomplete, untested.

TODO: needs La_aarch64* layout definition for morello
TODO: needs to save c9 for vararg abi
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 7f9c78bc3a TODO(pldd): cheri: elf: fix pldd to compile for purecap abi
Adjust types in the E(*) structs to support capabilities.

TODO: purecap pldd should refuse to deal with lp64 and ELF32 processes.
the code for the 32bit case should be disabled.
TODO: a correct fix requires support for all abis that can run on the
same system (purecap, lp64 and ELF32 too).
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 7dac60585d cheri: Update libc.abilist for getauxptr
Updates libc.abilist files for getauxptr to version 2.37.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 6cca02f732 cheri: elf: Fix tst-auxv for Morello 2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 2b9e393156 TODO(api): cheri: misc: Implement new function getauxptr for CHERI capabilities
New function to return values from the auxiliary vector as
capabilities. This is the same as implemented by other C libraries.

TODO: agree about exact semantics across libcs
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d74b162292 TODO(uapi): aarch64: morello: add HWCAP2_MORELLO
TODO: the value will change
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo f4fe4afdf0 support: Fix TEST_COMPARE for uintptr_t.
TEST_COMPARE should allow comparison between two capability values.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 3be82efc58 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.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo cec148df6f cheri: nptl: Check user provided stack for PCS constraints
In pthread_attr_setstack fail with EINVAL if the input stack does not
meet the PCS constraints.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d8173e2496 TODO(uapi): cheri: Fix sigevent ABI
TODO: depends on kernel sigevent definition update.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy bb648757f0 TODO(morello): cheri: fix posix timers
We need to distinguish timerids that are small integers returned by
the kernel and timerids that are pointers to struct timer. The existing
pointer tagging does not work for CHERI because of the pointer shift.

Simply use the top bit without shift to tag pointers. This still relies
on the top byte ignore of aarch64 (the top byte does not affect the
capability representation) and that pointers are not tagged for other
reasons (like HWASAN).

TODO: this is morello specific and does not work for generic cheri.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 989eb50954 TODO(api): cheri: elfptr_t in public api for unwinder
TODO: needs agreement across cheri libcs
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 93ab84cd80 TODO(l_addr): cheri: rtld: elfptr_t fix in rtld.c program header processing
TODO: depends on l_addr design
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 3eb1c569eb TODO(l_addr): aarch64: morello: dynamic linking support
Add morello specific dl-machine.h.

Add morello dynamic relocation processing support for purecap ABI.
Only support R_AARCH64_NONE, R_AARCH64_ABS64 and R_AARCH64_RELATIVE
dynamic relocs from the lp64 abi. This required several APIs to
change ElfW(Addr) to uintptr_t including in generic code (where
elfptr_t used to cover both traditional and capability abis).

RELATIVE and IRELATIVE relocs use a helper function to construct a
capability.  Also fixed the IRELATIVE handling for static linking.

Use new machine routines on morello for load address computation so it
is a valid capability:

 void *elf_machine_runtime_dynamic (void)
 uintptr_t elf_machine_load_address_from_args (void *)

The ld.so load address is either AT_BASE or if it is invoked as a
command then derived from AT_PHDR or _DYNAMIC (pcc).

ELF_MACHINE_START_ADDRESS is updated to turn the ElfW(Addr) user entry
into a capability based on l_addr.

TODO: __tls_get_addr should return a bounded pointer.
(in case traditional tls is defined for morello)

note: tls_index struct that is used for trad tls is changed for morello.
(this is abi once trad tls is defined for morello)

arguably _dl_make_tlsdesc_dynamic should set up tlsinfo.ti_size too.
(but it's better to avoid changing the generic code)

TODO: use cheri auxv entries to derive ld.so capabilities, this will
      require separate RW and RX base pointers instead of single l_addr.
      AT_BASE will not be a capability covering ld.so.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 6f93421a5f aarch64: rtld: avoid loading incompatible binaries
Prevent lp64 ld.so loading purecap binaries.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 392f32c841 aarch64: morello: add lazy binding entry code 2022-08-05 19:45:19 +01:00
Szabolcs Nagy d15c9f859f TODO(l_addr): cheri: rtld: elfptr_t fixes in dl-map-segments.h
Ensure map_end is derived from map_start.

Use stricter mmap bounds when using MAP_FIXED:
c->mapend is aligned up to pagesize, but the capability representing
the mapping has bounds that are not page aligned, so use c->dataend
that is the actual end bound of the loaded segment.

TODO: l_addr of a pde is 0 but it should cover the exe.
this will have to be fixed. (and must not use morello asm)
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 51fe1e15ed TODO(incomplete): cheri: rtld: more elfptr_t in linkmap struct
TODO: requires follwup patches to make sure all usage of the fields
preserve capabilities.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 2b1192cae0 cheri: elf: fix pointer provenance of l_tls_initimage 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 06fda78445 cheri: rtld: fix _dl_start to return elfptr_t
Functions returning a pointer to the user entry need to use an int type
that can represent pointers.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy a0cbaef87c aarch64: morello: rtld: add ld.so _start code
The purecap version of aarch64 dl-start.S. Note: self relocation of
ld.so is handled by the rtld bootstrap code.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 4f45607de9 aarch64: morello: rtld: define DL_RO_DYN_SECTION
The dynamic section cannot be relocated to hold pointers in place.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy c755eefac5 aarch64: morello: fix ldconfig for purecap abi
Add purecap ld cache flag. Add the purecap ld.so name to known names.
Handle lib64c system library paths. And set the purecap abi flag on
cache entries.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy c779cc818e aarch64: morello: disable the vpcs test
The asm code of the test is for lp64 ABI only.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo ec5240f821 aarch64: morello: add purecap ucontext support
Adjust ucontext layout for purecap ABI and add make/get/set/swapcontext
implementations accordingly.

Note: mcontext layout follows the linux sigcontext struct, in userspace
*context functions rely on the c registers stored in the extension area
and ignore the mcontext fields for x registers.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 89ab8ac121 aarch64: morello: add purecap setjmp/longjmp
Similar to lp64 setjmp/longjmp, but handles capability registers.
Save q regs instead of d regs to simplify the offset computation.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 257781e305 cheri: malloc: avoid switch over uintptr_t
We should use a type that guarantees to represent all address bits.
In CHERI C this would be ptraddr_t, but we use unsigned long for now
not to cause regressions on other targets where this type is missing.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 6af67120e8 cheri: malloc: fix alignment logic in obstack
If sizeof(ptrdiff_t) < sizeof(void*) the alignment logic was wrong
(incorrectly assumed that base was already sufficiently aligned).

Use more robust alignment logic: this one should work on any target.
Note: this is an installed header so it must be namespace clean and
portable.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 84068c087b cheri: malloc: use uintptr_t in alloc_buffer
This is the right type as the values hold pointers.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 4064e7a4fc cheri: malloc: align up without breaking capability in memalign 2022-08-05 19:45:19 +01:00
Szabolcs Nagy b3d26f52f7 cheri: malloc: Disable pointer protection
Such arithmetic invalidates capabilities so this security measure does
not work for CHERI.

Note: the architecture makes it hard to corrupt pointers in malloc
metadata, but not impossible: current allocation bounds include the
metadata and capabilities are not revoked after free. These issues can
be fixed by a capability aware malloc.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 0205012984 cheri: malloc: use intptr_t to preserve capabilities
Avoid integer casts and arithmetics that invalidates capabilities.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d0db1e8a12 cheri: fix invalid pointer use after realloc in localealias
This code updates pointers to a reallocated buffer to point to the new
buffer.  It is not conforming (does arithmetics with freed pointers),
but it also creates invalid capabilities because the provenance is
derived from the original freed pointers instead of the new buffer.

Change the arithmetics so provenance is derived from the new buffer.
The conformance issue is not fixed.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 68822420a6 cheri: fix pointer tagging in tsearch
USE_MALLOC_LOW_BIT should work for capabilities too, but we need to
ensure that pointer provenance is right: the red/black flag is
computed as uintptr_t, but with uintptr_t | uintptr_t it's not clear
which side provides the provenance.

So use unsigned int type for the flag (which is the type used in case
of !USE_MALLOC_LOW_BIT anyway), then unsigned int | uintptr_t works.

The type of RED is corrected too to match unsigned int.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 159a76a8dd cheri: fix qsort for capabilities
On capability targets avoid copying pointers via unsigned long.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy f7842f9392 cheri: wctype: turn wctype_t into a pointer
Make wctype_t a pointer so dereferencing it works. wctrans_t is already
a pointer and used the same way.

Existing targets are not affected, only capability targets where this
is necessary.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 5778537ccd cheri: rseq: remove const to avoid readonly permission
Using const on the definition does not work for a pure capability ABI:
the capability permissions when accessing the object will be read only.

Use a hack to hide the public declaration in the TU where the const
objects are initialized. (This should work on non-capability targets
too, but to err on the safe side only enable the hack on capability
targets.)
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 01faa1bcd4 aarch64: morello: nptl: fix thread pointer setup 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 63bee6f155 aarch64: morello: nptl: fix pthread types for 128 bit pointers 2022-08-05 19:45:19 +01:00
Szabolcs Nagy f29dda01e0 cheri: nptl: fix pthread_attr_t alignment
Alignment of the public definition did not match the internal layout.
Ensure that the type is at least pointer aligned.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy b38585301d cheri: nptl: fix thread ID types for capabilities 2022-08-05 19:45:19 +01:00
Szabolcs Nagy c8f1fc9d94 cheri: Implement 128-bit atomics
Arm Morello requires 128-bit atomics.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 7880bbd374 cheri: elf: Use elfptr_t in _dl_protect_relro
start/end should be capabilities now that l_addr is a capability.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d63bc8be87 cheri: elf: elfptr_t fixes for preinit/init/fini array
According to the ELF spec:

 "Each element of this array is a pointer to a function to be executed
  by the dynamic linker."

 "Note that the address of a function need not be the same as a pointer
  to a function as defined by the processor supplement."

so these should be accessed via uintptr_t type instead of ElfW(Addr).
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d257d001c3 TODO(l_addr): cheri: in static exe initialize l_addr to a zero capability
The base should be 0, but also a valid capability. Initialize to a zero
capability instead of relying on AT_BASE.

TODO: this is a hack. we will need stricter bounds and possibly separate
l_addr and bounds info.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 8536404f41 cheri: elf: use elfptr_t for auxv parsing 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 8022e6934e cheri: elf: Adjust Elf64_auxv_t for capabilities
The Elf64_auxv_t needs to be adjusted for the new capability size.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy a4f02d3f68 cheri: elf: make l_addr a capability
l_addr should be a capability on Morello. This is synchronized with the
same variable in gdb.

Use elfptr_t when ElfW(Addr) represents a runtime pointer that may be
dereferenced.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 091bcf0e1c cheri: elf: Add new a_type entries
The Morello Pure Capability kernel uABI defines new a_type entries:

https://git.morello-project.org/morello/kernel/linux/-/wikis/Morello-pure-capability-kernel-user-Linux-ABI-specification#auxiliary-vector-auxv
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 823a9cb203 elf: add EF_AARCH64_CHERI_PURECAP 2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo bb5bc76947 elf: add Arm Morello relocations to elf.h 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 110733491a cheri: fix __minimal_malloc
The linker created _end symbol does not have the right bounds, so
don't try to reuse leftover memory at the end of the .data section.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 4275aff6b8 cheri: fix static linking TLS setup
Use l_addr provenance for TLS initimage.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy cb79f5073a cheri: fix static linking early allocation
Store mmap result to intptr_t instead of long.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 887a33c6bb TODO(gcc): cheri: work around a gcc bug in _dl_setup_stack_chk_guard
morello purecap gcc in some cases inlines 16byte memcpy as a capability
load, which is wrong if the source or dest may be unaligned.

stack guard only needs random for the address portion since only that
part is compared, so 8 byte is enough with 64 bit addresses, but the
current code is only right on little endian systems.

TODO: drop when gcc is fixed
2022-08-05 19:45:19 +01:00
Szabolcs Nagy ff2cd89ebb cheri: don't use dl_random for pointer mangling
Pointer mangling cannot be supported on capability architectures.
And there is not enough bytes in dl_random for 128 bit pointers.

Stack guard is still loaded from dl_random: stack protection is
unlikely to be useful on a capability architecture, but it works.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 347f7e2ac1 TODO(relro): cheri: make __attribute_relro a nop
relro does not work in the libc, because capabilities are readonly
even before the page protection is applied.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo d77736297a TODO(ddc): aarch64: morello: purecap support in the CSU
Purecap ABI versions of start.S, crti.S and crtn.S.

TODO: must not use ddc but caps from auxv
TODO: start.S: dynamic linked case is now detected by x0 != 0 (ld.so passes
__rtld_fini there), but the value of c0 on entry is not abi, just that
it has to be passed back to the libc start code in c5, so ideally the
linker should be fixed to reliably emit __rela_dyn_start when a static
exe must self relocate.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 2d0278e6d7 cheri: aarch64: Add header for CHERI permissions
New file containing the capability permission bits.

The capability permission bits are defined in the Arm Architecture
Reference Manual Suplement- Morello for A-Profile Architecture:

https://developer.arm.com/documentation/ddi0606/latest
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 822571c5b1 TODO(uapi): aarch64: morello: use non-ifunc gettimeofday
TODO: Remove this once morello has vdso gettimeofday.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 9f92fe592b TODO(uapi): aarch64: morello: make brk always fail
TODO: drop this once linux brk always fails.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy fb41a562bf TODO(uapi): cheri: fix clone_args
Current clone_args does not support 128 bit pointers.

TODO: the fix is incomplete (missing clone3 abi checks) and has to be
aligned with purecap clone3 struct layout.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy ed90470cc0 aarch64: morello: fix missing variadic argument in fcntl
In fcntl va_arg is currently used even if the caller did not pass
any variadic arguments. This is undefined behaviour and does not
work with the Morello purecap ABI, so use a helper macro.

When the argument is missing, the result of the helper macro is
arbitrary as it will be ignored by the kernel, we just have to
ensure it does not cause a runtime crash.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d23dfc0324 aarch64: morello: fix vfork
No need to set the child stack to sp, 0 means the parent stack is used.
This avoids purecap specific ifdefs in vfork.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo ff371935db aarch64: morello: add purecap syscall support
Support the Morello Linux purecap syscall ABI.  The macro definitions
are moved to a morello specific sysdep.h to avoid cluttering the
aarch64 one.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 9ef71c0be0 aarch64: fix VDSO setup to only apply to known ABIs
New syscall ABI requires different VDSO support code.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 2d17978865 TODO(api): cheri: fix syscall return type
TODO: this affects API (syscall return type is long)
so breaks portability and requires doc updates.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy fbdd679dfe aarch64: morello: string: memcpy
from arm optimized-routines morello branch.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy dd44f97920 aarch64: morello: string: memset
memset from arm optimized-routines morello branch.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 30d6fef4c7 aarch64: morello: string: dummy c memcmp 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 05c7fd2959 aarch64: morello: string: dummy c memchr 2022-08-05 19:45:19 +01:00
Szabolcs Nagy df91141390 aarch64: morello: string: dummy c memrchr 2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 2e1fc3bdee aarch64: morello: purecap rawmemchr
Modified rawmemchr to support Arm Morello Capabilities.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 0ae704caef aarch64: morello: string: dummy c strchrnul 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 538a80eaf4 aarch64: morello: string: dummy c strlen 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 42ab155048 aarch64: morello: string: dummy c strnlen 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 424b0ffa6f aarch64: morello: string: dummy c strcpy and stpcpy 2022-08-05 19:45:19 +01:00
Szabolcs Nagy bec24b66e8 aarch64: morello: string: dummy c strcmp 2022-08-05 19:45:19 +01:00
Szabolcs Nagy d496a3dd55 aarch64: morello: string: dummy c strncmp 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 750a8bb78b aarch64: morello: string: dummy c strchr 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 3a0ce7aeb0 aarch64: morello: string: dummy c strrchr 2022-08-05 19:45:19 +01:00
Szabolcs Nagy eca95865e3 aarch64: morello: string: dummy c strspn
avoids out of bound access of the generic implementation.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy e8728f756a aarch64: morello: string: dummy c strcspn
avoids out of bounds access of the generic implementation.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo db037e48fb aarch64: morello: update sysdep.h for purecap ABI
Add macro definitions for purecap ABI in sysdep.h.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 434271f132 TODO(spec): cheri: __LP64__ is not defined for purecap ABI
TODO: there is no good ABI macro to check, for now we assume
__CHERI_PURE_CAPABILITY__ implies 64 bit long, 64 bit address and
128 bit pointer.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 93c5545300 cheri: headers: Define {u}intptr_t and {u}intcap_t for CHERI
The CHERI pure capability programming model for C requires special
definition of {u}intptr_t.

Only the pure capability model is supported for hosted compilation,
but for freestanding compilation there is limited support for other
(hybrid capability) programming models too, which require new
{u}intcap_t type definitions.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 77777d453d aarch64: morello: use separate c++-types.data
The c++ mangling ABI for intptr_t and pthread_t are different on
morello.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 78cc285037 aarch64: morello: use separate localplt data for morello
There is no longer PLT reference to matherr in libm.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy ccec84f408 aarch64: morello: Add separate lp64 and morello linux abilists
The base symbol version is 2.36.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 9e6811dafb aarch64: morello: Add purecap abi-variants on linux 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 18fb025070 aarch64: morello: configure change for purecap abi
Detect default-abi and add aarch64-purecap make variable.

Purecap abi sets HIDDEN_VAR_NEEDS_DYNAMIC_RELOC and unsets
SUPPORT_STATIC_PIE.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 4fc4072240 aarch64: morello: Use separate lp64 and morello sysdep directories
Provide separate directories for lp64 and purecap abi related sysdep
functionality.

purecap may be better name than morello, but we started with morello
and that is more future compatible with alternative cheri-like
extensions on top of aarch64.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 570f6858b7 aarch64: morello: add purecap support to build-many-glibcs.py
aarch64-linux-gnu compiler is a lp64,purecap multilib gcc and
supported glibc variants:

  aarch64-linux-gnu
  aarch64-linux-gnu-purecap
  aarch64-linux-gnu-purecap-nopie

aarch64-linux-gnu_purecap compiler is a default purecap gcc, with
supported glibc variants:

  aarch64-linux-gnu_purecap
  aarch64-linux-gnu_purecap-nopie

purecap libgomp and libitm builds fail so disabled for now.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 084ac620b1 aarch64: Use fewer ifdefs in bits/fcntl.h
This simplifies adding the Morello purecap abi target.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 2adfa58c4f aarch64: cleanup MOVL definition in sysdep.h
PTR_REG is for ILP32, there is no point using it under __LP64__.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy f8335dc69a libio: adjust _IO_FILE / _IO_FILE_complete for 128 bit pointers
The size of the reserved space has to be adjusted because it underflows
with 16 byte pointers.  With the new value there should be enough space
for 2 more pointers in the struct on CHERI targets.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 1cb2ecf162 cheri: Fix elf/tst-dlmodcount test
switch statement does not work for intptr_t, use a large int type
that's guaranteed to work.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy a87b3fcbb3 Fix the symbolic link of multilib dirs
If dir contains several / then 'ln -s . $dir' does not link it to the
current directory. Use the existing rellns.sh script to compute the
correct relative path to .
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 30719666f8 cheri: Fix pointer alignment in fts
ALIGN has to work on pointers and the code assumed unsigned long can
always represent pointers.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 1943345fa3 cheri: Fix invalid pointer deref in wcpcpy_chk
Accessing src via the dest pointer is invalid.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy dec33ea23f cheri: Fix invalid pointer deref in wcscpy_chk
The src pointer is const, accessing dest via it fails on CHERI targets.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy db674b0d98 Fix string/tester alignment code
The code assumed pointers can be converted to unsigned long without
loss of information.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d8ecbea3fc Fix resource/bug-ulimit1 test
ulimit is a variadic function and the second argument must have type
long (or unsigned long).
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 14c8e3a355 Fix stdlib/test-dlclose-exit-race to not hang 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 2f90599f89 aarch64: fix extension header write in getcontext and swapcontext
The extension header is two 32bit words and in the last header both
should be 0. There is plenty space in the __reserved area, but it's
better not to write more than we mean to.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 9ed39f584e aarch64: don't build wordcopy
Use an empty wordcopy.c to avoid building the generic one.
It does not seem to be used anywhere.
2022-08-05 19:45:09 +01:00
Szabolcs Nagy 9f22387b95 scripts: Use bool in tunables initializer 2022-08-05 15:28:42 +01:00
Florian Weimer c74bb93cfd dlfcn: Pass caller pointer to static dlopen implementation (bug 29446)
Fixes commit 0c1c3a771e ("dlfcn: Move
dlopen into libc").

(cherry picked from commit ed0185e412)
2022-08-04 17:57:11 +02:00
H.J. Lu 33f1b4c145 wcsmbs: Add missing test-c8rtomb/test-mbrtoc8 dependency
Make test-c8rtomb.out and test-mbrtoc8.out depend on $(gen-locales) for

  xsetlocale (LC_ALL, "de_DE.UTF-8");
  xsetlocale (LC_ALL, "zh_HK.BIG5-HKSCS");

Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit e03f5ccd6c)
2022-08-01 10:02:06 -03:00
Tom Honermann c3fda489cf stdlib: Suppress gcc diagnostic that char8_t is a keyword in C++20 in uchar.h.
gcc 13 issues the following diagnostic for the uchar.h header when the
-Wc++20-compat option is enabled in C++ modes that do not enable char8_t
as a builtin type (C++17 and earlier by default; subject to _GNU_SOURCE
and the gcc -f[no-]char8_t option).
  warning: identifier ‘char8_t’ is a keyword in C++20 [-Wc++20-compat]
This change modifies the uchar.h header to suppress the diagnostic through
the use of '#pragma GCC diagnostic' directives for gcc 10 and later (the
-Wc++20-compat option was added in gcc version 10).  Unfortunately, a bug
in gcc currently prevents those directives from having the intended effect
as reported at https://gcc.gnu.org/PR106423.  A patch for that issue has
been submitted and is available in the email thread archive linked below.
  https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598736.html

(cherry picked from commit 825f84f133)
2022-08-01 10:02:00 -03:00
218 changed files with 8135 additions and 224 deletions
+1 -1
View File
@@ -1002,7 +1002,7 @@ endef
define make-link-multidir
$(patsubst %/,cd %,$(objpfx)); \
$(addprefix $(abspath $(..)scripts/mkinstalldirs) ,$(dir $(multidir))); \
$(LN_S) . $(multidir) 2> /dev/null; \
$(SHELL) $(abspath $(..)scripts/rellns-sh) . $(multidir) 2> /dev/null; \
test -L $(multidir)
endef
else
+7
View File
@@ -4,6 +4,13 @@ See the end for copying conditions.
Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
using `glibc' in the "product" field.
Version 2.36.1
The following bugs are resolved with this release:
[29446] _dlopen now ignores dl_caller argument in static mode
Version 2.36
+1 -1
View File
@@ -62,7 +62,7 @@
#define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
#define __CPU_MASK_TYPE __ULONGWORD_TYPE
#ifdef __LP64__
#if defined __LP64__ || defined __CHERI_PURE_CAPABILITY__
/* Tell the libc code that off_t and off64_t are actually the same type
for all ABI purposes, even if possibly expressed as different base types
for C type-checking purposes. */
+2 -2
View File
@@ -139,8 +139,8 @@ call_init (int argc, char **argv, char **env)
if (init_array != NULL)
{
unsigned int jm
= l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
ElfW(Addr) *addrs = (void *) (init_array->d_un.d_ptr + l->l_addr);
= l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (elfptr_t);
elfptr_t *addrs = (void *) (init_array->d_un.d_ptr + l->l_addr);
for (unsigned int j = 0; j < jm; ++j)
((dl_init_t) addrs[j]) (argc, argv, env);
}
+1 -1
View File
@@ -125,7 +125,7 @@ __libc_setup_tls (void)
/* Remember the values we need. */
memsz = phdr->p_memsz;
filesz = phdr->p_filesz;
initimage = (void *) phdr->p_vaddr + main_map->l_addr;
initimage = phdr->p_vaddr + (void *) main_map->l_addr;
align = phdr->p_align;
if (phdr->p_align > max_align)
max_align = phdr->p_align;
+1 -2
View File
@@ -28,13 +28,12 @@ __wcpcpy_chk (wchar_t *dest, const wchar_t *src, size_t destlen)
{
wchar_t *wcp = (wchar_t *) dest - 1;
wint_t c;
const ptrdiff_t off = src - dest + 1;
do
{
if (__glibc_unlikely (destlen-- == 0))
__chk_fail ();
c = wcp[off];
c = *src++;
*++wcp = c;
}
while (c != L'\0');
+7 -27
View File
@@ -24,36 +24,16 @@ wchar_t *
__wcscpy_chk (wchar_t *dest, const wchar_t *src, size_t n)
{
wint_t c;
wchar_t *wcp;
wchar_t *wcp = dest;
if (__alignof__ (wchar_t) >= sizeof (wchar_t))
do
{
const ptrdiff_t off = dest - src - 1;
wcp = (wchar_t *) src;
do
{
if (__glibc_unlikely (n-- == 0))
__chk_fail ();
c = *wcp++;
wcp[off] = c;
}
while (c != L'\0');
}
else
{
wcp = dest;
do
{
if (__glibc_unlikely (n-- == 0))
__chk_fail ();
c = *src++;
*wcp++ = c;
}
while (c != L'\0');
if (__glibc_unlikely (n-- == 0))
__chk_fail ();
c = *src++;
*wcp++ = c;
}
while (c != L'\0');
return dest;
}
+1 -1
View File
@@ -90,7 +90,7 @@ compat_symbol (libdl, ___dlopen, dlopen, GLIBC_2_1);
void *
__dlopen (const char *file, int mode, void *dl_caller)
{
return dlopen_implementation (file, mode, RETURN_ADDRESS (0));
return dlopen_implementation (file, mode, dl_caller);
}
void *
+3
View File
@@ -210,6 +210,9 @@ print_entry (const char *lib, int flag, uint64_t hwcap,
case FLAG_AARCH64_LIB64:
fputs (",AArch64", stdout);
break;
case FLAG_AARCH64_PURECAP:
fputs (",purecap", stdout);
break;
/* Uses the ARM soft-float ABI. */
case FLAG_ARM_LIBSF:
fputs (",soft-float", stdout);
+3 -3
View File
@@ -119,11 +119,11 @@ call_destructors (void *closure)
if (map->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
(ElfW(Addr) *) (map->l_addr
elfptr_t *array =
(elfptr_t *) (map->l_addr
+ map->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
unsigned int sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)));
/ sizeof (elfptr_t));
while (sz-- > 0)
((fini_t) array[sz]) ();
+3 -3
View File
@@ -133,11 +133,11 @@ _dl_fini (void)
/* First see whether an array is given. */
if (l->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
(ElfW(Addr) *) (l->l_addr
elfptr_t *array =
(elfptr_t *) (l->l_addr
+ l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)));
/ sizeof (elfptr_t));
while (i-- > 0)
((fini_t) array[i]) ();
}
+6 -6
View File
@@ -61,11 +61,11 @@ call_init (struct link_map *l, int argc, char **argv, char **env)
{
unsigned int j;
unsigned int jm;
ElfW(Addr) *addrs;
elfptr_t *addrs;
jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (elfptr_t);
addrs = (ElfW(Addr) *) (init_array->d_un.d_ptr + l->l_addr);
addrs = (elfptr_t *) (init_array->d_un.d_ptr + l->l_addr);
for (j = 0; j < jm; ++j)
((dl_init_t) addrs[j]) (argc, argv, env);
}
@@ -88,16 +88,16 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
/* Don't do anything if there is no preinit array. */
if (__builtin_expect (preinit_array != NULL, 0)
&& preinit_array_size != NULL
&& (i = preinit_array_size->d_un.d_val / sizeof (ElfW(Addr))) > 0)
&& (i = preinit_array_size->d_un.d_val / sizeof (elfptr_t)) > 0)
{
ElfW(Addr) *addrs;
elfptr_t *addrs;
unsigned int cnt;
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
_dl_debug_printf ("\ncalling preinit: %s\n\n",
DSO_FILENAME (main_map->l_name));
addrs = (ElfW(Addr) *) (preinit_array->d_un.d_ptr + main_map->l_addr);
addrs = (elfptr_t *) (preinit_array->d_un.d_ptr + main_map->l_addr);
for (cnt = 0; cnt < i; ++cnt)
((dl_init_t) addrs[cnt]) (argc, argv, env);
}
+1 -1
View File
@@ -1369,7 +1369,7 @@ cannot enable executable stack as shared object requires");
/* Adjust the address of the TLS initialization image. */
if (l->l_tls_initimage != NULL)
l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
l->l_tls_initimage = (ElfW(Addr)) l->l_tls_initimage + (char *) l->l_addr;
/* Process program headers again after load segments are mapped in
case processing requires accessing those segments. Scan program
+21 -9
View File
@@ -21,12 +21,12 @@
/* Map a segment and align it properly. */
static __always_inline ElfW(Addr)
static __always_inline elfptr_t
_dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
const size_t maplength, int fd)
{
if (__glibc_likely (c->mapalign <= GLRO(dl_pagesize)))
return (ElfW(Addr)) __mmap ((void *) mappref, maplength, c->prot,
return (elfptr_t) __mmap ((void *) mappref, maplength, c->prot,
MAP_COPY|MAP_FILE, fd, c->mapoff);
/* If the segment alignment > the page size, allocate enough space to
@@ -34,15 +34,15 @@ _dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
ElfW(Addr) maplen = (maplength >= c->mapalign
? (maplength + c->mapalign)
: (2 * c->mapalign));
ElfW(Addr) map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplen,
elfptr_t map_start = (elfptr_t) __mmap ((void *) mappref, maplen,
PROT_NONE,
MAP_ANONYMOUS|MAP_PRIVATE,
-1, 0);
if (__glibc_unlikely ((void *) map_start == MAP_FAILED))
return map_start;
ElfW(Addr) map_start_aligned = ALIGN_UP (map_start, c->mapalign);
map_start_aligned = (ElfW(Addr)) __mmap ((void *) map_start_aligned,
elfptr_t map_start_aligned = ALIGN_UP (map_start, c->mapalign);
map_start_aligned = (elfptr_t) __mmap ((void *) map_start_aligned,
maplength, c->prot,
MAP_COPY|MAP_FILE|MAP_FIXED,
fd, c->mapoff);
@@ -54,7 +54,7 @@ _dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
ElfW(Addr) delta = map_start_aligned - map_start;
if (delta)
__munmap ((void *) map_start, delta);
ElfW(Addr) map_end = map_start_aligned + maplength;
elfptr_t map_end = map_start + (map_start_aligned - map_start) + maplength;
map_end = ALIGN_UP (map_end, GLRO(dl_pagesize));
delta = map_start + maplen - map_end;
if (delta)
@@ -126,6 +126,18 @@ _dl_map_segments (struct link_map *l, int fd,
goto postmap;
}
#ifdef __CHERI_PURE_CAPABILITY__
else
{
/* TODO: l_addr is 0 in an exe, but it should cover the load segments. */
uintptr_t l_addr = 0;
unsigned long allocend = ALIGN_UP (loadcmds[nloadcmds - 1].allocend,
GLRO(dl_pagesize));
asm volatile ("cvtd %0, %x0" : "+r"(l_addr));
asm volatile ("scbnds %0, %0, %x1" : "+r"(l_addr) : "r"(allocend));
l->l_addr = l_addr;
}
#endif
/* Remember which part of the address space this object uses. */
l->l_map_start = c->mapstart + l->l_addr;
@@ -134,10 +146,10 @@ _dl_map_segments (struct link_map *l, int fd,
while (c < &loadcmds[nloadcmds])
{
if (c->mapend > c->mapstart
if (c->dataend > c->mapstart
/* Map the segment contents from the file. */
&& (__mmap ((void *) (l->l_addr + c->mapstart),
c->mapend - c->mapstart, c->prot,
c->dataend - c->mapstart, c->prot,
MAP_FIXED|MAP_COPY|MAP_FILE,
fd, c->mapoff)
== MAP_FAILED))
@@ -150,7 +162,7 @@ _dl_map_segments (struct link_map *l, int fd,
{
/* Extra zero pages should appear at the end of this segment,
after the data mapped from the file. */
ElfW(Addr) zero, zeroend, zeropage;
elfptr_t zero, zeroend, zeropage;
zero = l->l_addr + c->dataend;
zeroend = l->l_addr + c->allocend;
+4 -1
View File
@@ -23,6 +23,7 @@
# pragma GCC visibility push(hidden)
#endif
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <ldsodefs.h>
#include <malloc/malloc-internal.h>
@@ -33,6 +34,7 @@ static void *alloc_ptr, *alloc_end, *alloc_last_block;
void *
__minimal_malloc (size_t n)
{
#ifndef __CHERI_PURE_CAPABILITY__
if (alloc_end == 0)
{
/* Consume any unused space in the last page of our data segment. */
@@ -42,9 +44,10 @@ __minimal_malloc (size_t n)
+ GLRO(dl_pagesize) - 1)
& ~(GLRO(dl_pagesize) - 1));
}
#endif
/* Make sure the allocation pointer is ideally aligned. */
alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + MALLOC_ALIGNMENT - 1)
alloc_ptr = (void *)(((uintptr_t)alloc_ptr + (MALLOC_ALIGNMENT - 1))
& ~(MALLOC_ALIGNMENT - 1));
if (alloc_ptr + n >= alloc_end || n >= -(uintptr_t) alloc_ptr)
+4
View File
@@ -182,6 +182,9 @@ static unsigned int log_hashfraction;
void
_dl_start_profile (void)
{
#ifdef __CHERI_PURE_CAPABILITY__
__libc_fatal ("Profiling is not supported on capability architectures.");
#else
char *filename;
int fd;
struct __stat64_t64 st;
@@ -482,6 +485,7 @@ _dl_start_profile (void)
/* Turn on profiling. */
running = 1;
#endif
}
+2 -2
View File
@@ -353,10 +353,10 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
void
_dl_protect_relro (struct link_map *l)
{
ElfW(Addr) start = ALIGN_DOWN((l->l_addr
elfptr_t start = ALIGN_DOWN((l->l_addr
+ l->l_relro_addr),
GLRO(dl_pagesize));
ElfW(Addr) end = ALIGN_DOWN((l->l_addr
elfptr_t end = ALIGN_DOWN((l->l_addr
+ l->l_relro_addr
+ l->l_relro_size),
GLRO(dl_pagesize));
+8
View File
@@ -248,6 +248,14 @@ _dl_aux_init (ElfW(auxv_t) *av)
GL(dl_sysinfo) = DL_SYSINFO_DEFAULT;
#endif
#ifdef __CHERI_PURE_CAPABILITY__
/* Base is 0 in non-pie static executable, but it needs to be a valid
capability. Use the zero capability instead of AT_BASE. */
elfptr_t zerocap;
asm volatile ("cvtd %0,xzr" : "=r"(zerocap));
_dl_main_map.l_addr = zerocap;
#endif
_dl_auxv = av;
dl_parse_auxv_t auxv_values;
/* Use an explicit initialization loop here because memset may not
+1 -1
View File
@@ -41,7 +41,7 @@ _dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value,
if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC))
{
DL_FIXUP_VALUE_TYPE fixup
= DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value);
= DL_FIXUP_MAKE_VALUE (result, (elfptr_t) value);
fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup));
value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup);
}
+2 -2
View File
@@ -41,14 +41,14 @@
static inline void __attribute__ ((always_inline))
elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) reladdr, ElfW(Addr) relsize,
elfptr_t reladdr, ElfW(Addr) relsize,
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
int lazy, int skip_ifunc)
{
const ElfW(Rel) *relative = (const void *) reladdr;
const ElfW(Rel) *r = relative + nrelative;
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
ElfW(Addr) l_addr = map->l_addr;
elfptr_t l_addr = map->l_addr;
const ElfW(Sym) *const symtab
= (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+6 -6
View File
@@ -37,7 +37,7 @@ elf_machine_rel (struct link_map *map, struct r_scope_elem *scope[],
const struct r_found_version *version,
void *const reloc_addr, int skip_ifunc);
static inline void __attribute__((always_inline))
elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
elf_machine_rel_relative (elfptr_t l_addr, const ElfW(Rel) *reloc,
void *const reloc_addr);
# endif
# if ! ELF_MACHINE_NO_RELA
@@ -47,18 +47,18 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
const struct r_found_version *version, void *const reloc_addr,
int skip_ifunc);
static inline void __attribute__((always_inline))
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
elf_machine_rela_relative (elfptr_t l_addr, const ElfW(Rela) *reloc,
void *const reloc_addr);
# endif
# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
static inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
elfptr_t l_addr, const ElfW(Rel) *reloc,
int skip_ifunc);
# else
static inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
elfptr_t l_addr, const ElfW(Rela) *reloc,
int skip_ifunc);
# endif
#endif
@@ -80,7 +80,7 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, test_rel) \
do { \
struct { ElfW(Addr) start, size; \
struct { elfptr_t start; ElfW(Addr) size; \
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \
ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; \
\
@@ -97,7 +97,7 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
if ((map)->l_info[DT_PLTREL] \
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
{ \
ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
elfptr_t start = D_PTR ((map), l_info[DT_JMPREL]); \
ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
\
if (ranges[0].start == 0) \
+39
View File
@@ -1159,6 +1159,14 @@ typedef struct
typedef struct
{
#if defined __CHERI_PURE_CAPABILITY__
uint64_t a_type;
uint64_t __pad;
union
{
__uintcap_t a_val;
} a_un;
#else
uint64_t a_type; /* Entry type */
union
{
@@ -1167,6 +1175,7 @@ typedef struct
though, since it does not work when using 32-bit definitions
on 64-bit platforms and vice versa. */
} a_un;
#endif
} Elf64_auxv_t;
/* Legal values for a_type (entry type). */
@@ -1243,6 +1252,12 @@ typedef struct
#define AT_MINSIGSTKSZ 51 /* Stack needed for signal delivery */
# define AT_CHERI_EXEC_RW_CAP 60
# define AT_CHERI_EXEC_RX_CAP 61
# define AT_CHERI_INTERP_RW_CAP 62
# define AT_CHERI_INTERP_RX_CAP 63
# define AT_CHERI_SEAL_CAP 64
/* Note section contents. Each entry in the note section begins with
a header of a fixed form. */
@@ -2906,6 +2921,9 @@ enum
/* MTE memory tag segment type. */
#define PT_AARCH64_MEMTAG_MTE (PT_LOPROC + 2)
/* Processor specific flags for the ELF header e_flags field. */
#define EF_AARCH64_CHERI_PURECAP 0x00010000
/* AArch64 specific values for the Dyn d_tag field. */
#define DT_AARCH64_BTI_PLT (DT_LOPROC + 1)
#define DT_AARCH64_PAC_PLT (DT_LOPROC + 3)
@@ -2915,6 +2933,27 @@ enum
/* AArch64 specific values for the st_other field. */
#define STO_AARCH64_VARIANT_PCS 0x80
/* Morello relocs. */
#define R_MORELLO_TSTBR14 57344
#define R_MORELLO_CONDBR19 57345
#define R_MORELLO_JUMP26 57346
#define R_MORELLO_CALL26 57347
#define R_MORELLO_LD_PREL_LO17 57348
#define R_MORELLO_ADR_PREL_PG_HI20 57349
#define R_MORELLO_ADR_PREL_PG_HI20_NC 57350
#define R_MORELLO_ADR_GOT_PAGE 57351
#define R_MORELLO_LD128_GOT_LO12_NC 57352
#define R_MORELLO_TLSDESC_ADR_PAGE20 57600
#define R_MORELLO_TLSDESC_LD128_LO12 57601
#define R_MORELLO_TLSDESC_CALL 57602
#define R_MORELLO_CAPINIT 59392
#define R_MORELLO_GLOB_DAT 59393
#define R_MORELLO_JUMP_SLOT 59394
#define R_MORELLO_RELATIVE 59395
#define R_MORELLO_IRELATIVE 59396
#define R_MORELLO_TLSDESC 59397
#define R_MORELLO_TPREL128 59398
/* ARM relocs. */
#define R_ARM_NONE 0 /* No reloc */
+7 -1
View File
@@ -34,6 +34,12 @@
#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
#include <bits/link.h>
#ifdef __CHERI_PURE_CAPABILITY__
typedef uintptr_t elfptr_t;
#else
typedef ElfW(Addr) elfptr_t;
#endif
/* The legacy rendezvous structure used by the run-time dynamic linker to
communicate details of shared object loading to the debugger. */
@@ -154,7 +160,7 @@ enum
struct dl_phdr_info
{
ElfW(Addr) dlpi_addr;
elfptr_t dlpi_addr;
const char *dlpi_name;
const ElfW(Phdr) *dlpi_phdr;
ElfW(Half) dlpi_phnum;
+43 -15
View File
@@ -24,6 +24,7 @@
#include <dl-r_debug.h>
#ifndef __CHERI_PURE_CAPABILITY__
struct E(link_map)
{
EW(Addr) l_addr;
@@ -35,6 +36,48 @@ struct E(link_map)
Lmid_t l_ns;
EW(Addr) l_libname;
};
struct E(libname_list)
{
EW(Addr) name;
EW(Addr) next;
};
struct E(r_debug)
{
int r_version;
# if CLASS == 64
int pad;
# endif
EW(Addr) r_map;
};
#else
struct E(link_map)
{
uintptr_t l_addr;
uintptr_t l_name;
uintptr_t l_ld;
uintptr_t l_next;
uintptr_t l_prev;
uintptr_t l_real;
Lmid_t l_ns;
uintptr_t l_libname;
};
struct E(libname_list)
{
uintptr_t name;
uintptr_t next;
};
struct E(r_debug)
{
int r_version;
int pad;
uintptr_t r_map;
};
#endif
#if CLASS == __ELF_NATIVE_CLASS
_Static_assert (offsetof (struct link_map, l_addr)
== offsetof (struct E(link_map), l_addr), "l_addr");
@@ -44,27 +87,12 @@ _Static_assert (offsetof (struct link_map, l_next)
== offsetof (struct E(link_map), l_next), "l_next");
#endif
struct E(libname_list)
{
EW(Addr) name;
EW(Addr) next;
};
#if CLASS == __ELF_NATIVE_CLASS
_Static_assert (offsetof (struct libname_list, name)
== offsetof (struct E(libname_list), name), "name");
_Static_assert (offsetof (struct libname_list, next)
== offsetof (struct E(libname_list), next), "next");
#endif
struct E(r_debug)
{
int r_version;
#if CLASS == 64
int pad;
#endif
EW(Addr) r_map;
};
#if CLASS == __ELF_NATIVE_CLASS
_Static_assert (offsetof (struct r_debug, r_version)
== offsetof (struct E(r_debug), r_version), "r_version");
+13 -8
View File
@@ -416,15 +416,15 @@ DL_SYSINFO_IMPLEMENTATION
#endif
#ifdef DONT_USE_BOOTSTRAP_MAP
static ElfW(Addr) _dl_start_final (void *arg);
static elfptr_t _dl_start_final (void *arg);
#else
struct dl_start_final_info
{
struct link_map l;
RTLD_TIMING_VAR (start_time);
};
static ElfW(Addr) _dl_start_final (void *arg,
struct dl_start_final_info *info);
static elfptr_t _dl_start_final (void *arg,
struct dl_start_final_info *info);
#endif
/* These are defined magically by the linker. */
@@ -446,10 +446,10 @@ RTLD_START
this function is not inlined (see below). */
#ifdef DONT_USE_BOOTSTRAP_MAP
static inline ElfW(Addr) __attribute__ ((always_inline))
static inline elfptr_t __attribute__ ((always_inline))
_dl_start_final (void *arg)
#else
static ElfW(Addr) __attribute__ ((noinline))
static elfptr_t __attribute__ ((noinline))
_dl_start_final (void *arg, struct dl_start_final_info *info)
#endif
{
@@ -515,7 +515,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
# define bootstrap_map info.l
#endif
static ElfW(Addr) __attribute_used__
static elfptr_t __attribute_used__
_dl_start (void *arg)
{
#ifdef DONT_USE_BOOTSTRAP_MAP
@@ -542,11 +542,16 @@ _dl_start (void *arg)
# endif
#endif
#ifdef __CHERI_PURE_CAPABILITY__
bootstrap_map.l_addr = elf_machine_load_address_from_args (arg);
bootstrap_map.l_ld = elf_machine_runtime_dynamic ();
#else
/* Figure out the run-time load address of the dynamic linker itself. */
bootstrap_map.l_addr = elf_machine_load_address ();
/* Read our own dynamic section and fill in the info array. */
bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic ();
#endif
bootstrap_map.l_ld_readonly = DL_RO_DYN_SECTION;
elf_get_dynamic_info (&bootstrap_map, true, false);
@@ -1152,7 +1157,7 @@ rtld_setup_main_map (struct link_map *main_map)
{
case PT_PHDR:
/* Find out the load address. */
main_map->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr;
main_map->l_addr = (elfptr_t) phdr - ph->p_vaddr;
break;
case PT_DYNAMIC:
/* This tells us where to find the dynamic section,
@@ -1274,7 +1279,7 @@ rtld_setup_main_map (struct link_map *main_map)
the executable is actually an ET_DYN object. */
if (main_map->l_tls_initimage != NULL)
main_map->l_tls_initimage
= (char *) main_map->l_tls_initimage + main_map->l_addr;
= (ElfW(Addr)) main_map->l_tls_initimage + (char *) main_map->l_addr;
if (! main_map->l_map_end)
main_map->l_map_end = ~0;
if (! main_map->l_text_end)
+8
View File
@@ -27,7 +27,11 @@ static int
do_test (int argc, char *argv[])
{
errno = 0;
#ifndef __CHERI_PURE_CAPABILITY__
const char *execfn = (const char *) getauxval (AT_NULL);
#else
const char *execfn = (const char *) getauxptr (AT_NULL);
#endif
if (errno != ENOENT)
{
@@ -43,7 +47,11 @@ do_test (int argc, char *argv[])
}
errno = 0;
#ifndef __CHERI_PURE_CAPABILITY__
execfn = (const char *) getauxval (AT_EXECFN);
#else
execfn = (const char *) getauxptr (AT_EXECFN);
#endif
if (execfn == NULL)
{
+1 -1
View File
@@ -30,7 +30,7 @@ static int
callback (struct dl_phdr_info *info, size_t size, void *ptr)
{
static int last_adds = 0, last_subs = 0;
intptr_t cmd = (intptr_t) ptr;
unsigned long cmd = (intptr_t) ptr;
printf (" size = %Zu\n", size);
if (size < (offsetof (struct dl_phdr_info, dlpi_subs)
+6 -5
View File
@@ -82,6 +82,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <sys/param.h>
#include <libc-pointer-arith.h>
/* struct alloc_buffer objects refer to a region of bytes in memory of a
fixed size. The functions below can be used to allocate single
@@ -248,9 +249,9 @@ __alloc_buffer_alloc (struct alloc_buffer *buf, size_t size, size_t align)
if (size == 1 && align == 1)
return alloc_buffer_alloc_bytes (buf, size);
size_t current = buf->__alloc_buffer_current;
size_t aligned = roundup (current, align);
size_t new_current = aligned + size;
uintptr_t current = buf->__alloc_buffer_current;
uintptr_t aligned = roundup (current, align);
uintptr_t new_current = aligned + size;
if (aligned >= current /* No overflow in align step. */
&& new_current >= size /* No overflow in size computation. */
&& new_current <= buf->__alloc_buffer_end) /* Room in buffer. */
@@ -282,8 +283,8 @@ __alloc_buffer_next (struct alloc_buffer *buf, size_t align)
if (align == 1)
return (const void *) buf->__alloc_buffer_current;
size_t current = buf->__alloc_buffer_current;
size_t aligned = roundup (current, align);
uintptr_t current = buf->__alloc_buffer_current;
uintptr_t aligned = roundup (current, align);
if (aligned >= current /* No overflow in align step. */
&& aligned <= buf->__alloc_buffer_end) /* Room in buffer. */
{
+15 -2
View File
@@ -62,6 +62,8 @@
__atg1_result = pre##_32_##post (mem, __VA_ARGS__); \
else if (sizeof (*mem) == 8) \
__atg1_result = pre##_64_##post (mem, __VA_ARGS__); \
else if (sizeof (*mem) == 16) \
__atg1_result = pre##_128_##post (mem, __VA_ARGS__); \
else \
abort (); \
__atg1_result; \
@@ -77,6 +79,8 @@
__atg2_result = pre##_32_##post (mem, __VA_ARGS__); \
else if (sizeof (*mem) == 8) \
__atg2_result = pre##_64_##post (mem, __VA_ARGS__); \
else if (sizeof (*mem) == 16) \
__atg2_result = pre##_128_##post (mem, __VA_ARGS__); \
else \
abort (); \
__atg2_result; \
@@ -540,7 +544,11 @@
/* We require 32b atomic operations; some archs also support 64b atomic
operations. */
void __atomic_link_error (void);
# if __HAVE_64B_ATOMICS == 1
# if defined __CHERI_PURE_CAPABILITY__
# define __atomic_check_size(mem) \
if ((sizeof (*mem) != 4) && (sizeof (*mem) != 8) && (sizeof (*mem) != 16)) \
__atomic_link_error ();
# elif __HAVE_64B_ATOMICS == 1
# define __atomic_check_size(mem) \
if ((sizeof (*mem) != 4) && (sizeof (*mem) != 8)) \
__atomic_link_error ();
@@ -553,7 +561,12 @@ void __atomic_link_error (void);
need other atomic operations of such sizes, and restricting the support to
loads and stores makes this easier for archs that do not have native
support for atomic operations to less-than-word-sized data. */
# if __HAVE_64B_ATOMICS == 1
# if defined __CHERI_PURE_CAPABILITY__
# define __atomic_check_size_ls(mem) \
if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && (sizeof (*mem) != 4) \
&& (sizeof (*mem) != 8) && (sizeof (*mem) != 16)) \
__atomic_link_error ();
# elif __HAVE_64B_ATOMICS == 1
# define __atomic_check_size_ls(mem) \
if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && (sizeof (*mem) != 4) \
&& (sizeof (*mem) != 8)) \
+5 -1
View File
@@ -426,8 +426,12 @@ for linking")
#define attribute_tls_model_ie __attribute__ ((tls_model ("initial-exec")))
#if defined __CHERI_PURE_CAPABILITY__
/* avoid readonly caps at startup when relro has to be writable */
#define attribute_relro
#else
#define attribute_relro __attribute__ ((section (".data.rel.ro")))
#endif
/* Used to disable stack protection in sensitive places, like ifunc
resolvers and early static TLS init. */
+6 -5
View File
@@ -83,6 +83,7 @@ struct r_search_path_struct
extern struct r_search_path_struct __rtld_search_dirs attribute_hidden;
extern struct r_search_path_struct __rtld_env_path_list attribute_hidden;
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
members form a chain of all the shared objects loaded at startup.
@@ -96,9 +97,9 @@ struct link_map
{
/* These first few members are part of the protocol with the debugger.
This is the same format used in SVR4. */
ElfW(Addr) l_addr; /* Difference between the address in the ELF
elfptr_t l_addr; /* Difference between the address in the ELF
file and the addresses in memory. */
char *l_name; /* Absolute file name object was found in. */
ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */
struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
@@ -252,9 +253,9 @@ struct link_map
/* Start and finish of memory map for this object. l_map_start
need not be the same as l_addr. */
ElfW(Addr) l_map_start, l_map_end;
elfptr_t l_map_start, l_map_end;
/* End of the executable part of the mapping. */
ElfW(Addr) l_text_end;
elfptr_t l_text_end;
/* Default array for 'l_scope'. */
struct r_scope_elem *l_scope_mem[4];
@@ -343,7 +344,7 @@ struct link_map
/* Information used to change permission after the relocations are
done. */
ElfW(Addr) l_relro_addr;
elfptr_t l_relro_addr;
size_t l_relro_size;
unsigned long long int l_serial;
+4
View File
@@ -10,4 +10,8 @@ libc_hidden_proto (__getauxval)
_Bool __getauxval2 (unsigned long int type, unsigned long int *result);
libc_hidden_proto (__getauxval2)
/* Like getauxval, but for Arm Morello capabilities. */
extern __typeof (getauxptr) __getauxptr;
libc_hidden_proto (__getauxptr)
#endif /* !_ISOMAC */
+4 -2
View File
@@ -340,8 +340,10 @@ read_alias_file (const char *fname, int fname_len)
for (i = 0; i < nmap; i++)
{
map[i].alias += new_pool - string_space;
map[i].value += new_pool - string_space;
map[i].alias = new_pool
+ (map[i].alias - string_space);
map[i].value = new_pool
+ (map[i].value - string_space);
}
}
+2 -1
View File
@@ -55,6 +55,7 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#include <dirent.h>
#include <errno.h>
#include <fts.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -67,7 +68,7 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#endif
/* Align P to that size. */
#ifndef ALIGN
#define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
#define ALIGN(p) (((uintptr_t) (p) + ALIGNBYTES) & ~ALIGNBYTES)
#endif
+3 -1
View File
@@ -95,7 +95,9 @@ struct _IO_FILE_complete
size_t __pad5;
int _mode;
/* Make sure we don't get into trouble again. */
char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
char _unused2[sizeof (void *) == 4 * sizeof (int)
? 9 * sizeof (int)
: 15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
};
/* These macros are used by bits/stdio.h and internal headers. */
+3 -3
View File
@@ -23,12 +23,12 @@ void *
__libc_alloc_buffer_alloc_array (struct alloc_buffer *buf, size_t element_size,
size_t align, size_t count)
{
size_t current = buf->__alloc_buffer_current;
uintptr_t current = buf->__alloc_buffer_current;
/* The caller asserts that align is a power of two. */
size_t aligned = ALIGN_UP (current, align);
uintptr_t aligned = ALIGN_UP (current, align);
size_t size;
bool overflow = __builtin_mul_overflow (element_size, count, &size);
size_t new_current = aligned + size;
uintptr_t new_current = aligned + size;
if (!overflow /* Multiplication did not overflow. */
&& aligned >= current /* No overflow in align step. */
&& new_current >= size /* No overflow in size computation. */
+3 -3
View File
@@ -444,7 +444,7 @@ dump_heap (heap_info *heap)
fprintf (stderr, "Heap %p, size %10lx:\n", heap, (long) heap->size);
ptr = (heap->ar_ptr != (mstate) (heap + 1)) ?
(char *) (heap + 1) : (char *) (heap + 1) + sizeof (struct malloc_state);
p = (mchunkptr) (((unsigned long) ptr + MALLOC_ALIGN_MASK) &
p = (mchunkptr) (((uintptr_t) ptr + MALLOC_ALIGN_MASK) &
~MALLOC_ALIGN_MASK);
for (;; )
{
@@ -518,7 +518,7 @@ alloc_new_heap (size_t size, size_t top_pad, size_t pagesize,
p1 = (char *) MMAP (0, max_size << 1, PROT_NONE, mmap_flags);
if (p1 != MAP_FAILED)
{
p2 = (char *) (((unsigned long) p1 + (max_size - 1))
p2 = (char *) (((uintptr_t) p1 + (max_size - 1))
& ~(max_size - 1));
ul = p2 - p1;
if (ul)
@@ -760,7 +760,7 @@ _int_new_arena (size_t size)
/* Set up the top chunk, with proper alignment. */
ptr = (char *) (a + 1);
misalign = (unsigned long) chunk2mem (ptr) & MALLOC_ALIGN_MASK;
misalign = (uintptr_t) chunk2mem (ptr) & MALLOC_ALIGN_MASK;
if (misalign > 0)
ptr += MALLOC_ALIGNMENT - misalign;
top (a) = (mchunkptr) ptr;
+5 -2
View File
@@ -341,8 +341,12 @@ Fatal glibc error: malloc assertion failure in %s: %s\n",
It assumes a minimum page size of 4096 bytes (12 bits). Systems with
larger pages provide less entropy, although the pointer mangling
still works. */
#ifdef __CHERI_PURE_CAPABILITY__
#define PROTECT_PTR(pos, ptr) (ptr)
#else
#define PROTECT_PTR(pos, ptr) \
((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
#endif
#define REVEAL_PTR(ptr) PROTECT_PTR (&ptr, ptr)
/*
@@ -4978,8 +4982,7 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
we can move to the next aligned spot -- we've allocated enough
total room so that this is always possible.
*/
brk = (char *) mem2chunk (((unsigned long) (m + alignment - 1)) &
- ((signed long) alignment));
brk = (char *) mem2chunk (m + alignment - ((unsigned long) (m) % alignment));
if ((unsigned long) (brk - (char *) (p)) < MINSIZE)
brk += alignment;
+1 -1
View File
@@ -74,7 +74,7 @@ checkhdr (const struct hdr *hdr)
an error and report it. */
return MCHECK_OK;
switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next))
switch (hdr->magic ^ ((unsigned long) hdr->prev + (unsigned long) hdr->next))
{
default:
status = MCHECK_HEAD;
+3 -16
View File
@@ -116,22 +116,9 @@
# define PTR_INT_TYPE ptrdiff_t
#endif
/* If B is the base of an object addressed by P, return the result of
aligning P to the next multiple of A + 1. B and P must be of type
char *. A + 1 must be a power of 2. */
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case
where pointers can be converted to integers, aligned as integers,
and converted back again. If PTR_INT_TYPE is narrower than a
pointer (e.g., the AS/400), play it safe and compute the alignment
relative to B. Otherwise, use the faster strategy of computing the
alignment relative to 0. */
#define __PTR_ALIGN(B, P, A) \
__BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
P, A)
/* Align P to the next multiple of A + 1, where A + 1 is a power of 2,
A fits into unsigned long and P has type char *. */
#define __PTR_ALIGN(B, P, A) ((P) + (-(unsigned long)(P) & (A)))
#include <string.h>
+3
View File
@@ -164,6 +164,9 @@ libc {
GLIBC_2.32 {
__libc_single_threaded;
}
GLIBC_2.37 {
__getauxptr; getauxptr;
}
GLIBC_PRIVATE {
__madvise;
__mktemp;
+33
View File
@@ -20,6 +20,39 @@
#include <ldsodefs.h>
#include <stdbool.h>
void *
__getauxptr (unsigned long int type)
{
/* error if asking for a non-pointer from getauxptr(). This list is not a
perfect enforcement as it currently supports both transitional and draft
ABIs, which have different capability entries. */
switch (type) {
case AT_ENTRY:
case AT_PHDR:
case AT_BASE:
case AT_SYSINFO_EHDR:
case AT_EXECFN:
case AT_RANDOM:
case AT_PLATFORM:
case AT_CHERI_EXEC_RW_CAP:
case AT_CHERI_EXEC_RX_CAP:
case AT_CHERI_INTERP_RW_CAP:
case AT_CHERI_INTERP_RX_CAP:
case AT_CHERI_SEAL_CAP:
{
ElfW(auxv_t) *p;
for (p = GLRO(dl_auxv); p->a_type != AT_NULL; p++)
if (p->a_type == type)
return (void *) p->a_un.a_val;
}
}
__set_errno (ENOENT);
return 0;
}
weak_alias (__getauxptr, getauxptr)
libc_hidden_def (__getauxptr)
bool
__getauxval2 (unsigned long int type, unsigned long int *result)
{
+4
View File
@@ -31,6 +31,10 @@ __BEGIN_DECLS
extern unsigned long int getauxval (unsigned long int __type)
__THROW;
/* Same as getauxval, but for Arm Morello capabilities. */
extern void * getauxptr (unsigned long int __type)
__THROW;
__END_DECLS
#endif /* sys/auxv.h */
+4 -4
View File
@@ -131,15 +131,15 @@ typedef struct node_t
uintptr_t right_node;
} *node;
#define RED(N) (node)((N)->left_node & ((uintptr_t) 0x1))
#define RED(N) (unsigned int)((N)->left_node & ((uintptr_t) 0x1))
#define SETRED(N) (N)->left_node |= ((uintptr_t) 0x1)
#define SETBLACK(N) (N)->left_node &= ~((uintptr_t) 0x1)
#define SETNODEPTR(NP,P) (*NP) = (node)((((uintptr_t)(*NP)) \
#define SETNODEPTR(NP,P) (*NP) = (node)((unsigned int)(((uintptr_t)(*NP)) \
& (uintptr_t) 0x1) | (uintptr_t)(P))
#define LEFT(N) (node)((N)->left_node & ~((uintptr_t) 0x1))
#define LEFTPTR(N) (node *)(&(N)->left_node)
#define SETLEFT(N,L) (N)->left_node = (((N)->left_node & (uintptr_t) 0x1) \
| (uintptr_t)(L))
#define SETLEFT(N,L) (N)->left_node = ((unsigned int)((N)->left_node \
& (uintptr_t) 0x1) | (uintptr_t)(L))
#define RIGHT(N) (node)((N)->right_node)
#define RIGHTPTR(N) (node *)(&(N)->right_node)
#define SETRIGHT(N,R) (N)->right_node = (uintptr_t)(R)
+8 -1
View File
@@ -19,7 +19,9 @@
#include <limits.h>
#include "pthreadP.h"
#include <shlib-compat.h>
#ifdef __CHERI_PURE_CAPABILITY__
# include <cheri_perms.h>
#endif
#ifndef NEW_VERNUM
# define NEW_VERNUM GLIBC_2_3_3
@@ -43,6 +45,11 @@ __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
EXTRA_PARAM_CHECKS;
#endif
#ifdef __CHERI_PURE_CAPABILITY__
if (!STACK_CAP_CHECK (stackaddr, stacksize))
return EINVAL;
#endif
iattr->stacksize = stacksize;
#if _STACK_GROWS_DOWN
iattr->stackaddr = (char *) stackaddr + stacksize;
+4
View File
@@ -204,7 +204,11 @@ typedef __off64_t __loff_t; /* Type of file sizes and offsets (LFS). */
typedef char *__caddr_t;
/* Duplicates info from stdint.h but this is used in unistd.h. */
#ifdef __CHERI_PURE_CAPABILITY__
__STD_TYPE __intcap_t __intptr_t;
#else
__STD_TYPE __SWORD_TYPE __intptr_t;
#endif
/* Duplicate info from sys/socket.h. */
__STD_TYPE __U32_TYPE __socklen_t;
+1 -1
View File
@@ -7,7 +7,7 @@ main (void)
int retval = 0;
long int res;
res = ulimit (UL_SETFSIZE, 10000);
res = ulimit (UL_SETFSIZE, 10000L);
printf ("Result of ulimit (UL_SETFSIZE, 10000): %ld\n", res);
if (res != 10000)
retval = 1;
+17 -1
View File
@@ -159,8 +159,24 @@ class Context(object):
"""Add all known glibc build configurations."""
self.add_config(arch='aarch64',
os_name='linux-gnu',
gcc_cfg=['--with-multilib-list=lp64,purecap',
'--disable-libgomp', '--disable-libitm'],
glibcs=[{},
{'variant': 'purecap',
'ccopts': '-mabi=purecap -march=morello+c64',
'cfg': ['--disable-werror']}],
extra_glibcs=[{'variant': 'disable-multi-arch',
'cfg': ['--disable-multi-arch']}])
'cfg': ['--disable-multi-arch']},
{'variant': 'purecap-nopie',
'ccopts': '-mabi=purecap -march=morello+c64',
'cfg': ['--disable-werror', '--disable-default-pie']}])
self.add_config(arch='aarch64',
os_name='linux-gnu_purecap',
gcc_cfg=['--with-abi=purecap', '--with-arch=morello+c64', '--disable-multilib',
'--disable-libgomp', '--disable-libitm'],
glibcs=[{'cfg': ['--disable-werror']}],
extra_glibcs=[{'variant': 'nopie',
'cfg': ['--disable-werror', '--disable-default-pie']}])
self.add_config(arch='aarch64_be',
os_name='linux-gnu')
self.add_config(arch='arc',
+1 -1
View File
@@ -177,7 +177,7 @@ END {
n = indices[2];
m = indices[3];
printf (" {TUNABLE_NAME_S(%s, %s, %s)", t, n, m)
printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n",
printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, false, TUNABLE_SECLEVEL_%s, %s},\n",
types[t,n,m], minvals[t,n,m], maxvals[t,n,m],
default_val[t,n,m], security_level[t,n,m], env_alias[t,n,m]);
}
+5
View File
@@ -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;
+2 -1
View File
@@ -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. */
};
+13
View File
@@ -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;
+121
View File
@@ -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');
+4
View File
@@ -289,6 +289,10 @@ __qsort_r (void *b, size_t n, size_t s, __compar_d_fn_t cmp, void *arg)
&& ((char *) b - (char *) 0) % __alignof__ (uint64_t) == 0)
p.var = 1;
else if ((s & (sizeof (unsigned long) - 1)) == 0
#ifdef __CHERI_PURE_CAPABILITY__
&& ((char *) b - (char *) 0)
% __alignof__ (void *) != 0
#endif
&& ((char *) b - (char *) 0)
% __alignof__ (unsigned long) == 0)
p.var = 2;
+12
View File
@@ -84,10 +84,22 @@ typedef unsigned long long int uint_fast64_t;
/* Types for `void *' pointers. */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
# ifdef __CHERI_PURE_CAPABILITY__
typedef __intcap_t intptr_t;
# else
typedef long int intptr_t;
# endif
# define __intptr_t_defined
# endif
# ifdef __CHERI_PURE_CAPABILITY__
typedef __uintcap_t uintptr_t;
# else
typedef unsigned long int uintptr_t;
# endif
# if defined __CHERI__ && !defined __CHERI_PURE_CAPABILITY__
typedef __uintcap_t uintcap_t;
typedef __intcap_t intcap_t;
# endif
#else
# ifndef __intptr_t_defined
typedef int intptr_t;
+3 -1
View File
@@ -63,7 +63,7 @@ last (void)
}
int
main (void)
do_test (void)
{
int value;
void *dso;
@@ -90,3 +90,5 @@ main (void)
FAIL_EXIT1 ("Did not terminate via exit(0) in exit_thread() as expected.");
}
#include <support/test-driver.c>
+7 -6
View File
@@ -27,6 +27,7 @@
#endif
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -529,7 +530,7 @@ test_strlen (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
check (strlen (p) == 2, 4+i);
@@ -554,7 +555,7 @@ test_strnlen (void)
char buf[4096];
for (int i = 0; i < 0x100; ++i)
{
char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
char *p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p + 3, "BAD/WRONG");
check (strnlen (p, 100) == 2, 10 + i);
@@ -582,7 +583,7 @@ test_strchr (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
check (strchr (p, '/') == NULL, 9+i);
@@ -614,7 +615,7 @@ test_strchrnul (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
cp = strchrnul (p, '/');
@@ -643,7 +644,7 @@ test_rawmemchr (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
check (rawmemchr (p, 'R') == p+8, 6+i);
@@ -689,7 +690,7 @@ test_strrchr (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
check (strrchr (p, '/') == NULL, 9+i);
+40 -2
View File
@@ -98,7 +98,8 @@ void support_record_failure (void);
/* Compare the two integers LEFT and RIGHT and report failure if they
are different. */
#define TEST_COMPARE(left, right) \
#ifndef __CHERI_PURE_CAPABILITY__
# define TEST_COMPARE(left, right) \
({ \
/* + applies the integer promotions, for bitfield support. */ \
typedef __typeof__ (+ (left)) __left_type; \
@@ -126,6 +127,32 @@ void support_record_failure (void);
#left, __left_value, __left_is_positive, sizeof (__left_type), \
#right, __right_value, __right_is_positive, sizeof (__right_type)); \
})
#else
# define TEST_COMPARE(left, right) \
({ \
/* + applies the integer promotions, for bitfield support. */ \
typedef __typeof__ (+ (left)) __left_type; \
typedef __typeof__ (+ (right)) __right_type; \
__left_type __left_value = (left); \
__right_type __right_value = (right); \
int __left_is_positive = __left_value > 0; \
int __right_is_positive = __right_value > 0; \
/* Prevent use with floating-point types. */ \
support_static_assert ((__left_type) 1.0 == (__left_type) 1.5, \
"left value has floating-point type"); \
support_static_assert ((__right_type) 1.0 == (__right_type) 1.5, \
"right value has floating-point type"); \
/* Compare the value. */ \
if (__left_value != __right_value \
|| __left_is_positive != __right_is_positive) \
/* Pass the sign for printing the correct value. */ \
support_test_compare_failure \
(__FILE__, __LINE__, \
#left, __left_value, __left_is_positive, sizeof (__left_type), \
#right, __right_value, __right_is_positive, sizeof (__right_type)); \
})
#endif
/* Internal implementation of TEST_COMPARE. LEFT_POSITIVE and
RIGHT_POSITIVE are used to store the sign separately, so that both
@@ -133,6 +160,7 @@ void support_record_failure (void);
RIGHT_VALUE, and the function can still print the original value.
LEFT_SIZE and RIGHT_SIZE specify the size of the argument in bytes,
for hexadecimal formatting. */
#ifndef __CHERI_PURE_CAPABILITY__
void support_test_compare_failure (const char *file, int line,
const char *left_expr,
long long left_value,
@@ -142,7 +170,17 @@ void support_test_compare_failure (const char *file, int line,
long long right_value,
int right_positive,
int right_size);
#else
void support_test_compare_failure (const char *file, int line,
const char *left_expr,
__uintcap_t left_value,
int left_positive,
int left_size,
const char *right_expr,
__uintcap_t right_value,
int right_positive,
int right_size);
#endif
/* Compare [LEFT, LEFT + LEFT_LENGTH) with [RIGHT, RIGHT +
RIGHT_LENGTH) and report a test failure if the arrays are
+25
View File
@@ -34,6 +34,7 @@ report (const char *which, const char *expr, long long value, int positive,
printf (" (0x%llx); from: %s\n", (unsigned long long) value & mask, expr);
}
#ifndef __CHERI_PURE_CAPABILITY__
void
support_test_compare_failure (const char *file, int line,
const char *left_expr,
@@ -56,3 +57,27 @@ support_test_compare_failure (const char *file, int line,
report ("right", right_expr, right_value, right_positive, right_size);
errno = saved_errno;
}
#else
void
support_test_compare_failure (const char *file, int line,
const char *left_expr,
__uintcap_t left_value,
int left_positive,
int left_size,
const char *right_expr,
__uintcap_t right_value,
int right_positive,
int right_size)
{
int saved_errno = errno;
support_record_failure ();
if (left_size != right_size)
printf ("%s:%d: numeric comparison failure (widths %d and %d)\n",
file, line, left_size * 8, right_size * 8);
else
printf ("%s:%d: numeric comparison failure\n", file, line);
report (" left", left_expr, left_value, left_positive, left_size);
report ("right", right_expr, right_value, right_positive, right_size);
errno = saved_errno;
}
#endif
+1 -1
View File
@@ -39,7 +39,7 @@ gen-as-const-headers += dl-link.sym
tests-internal += tst-ifunc-arg-1 tst-ifunc-arg-2
ifeq (yes,$(aarch64-variant-pcs))
ifeq (yesyesno,$(aarch64-variant-pcs)$(build-shared)$(aarch64-purecap))
tests += tst-vpcs
modules-names += tst-vpcs-mod
LDFLAGS-tst-vpcs-mod.so = -Wl,-z,lazy
+21
View File
@@ -54,6 +54,13 @@
model, __ATOMIC_RELAXED); \
})
# define __arch_compare_and_exchange_bool_128_int(mem, newval, oldval, model) \
({ \
typeof (*mem) __oldval = (oldval); \
!__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
model, __ATOMIC_RELAXED); \
})
# define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \
({ \
typeof (*mem) __oldval = (oldval); \
@@ -86,6 +93,14 @@
__oldval; \
})
# define __arch_compare_and_exchange_val_128_int(mem, newval, oldval, model) \
({ \
typeof (*mem) __oldval = (oldval); \
__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
model, __ATOMIC_RELAXED); \
__oldval; \
})
/* Compare and exchange with "acquire" semantics, ie barrier after. */
@@ -118,6 +133,9 @@
# define __arch_exchange_64_int(mem, newval, model) \
__atomic_exchange_n (mem, newval, model)
# define __arch_exchange_128_int(mem, newval, model) \
__atomic_exchange_n (mem, newval, model)
# define atomic_exchange_acq(mem, value) \
__atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE)
@@ -139,6 +157,9 @@
# define __arch_exchange_and_add_64_int(mem, value, model) \
__atomic_fetch_add (mem, value, model)
# define __arch_exchange_and_add_128_int(mem, value, model) \
__atomic_fetch_add (mem, value, model)
# define atomic_exchange_and_add_acq(mem, value) \
__atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
__ATOMIC_ACQUIRE)
+19
View File
@@ -28,6 +28,7 @@ typedef union
} La_aarch64_vector;
/* Registers for entry into PLT on AArch64. */
#ifndef __CHERI_PURE_CAPABILITY__
typedef struct La_aarch64_regs
{
uint64_t lr_xreg[9];
@@ -46,6 +47,24 @@ typedef struct La_aarch64_retval
La_aarch64_vector lrv_vreg[8];
void *lrv_vpcs;
} La_aarch64_retval;
#else
typedef struct La_aarch64_regs
{
uintptr_t lr_xreg[9];
La_aarch64_vector lr_vreg[8];
uintptr_t lr_sp;
uintptr_t lr_lr;
void *lr_vpcs;
} La_aarch64_regs;
typedef struct La_aarch64_retval
{
uintptr_t lrv_xreg[8];
La_aarch64_vector lrv_vreg[8];
void *lrv_vpcs;
} La_aarch64_retval;
#endif
__BEGIN_DECLS
extern ElfW(Addr)
+4 -1
View File
@@ -27,7 +27,10 @@
/* Jump buffer contains:
x19-x28, x29(fp), x30(lr), (x31)sp, d8-d15. Other registers are not
saved. */
# ifndef __CHERI_PURE_CAPABILITY__
__extension__ typedef unsigned long long __jmp_buf [22];
# else
__extension__ typedef __uintcap_t __jmp_buf [22];
# endif
#endif
#endif
+1 -1
View File
@@ -17,7 +17,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifdef __LP64__
#if defined __LP64__ || defined __CHERI_PURE_CAPABILITY__
# define __WORDSIZE 64
#else
# define __WORDSIZE 32
Vendored Regular → Executable
+45 -9
View File
@@ -1,10 +1,6 @@
# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
# Local configure fragment for sysdeps/aarch64.
# Static PIE is supported.
$as_echo "#define SUPPORT_STATIC_PIE 1" >>confdefs.h
# We check to see if the compiler and flags are
# selecting the big endian ABI and if they are then
# we set libc_cv_aarch64_be to yes which causes
@@ -167,16 +163,56 @@ rm -f conftest*
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_be" >&5
$as_echo "$libc_cv_aarch64_be" >&6; }
# Check for purecap ABI too, an alternative name is l64pc128.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for purecap ABI" >&5
$as_echo_n "checking for purecap ABI... " >&6; }
if ${libc_cv_aarch64_purecap+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __CHERI_PURE_CAPABILITY__
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
libc_cv_aarch64_purecap=yes
else
libc_cv_aarch64_purecap=no
fi
rm -f conftest*
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_purecap" >&5
$as_echo "$libc_cv_aarch64_purecap" >&6; }
config_vars="$config_vars
aarch64-purecap = $libc_cv_aarch64_purecap"
libc_aarch64_be=""
if test $libc_cv_aarch64_be = yes; then
$as_echo "#define HAVE_AARCH64_BE 1" >>confdefs.h
config_vars="$config_vars
default-abi = lp64_be"
else
config_vars="$config_vars
default-abi = lp64"
libc_aarch64_be="_be"
fi
libc_aarch64_abi="lp64"
if test $libc_cv_aarch64_purecap = yes; then
libc_aarch64_abi="purecap"
# The purecap abi requires relocations because objects may not be
# within bounds for PCC. This means static-pie is not supported.
$as_echo "#define HIDDEN_VAR_NEEDS_DYNAMIC_RELOC 1" >>confdefs.h
else
# Static PIE is supported. Hidden variables only need relocations
# in PIE with -mcmodel=large, but that's unsupported.
$as_echo "#define SUPPORT_STATIC_PIE 1" >>confdefs.h
fi
config_vars="$config_vars
default-abi = $libc_aarch64_abi$libc_aarch64_be"
# Only consider BTI supported if -mbranch-protection=bti is
# on by default in the compiler and the linker produces
# binaries with GNU property notes in PT_GNU_PROPERTY segment.
+24 -6
View File
@@ -1,9 +1,6 @@
GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
# Local configure fragment for sysdeps/aarch64.
# Static PIE is supported.
AC_DEFINE(SUPPORT_STATIC_PIE)
# We check to see if the compiler and flags are
# selecting the big endian ABI and if they are then
# we set libc_cv_aarch64_be to yes which causes
@@ -17,13 +14,34 @@ AC_CACHE_CHECK([for big endian],
yes
#endif
], libc_cv_aarch64_be=yes, libc_cv_aarch64_be=no)])
# Check for purecap ABI too, an alternative name is l64pc128.
AC_CACHE_CHECK([for purecap ABI],
[libc_cv_aarch64_purecap],
[AC_EGREP_CPP(yes,[#ifdef __CHERI_PURE_CAPABILITY__
yes
#endif
], libc_cv_aarch64_purecap=yes, libc_cv_aarch64_purecap=no)])
LIBC_CONFIG_VAR([aarch64-purecap], [$libc_cv_aarch64_purecap])
libc_aarch64_be=""
if test $libc_cv_aarch64_be = yes; then
AC_DEFINE(HAVE_AARCH64_BE)
LIBC_CONFIG_VAR([default-abi], [lp64_be])
else
LIBC_CONFIG_VAR([default-abi], [lp64])
libc_aarch64_be="_be"
fi
libc_aarch64_abi="lp64"
if test $libc_cv_aarch64_purecap = yes; then
libc_aarch64_abi="purecap"
# The purecap abi requires relocations because objects may not be
# within bounds for PCC. This means static-pie is not supported.
AC_DEFINE(HIDDEN_VAR_NEEDS_DYNAMIC_RELOC)
else
# Static PIE is supported. Hidden variables only need relocations
# in PIE with -mcmodel=large, but that's unsupported.
AC_DEFINE(SUPPORT_STATIC_PIE)
fi
LIBC_CONFIG_VAR([default-abi], [$libc_aarch64_abi$libc_aarch64_be])
# Only consider BTI supported if -mbranch-protection=bti is
# on by default in the compiler and the linker produces
# binaries with GNU property notes in PT_GNU_PROPERTY segment.
+2 -1
View File
@@ -36,7 +36,8 @@
static inline int __attribute__ ((unused))
elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
{
return ehdr->e_machine == EM_AARCH64;
return ehdr->e_machine == EM_AARCH64
&& (ehdr->e_flags & EF_AARCH64_CHERI_PURECAP) == 0;
}
/* Return the run-time load address of the shared object. */
+1 -1
View File
@@ -20,7 +20,7 @@
struct link_map_machine
{
ElfW(Addr) plt; /* Address of .plt */
elfptr_t plt; /* Address of .plt */
void *tlsdesc_table; /* Address of TLS descriptor hash table. */
bool bti_fail; /* Failed to enable Branch Target Identification. */
};
+108
View File
@@ -0,0 +1,108 @@
/* Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#include <jmpbuf-offsets.h>
#include <stap-probe.h>
/* __longjmp(jmpbuf, val) */
ENTRY (__longjmp)
cfi_def_cfa(c0, 0)
cfi_offset(c19, JB_X19<<4)
cfi_offset(c20, JB_X20<<4)
cfi_offset(c21, JB_X21<<4)
cfi_offset(c22, JB_X22<<4)
cfi_offset(c23, JB_X23<<4)
cfi_offset(c24, JB_X24<<4)
cfi_offset(c25, JB_X25<<4)
cfi_offset(c26, JB_X26<<4)
cfi_offset(c27, JB_X27<<4)
cfi_offset(c28, JB_X28<<4)
cfi_offset(c29, JB_X29<<4)
cfi_offset(c30, JB_LR<<4)
cfi_offset(q8, JB_D8<<4)
cfi_offset(q9, JB_D9<<4)
cfi_offset(q10, JB_D10<<4)
cfi_offset(q11, JB_D11<<4)
cfi_offset(q12, JB_D12<<4)
cfi_offset(q13, JB_D13<<4)
cfi_offset(q14, JB_D14<<4)
cfi_offset(q15, JB_D15<<4)
ldp c19, c20, [c0, #JB_X19<<4]
ldp c21, c22, [c0, #JB_X21<<4]
ldp c23, c24, [c0, #JB_X23<<4]
ldp c25, c26, [c0, #JB_X25<<4]
ldp c27, c28, [c0, #JB_X27<<4]
ldp c29, c30, [c0, #JB_X29<<4]
/* longjmp probe takes 3 arguments, address of jump buffer as
first argument (8@x0), return value as second argument (-4@x1),
and target address (8@x30), respectively. */
LIBC_PROBE (longjmp, 3, 8@c0, -4@c1, 8@c30)
ldp q8, q9, [c0, #JB_D8<<4]
ldp q10, q11, [c0, #JB_D10<<4]
ldp q12, q13, [c0, #JB_D12<<4]
ldp q14, q15, [c0, #JB_D14<<4]
/* Originally this was implemented with a series of
.cfi_restore() directives.
The theory was that cfi_restore should revert to previous
frame value is the same as the current value. In practice
this doesn't work, even after cfi_restore() gdb continues
to try to recover a previous frame value offset from x0,
which gets stuffed after a few more instructions. The
cfi_same_value() mechanism appears to work fine. */
cfi_same_value(c19)
cfi_same_value(c20)
cfi_same_value(c21)
cfi_same_value(c22)
cfi_same_value(c23)
cfi_same_value(c24)
cfi_same_value(c25)
cfi_same_value(c26)
cfi_same_value(c27)
cfi_same_value(c28)
cfi_same_value(c29)
cfi_same_value(c30)
cfi_same_value(q8)
cfi_same_value(q9)
cfi_same_value(q10)
cfi_same_value(q11)
cfi_same_value(q12)
cfi_same_value(q13)
cfi_same_value(q14)
cfi_same_value(q15)
ldr c5, [c0, #JB_SP<<4]
mov csp, c5
/* longjmp_target probe takes 3 arguments, address of jump buffer
as first argument (8@x0), return value as second argument (-4@x1),
and target address (8@x30), respectively. */
LIBC_PROBE (longjmp_target, 3, 8@c0, -4@c1, 8@c30)
cmp x1, #0
mov x0, #1
csel x0, x1, x0, ne
/* Use br instead of ret because ret is guaranteed to mispredict */
br c30
END (__longjmp)
+66
View File
@@ -0,0 +1,66 @@
/* Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _AARCH64_MORELLO_CHERI_PERMS_H
#define _AARCH64_MORELLO_CHERI_PERMS_H
/* Capability permission bits. These are defined in the Arm Architecture
Reference Manual Suplement- Morello for A-Profile Architecture:
https://developer.arm.com/documentation/ddi0606/latest */
#define CAP_PERM_LOAD (1 << 17)
#define CAP_PERM_STORE (1 << 16)
#define CAP_PERM_EXECUTE (1 << 15)
#define CAP_PERM_LOAD_CAP (1 << 14)
#define CAP_PERM_STORE_CAP (1 << 13)
#define CAP_PERM_STORE_LOCAL (1 << 12)
#define CAP_PERM_SEAL (1 << 11)
#define CAP_PERM_UNSEAL (1 << 10)
#define CAP_PERM_COMPARTMENT_ID (1 << 7)
#define CAP_PERM_MUTABLE_LOAD (1 << 6)
#define CAP_PERM_EXECUTIVE (1 << 1)
#define CAP_PERM_GLOBAL (1 << 0)
/* Used with __builtin_cheri_perms_and. */
#define CAP_PERM_MASK_BASE (-1UL ^ ( \
CAP_PERM_LOAD | \
CAP_PERM_STORE | \
CAP_PERM_EXECUTE | \
CAP_PERM_LOAD_CAP | \
CAP_PERM_STORE_CAP | \
CAP_PERM_SEAL | \
CAP_PERM_UNSEAL | \
CAP_PERM_COMPARTMENT_ID))
#define CAP_PERM_MASK_R (CAP_PERM_MASK_BASE | CAP_PERM_LOAD | CAP_PERM_LOAD_CAP)
#define CAP_PERM_MASK_RW (CAP_PERM_MASK_R | CAP_PERM_STORE | CAP_PERM_STORE_CAP)
#define CAP_PERM_MASK_RX (CAP_PERM_MASK_R | CAP_PERM_EXECUTE)
#define STACK_CAP_PERM_PCS ( \
CAP_PERM_LOAD | \
CAP_PERM_STORE | \
CAP_PERM_LOAD_CAP | \
CAP_PERM_STORE_CAP | \
CAP_PERM_MUTABLE_LOAD)
/* Check if stack is valid according to stack PCS rules. Only permissions
are checked, seal and invalid tag cause fault on access. */
#define STACK_CAP_CHECK(stack, size) \
({unsigned long __perm = __builtin_cheri_perms_get (stack); \
(__perm & (CAP_PERM_GLOBAL|CAP_PERM_STORE_LOCAL)) \
&& (__perm & STACK_CAP_PERM_PCS) == STACK_CAP_PERM_PCS;})
#endif
+93
View File
@@ -0,0 +1,93 @@
/* Special .init and .fini section support for Morello.
Copyright (C) 1995-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* crti.S puts a function prologue at the beginning of the .init and
.fini sections and defines global symbols for those addresses, so
they can be called as functions. The symbols _init and _fini are
magic and cause the linker to emit DT_INIT and DT_FINI. */
#include <sysdep.h>
#include <libc-symbols.h>
#ifndef PREINIT_FUNCTION
# define PREINIT_FUNCTION __gmon_start__
#endif
#ifndef PREINIT_FUNCTION_WEAK
# define PREINIT_FUNCTION_WEAK 1
#endif
#if PREINIT_FUNCTION_WEAK
weak_extern (PREINIT_FUNCTION)
#else
.hidden PREINIT_FUNCTION
#endif
#if PREINIT_FUNCTION_WEAK
.align 2
.type call_weak_fn, %function
call_weak_fn:
adrp c0, :got:PREINIT_FUNCTION
ldr c0, [c0, #:got_lo12:PREINIT_FUNCTION]
cbz x0, 1f
b PREINIT_FUNCTION
1:
RET
.size call_weak_fn, .-call_weak_fn
#endif
.section .init,"ax",%progbits
.align 2
.global _init
.hidden _init
.type _init, %function
_init:
stp c29, c30, [csp, -32]!
mov c29, csp
#if PREINIT_FUNCTION_WEAK
bl call_weak_fn
#else
bl PREINIT_FUNCTION
#endif
.section .fini,"ax",%progbits
.align 2
.global _fini
.hidden _fini
.type _fini, %function
_fini:
stp c29, c30, [csp, -32]!
mov c29, csp
+48
View File
@@ -0,0 +1,48 @@
/* Special .init and .fini section support for Morello.
Copyright (C) 1995-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* crtn.S puts function epilogues in the .init and .fini sections
corresponding to the prologues in crti.S. */
#include <sysdep.h>
.section .init,"ax",%progbits
ldp c29, c30, [csp], 32
RET
.section .fini,"ax",%progbits
ldp c29, c30, [csp], 32
RET
+100
View File
@@ -0,0 +1,100 @@
/* Machine-dependent ELF indirect relocation inline functions.
AArch64 version.
Copyright (C) 2012-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _DL_IREL_H
#define _DL_IREL_H
#include <stdio.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <sysdep.h>
#include <sys/ifunc.h>
#define ELF_MACHINE_IRELA 1
static inline uintptr_t
__attribute ((always_inline))
elf_ifunc_invoke (uintptr_t addr)
{
__ifunc_arg_t arg;
arg._size = sizeof (arg);
arg._hwcap = GLRO(dl_hwcap);
arg._hwcap2 = GLRO(dl_hwcap2);
return ((uintptr_t (*) (uint64_t, const __ifunc_arg_t *)) (addr))
(GLRO(dl_hwcap) | _IFUNC_ARG_HWCAP, &arg);
}
#include <cheri_perms.h>
static inline uintptr_t
__attribute__ ((always_inline))
morello_relative_value (uintptr_t l_addr,
const ElfW(Rela) *reloc,
void *reloc_addr)
{
uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
/* Fragment identified by r_offset has the following information:
| 64-bit: address | 56-bits: length | 8-bits: permissions | */
unsigned long loc = u64_reloc_addr[0];
unsigned long len = u64_reloc_addr[1] & ((1UL << 56) - 1);
unsigned long perm = u64_reloc_addr[1] >> 56;
unsigned long perm_mask = 0;
uintptr_t value = __builtin_cheri_bounds_set_exact (l_addr + loc, len);
value = value + reloc->r_addend;
/* Set permissions. Permissions field encoded as:
4 = executable, 2 = read/write, 1 = read-only.
Mask should follow the same encoding as the ELF segment permissions. */
if (perm == 1)
perm_mask = CAP_PERM_MASK_R;
if (perm == 2)
perm_mask = CAP_PERM_MASK_RW;
if (perm == 4)
perm_mask = CAP_PERM_MASK_RX;
value = __builtin_cheri_perms_and (value, perm_mask);
/* Seal capabilities, which provide execute permission, with MORELLO_RB. */
if (perm == 4)
value = __builtin_cheri_seal_entry (value);
return value;
}
static inline void
__attribute ((always_inline))
elf_irela (const ElfW(Rela) *reloc)
{
const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
if (__glibc_likely (r_type == MORELLO_R(IRELATIVE)))
{
struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
void *reloc_addr = (void *) main_map->l_addr + reloc->r_offset;
uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
uintptr_t value
= morello_relative_value (main_map->l_addr, reloc, reloc_addr);
*cap_reloc_addr = elf_ifunc_invoke (value);
}
else
__libc_fatal ("Unexpected reloc type in static binary.\n");
}
#endif
+438
View File
@@ -0,0 +1,438 @@
/* Copyright (C) 1995-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef dl_machine_h
#define dl_machine_h
#define ELF_MACHINE_NAME "aarch64"
#include <sysdep.h>
#include <tls.h>
#include <dl-tlsdesc.h>
#include <dl-static-tls.h>
#include <dl-irel.h>
#include <dl-machine-rel.h>
#include <cpu-features.c>
/* Translate a processor specific dynamic tag to the index in l_info array. */
#define DT_AARCH64(x) (DT_AARCH64_##x - DT_LOPROC + DT_NUM)
/* Return nonzero iff ELF header is compatible with the running host. */
static inline int __attribute__ ((unused))
elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
{
return ehdr->e_machine == EM_AARCH64
&& (ehdr->e_flags & EF_AARCH64_CHERI_PURECAP) != 0;
}
/* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int __attribute__ ((unused))
elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
int lazy, int profile)
{
if (l->l_info[DT_JMPREL] && lazy)
{
uintptr_t *got;
extern void _dl_runtime_resolve (ElfW(Word));
extern void _dl_runtime_profile (ElfW(Word));
got = (uintptr_t *) D_PTR (l, l_info[DT_PLTGOT]);
if (got[1])
{
l->l_mach.plt = (uint64_t) got[1] + l->l_addr;
}
got[1] = (uintptr_t) l;
/* The got[2] entry contains the address of a function which gets
called to get the address of a so far unresolved function and
jump to it. The profiling extension of the dynamic linker allows
to intercept the calls to collect information. In this case we
don't store the address in the GOT so that all future calls also
end in this function. */
if ( profile)
{
got[2] = (uintptr_t) &_dl_runtime_profile;
if (GLRO(dl_profile) != NULL
&& _dl_name_match_p (GLRO(dl_profile), l))
/* Say that we really want profiling and the timers are
started. */
GL(dl_profile_map) = l;
}
else
{
/* This function will get called to fix up the GOT entry
indicated by the offset on the stack, and then jump to
the resolved address. */
got[2] = (uintptr_t) &_dl_runtime_resolve;
}
}
return lazy;
}
/* Runtime _DYNAMIC without dynamic relocations. */
static void * __attribute__ ((unused))
elf_machine_runtime_dynamic (void)
{
void *p;
asm (""
".weak _DYNAMIC\n"
".hidden _DYNAMIC\n"
"adrp %0, _DYNAMIC\n"
"add %0, %0, :lo12:_DYNAMIC\n" : "=r"(p));
return p;
}
/* Load address of the dynamic linker with correct bounds. */
static uintptr_t __attribute__ ((unused))
elf_machine_load_address_from_args (void *arg)
{
uintptr_t *sp;
long argc;
uintptr_t phdr = 0;
size_t phentsize = sizeof (ElfW(Phdr));
size_t phnum = 0;
sp = arg;
argc = sp[0];
/* Skip argv. */
sp += argc + 2;
/* Skip environ. */
for (; *sp; sp++);
sp++;
for (; *sp != AT_NULL; sp += 2)
{
long t = sp[0];
if (t == AT_BASE && sp[1])
return sp[1];
else if (t == AT_PHDR)
phdr = sp[1];
else if (t == AT_PHNUM)
phnum = sp[1];
else if (t == AT_PHENT)
phentsize = sp[1];
}
for (size_t i = 0; i < phnum; i++)
{
ElfW(Phdr) *p = (ElfW(Phdr) *)(phdr + i * phentsize);
if (p->p_type == PT_PHDR)
return phdr - p->p_vaddr;
if (p->p_type == PT_DYNAMIC)
return (uintptr_t) elf_machine_runtime_dynamic () - p->p_vaddr;
}
/* Fail. */
return 0;
}
/* In elf/rtld.c _dl_start should be global so dl-start.S can reference it. */
#define RTLD_START asm (".globl _dl_start");
#define elf_machine_type_class(type) \
(((type) == MORELLO_R(JUMP_SLOT) \
|| (type) == MORELLO_R(TPREL128) \
|| (type) == MORELLO_R(TLSDESC)) * ELF_RTYPE_CLASS_PLT)
#define ELF_MACHINE_JMP_SLOT MORELLO_R(JUMP_SLOT)
/* Return the address of the entry point. */
#define ELF_MACHINE_START_ADDRESS(map, start) ((map)->l_addr + ((start) - (ElfW(Addr))(map)->l_addr))
#define DL_PLATFORM_INIT dl_platform_init ()
static inline void __attribute__ ((unused))
dl_platform_init (void)
{
if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
/* Avoid an empty string which would disturb us. */
GLRO(dl_platform) = NULL;
#ifdef SHARED
/* init_cpu_features has been called early from __libc_start_main in
static executable. */
init_cpu_features (&GLRO(dl_aarch64_cpu_features));
#endif
}
static inline uintptr_t
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
const ElfW(Rela) *reloc,
uintptr_t *reloc_addr,
uintptr_t value)
{
return *reloc_addr = value;
}
/* Return the final value of a plt relocation. */
static inline uintptr_t
elf_machine_plt_value (struct link_map *map,
const ElfW(Rela) *reloc,
uintptr_t value)
{
return value;
}
#endif
/* Names of the architecture-specific auditing callback functions. */
#define ARCH_LA_PLTENTER aarch64_gnu_pltenter
#define ARCH_LA_PLTEXIT aarch64_gnu_pltexit
#ifdef RESOLVE_MAP
# include <cheri_perms.h>
static inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
const struct r_found_version *version,
void *const reloc_addr, int skip_ifunc)
{
uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
if (r_type == MORELLO_R(RELATIVE))
*cap_reloc_addr = morello_relative_value (map->l_addr, reloc, reloc_addr);
else if (r_type == AARCH64_R(RELATIVE))
*u64_reloc_addr = map->l_addr + reloc->r_addend;
else if (__builtin_expect (r_type == R_AARCH64_NONE, 0))
return;
else
{
# ifndef RTLD_BOOTSTRAP
const ElfW(Sym) *const refsym = sym;
# endif
struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
r_type);
uintptr_t value = SYMBOL_ADDRESS (sym_map, sym, true);
if (sym != NULL
&& __glibc_unlikely (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC)
&& __glibc_likely (sym->st_shndx != SHN_UNDEF)
&& __glibc_likely (!skip_ifunc))
value = elf_ifunc_invoke (value);
switch (r_type)
{
case MORELLO_R(CAPINIT):
case MORELLO_R(GLOB_DAT):
case MORELLO_R(JUMP_SLOT):
{
if (sym == NULL)
{
/* Undefined weak symbol. */
*cap_reloc_addr = value + reloc->r_addend;
break;
}
unsigned long perm_mask;
switch (ELFW(ST_TYPE) (sym->st_info))
{
case STT_OBJECT:
value = __builtin_cheri_bounds_set_exact (value, sym->st_size);
perm_mask = CAP_PERM_MASK_RW;
break;
case STT_FUNC:
case STT_GNU_IFUNC:
/* Use l_addr for function pointer bounds. */
value = sym_map->l_addr + (value - sym_map->l_addr);
perm_mask = CAP_PERM_MASK_RX;
break;
default:
{
const char *strtab;
strtab = (const void *) D_PTR (sym_map, l_info[DT_STRTAB]);
_dl_error_printf ("%s: symbol `%s' from `%s' has unknown type, when relocating `%s'.\n",
RTLD_PROGNAME, strtab + sym->st_name, sym_map->l_name, map->l_name);
perm_mask = CAP_PERM_MASK_R;
}
}
value = value + reloc->r_addend;
value = __builtin_cheri_perms_and (value, perm_mask);
/* Seal capabilities, which provide execute permission, with MORELLO_RB. */
if (perm_mask == CAP_PERM_MASK_RX)
value = __builtin_cheri_seal_entry (value);
*cap_reloc_addr = value;
}
break;
# ifndef RTLD_BOOTSTRAP
case AARCH64_R(ABS64):
*u64_reloc_addr = value + reloc->r_addend;
break;
case MORELLO_R(IRELATIVE):
{
uintptr_t value
= morello_relative_value (map->l_addr, reloc, reloc_addr);
if (__glibc_likely (!skip_ifunc))
value = elf_ifunc_invoke (value);
*cap_reloc_addr = value;
}
break;
case MORELLO_R(TLSDESC):
{
struct tlsdesc volatile *td = reloc_addr;
if (! sym)
{
td->pair.off = reloc->r_addend;
td->entry = _dl_tlsdesc_undefweak;
}
else
{
# ifndef SHARED
CHECK_STATIC_TLS (map, sym_map);
# else
if (!TRY_STATIC_TLS (map, sym_map))
{
size_t size = td->pair.size;
if (size == 0)
size = sym->st_size;
struct tlsdesc_dynamic_arg *arg = _dl_make_tlsdesc_dynamic
(sym_map, sym->st_value + reloc->r_addend);
arg->tlsinfo.ti_size = size;
td->arg = arg;
td->entry = _dl_tlsdesc_dynamic;
}
else
# endif
{
td->pair.off = sym->st_value + sym_map->l_tls_offset
+ reloc->r_addend;
if (td->pair.size == 0)
td->pair.size = sym->st_size;
td->entry = _dl_tlsdesc_return;
}
}
}
break;
case MORELLO_R(TPREL128):
{
CHECK_STATIC_TLS (map, sym_map);
u64_reloc_addr[0] = sym->st_value + reloc->r_addend
+ sym_map->l_tls_offset;
if (u64_reloc_addr[1] == 0)
u64_reloc_addr[1] = sym->st_size;
}
break;
# endif /* !RTLD_BOOTSTRAP */
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
}
}
}
static inline void
__attribute__ ((always_inline))
elf_machine_rela_relative (uintptr_t l_addr,
const ElfW(Rela) *reloc,
void *const reloc_addr)
{
uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
if (r_type == MORELLO_R(RELATIVE))
*cap_reloc_addr = morello_relative_value (l_addr, reloc, reloc_addr);
else
*u64_reloc_addr = l_addr + reloc->r_addend;
}
static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
uintptr_t l_addr,
const ElfW(Rela) *reloc,
int skip_ifunc)
{
void *reloc_addr = (void *) (l_addr + reloc->r_offset);
uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
/* Check for unexpected PLT reloc type. */
if (__builtin_expect (r_type == MORELLO_R(JUMP_SLOT), 1))
{
if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL))
{
/* Check the symbol table for variant PCS symbols. */
const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
const ElfW (Sym) *symtab =
(const void *)D_PTR (map, l_info[DT_SYMTAB]);
const ElfW (Sym) *sym = &symtab[symndx];
if (__glibc_unlikely (sym->st_other & STO_AARCH64_VARIANT_PCS))
{
/* Avoid lazy resolution of variant PCS symbols. */
const struct r_found_version *version = NULL;
if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
const ElfW (Half) *vernum =
(const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
version = &map->l_versions[vernum[symndx] & 0x7fff];
}
elf_machine_rela (map, scope, reloc, sym, version, reloc_addr,
skip_ifunc);
return;
}
}
if (map->l_mach.plt == 0)
*cap_reloc_addr = (uint64_t) *cap_reloc_addr + l_addr;
else
*cap_reloc_addr = map->l_mach.plt;
}
else if (__builtin_expect (r_type == MORELLO_R(TLSDESC), 1))
{
const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
const ElfW (Sym) *sym = &symtab[symndx];
const struct r_found_version *version = NULL;
if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
const ElfW (Half) *vernum =
(const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
version = &map->l_versions[vernum[symndx] & 0x7fff];
}
/* Always initialize TLS descriptors completely, because lazy
initialization requires synchronization at every TLS access. */
elf_machine_rela (map, scope, reloc, sym, version, reloc_addr,
skip_ifunc);
}
else if (__glibc_unlikely (r_type == MORELLO_R(IRELATIVE)))
{
uintptr_t value
= morello_relative_value (map->l_addr, reloc, reloc_addr);
if (__glibc_likely (!skip_ifunc))
value = elf_ifunc_invoke (value);
*cap_reloc_addr = value;
}
else
_dl_reloc_bad_type (map, r_type, 1);
}
#endif
+25
View File
@@ -0,0 +1,25 @@
/* Check if dynamic section should be relocated. Morello version.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _DL_RELOCATE_LD_H
#define _DL_RELOCATE_LD_H
/* Don't relocate the dynamic section because capabilities don't fit. */
#define DL_RO_DYN_SECTION 1
#endif /* _DL_RELOCATE_LD_H */
+68
View File
@@ -0,0 +1,68 @@
/* ld.so _start code.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
ENTRY(_start)
/* Create an initial frame with 0 LR and FP */
cfi_undefined (c30)
mov c29, czr
mov c30, czr
mov c0, csp
bl _dl_start
/* Returns user entry point in x0. */
mov c21, c0
.globl _dl_start_user
.type _dl_start_user, %function
_dl_start_user:
/* Get argc. */
ldr x1, [csp]
/* Get argv. */
add c2, csp, 16
/* Compute envp. */
add c3, c2, x1, lsl 4
add c3, c3, 16
adrp c16, capinit_rtld_local
ldr c16, [c16, :lo12:capinit_rtld_local]
ldr c0, [c16]
bl _dl_init
/* Load the finalizer function. */
adrp c0, capinit_dl_fini
ldr c0, [c0, :lo12:capinit_dl_fini]
/* Jump to the user's entry point. */
mov c16, c21
br c16
END(_start)
.section .data.rel.ro.local,"aw"
.align 4
.type capinit_rtld_local, %object
.size capinit_rtld_local, 16
capinit_rtld_local:
.capinit _rtld_local
.xword 0
.xword 0
.type capinit_dl_fini, %object
.size capinit_dl_fini, 16
capinit_dl_fini:
.capinit _dl_fini
.xword 0
.xword 0
+229
View File
@@ -0,0 +1,229 @@
/* Thread-local storage handling in the ELF dynamic linker.
AArch64 Morello version.
Copyright (C) 2011-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#include <tls.h>
#include "tlsdesc.h"
#define NSAVEDQREGPAIRS 16
#define SAVE_Q_REGISTERS \
stp q0, q1, [csp, #-32*NSAVEDQREGPAIRS]!; \
cfi_adjust_cfa_offset (32*NSAVEDQREGPAIRS); \
stp q2, q3, [csp, #32*1]; \
stp q4, q5, [csp, #32*2]; \
stp q6, q7, [csp, #32*3]; \
stp q8, q9, [csp, #32*4]; \
stp q10, q11, [csp, #32*5]; \
stp q12, q13, [csp, #32*6]; \
stp q14, q15, [csp, #32*7]; \
stp q16, q17, [csp, #32*8]; \
stp q18, q19, [csp, #32*9]; \
stp q20, q21, [csp, #32*10]; \
stp q22, q23, [csp, #32*11]; \
stp q24, q25, [csp, #32*12]; \
stp q26, q27, [csp, #32*13]; \
stp q28, q29, [csp, #32*14]; \
stp q30, q31, [csp, #32*15];
#define RESTORE_Q_REGISTERS \
ldp q2, q3, [csp, #32*1]; \
ldp q4, q5, [csp, #32*2]; \
ldp q6, q7, [csp, #32*3]; \
ldp q8, q9, [csp, #32*4]; \
ldp q10, q11, [csp, #32*5]; \
ldp q12, q13, [csp, #32*6]; \
ldp q14, q15, [csp, #32*7]; \
ldp q16, q17, [csp, #32*8]; \
ldp q18, q19, [csp, #32*9]; \
ldp q20, q21, [csp, #32*10]; \
ldp q22, q23, [csp, #32*11]; \
ldp q24, q25, [csp, #32*12]; \
ldp q26, q27, [csp, #32*13]; \
ldp q28, q29, [csp, #32*14]; \
ldp q30, q31, [csp, #32*15]; \
ldp q0, q1, [csp], #32*NSAVEDQREGPAIRS; \
cfi_adjust_cfa_offset (-32*NSAVEDQREGPAIRS);
.text
/* Compute the address for symbols in the static TLS block.
Prototype:
_dl_tlsdesc_return (tlsdesc *tdp, void *unused, void *tp);
*/
.hidden _dl_tlsdesc_return
.global _dl_tlsdesc_return
.type _dl_tlsdesc_return,%function
cfi_startproc
.align 2
_dl_tlsdesc_return:
ldp x0, x1, [c0, #PTR_SIZE] /* Load offset, size. */
add c0, c2, x0
scbndse c0, c0, x1
RET
cfi_endproc
.size _dl_tlsdesc_return, .-_dl_tlsdesc_return
/* Handler for undefined weak TLS symbols: returns NULL.
Prototype:
_dl_tlsdesc_undefweak (tlsdesc *tdp, void *unused, void *tp);
*/
.hidden _dl_tlsdesc_undefweak
.global _dl_tlsdesc_undefweak
.type _dl_tlsdesc_undefweak,%function
cfi_startproc
.align 2
_dl_tlsdesc_undefweak:
mov x0, 0
RET
cfi_endproc
.size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
#ifdef SHARED
/* Handler for dynamic TLS symbols.
Prototype:
_dl_tlsdesc_dynamic (tlsdesc *tdp, void *unused, void *tp);
The second word of the descriptor points to a
tlsdesc_dynamic_arg structure.
Returns the address of the tls object.
void *
_dl_tlsdesc_dynamic (struct tlsdesc *tdp, void *unused, void *tp)
{
struct tlsdesc_dynamic_arg *td = tdp->arg;
dtv_t *dtv = *(dtv_t **)((char *)tp + TCBHEAD_DTV);
if (__builtin_expect (td->gen_count <= dtv[0].counter
&& (dtv[td->tlsinfo.ti_module].pointer.val
!= TLS_DTV_UNALLOCATED),
1))
return dtv[td->tlsinfo.ti_module].pointer.val
+ td->tlsinfo.ti_offset;
return ___tls_get_addr (&td->tlsinfo);
}
*/
.hidden _dl_tlsdesc_dynamic
.global _dl_tlsdesc_dynamic
.type _dl_tlsdesc_dynamic,%function
cfi_startproc
.align 2
_dl_tlsdesc_dynamic:
/* Save just enough registers to support fast path, if we fall
into slow path we will save additional registers. */
stp c3, c4, [csp, #-32]!
cfi_adjust_cfa_offset (32)
cfi_rel_offset (c3, 0)
cfi_rel_offset (c4, 16)
ldr c1, [c0,#TLSDESC_ARG]
ldr c0, [c2,#TCBHEAD_DTV]
ldr x3, [c1,#TLSDESC_GEN_COUNT]
ldr x4, [c0,#DTV_COUNTER]
cmp x3, x4
b.hi 2f
/* Load r3 = td->tlsinfo.ti_module and r4 = td->tlsinfo.ti_offset. */
ldp x3, x4, [c1,#TLSDESC_MODID]
lsl x3, x3, #(PTR_LOG_SIZE+1)
ldr c0, [c0, x3] /* Load val member of DTV entry. */
cmp x0, #TLS_DTV_UNALLOCATED
b.eq 2f
cfi_remember_state
/* Load r3 = td->tlsinfo.ti_size. */
ldr x3, [c1, #TLSDESC_SIZE]
add c0, c0, x4
scbndse c0, c0, x3
1:
ldp c3, c4, [csp], #32
cfi_adjust_cfa_offset (-32)
RET
2:
/* This is the slow path. We need to call __tls_get_addr() which
means we need to save and restore all the register that the
callee will trash. */
/* Save the remaining registers that we must treat as caller save. */
cfi_restore_state
# define NSAVEXREGPAIRS 9
stp c29, c30, [csp,#-32*NSAVEXREGPAIRS]!
cfi_adjust_cfa_offset (32*NSAVEXREGPAIRS)
cfi_rel_offset (c29, 0)
cfi_rel_offset (c30, 16)
mov c29, csp
stp c5, c6, [csp, #32*1]
stp c7, c8, [csp, #32*2]
stp c9, c10, [csp, #32*3]
stp c11, c12, [csp, #32*4]
stp c13, c14, [csp, #32*5]
stp c15, c16, [csp, #32*6]
stp c17, c18, [csp, #32*7]
cfi_rel_offset (c5, 32*1)
cfi_rel_offset (c6, 32*1+8)
cfi_rel_offset (c7, 32*2)
cfi_rel_offset (c8, 32*2+8)
cfi_rel_offset (c9, 32*3)
cfi_rel_offset (c10, 32*3+8)
cfi_rel_offset (c11, 32*4)
cfi_rel_offset (c12, 32*4+8)
cfi_rel_offset (c13, 32*5)
cfi_rel_offset (c14, 32*5+8)
cfi_rel_offset (c15, 32*6)
cfi_rel_offset (c16, 32*6+8)
cfi_rel_offset (c17, 32*7)
cfi_rel_offset (c18, 32*7+8)
SAVE_Q_REGISTERS
/* TODO: remove once __tls_get_addr is fixed. */
str c1, [csp, #32*8]
mov c0, c1
bl __tls_get_addr
/* TODO: __tls_get_addr should return bounded pointer,
currently it does not so bound it here. */
ldr c1, [csp, #32*8]
ldr x3, [c1, #TLSDESC_SIZE]
scbndse c0, c0, x3
mrs c2, ctpidr_el0 /* Restore c2. */
RESTORE_Q_REGISTERS
ldp c5, c6, [csp, #32*1]
ldp c7, c8, [csp, #32*2]
ldp c9, c10, [csp, #32*3]
ldp c11, c12, [csp, #32*4]
ldp c13, c14, [csp, #32*5]
ldp c15, c16, [csp, #32*6]
ldp c17, c18, [csp, #32*7]
ldp c29, c30, [csp], #32*NSAVEXREGPAIRS
cfi_adjust_cfa_offset (-32*NSAVEXREGPAIRS)
cfi_restore (c29)
cfi_restore (c30)
b 1b
cfi_endproc
.size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
# undef NSAVEXREGPAIRS
#endif
+62
View File
@@ -0,0 +1,62 @@
/* Thread-local storage descriptor handling in the ELF dynamic linker.
Morello version.
Copyright (C) 2011-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _AARCH64_MORELLO_DL_TLSDESC_H
#define _AARCH64_MORELLO_DL_TLSDESC_H 1
/* Type used to represent a TLS descriptor in the GOT. */
struct tlsdesc
{
void *(*entry) (struct tlsdesc *, void *, void *);
union {
void *arg;
struct { unsigned long off, size; } pair;
};
};
typedef struct dl_tls_index
{
unsigned long int ti_module;
unsigned long int ti_offset;
unsigned long int ti_size;
} tls_index;
/* Type used as the argument in a TLS descriptor for a symbol that
needs dynamic TLS offsets. */
struct tlsdesc_dynamic_arg
{
tls_index tlsinfo;
size_t gen_count;
};
extern attribute_hidden void *
_dl_tlsdesc_return (struct tlsdesc *, void *, void *);
extern attribute_hidden void *
_dl_tlsdesc_undefweak (struct tlsdesc *, void *, void *);
# ifdef SHARED
extern void *_dl_make_tlsdesc_dynamic (struct link_map *, size_t);
extern attribute_hidden void *
_dl_tlsdesc_dynamic (struct tlsdesc *, void *, void *);
#endif
#endif
+307
View File
@@ -0,0 +1,307 @@
/* Copyright (C) 2005-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#include <libc-symbols.h>
#include "dl-link.h"
#define ip0 c16
#define ip0l c16
#define ip1 c17
#define lr c30
#define RELA_SIZE 24
.text
.globl _dl_runtime_resolve
.type _dl_runtime_resolve, #function
cfi_startproc
.align 2
_dl_runtime_resolve:
/* Morello we get called with:
ip0 &PLTGOT[2]
ip1 temp(dl resolver entry point)
[sp, #16] lr
[sp, #0] &PLTGOT[n]
*/
cfi_rel_offset (lr, 16)
/* Save arguments. */
stp c8, c9, [csp, #-(160+8*16)]!
cfi_adjust_cfa_offset (160+8*16)
cfi_rel_offset (c8, 0)
cfi_rel_offset (c9, 16)
stp c6, c7, [csp, #32]
cfi_rel_offset (c6, 32)
cfi_rel_offset (c7, 48)
stp c4, c5, [csp, #64]
cfi_rel_offset (c4, 64)
cfi_rel_offset (c5, 80)
stp c2, c3, [csp, #96]
cfi_rel_offset (c2, 96)
cfi_rel_offset (c3, 112)
stp c0, c1, [csp, #128]
cfi_rel_offset (c0, 128)
cfi_rel_offset (c1, 144)
stp q0, q1, [csp, #(160+0*16)]
cfi_rel_offset (q0, 160+0*16)
cfi_rel_offset (q1, 160+1*16)
stp q2, q3, [csp, #(160+2*16)]
cfi_rel_offset (q0, 160+2*16)
cfi_rel_offset (q1, 160+3*16)
stp q4, q5, [csp, #(160+4*16)]
cfi_rel_offset (q0, 160+4*16)
cfi_rel_offset (q1, 160+5*16)
stp q6, q7, [csp, #(160+6*16)]
cfi_rel_offset (q0, 160+6*16)
cfi_rel_offset (q1, 160+7*16)
/* Get pointer to linker struct. */
ldr c0, [ip0, #-PTR_SIZE]
/* Prepare to call _dl_fixup(). */
ldr c1, [csp, 160+8*16] /* Recover &PLTGOT[n] */
sub x1, x1, x16
add x1, x1, x1, lsl #1
lsr x1, x1, #1
sub x1, x1, #RELA_SIZE
/* Call fixup routine. */
bl _dl_fixup
/* Save the return. */
mov ip0, c0
/* Get arguments and return address back. */
ldp q0, q1, [csp, #(160+0*16)]
ldp q2, q3, [csp, #(160+2*16)]
ldp q4, q5, [csp, #(160+4*16)]
ldp q6, q7, [csp, #(160+6*16)]
ldp c0, c1, [csp, #128]
ldp c2, c3, [csp, #96]
ldp c4, c5, [csp, #64]
ldp c6, c7, [csp, #32]
ldp c8, c9, [csp], #(160+8*16)
cfi_adjust_cfa_offset (-(160+8*16))
ldp ip1, lr, [csp], #32
cfi_adjust_cfa_offset (-32)
/* Jump to the newly found address. */
br ip0
cfi_endproc
.size _dl_runtime_resolve, .-_dl_runtime_resolve
#ifndef PROF
.globl _dl_runtime_profile
.type _dl_runtime_profile, #function
cfi_startproc
.align 2
_dl_runtime_profile:
/* Morello we get called with:
ip0 &PLTGOT[2]
ip1 temp(dl resolver entry point)
[csp, #16] lr
[csp, #0] &PLTGOT[n]
Stack frame layout:
[csp, #...] lr
[csp, #...] &PLTGOT[n]
[csp, #192] La_aarch64_regs
[csp, #96] La_aarch64_retval
[csp, #80] frame size return from pltenter
[csp, #64] dl_profile_call saved c1
[csp, #48] dl_profile_call saved c0
[csp, #32] t1
[csp, #0] c29, lr <- c29
*/
# define OFFSET_T1 32
# define OFFSET_SAVED_CALL_X0 OFFSET_T1 + 16
# define OFFSET_FS OFFSET_SAVED_CALL_X0 + 32
# define OFFSET_RV OFFSET_FS + 16
# define OFFSET_RG OFFSET_RV + DL_SIZEOF_RV
# define SF_SIZE OFFSET_RG + DL_SIZEOF_RG
# define OFFSET_PLTGOTN SF_SIZE
# define OFFSET_LR OFFSET_PLTGOTN + 16
/* Save arguments. */
mov c11, csp
sub x11, x11, #SF_SIZE
scvalue csp, csp, x11
cfi_adjust_cfa_offset (SF_SIZE)
stp c29, c30, [csp, #0]
mov c29, csp
cfi_def_cfa_register (c29)
cfi_rel_offset (c29, 0)
cfi_rel_offset (lr, 8)
stp c0, c1, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*0]
cfi_rel_offset (c0, OFFSET_RG + DL_OFFSET_RG_X0 + 32*0 + 0)
cfi_rel_offset (c1, OFFSET_RG + DL_OFFSET_RG_X0 + 32*0 + 16)
stp c2, c3, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*1]
cfi_rel_offset (c2, OFFSET_RG + DL_OFFSET_RG_X0 + 32*1 + 0)
cfi_rel_offset (c3, OFFSET_RG + DL_OFFSET_RG_X0 + 32*1 + 16)
stp c4, c5, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*2]
cfi_rel_offset (c4, OFFSET_RG + DL_OFFSET_RG_X0 + 32*2 + 0)
cfi_rel_offset (c5, OFFSET_RG + DL_OFFSET_RG_X0 + 32*2 + 16)
stp c6, c7, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*3]
cfi_rel_offset (c6, OFFSET_RG + DL_OFFSET_RG_X0 + 32*3 + 0)
cfi_rel_offset (c7, OFFSET_RG + DL_OFFSET_RG_X0 + 32*3 + 16)
stp q0, q1, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0]
cfi_rel_offset (q0, OFFSET_RG + DL_OFFSET_RG_V0 + 32*0)
cfi_rel_offset (q1, OFFSET_RG + DL_OFFSET_RG_V0 + 32*0 + 16)
stp q2, q3, [c29, #OFFSET_RG+ DL_OFFSET_RG_V0 + 32*1]
cfi_rel_offset (q2, OFFSET_RG + DL_OFFSET_RG_V0 + 32*1 + 0)
cfi_rel_offset (q3, OFFSET_RG + DL_OFFSET_RG_V0 + 32*1 + 16)
stp q4, q5, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2]
cfi_rel_offset (q4, OFFSET_RG + DL_OFFSET_RG_V0 + 32*2 + 0)
cfi_rel_offset (q5, OFFSET_RG + DL_OFFSET_RG_V0 + 32*2 + 16)
stp q6, q7, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3]
cfi_rel_offset (q6, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 0)
cfi_rel_offset (q7, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 16)
add c0, c29, #SF_SIZE + 32
ldr c1, [c29, #OFFSET_LR]
stp c0, c1, [c29, #OFFSET_RG + DL_OFFSET_RG_SP]
/* Get pointer to linker struct. */
ldr c0, [ip0, #-PTR_SIZE]
/* Prepare to call _dl_profile_fixup(). */
ldr c1, [c29, OFFSET_PLTGOTN] /* Recover &PLTGOT[n] */
mov c11, c1
sub x1, x1, x16
add x1, x1, x1, lsl #1
lsl x1, x1, #3
sub x1, x1, #(RELA_SIZE<<3)
lsr x1, x1, #3
scvalue c1, c11, x1
stp c0, c1, [c29, #OFFSET_SAVED_CALL_X0]
/* Set up extra args for _dl_profile_fixup */
ldr c2, [c29, #OFFSET_LR] /* load saved LR */
add c3, c29, #OFFSET_RG /* address of La_aarch64_reg */
add c4, c29, #OFFSET_FS /* address of framesize */
bl _dl_profile_fixup
ldr ip0l, [c29, #OFFSET_FS] /* framesize == 0 */
cmp x16, #0
bge 1f
cfi_remember_state
/* Save the return. */
mov ip0, c0
/* Get arguments and return address back. */
ldp c0, c1, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*0]
ldp c2, c3, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*1]
ldp c4, c5, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*2]
ldp c6, c7, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*3]
ldp q0, q1, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0]
ldp q2, q3, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*1]
ldp q4, q5, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2]
ldp q6, q7, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3]
cfi_def_cfa_register (csp)
ldp c29, c30, [c29, #0]
cfi_restore(c29)
cfi_restore(c30)
add csp, csp, SF_SIZE + 16
cfi_adjust_cfa_offset (- SF_SIZE - 32)
/* Jump to the newly found address. */
br ip0
cfi_restore_state
1:
/* The new frame size is in ip0. */
mov c11, c1
sub x1, x29, x16
and x12, x1, #0xfffffffffffffff0
scvalue csp, csp, x12
scvalue c1, c11, x1
str c0, [c29, #OFFSET_T1]
mov c0, csp
add c1, c29, #SF_SIZE + 16
mov c2, ip0
bl memcpy
ldr ip0, [c29, #OFFSET_T1]
/* Call the function. */
ldp c0, c1, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*0]
ldp c2, c3, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*1]
ldp c4, c5, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*2]
ldp c6, c7, [c29, #OFFSET_RG + DL_OFFSET_RG_X0 + 32*3]
ldp q0, q1, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0]
ldp q2, q3, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*1]
ldp q4, q5, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2]
ldp q6, q7, [c29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3]
blr ip0
stp c0, c1, [c29, #OFFSET_RV + DL_OFFSET_RV_X0]
stp q0, q1, [c29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0]
stp q2, q3, [c29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1]
/* Setup call to pltexit */
ldp c0, c1, [c29, #OFFSET_SAVED_CALL_X0]
add c2, c29, #OFFSET_RG
add c3, c29, #OFFSET_RV
bl _dl_audit_pltexit
ldp c0, c1, [c29, #OFFSET_RV + DL_OFFSET_RV_X0]
ldp d0, d1, [c29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0]
ldp d2, d3, [c29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1]
/* LR from within La_aarch64_reg */
ldr lr, [c29, #OFFSET_RG + DL_OFFSET_RG_LR]
cfi_restore(lr)
mov csp, c29
cfi_def_cfa_register (csp)
ldr c29, [c29, #0]
cfi_restore(c29)
add csp, csp, SF_SIZE + 32
cfi_adjust_cfa_offset (- SF_SIZE - 32)
br lr
cfi_endproc
.size _dl_runtime_profile, .-_dl_runtime_profile
#endif
.previous
+33
View File
@@ -0,0 +1,33 @@
/* Simple memchr.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
void *__memchr (const void *s, int c, size_t n)
{
unsigned char uc = c;
const unsigned char *us = s;
for (; n > 0; n--, us++)
if (*us == uc)
return (void *) us;
return NULL;
}
weak_alias (__memchr, memchr)
libc_hidden_builtin_def (memchr)
+38
View File
@@ -0,0 +1,38 @@
/* Simple memcmp.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
int memcmp (const void *s1, const void *s2, size_t n)
{
const unsigned char *us1 = s1;
const unsigned char *us2 = s2;
for (; n > 0; us1++, us2++, n--)
if (*us1 != *us2)
return *us1 - *us2;
return 0;
}
#undef bcmp
weak_alias (memcmp, bcmp)
libc_hidden_builtin_def (memcmp)
#undef __memcmpeq
strong_alias (memcmp, __memcmpeq)
libc_hidden_def(__memcmpeq)
+486
View File
@@ -0,0 +1,486 @@
/* Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
/* Assumptions:
*
* ARMv8-a, AArch64, Morello, Advanced SIMD, unaligned accesses.
*
*/
#ifndef MEMMOVE
# define MEMMOVE memmove
#endif
#ifndef MEMCPY
# define MEMCPY memcpy
#endif
#define xdstin x0
#define xsrc x1
#define count x2
#define xsrcend x4
#define A_l x6
#define A_lw w6
#define A_h x7
#define B_l x8
#define B_lw w8
#define B_h x9
#define C_lw w10
#define auoff x14
#define cap_count x15
#define tmp1 x16
#define tmp2 x17
#if defined(__CHERI_PURE_CAPABILITY__)
#define dstin c0
#define src c1
#define dst c3
#define srcend c4
#define dstend c5
#define tmp1_ptr c16
#else
#define dstin x0
#define src x1
#define dst x3
#define srcend x4
#define dstend x5
#define tmp1_ptr x16
#endif
#define A_q q0
#define B_q q1
#define C_q q2
#define D_q q3
#define E_q q4
#define F_q q5
#define G_q q6
#define H_q q7
#define A_cap c6
#define B_cap c7
#define C_cap c8
#define D_cap c9
#define E_cap c10
#define F_cap c11
#define G_cap c12
#define H_cap c13
/* This algorithm has not been benchmarked. It's derived
from the base aarch64 one with small changes to account
for copying tags.
1. We're copying less than 16 bytes, so no capabilities.
Use the traditional code path for these.
2. src mod 16 != dst mode 16. We're not copying capabilities,
so again use the traditional memcpy.
3. We're copying more than 8 capabilities plus the head and tail.
a. No overlap, use forward copy
b. Overlap, use backward copy
4. We're copying 0..8 capabilities
a. No capabilities to copy. This means we are copying 16..30 bytes.
Use the existing code path to do this from the original algorithm.
b. Copying 1..2 capabilities plus the head and tail
Use a branchless sequence.
c. Copying 3..4 capabilities plus the head and tail
Use a branchless sequence.
d. Copying 5..8 capabilities plus the head and tail
Use a branchless sequence.
*/
ENTRY (MEMCPY)
PTR_ARG (0)
PTR_ARG (1)
SIZE_ARG (2)
add srcend, src, count
add dstend, dstin, count
/* Copies of less than 16 bytes don't use capabilities. */
cmp count, 16
b.lo L(copy16)
/* If src mod 16 != dst mod 16 we're not transfering tags. */
and tmp1, xsrc, 15
and tmp2, xdstin, 15
cmp tmp1, tmp2
b.ne L(memcpy_nocap)
/* Get the number of capabilities that we need to store. */
neg tmp2, tmp1
add tmp2, tmp2, 16
and auoff, tmp2, 15
sub cap_count, count, auoff
lsr cap_count, cap_count, 4
cmp cap_count, 8
b.hi L(copy_long_cap)
cmp cap_count, 2
b.hi L(copy32_128_cap)
/* Copy 0..2 capabilities using a branchless sequence. */
cbz cap_count, L(copy32)
ldr A_q, [src]
ldr B_q, [srcend, -16]
add src, src, auoff /* align up src to 16 bytes */
#if defined(__CHERI_PURE_CAPABILITY__)
alignd srcend, srcend, 4
#else
bic srcend, srcend, 15
#endif
ldr A_cap, [src]
ldr B_cap, [srcend, -16]
str A_q, [dstin]
str B_q, [dstend, -16]
add tmp1_ptr, dstin, auoff /* align up dstin to 16 bytes */
#if defined (__CHERI_PURE_CAPABILITY__)
alignd dstend, dstend, 4
#else
bic dstend, dstend, 15
#endif
str A_cap, [tmp1_ptr]
str B_cap, [dstend, -16]
ret
.p2align 4
L(copy32_128_cap):
cmp cap_count, 4
b.hi L(copy128_cap)
/* Copy 3..4 capabilties using a branchless sequence. */
ldr A_q, [src]
ldr B_q, [srcend, -16]
add src, src, auoff /* align up src to 16 bytes */
#if defined (__CHERI_PURE_CAPABILITY__)
alignd srcend, srcend, 4
#else
bic srcend, srcend, 15
#endif
ldp A_cap, B_cap, [src]
ldp C_cap, D_cap, [srcend, -32]
str A_q, [dstin]
str B_q, [dstend, -16]
add tmp1_ptr, dstin, auoff /* align up dstin to 16 bytes */
#if defined (__CHERI_PURE_CAPABILITY__)
alignd dstend, dstend, 4
#else
bic dstend, dstend, 15
#endif
stp A_cap, B_cap, [tmp1_ptr]
stp C_cap, D_cap, [dstend, -32]
ret
.p2align 4
L(copy128_cap):
/* Copy 5..8 capabilities using a branchless sequence. */
ldr A_q, [src]
ldr B_q, [srcend, -16]
add src, src, auoff /* align up src to 16 bytes */
#if defined (__CHERI_PURE_CAPABILITY__)
alignd srcend, srcend, 4
#else
bic srcend, srcend, 15
#endif
ldp A_cap, B_cap, [src]
ldp C_cap, D_cap, [src, 32]
ldp E_cap, F_cap, [srcend, -32]
ldp G_cap, H_cap, [srcend, -64]
str A_q, [dstin]
str B_q, [dstend, -16]
add tmp1_ptr, dstin, auoff /* align up src to 16 bytes */
#if defined (__CHERI_PURE_CAPABILITY__)
alignd dstend, dstend, 4
#else
bic dstend, dstend, 15
#endif
stp A_cap, B_cap, [tmp1_ptr]
stp C_cap, D_cap, [tmp1_ptr, 32]
stp E_cap, F_cap, [dstend, -32]
stp G_cap, H_cap, [dstend, -64]
ret
L(copy_long_cap):
/* Use backwards copy if there is an overlap. */
sub tmp1, xdstin, xsrc
cmp tmp1, count
b.lo L(copy_long_backwards_cap)
/* Copy 16 bytes and then align src to 16-byte alignment. */
ldr D_q, [src]
ldr E_cap, [src, auoff]
and tmp1, xsrc, 15
#if defined(__CHERI_PURE_CAPABILITY__)
alignd src, src, 4
neg tmp2, tmp1
add dst, dstin, tmp2
#else
bic src, src, 15
sub dst, dstin, tmp1
#endif
add count, count, tmp1 /* Count is now 16 too large. */
ldp A_cap, B_cap, [src, 16]
str D_q, [dstin]
str E_cap, [dstin, auoff]
ldp C_cap, D_cap, [src, 48]
subs count, count, 128 + 16 /* Test and readjust count. */
b.ls L(copy64_from_end_cap)
L(loop64_cap):
stp A_cap, B_cap, [dst, 16]
ldp A_cap, B_cap, [src, 80]
stp C_cap, D_cap, [dst, 48]
ldp C_cap, D_cap, [src, 112]
add src, src, 64
add dst, dst, 64
subs count, count, 64
b.hi L(loop64_cap)
/* Write the last iteration and copy the last 16-byte aligned 64 byte block
from the end and the tail. */
L(copy64_from_end_cap):
ldr A_q, [srcend, -16]
#if defined(__CHERI_PURE_CAPABILITY__)
alignd srcend, srcend, 4
alignd tmp1_ptr, dstend, 4
#else
bic srcend, srcend, 15
bic tmp1_ptr, dstend, 15
#endif
ldp E_cap, F_cap, [srcend, -64]
stp A_cap, B_cap, [dst, 16]
ldp A_cap, B_cap, [srcend, -32]
stp C_cap, D_cap, [dst, 48]
stp E_cap, F_cap, [tmp1_ptr, -64]
str A_q, [dstend, -16]
stp A_cap, B_cap, [tmp1_ptr, -32]
ret
L(copy_long_backwards_cap):
cbz tmp1, L(copy0)
ldr D_q, [srcend, -16]
and tmp1, xsrcend, 15
#if defined(__CHERI_PURE_CAPABILITY__)
alignd srcend, srcend, 4
neg tmp2, tmp1
add count, count, tmp2
#else
bic srcend, srcend, 15
sub count, count, tmp1
#endif
ldp A_cap, B_cap, [srcend, -32]
str D_q, [dstend, -16]
ldp C_cap, D_cap, [srcend, -64]
#if defined(__CHERI_PURE_CAPABILITY__)
add dstend, dstend, tmp2 /* tmp1 was negated above to tmp2. */
#else
sub dstend, dstend, tmp1
#endif
subs count, count, 128
b.ls L(copy64_from_start)
L(loop64_backwards_cap):
str B_cap, [dstend, -16]
str A_cap, [dstend, -32]
ldp A_cap, B_cap, [srcend, -96]
str D_cap, [dstend, -48]
str C_cap, [dstend, -64]!
ldp C_cap, D_cap, [srcend, -128]
sub srcend, srcend, 64
subs count, count, 64
b.hi L(loop64_backwards_cap)
/* Write the last iteration and copy 64 bytes from the start. */
L(copy64_from_start_cap):
ldr A_q, [src]
add src, src, auoff /* align up src to 16 bytes */
add tmp1_ptr, dstin, auoff /* align up dstin to 16 bytes */
ldp E_cap, F_cap, [src, 32]
stp A_cap, B_cap, [dstend, -32]
ldp A_cap, B_cap, [src]
stp C_cap, D_cap, [dstend, -64]
stp E_cap, F_cap, [tmp1_ptr, 32]
str A_q, [dstin]
stp A_cap, B_cap, [tmp1_ptr]
ret
L(memcpy_nocap):
cmp count, 128
b.hi L(copy_long)
cmp count, 32
b.hi L(copy32_128)
L(copy32):
/* Small copies: 16..32 bytes. */
/* Note the 0..15 case is already handled at the start of memcpy */
ldr A_q, [src]
ldr B_q, [srcend, -16]
str A_q, [dstin]
str B_q, [dstend, -16]
ret
/* Copy 8-15 bytes. */
L(copy16):
tbz count, 3, L(copy8)
ldr A_l, [src]
ldr A_h, [srcend, -8]
str A_l, [dstin]
str A_h, [dstend, -8]
ret
.p2align 3
/* Copy 4-7 bytes. */
L(copy8):
tbz count, 2, L(copy4)
ldr A_lw, [src]
ldr B_lw, [srcend, -4]
str A_lw, [dstin]
str B_lw, [dstend, -4]
ret
/* Copy 0..3 bytes using a branchless sequence. */
L(copy4):
cbz count, L(copy0)
lsr tmp1, count, 1
ldrb A_lw, [src]
ldrb C_lw, [srcend, -1]
ldrb B_lw, [src, tmp1]
strb A_lw, [dstin]
strb B_lw, [dstin, tmp1]
strb C_lw, [dstend, -1]
L(copy0):
ret
.p2align 4
/* Medium copies: 33..128 bytes. */
L(copy32_128):
ldp A_q, B_q, [src]
ldp C_q, D_q, [srcend, -32]
cmp count, 64
b.hi L(copy128)
stp A_q, B_q, [dstin]
stp C_q, D_q, [dstend, -32]
ret
.p2align 4
/* Copy 65..128 bytes. */
L(copy128):
ldp E_q, F_q, [src, 32]
cmp count, 96
b.ls L(copy96)
ldp G_q, H_q, [srcend, -64]
stp G_q, H_q, [dstend, -64]
L(copy96):
stp A_q, B_q, [dstin]
stp E_q, F_q, [dstin, 32]
stp C_q, D_q, [dstend, -32]
ret
/* Copy more than 128 bytes. */
L(copy_long):
/* Use backwards copy if there is an overlap. */
sub tmp1, xdstin, xsrc
cmp tmp1, count
b.lo L(copy_long_backwards)
/* Copy 16 bytes and then align src to 16-byte alignment. */
ldr D_q, [src]
and tmp1, xsrc, 15
#if defined(__CHERI_PURE_CAPABILITY__)
alignd src, src, 4
neg tmp2, tmp1
add dst, dstin, tmp2
#else
bic src, src, 15
sub dst, dstin, tmp1
#endif
add count, count, tmp1 /* Count is now 16 too large. */
ldp A_q, B_q, [src, 16]
str D_q, [dstin]
ldp C_q, D_q, [src, 48]
subs count, count, 128 + 16 /* Test and readjust count. */
b.ls L(copy64_from_end)
L(loop64):
stp A_q, B_q, [dst, 16]
ldp A_q, B_q, [src, 80]
stp C_q, D_q, [dst, 48]
ldp C_q, D_q, [src, 112]
add src, src, 64
add dst, dst, 64
subs count, count, 64
b.hi L(loop64)
/* Write the last iteration and copy 64 bytes from the end. */
L(copy64_from_end):
ldp E_q, F_q, [srcend, -64]
stp A_q, B_q, [dst, 16]
ldp A_q, B_q, [srcend, -32]
stp C_q, D_q, [dst, 48]
stp E_q, F_q, [dstend, -64]
stp A_q, B_q, [dstend, -32]
ret
/* Large backwards copy for overlapping copies.
Copy 16 bytes and then align srcend to 16-byte alignment. */
L(copy_long_backwards):
cbz tmp1, L(copy0)
ldr D_q, [srcend, -16]
and tmp1, xsrcend, 15
#if defined(__CHERI_PURE_CAPABILITY__)
alignd srcend, srcend, 4
neg tmp2, tmp1
add count, count, tmp2
#else
bic srcend, srcend, 15
sub count, count, tmp1
#endif
ldp A_q, B_q, [srcend, -32]
str D_q, [dstend, -16]
ldp C_q, D_q, [srcend, -64]
#if defined(__CHERI_PURE_CAPABILITY__)
add dstend, dstend, tmp2 /* tmp1 was already negated above. */
#else
sub dstend, dstend, tmp1
#endif
subs count, count, 128
b.ls L(copy64_from_start)
L(loop64_backwards):
str B_q, [dstend, -16]
str A_q, [dstend, -32]
ldp A_q, B_q, [srcend, -96]
str D_q, [dstend, -48]
str C_q, [dstend, -64]!
ldp C_q, D_q, [srcend, -128]
sub srcend, srcend, 64
subs count, count, 64
b.hi L(loop64_backwards)
/* Write the last iteration and copy 64 bytes from the start. */
L(copy64_from_start):
ldp E_q, F_q, [src, 32]
stp A_q, B_q, [dstend, -32]
ldp A_q, B_q, [src]
stp C_q, D_q, [dstend, -64]
stp E_q, F_q, [dstin, 32]
stp A_q, B_q, [dstin]
ret
END (MEMCPY)
weak_alias (MEMCPY, MEMMOVE)
libc_hidden_builtin_def (MEMCPY)
libc_hidden_builtin_def (MEMMOVE)
+32
View File
@@ -0,0 +1,32 @@
/* Simple memrchr.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
void *__memrchr (const void *s, int c, size_t n)
{
unsigned char uc = c;
const unsigned char *us = s;
while (n-- > 0)
if (us[n] == uc)
return (void *) (us + n);
return NULL;
}
weak_alias (__memrchr, memrchr)
+154
View File
@@ -0,0 +1,154 @@
/* Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#ifndef MEMSET
# define MEMSET memset
#endif
/* Assumptions:
*
* ARMv8-a, AArch64, Morello, Advanced SIMD, unaligned accesses.
*
*/
#if defined(__CHERI_PURE_CAPABILITY__)
#define dstin c0
#define val x1
#define valw w1
#define count x2
#define dst c3
#define xdst x3
#define dstend c4
#define xdstend x4
#define zva_val x5
#else
#define dstin x0
#define val x1
#define valw w1
#define count x2
#define dst x3
#define xdst x3
#define dstend x4
#define xdstend x4
#define zva_val x5
#endif
ENTRY (MEMSET)
PTR_ARG (0)
SIZE_ARG (2)
dup v0.16B, valw
add dstend, dstin, count
cmp count, 96
b.hi L(set_long)
cmp count, 16
b.hs L(set_medium)
mov val, v0.D[0]
/* Set 0..15 bytes. */
tbz count, 3, 1f
str val, [dstin]
str val, [dstend, -8]
ret
.p2align 4
1: tbz count, 2, 2f
str valw, [dstin]
str valw, [dstend, -4]
ret
2: cbz count, 3f
strb valw, [dstin]
tbz count, 1, 3f
strh valw, [dstend, -2]
3: ret
/* Set 17..96 bytes. */
L(set_medium):
str q0, [dstin]
tbnz count, 6, L(set96)
str q0, [dstend, -16]
tbz count, 5, 1f
str q0, [dstin, 16]
str q0, [dstend, -32]
1: ret
.p2align 4
/* Set 64..96 bytes. Write 64 bytes from the start and
32 bytes from the end. */
L(set96):
str q0, [dstin, 16]
stp q0, q0, [dstin, 32]
stp q0, q0, [dstend, -32]
ret
.p2align 4
L(set_long):
and valw, valw, 255
#if defined(__CHERI_PURE_CAPABILITY__)
alignd dst, dstin, 4
#else
bic dst, dstin, 15
#endif
str q0, [dstin]
cmp count, 160
ccmp valw, 0, 0, hs
b.ne L(no_zva)
#ifndef SKIP_ZVA_CHECK
mrs zva_val, dczid_el0
and zva_val, zva_val, 31
cmp zva_val, 4 /* ZVA size is 64 bytes. */
b.ne L(no_zva)
#endif
str q0, [dst, 16]
stp q0, q0, [dst, 32]
#if defined(__CHERI_PURE_CAPABILITY__)
alignd dst, dst, 6
#else
bic dst, dst, 63
#endif
sub count, xdstend, xdst /* Count is now 64 too large. */
sub count, count, 128 /* Adjust count and bias for loop. */
.p2align 4
L(zva_loop):
add dst, dst, 64
dc zva, dst
subs count, count, 64
b.hi L(zva_loop)
stp q0, q0, [dstend, -64]
stp q0, q0, [dstend, -32]
ret
L(no_zva):
sub count, xdstend, xdst /* Count is 16 too large. */
sub dst, dst, 16 /* Dst is biased by -32. */
sub count, count, 64 + 16 /* Adjust count and bias for loop. */
L(no_zva_loop):
stp q0, q0, [dst, 32]
stp q0, q0, [dst, 64]!
subs count, count, 64
b.hi L(no_zva_loop)
stp q0, q0, [dstend, -64]
stp q0, q0, [dstend, -32]
ret
END (MEMSET)
libc_hidden_builtin_def (MEMSET)
+43
View File
@@ -0,0 +1,43 @@
/* rawmemchr - find a character in a memory zone
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
/* Special case rawmemchr (s, 0) as strlen, otherwise tailcall memchr.
Call strlen without setting up a full frame - it preserves x14/x15.
*/
ENTRY (__rawmemchr)
cbz w1, L(do_strlen)
mov x2, -1
b __memchr
L(do_strlen):
mov c15, c30
cfi_return_column (c15)
mov c14, c0
bl __strlen
add c0, c14, x0
ret c15
END (__rawmemchr)
weak_alias (__rawmemchr, rawmemchr)
libc_hidden_builtin_def (__rawmemchr)
+64
View File
@@ -0,0 +1,64 @@
/* Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#include <jmpbuf-offsets.h>
#include <stap-probe.h>
/* Keep traditional entry points in with sigsetjmp(). */
ENTRY (setjmp)
mov x1, #1
b 1f
END (setjmp)
ENTRY (_setjmp)
mov x1, #0
b 1f
END (_setjmp)
libc_hidden_def (_setjmp)
ENTRY (__sigsetjmp)
1:
stp c19, c20, [c0, #JB_X19<<4]
stp c21, c22, [c0, #JB_X21<<4]
stp c23, c24, [c0, #JB_X23<<4]
stp c25, c26, [c0, #JB_X25<<4]
stp c27, c28, [c0, #JB_X27<<4]
stp c29, c30, [c0, #JB_X29<<4]
/* setjmp probe takes 3 arguments, address of jump buffer
first argument (8@x0), return value second argument (-4@x1),
and target address (8@x30), respectively. */
LIBC_PROBE (setjmp, 3, 8@c0, -4@c1, 8@c30)
stp q8, q9, [c0, #JB_D8<<4]
stp q10, q11, [c0, #JB_D10<<4]
stp q12, q13, [c0, #JB_D12<<4]
stp q14, q15, [c0, #JB_D14<<4]
mov c2, csp
str c2, [c0, #JB_SP<<4]
#if IS_IN (rtld)
/* In ld.so we never save the signal mask */
mov w0, #0
RET
#else
b C_SYMBOL_NAME(__sigjmp_save)
#endif
END (__sigsetjmp)
hidden_def (__sigsetjmp)
+216
View File
@@ -0,0 +1,216 @@
/* Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#include <linux/auxvec.h>
#include <cheri_perms.h>
weak_extern (__rela_dyn_start)
weak_extern (__rela_dyn_end)
/* This is the canonical entry point, usually the first thing in the text
segment.
Note that the code in the .init section has already been run.
This includes _init and _libc_init
At this entry point, most registers' values are unspecified, except:
x0/w0 Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
sp The stack contains the arguments and environment:
0(sp) argc
8(sp) argv[0]
...
(8*argc)(sp) NULL
(8*(argc+1))(sp) envp[0]
...
NULL
*/
.text
ENTRY(_start)
/* Create an initial frame with 0 LR and FP */
cfi_undefined (c30)
mov c29, czr
mov c30, czr
/* TODO: Use the presence of __rela_dyn_start. */
mov c5, c0
cbnz x0, L(rtld_done)
/* Initialize capabilities. */
#ifndef SHARED
/* The GNU Linker emits a R_MORELLO_RELATIVE relocation along with
__rela_dyn_start and __rela_dyn_end symbols around the relocation section.
r_offset contains the location, size and permissions:
capability location // offset 0 (64 bits)
length // offset 8 (56 bits)
permissions // (8 bits)
addend (capability offset) // offset 16
according to the ABI document in:
https://github.com/ARM-software/abi-aa/blob/main/aaelf64-morello/aaelf64-morello.rst#dynamic-linking-with-morello
The addend is the capability offset.
Note that this will not work with clang, since lld emits a __cap_relocs
struct that has a different layout. If we need to support clang+lld, then
we need to copy the capability initialization steps from Bionic, in:
libc/arch-morello/bionic/__morello_init_static.S. */
adrp c0, __rela_dyn_start
add c0, c0, #:lo12:__rela_dyn_start
adrp c1, __rela_dyn_end
add c1, c1, #:lo12:__rela_dyn_end
1:
/* No capabilities to initialize. Skip to stack adjustment. */
cmp c0, c1
b.eq 3f
/* Load the address of capability. */
ldr x2, [c0, #0]
/* Construct capability location from DDC and r_offset. */
cvtd c2, x2
/* Base in x3. */
ldr x3, [c2]
/* Length + permissions in x5. */
ldr x5, [c2, #8]
/* Permissions in x6. */
lsr x6, x5, #56
/* Permissions encoded as:
4 = X (executable)
2 = W (read/write)
1 = R (read only)
Permissions to clear in x8 and x11. */
mov x8, (CAP_PERM_STORE_CAP | CAP_PERM_EXECUTE)
movk x8, (CAP_PERM_STORE >> 16), lsl #16
mov x9, (CAP_PERM_EXECUTE)
mov x10, (CAP_PERM_STORE_CAP)
movk x10, (CAP_PERM_STORE >> 16), lsl #16
mov x11, (CAP_PERM_UNSEAL | CAP_PERM_SEAL | CAP_PERM_COMPARTMENT_ID)
cmp x6, #0x2
csel x8, x9, x8, eq
cmp x6, #0x4
csel x8, x10, x8, eq
/* Length in x5. */
and x5, x5, #0xffffffffffffff
/* Offset in x7. */
ldr x7, [c0, #16]
/* Construct capability from DDC with value equal to base. */
cvtd c3, x3
/* Set bounds to [base ; base + length]. */
scbndse c3, c3, x5
/* Compute the capability value from addend. */
add c3, c3, x7
/* Clear permissions. */
clrperm c3, c3, x8
clrperm c3, c3, x11
/* Seal capabilities, which provide execute permission, with MORELLO_RB */
tst x8, #CAP_PERM_EXECUTE
b.ne 2f
seal c3, c3, rb
2:
/* Store the constructed capability to the target location. */
str c3, [c2]
/* Move to the next __rela_dyn entry. */
add c0, c0, #24
b 1b
3:
#endif /* !SHARED */
/* Setup rtld_fini in argument register */
mov c5, czr
L(rtld_done):
/* Load argc and a pointer to argv */
ldr c1, [csp, #0]
add c2, csp, #16
/* Setup stack limit in argument register */
mov c6, csp
#ifdef PIC
# ifdef SHARED
adrp c0, :got:main
ldr c0, [c0, #:got_lo12:main]
# else
adrp c0, __wrap_main
add c0, c0, :lo12:__wrap_main
# endif /* SHARED */
#else
/* Set up the other arguments in registers */
MOVL (0, main)
cvtd c0, x0
#endif /* PIC */
mov x3, #0 /* Used to be init. */
mov x4, #0 /* Used to be fini. */
/* __libc_start_main (main, argc, argv, init, fini, rtld_fini,
stack_end) */
/* Let the libc call main and exit with its return code. */
bl __libc_start_main
/* should never get here....*/
bl abort
END(_start)
#if defined PIC && !defined SHARED
/* When main is not defined in the executable but in a shared library
then a wrapper is needed in crt1.o of the static-pie enabled libc,
because crt1.o and rcrt1.o share code and the later must avoid the
use of GOT relocations before __libc_start_main is called. */
ENTRY(__wrap_main)
b main
END(__wrap_main)
#endif
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start
+34
View File
@@ -0,0 +1,34 @@
/* Simple stpcpy.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#define NO_MEMPCPY_STPCPY_REDIRECT
#include <string.h>
#undef stpcpy
#undef __stpcpy
char *__stpcpy (char *d, const char *s)
{
size_t n = strlen (s);
return memcpy (d, s, n+1) + n;
}
weak_alias (__stpcpy, stpcpy)
libc_hidden_def (__stpcpy)
libc_hidden_builtin_def (stpcpy)
+33
View File
@@ -0,0 +1,33 @@
/* Simple strchr.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
char *strchr (const char *s, int c)
{
unsigned char uc = c;
const unsigned char *us = (const unsigned char *) s;
for (; *us != uc; us++)
if (*us == 0)
return NULL;
return (char *) us;
}
weak_alias (strchr, index)
libc_hidden_builtin_def (strchr)
+30
View File
@@ -0,0 +1,30 @@
/* Simple strchrnul.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
char *__strchrnul (const char *s, int c)
{
unsigned char uc = c;
const unsigned char *us = (const unsigned char *) s;
for (; *us != uc && *us != 0; us++);
return (char *) us;
}
weak_alias (__strchrnul, strchrnul)
+30
View File
@@ -0,0 +1,30 @@
/* Simple strcmp.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
int strcmp(const char *s1, const char *s2)
{
const unsigned char *us1 = (const unsigned char *) s1;
const unsigned char *us2 = (const unsigned char *) s2;
for (; *us1 == *us2 && *us1 != 0; us1++, us2++);
return *us1 - *us2;
}
libc_hidden_builtin_def (strcmp)
+28
View File
@@ -0,0 +1,28 @@
/* Simple strcpy.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
char *strcpy (char *d, const char *s)
{
size_t n = strlen (s);
return memcpy (d, s, n+1);
}
libc_hidden_builtin_def (strcpy)
+35
View File
@@ -0,0 +1,35 @@
/* Simple strcspn.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <string.h>
size_t strcspn (const char *str, const char *reject)
{
if (reject[0] == 0 || reject[1] == 0)
return __strchrnul (str, reject[0]) - str;
unsigned char table[256] = {0};
unsigned char *us;
for (us = (unsigned char*) reject; *us != 0; table[*us++] = 1);
table[*us] = 1;
for (us = (unsigned char*) str; table[*us] == 0; us++);
return us - (unsigned char *) str;
}
libc_hidden_builtin_def (strcspn)
+30
View File
@@ -0,0 +1,30 @@
/* Simple strlen.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
size_t __strlen (const char *s)
{
size_t n;
for (n = 0; s[n] != 0; n++);
return n;
}
weak_alias (__strlen, strlen)
libc_hidden_builtin_def (strlen)
+32
View File
@@ -0,0 +1,32 @@
/* Simple strncmp.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
int strncmp(const char *s1, const char *s2, size_t n)
{
const unsigned char *us1 = (const unsigned char *) s1;
const unsigned char *us2 = (const unsigned char *) s2;
for (; n > 0; us1++, us2++, n--)
if (*us1 != *us2 || *us1 == 0)
return *us1 - *us2;
return 0;
}
libc_hidden_builtin_def (strncmp)
+31
View File
@@ -0,0 +1,31 @@
/* Simple strnlen.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
size_t __strnlen (const char *s, size_t m)
{
size_t n;
for (n = 0; n < m && s[n] != 0; n++);
return n;
}
weak_alias (__strnlen, strnlen)
libc_hidden_def (__strnlen)
libc_hidden_def (strnlen)
+29
View File
@@ -0,0 +1,29 @@
/* Simple strrchr.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <string.h>
char *strrchr (const char *s, int c)
{
size_t n = strlen (s) + 1;
return __memrchr (s, c, n);
}
weak_alias (strrchr, rindex)
libc_hidden_builtin_def (strrchr)
+40
View File
@@ -0,0 +1,40 @@
/* Simple strspn.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <string.h>
size_t strspn (const char *str, const char *accept)
{
if (accept[0] == 0)
return 0;
if (accept[1] == 0)
{
const char *p;
for (p = str; *p == accept[0]; p++);
return p - str;
}
unsigned char table[256] = {0};
unsigned char *us;
for (us = (unsigned char*) accept; *us != 0; table[*us++] = 1);
for (us = (unsigned char*) str; table[*us] != 0; us++);
return us - (unsigned char *) str;
}
libc_hidden_builtin_def (strspn)
+19
View File
@@ -0,0 +1,19 @@
#include <stddef.h>
#include <sysdep.h>
#include <tls.h>
#include <link.h>
#include <dl-tlsdesc.h>
--
-- Abuse tls.h macros to derive offsets relative to the thread register.
TLSDESC_ARG offsetof(struct tlsdesc, arg)
TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count)
TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
TLSDESC_SIZE offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_size)
TCBHEAD_DTV offsetof(tcbhead_t, dtv)
DTV_COUNTER offsetof(dtv_t, counter)
TLS_DTV_UNALLOCATED TLS_DTV_UNALLOCATED
+3 -1
View File
@@ -35,4 +35,6 @@
bool __attribute__((unused)) mte = \
MTE_ENABLED (); \
bool __attribute__((unused)) sve = \
GLRO(dl_aarch64_cpu_features).sve;
GLRO(dl_aarch64_cpu_features).sve; \
bool __attribute__((unused)) morello = \
GLRO(dl_hwcap2) & HWCAP2_MORELLO;

Some files were not shown because too many files have changed in this diff Show More