Skip to content

Commit f24c854

Browse files
committed
Write more runtime tests and fix bugs
This change adds tests for the new memory manager code particularly with its windows support. Function call tracing now works reliably on Silicon since our function hooker was missing new Apple self-modifying code APIs Many tests that were disabled a long time ago on aarch64 are reactivated by this change, now that arm support is on equal terms with x86. There's been a lot of places where ftrace could cause deadlocks, which have been hunted down across all platforms thanks to new tests. A bug in Windows's kill() function has been identified.
1 parent 0b3c81d commit f24c854

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+541
-863
lines changed

libc/calls/ntspawn.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
│ PERFORMANCE OF THIS SOFTWARE. │
1818
╚─────────────────────────────────────────────────────────────────────────────*/
1919
#include "libc/proc/ntspawn.h"
20+
#include "libc/calls/state.internal.h"
2021
#include "libc/calls/struct/sigset.internal.h"
2122
#include "libc/calls/syscall_support-nt.internal.h"
2223
#include "libc/intrin/strace.h"

libc/intrin/fds.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@ textstartup void __init_fds(int argc, char **argv, char **envp) {
190190
map->prot = PROT_READ | PROT_WRITE;
191191
map->flags = MAP_SHARED | MAP_ANONYMOUS;
192192
map->hand = shand;
193+
__maps_lock();
193194
__maps_insert(map);
195+
__maps_unlock();
194196
}
195197
}
196198
}

libc/intrin/maps.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ void __maps_init(void) {
112112
}
113113

114114
bool __maps_held(void) {
115+
return !__tls_enabled || (__get_tls()->tib_flags & TIB_FLAG_VFORKED) ||
116+
MUTEX_OWNER(
117+
atomic_load_explicit(&__maps.lock.word, memory_order_relaxed)) ==
118+
atomic_load_explicit(&__get_tls()->tib_ptid, memory_order_relaxed);
119+
}
120+
121+
bool __maps_reentrant(void) {
115122
return __tls_enabled && !(__get_tls()->tib_flags & TIB_FLAG_VFORKED) &&
116123
MUTEX_OWNER(
117124
atomic_load_explicit(&__maps.lock.word, memory_order_relaxed)) ==

libc/intrin/maps.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ void __maps_init(void);
8484
void __maps_lock(void);
8585
void __maps_check(void);
8686
void __maps_unlock(void);
87+
bool __maps_reentrant(void);
8788
void *__maps_randaddr(void);
8889
void __maps_add(struct Map *);
8990
void __maps_free(struct Map *);
@@ -103,28 +104,28 @@ forceinline optimizespeed int __maps_search(const void *key,
103104
return (addr > map->addr) - (addr < map->addr);
104105
}
105106

106-
dontinstrument static inline struct Map *__maps_next(struct Map *map) {
107+
static inline struct Map *__maps_next(struct Map *map) {
107108
struct Tree *node;
108109
if ((node = tree_next(&map->tree)))
109110
return MAP_TREE_CONTAINER(node);
110111
return 0;
111112
}
112113

113-
dontinstrument static inline struct Map *__maps_prev(struct Map *map) {
114+
static inline struct Map *__maps_prev(struct Map *map) {
114115
struct Tree *node;
115116
if ((node = tree_prev(&map->tree)))
116117
return MAP_TREE_CONTAINER(node);
117118
return 0;
118119
}
119120

120-
dontinstrument static inline struct Map *__maps_first(void) {
121+
static inline struct Map *__maps_first(void) {
121122
struct Tree *node;
122123
if ((node = tree_first(__maps.maps)))
123124
return MAP_TREE_CONTAINER(node);
124125
return 0;
125126
}
126127

127-
dontinstrument static inline struct Map *__maps_last(void) {
128+
static inline struct Map *__maps_last(void) {
128129
struct Tree *node;
129130
if ((node = tree_last(__maps.maps)))
130131
return MAP_TREE_CONTAINER(node);

libc/intrin/mmap.c

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
#include "libc/thread/thread.h"
5050
#include "libc/thread/tls.h"
5151

52-
#define MMDEBUG 1
52+
#define MMDEBUG 0
5353
#define MAX_SIZE 0x0ff800000000ul
5454

5555
#define MAP_FIXED_NOREPLACE_linux 0x100000
@@ -94,8 +94,11 @@ privileged optimizespeed struct Map *__maps_floor(const char *addr) {
9494
}
9595

9696
static bool __maps_overlaps(const char *addr, size_t size) {
97-
struct Map *map, *floor = __maps_floor(addr);
98-
for (map = floor; map && map->addr <= addr + size; map = __maps_next(map))
97+
struct Map *map;
98+
ASSERT(__maps_held());
99+
if (!(map = __maps_floor(addr)))
100+
map = __maps_first();
101+
for (; map && map->addr <= addr + size; map = __maps_next(map))
99102
if (MAX(addr, map->addr) <
100103
MIN(addr + PGUP(size), map->addr + PGUP(map->size)))
101104
return true;
@@ -105,30 +108,33 @@ static bool __maps_overlaps(const char *addr, size_t size) {
105108
// returns true if all fragments of all allocations which overlap
106109
// [addr,addr+size) are completely contained by [addr,addr+size).
107110
textwindows static bool __maps_envelops(const char *addr, size_t size) {
108-
struct Map *map, *next;
111+
struct Map *map;
109112
size = PGUP(size);
113+
ASSERT(__maps_held());
110114
if (!(map = __maps_floor(addr)))
111-
if (!(map = __maps_first()))
112-
return true;
113-
do {
114-
if (MAX(addr, map->addr) >= MIN(addr + size, map->addr + map->size))
115-
break; // didn't overlap mapping
116-
if (!__maps_isalloc(map))
117-
return false; // didn't include first fragment of alloc
118-
if (addr > map->addr)
119-
return false; // excluded leading pages of first fragment
120-
// set map to last fragment in allocation
121-
for (; (next = __maps_next(map)) && !__maps_isalloc(next); map = next)
122-
// fragments within an allocation must be perfectly contiguous
123-
ASSERT(map->addr + map->size == next->addr);
124-
if (addr + size < map->addr + PGUP(map->size))
125-
return false; // excluded trailing pages of allocation
126-
} while ((map = next));
115+
map = __maps_first();
116+
while (map && map->addr <= addr + size) {
117+
if (MAX(addr, map->addr) < MIN(addr + size, map->addr + map->size)) {
118+
if (!__maps_isalloc(map))
119+
return false; // didn't include first fragment of alloc
120+
if (addr > map->addr)
121+
return false; // excluded leading pages of first fragment
122+
struct Map *next; // set map to last fragment in allocation
123+
for (; (next = __maps_next(map)) && !__maps_isalloc(next); map = next)
124+
ASSERT(map->addr + map->size == next->addr); // contiguous
125+
if (addr + size < map->addr + PGUP(map->size))
126+
return false; // excluded trailing pages of allocation
127+
map = next;
128+
} else {
129+
map = __maps_next(map);
130+
}
131+
}
127132
return true;
128133
}
129134

130135
void __maps_check(void) {
131136
#if MMDEBUG
137+
ASSERT(__maps_held());
132138
size_t maps = 0;
133139
size_t pages = 0;
134140
static unsigned mono;
@@ -152,20 +158,37 @@ void __maps_check(void) {
152158
#endif
153159
}
154160

161+
#if MMDEBUG
162+
static void __maps_ok(void) {
163+
ASSERT(!__maps_reentrant());
164+
__maps_lock();
165+
__maps_check();
166+
__maps_unlock();
167+
}
168+
__attribute__((__constructor__)) static void __maps_ctor(void) {
169+
atexit(__maps_ok);
170+
__maps_ok();
171+
}
172+
__attribute__((__destructor__)) static void __maps_dtor(void) {
173+
__maps_ok();
174+
}
175+
#endif
176+
155177
static int __muntrack(char *addr, size_t size, struct Map **deleted,
156178
struct Map **untracked, struct Map temp[2]) {
157179
int rc = 0;
158180
size_t ti = 0;
159181
struct Map *map;
160182
struct Map *next;
161183
size = PGUP(size);
184+
ASSERT(__maps_held());
162185
if (!(map = __maps_floor(addr)))
163186
map = __maps_first();
164187
for (; map && map->addr <= addr + size; map = next) {
165188
next = __maps_next(map);
166189
char *map_addr = map->addr;
167190
size_t map_size = map->size;
168-
if (!(MAX(addr, map_addr) < MIN(addr + size, map_addr + PGUP(map_size))))
191+
if (MAX(addr, map_addr) >= MIN(addr + size, map_addr + PGUP(map_size)))
169192
continue;
170193
if (addr <= map_addr && addr + size >= map_addr + PGUP(map_size)) {
171194
if (map->hand == MAPS_RESERVATION)
@@ -350,6 +373,7 @@ static bool __maps_mergeable(const struct Map *x, const struct Map *y) {
350373
void __maps_insert(struct Map *map) {
351374
struct Map *left, *right;
352375
ASSERT(map->size);
376+
ASSERT(__maps_held());
353377
ASSERT(!__maps_overlaps(map->addr, map->size));
354378
__maps.pages += (map->size + __pagesize - 1) / __pagesize;
355379

@@ -460,7 +484,7 @@ static int __munmap(char *addr, size_t size) {
460484
return einval();
461485

462486
// test for signal handler tragedy
463-
if (__maps_held())
487+
if (__maps_reentrant())
464488
return edeadlk();
465489

466490
// lock the memory manager
@@ -469,8 +493,10 @@ static int __munmap(char *addr, size_t size) {
469493

470494
// on windows we can only unmap whole allocations
471495
if (IsWindows())
472-
if (!__maps_envelops(addr, size))
496+
if (!__maps_envelops(addr, size)) {
497+
__maps_unlock();
473498
return enotsup();
499+
}
474500

475501
// untrack mappings
476502
int rc;
@@ -500,6 +526,7 @@ void *__maps_randaddr(void) {
500526
}
501527

502528
static void *__maps_pickaddr(size_t size) {
529+
ASSERT(__maps_held());
503530
char *addr = 0;
504531
struct Map *map, *prev;
505532
size = GRUP(size);
@@ -569,11 +596,15 @@ static void *__mmap_impl(char *addr, size_t size, int prot, int flags, int fd,
569596
noreplace = true;
570597
sysflags |= MAP_FIXED_NOREPLACE_linux;
571598
} else if (IsFreebsd() || IsNetbsd()) {
599+
// todo: insert a reservation like windows
572600
sysflags |= MAP_FIXED;
601+
__maps_lock();
573602
if (__maps_overlaps(addr, size)) {
603+
__maps_unlock();
574604
__maps_free(map);
575605
return (void *)eexist();
576606
}
607+
__maps_unlock();
577608
} else {
578609
noreplace = true;
579610
}
@@ -729,7 +760,7 @@ static void *__mmap(char *addr, size_t size, int prot, int flags, int fd,
729760
return (void *)enomem();
730761

731762
// test for signal handler reentry
732-
if (__maps_held())
763+
if (__maps_reentrant())
733764
return (void *)edeadlk();
734765

735766
// create memory mappping
@@ -874,7 +905,7 @@ static void *__mremap(char *old_addr, size_t old_size, size_t new_size,
874905
return (void *)enomem();
875906

876907
// test for signal handler reentry
877-
if (__maps_held())
908+
if (__maps_reentrant())
878909
return (void *)edeadlk();
879910

880911
// lock the memory manager

libc/intrin/mprotect.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,17 @@ int __mprotect(char *addr, size_t size, int prot) {
6767
size = (size + pagesz - 1) & -pagesz;
6868

6969
// test for signal handler reentry
70-
if (__maps_held())
70+
if (__maps_reentrant())
7171
return edeadlk();
7272

7373
// change mappings
7474
int rc = 0;
7575
bool found = false;
7676
__maps_lock();
77-
struct Map *map, *floor;
78-
floor = __maps_floor(addr);
79-
for (map = floor; map && map->addr <= addr + size; map = __maps_next(map)) {
77+
struct Map *map;
78+
if (!(map = __maps_floor(addr)))
79+
map = __maps_first();
80+
for (; map && map->addr <= addr + size; map = __maps_next(map)) {
8081
char *map_addr = map->addr;
8182
size_t map_size = map->size;
8283
char *beg = MAX(addr, map_addr);
@@ -85,7 +86,7 @@ int __mprotect(char *addr, size_t size, int prot) {
8586
continue;
8687
found = true;
8788
if (addr <= map_addr && addr + size >= map_addr + PGUP(map_size)) {
88-
// change protection of entire mapping
89+
// change protection status of pages
8990
if (!__mprotect_chunk(map_addr, map_size, prot, map->iscow)) {
9091
map->prot = prot;
9192
} else {

libc/intrin/msync-nt.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,32 +31,29 @@ textwindows int sys_msync_nt(char *addr, size_t size, int flags) {
3131

3232
if ((uintptr_t)addr & (__pagesize - 1))
3333
return einval();
34-
if (__maps_held())
34+
if (__maps_reentrant())
3535
return edeadlk();
3636

3737
int rc = 0;
3838
__maps_lock();
39-
struct Map *map, *next;
39+
struct Map *next, *map;
4040
if (!(map = __maps_floor(addr)))
41-
if (!(map = __maps_first()))
42-
return true;
43-
for (; map; map = next) {
41+
map = __maps_first();
42+
for (; map && map->addr <= addr + size; map = next) {
4443
next = __maps_next(map);
4544
if (!__maps_isalloc(map))
4645
continue;
4746
if (map->flags & MAP_ANONYMOUS)
4847
continue;
4948
if (MAX(addr, map->addr) >= MIN(addr + size, map->addr + map->size))
50-
break; // didn't overlap mapping
49+
continue; // didn't overlap mapping
5150

5251
// get true size of win32 allocation
5352
size_t allocsize = map->size;
54-
for (struct Map *map2 = next; map2; map2 = __maps_next(map2)) {
55-
if (!__maps_isalloc(map2) && map->addr + allocsize == map2->addr) {
56-
allocsize += map2->size;
57-
} else {
58-
break;
59-
}
53+
while (next && !__maps_isalloc(next) &&
54+
next->addr + allocsize == next->addr) {
55+
allocsize += next->size;
56+
next = __maps_next(next);
6057
}
6158

6259
// perform the flush

libc/log/oncrash_arm64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "libc/runtime/runtime.h"
4848
#include "libc/runtime/stack.h"
4949
#include "libc/runtime/symbols.internal.h"
50+
#include "libc/runtime/syslib.internal.h"
5051
#include "libc/stdio/stdio.h"
5152
#include "libc/str/str.h"
5253
#include "libc/sysv/consts/auxv.h"

libc/log/showcrashreports.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,7 @@ void ShowCrashReports(void) {
8282
ss.ss_sp = crashstack;
8383
unassert(!sigaltstack(&ss, 0));
8484
InstallCrashHandler(SIGQUIT, 0);
85-
#ifdef __x86_64__
8685
InstallCrashHandler(SIGTRAP, 0);
87-
#else
88-
InstallCrashHandler(SIGTRAP, 0);
89-
#endif
9086
InstallCrashHandler(SIGFPE, 0);
9187
InstallCrashHandler(SIGILL, 0);
9288
InstallCrashHandler(SIGBUS, 0);

libc/proc/fork-nt.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
╚─────────────────────────────────────────────────────────────────────────────*/
1919
#include "libc/calls/internal.h"
2020
#include "libc/calls/sig.internal.h"
21+
#include "libc/calls/state.internal.h"
2122
#include "libc/calls/syscall_support-nt.internal.h"
2223
#include "libc/errno.h"
2324
#include "libc/intrin/directmap.h"

0 commit comments

Comments
 (0)