1//===-- Implementation of libc death test executors -----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <stddef.h>
10#include <stdint.h>
11
12namespace LIBC_NAMESPACE {
13
14int bcmp(const void *lhs, const void *rhs, size_t count);
15void bzero(void *ptr, size_t count);
16int memcmp(const void *lhs, const void *rhs, size_t count);
17void *memcpy(void *__restrict, const void *__restrict, size_t);
18void *memmove(void *dst, const void *src, size_t count);
19void *memset(void *ptr, int value, size_t count);
20int atexit(void (*func)(void));
21
22} // namespace LIBC_NAMESPACE
23
24namespace {
25
26// Integration tests cannot use the SCUDO standalone allocator as SCUDO pulls
27// various other parts of the libc. Since SCUDO development does not use
28// LLVM libc build rules, it is very hard to keep track or pull all that SCUDO
29// requires. Hence, as a work around for this problem, we use a simple allocator
30// which just hands out continuous blocks from a statically allocated chunk of
31// memory.
32static constexpr uint64_t MEMORY_SIZE = 65336;
33static uint8_t memory[MEMORY_SIZE];
34static uint8_t *ptr = memory;
35
36} // anonymous namespace
37
38extern "C" {
39
40// Hermetic tests rely on the following memory functions. This is because the
41// compiler code generation can emit calls to them. We want to map the external
42// entrypoint to the internal implementation of the function used for testing.
43// This is done manually as not all targets support aliases.
44
45int bcmp(const void *lhs, const void *rhs, size_t count) {
46 return LIBC_NAMESPACE::bcmp(lhs, rhs, count);
47}
48void bzero(void *ptr, size_t count) { LIBC_NAMESPACE::bzero(ptr, count); }
49int memcmp(const void *lhs, const void *rhs, size_t count) {
50 return LIBC_NAMESPACE::memcmp(lhs, rhs, count);
51}
52void *memcpy(void *__restrict dst, const void *__restrict src, size_t count) {
53 return LIBC_NAMESPACE::memcpy(dst, src, count);
54}
55void *memmove(void *dst, const void *src, size_t count) {
56 return LIBC_NAMESPACE::memmove(dst, src, count);
57}
58void *memset(void *ptr, int value, size_t count) {
59 return LIBC_NAMESPACE::memset(ptr, value, count);
60}
61
62// This is needed if the test was compiled with '-fno-use-cxa-atexit'.
63int atexit(void (*func)(void)) { return LIBC_NAMESPACE::atexit(func); }
64
65constexpr uint64_t ALIGNMENT = alignof(uintptr_t);
66
67void *malloc(size_t s) {
68 // Keep the bump pointer aligned on an eight byte boundary.
69 s = ((s + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT;
70 void *mem = ptr;
71 ptr += s;
72 return static_cast<uint64_t>(ptr - memory) >= MEMORY_SIZE ? nullptr : mem;
73}
74
75void free(void *) {}
76
77void *realloc(void *mem, size_t s) {
78 if (mem == nullptr)
79 return malloc(s);
80 uint8_t *newmem = reinterpret_cast<uint8_t *>(malloc(s));
81 if (newmem == nullptr)
82 return nullptr;
83 uint8_t *oldmem = reinterpret_cast<uint8_t *>(mem);
84 // We use a simple for loop to copy the data over.
85 // If |s| is less the previous alloc size, the copy works as expected.
86 // If |s| is greater than the previous alloc size, then garbage is copied
87 // over to the additional part in the new memory block.
88 for (size_t i = 0; i < s; ++i)
89 newmem[i] = oldmem[i];
90 return newmem;
91}
92
93// The unit test framework uses pure virtual functions. Since hermetic tests
94// cannot depend C++ runtime libraries, implement dummy functions to support
95// the virtual function runtime.
96void __cxa_pure_virtual() {
97 // A pure virtual being called is an error so we just trap.
98 __builtin_trap();
99}
100
101// Hermetic tests are linked with -nostdlib. BFD linker expects
102// __dso_handle when -nostdlib is used.
103void *__dso_handle = nullptr;
104
105} // extern "C"
106
107void *operator new(unsigned long size, void *ptr) { return ptr; }
108
109void *operator new(size_t size) { return malloc(s: size); }
110
111void *operator new[](size_t size) { return malloc(s: size); }
112
113void operator delete(void *) {
114 // The libc runtime should not use the global delete operator. Hence,
115 // we just trap here to catch any such accidental usages.
116 __builtin_trap();
117}
118
119void operator delete(void *ptr, size_t size) { __builtin_trap(); }
120

source code of libc/test/UnitTest/HermeticTestUtils.cpp