mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 13:52:28 +00:00
Fix regression in _gclongjmp()
This commit is contained in:
parent
da45c7c80b
commit
65f32fad52
12 changed files with 225 additions and 25 deletions
39
libc/log/getsymbol.c
Normal file
39
libc/log/getsymbol.c
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/alg/bisectcarleft.internal.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/symbols.internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns name of symbol at address.
|
||||||
|
*/
|
||||||
|
char *GetSymbolByAddr(int64_t addr) {
|
||||||
|
struct SymbolTable *st;
|
||||||
|
if ((st = GetSymbolTable()) && st->count &&
|
||||||
|
((intptr_t)addr >= (intptr_t)&_base &&
|
||||||
|
(intptr_t)addr <= (intptr_t)&_end)) {
|
||||||
|
return st->name_base +
|
||||||
|
st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
|
||||||
|
st->count, addr - st->addr_base)]
|
||||||
|
.name_rva;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,9 @@ bool32 IsDebuggerPresent(bool);
|
||||||
bool IsRunningUnderMake(void);
|
bool IsRunningUnderMake(void);
|
||||||
const char *GetSiCodeName(int, int);
|
const char *GetSiCodeName(int, int);
|
||||||
void AppendResourceReport(char **, struct rusage *, const char *);
|
void AppendResourceReport(char **, struct rusage *, const char *);
|
||||||
|
char *GetSymbolByAddr(int64_t);
|
||||||
|
void PrintGarbage(FILE *);
|
||||||
|
void PrintGarbageNumeric(FILE *);
|
||||||
|
|
||||||
#define showcrashreports() ShowCrashReports()
|
#define showcrashreports() ShowCrashReports()
|
||||||
|
|
||||||
|
|
42
libc/log/printgarbage.c
Normal file
42
libc/log/printgarbage.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/nexgen32e/gc.internal.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
/* clang-format off */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints list of deferred operations on shadow stack.
|
||||||
|
*/
|
||||||
|
void PrintGarbage(FILE *f) {
|
||||||
|
size_t i;
|
||||||
|
f = stderr;
|
||||||
|
fprintf(f, "\n");
|
||||||
|
fprintf(f, " SHADOW STACK @ 0x%016lx\n", __builtin_frame_address(0));
|
||||||
|
fprintf(f, " garbage entry parent frame original ret callback arg \n");
|
||||||
|
fprintf(f, "-------------- -------------- ------------------ ------------------ ------------------\n");
|
||||||
|
for (i = __garbage.i; i--;) {
|
||||||
|
fprintf(f, "0x%012lx 0x%012lx %-18s %-18s 0x%016lx\n",
|
||||||
|
__garbage.p + i,
|
||||||
|
__garbage.p[i].frame,
|
||||||
|
GetSymbolByAddr(__garbage.p[i].ret-1),
|
||||||
|
GetSymbolByAddr(__garbage.p[i].fn),
|
||||||
|
__garbage.p[i].arg);
|
||||||
|
}
|
||||||
|
}
|
42
libc/log/printgarbagenumeric.c
Normal file
42
libc/log/printgarbagenumeric.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/nexgen32e/gc.internal.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
/* clang-format off */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints list of deferred operations on shadow stack w/o symbols.
|
||||||
|
*/
|
||||||
|
void PrintGarbageNumeric(FILE *f) {
|
||||||
|
size_t i;
|
||||||
|
f = stderr;
|
||||||
|
fprintf(f, "\n");
|
||||||
|
fprintf(f, " SHADOW STACK @ 0x%016lx\n", __builtin_frame_address(0));
|
||||||
|
fprintf(f, " garbage entry parent frame original ret callback arg \n");
|
||||||
|
fprintf(f, "-------------- -------------- ------------------ ------------------ ------------------\n");
|
||||||
|
for (i = __garbage.i; i--;) {
|
||||||
|
fprintf(f, "0x%012lx 0x%012lx 0x%016lx 0x%016lx 0x%016lx\n",
|
||||||
|
__garbage.p + i,
|
||||||
|
__garbage.p[i].frame,
|
||||||
|
__garbage.p[i].ret,
|
||||||
|
__garbage.p[i].fn,
|
||||||
|
__garbage.p[i].arg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ void __deferer(struct StackFrame *frame, void *fn, void *arg) {
|
||||||
__garbage.p = p2;
|
__garbage.p = p2;
|
||||||
__garbage.n = n2;
|
__garbage.n = n2;
|
||||||
}
|
}
|
||||||
__garbage.p[__garbage.i].frame = frame->next;
|
__garbage.p[__garbage.i].frame = frame;
|
||||||
__garbage.p[__garbage.i].fn = (intptr_t)fn;
|
__garbage.p[__garbage.i].fn = (intptr_t)fn;
|
||||||
__garbage.p[__garbage.i].arg = (intptr_t)arg;
|
__garbage.p[__garbage.i].arg = (intptr_t)arg;
|
||||||
__garbage.p[__garbage.i].ret = frame->addr;
|
__garbage.p[__garbage.i].ret = frame->addr;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/notice.inc"
|
#include "libc/notice.inc"
|
||||||
|
|
||||||
#define INITIAL_CAPACITY 4
|
#define INITIAL_CAPACITY 4
|
||||||
|
|
||||||
// Invokes deferred function calls.
|
// Invokes deferred function calls.
|
||||||
|
@ -44,19 +45,17 @@ __gc: decq __garbage(%rip)
|
||||||
// </LIMBO>
|
// </LIMBO>
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
sub $0x20,%rsp
|
sub $16,%rsp
|
||||||
push %rax
|
push %rax
|
||||||
push %rdx
|
push %rdx
|
||||||
movdqa %xmm0,-0x20(%rbp)
|
movdqa %xmm0,-16(%rbp)
|
||||||
movdqa %xmm1,-0x10(%rbp)
|
|
||||||
call *%r9
|
call *%r9
|
||||||
movdqa -0x10(%rbp),%xmm1
|
movdqa -16(%rbp),%xmm0
|
||||||
movdqa -0x20(%rbp),%xmm0
|
|
||||||
pop %rdx
|
pop %rdx
|
||||||
pop %rax
|
pop %rax
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
9: call abort
|
9: hlt
|
||||||
.endfn __gc,globl,hidden
|
.endfn __gc,globl,hidden
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
|
|
|
@ -30,29 +30,27 @@
|
||||||
// @see examples/ctrlc.c
|
// @see examples/ctrlc.c
|
||||||
// @noreturn
|
// @noreturn
|
||||||
_gclongjmp:
|
_gclongjmp:
|
||||||
.leafprologue
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
.profilable
|
.profilable
|
||||||
.weak __garbage
|
|
||||||
lea __garbage(%rip),%r12
|
lea __garbage(%rip),%r12
|
||||||
test %r12,%r12
|
mov (%r12),%r13 # garbage.i
|
||||||
|
test %r13,%r13
|
||||||
jnz .L.unwind.destructors
|
jnz .L.unwind.destructors
|
||||||
0: jmp longjmp
|
0: jmp longjmp
|
||||||
.L.unwind.destructors:
|
.L.unwind.destructors:
|
||||||
push %rdi
|
push %rdi
|
||||||
push %rsi
|
push %rsi
|
||||||
mov (%r12),%r13 # garbage.i
|
|
||||||
mov 16(%r12),%r14 # garbage.p
|
mov 16(%r12),%r14 # garbage.p
|
||||||
mov (%rdi),%r15 # jmp_buf[0] is new %rsp
|
mov (%rdi),%r15 # jmp_buf[0] is new %rsp
|
||||||
shl $5,%r13
|
shl $5,%r13 # log2(sizeof(struct Garbage))
|
||||||
1: test %r13,%r13
|
1: sub $32,%r13 # 𝑖--
|
||||||
jz 2f
|
js 2f
|
||||||
sub $32,%r13
|
cmp (%r14,%r13),%r15 # new %rsp > garbage.p[𝑖].frame
|
||||||
cmp (%r14,%r13),%r15
|
jbe 2f
|
||||||
ja 2f
|
|
||||||
mov 8(%r14,%r13),%rax # garbage.p[𝑖].fn
|
|
||||||
mov 16(%r14,%r13),%rdi # garbage.p[𝑖].arg
|
mov 16(%r14,%r13),%rdi # garbage.p[𝑖].arg
|
||||||
call *%rax
|
callq *8(%r14,%r13) # garbage.p[𝑖].fn
|
||||||
decq (%r12)
|
decq (%r12) # garbage.i--
|
||||||
jmp 1b
|
jmp 1b
|
||||||
2: pop %rsi
|
2: pop %rsi
|
||||||
pop %rdi
|
pop %rdi
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
// @assume system five nexgen32e abi conformant
|
// @assume system five nexgen32e abi conformant
|
||||||
// @note code built w/ microsoft abi compiler can't call this
|
// @note code built w/ microsoft abi compiler can't call this
|
||||||
// @see _gclongjmp() unwinds _gc() destructors
|
// @see _gclongjmp() unwinds _gc() destructors
|
||||||
longjmp:mov %esi,%eax
|
longjmp:
|
||||||
|
mov %esi,%eax
|
||||||
test %eax,%eax
|
test %eax,%eax
|
||||||
jnz 1f
|
jnz 1f
|
||||||
inc %eax
|
inc %eax
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
#include "libc/runtime/gc.h"
|
#include "libc/runtime/gc.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
|
||||||
#define gc(THING) _gc(THING)
|
#define gc(THING) _gc(THING)
|
||||||
#define defer(FN, ARG) _defer(FN, ARG)
|
#define defer(FN, ARG) _defer(FN, ARG)
|
||||||
|
#define gclongjmp(JB, ARG) _gclongjmp(JB, ARG)
|
||||||
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_GC_INTERNAL_H_ */
|
#endif /* COSMOPOLITAN_LIBC_RUNTIME_GC_INTERNAL_H_ */
|
||||||
|
|
75
test/libc/nexgen32e/gclongjmp_test.c
Normal file
75
test/libc/nexgen32e/gclongjmp_test.c
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/nexgen32e/gc.internal.h"
|
||||||
|
#include "libc/nexgen32e/nexgen32e.h"
|
||||||
|
#include "libc/runtime/gc.internal.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
|
|
||||||
|
#undef _gc
|
||||||
|
#define _gc(x) _defer(Free, x)
|
||||||
|
|
||||||
|
char *x;
|
||||||
|
char *y;
|
||||||
|
char *z;
|
||||||
|
jmp_buf jb;
|
||||||
|
|
||||||
|
void Free(char *p) {
|
||||||
|
strcpy(p, "FREE");
|
||||||
|
}
|
||||||
|
|
||||||
|
void C(void) {
|
||||||
|
x = _gc(strdup("abcd"));
|
||||||
|
if (0) PrintGarbage(stderr);
|
||||||
|
_gclongjmp(jb, 1);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void B(void C(void)) {
|
||||||
|
y = _gc(strdup("HIHI"));
|
||||||
|
C();
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void A(void C(void), void B(void(void))) {
|
||||||
|
z = _gc(strdup("yoyo"));
|
||||||
|
B(C);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*Ap)(void(void), void(void(void))) = A;
|
||||||
|
void (*Bp)(void(void)) = B;
|
||||||
|
void (*Cp)(void) = C;
|
||||||
|
|
||||||
|
TEST(gclongjmp, test) {
|
||||||
|
if (!setjmp(jb)) {
|
||||||
|
Ap(Cp, Bp);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
EXPECT_STREQ("FREE", x);
|
||||||
|
EXPECT_STREQ("FREE", y);
|
||||||
|
EXPECT_STREQ("FREE", z);
|
||||||
|
free(z);
|
||||||
|
free(y);
|
||||||
|
free(x);
|
||||||
|
}
|
2
third_party/lua/ltests.c
vendored
2
third_party/lua/ltests.c
vendored
|
@ -1238,7 +1238,7 @@ static int panicback (lua_State *L) {
|
||||||
b = (struct Aux *)lua_touserdata(L, -1);
|
b = (struct Aux *)lua_touserdata(L, -1);
|
||||||
lua_pop(L, 1); /* remove 'Aux' struct */
|
lua_pop(L, 1); /* remove 'Aux' struct */
|
||||||
runC(b->L, L, b->paniccode); /* run optional panic code */
|
runC(b->L, L, b->paniccode); /* run optional panic code */
|
||||||
longjmp(b->jb, 1);
|
_gclongjmp(b->jb, 1);
|
||||||
return 1; /* to avoid warnings */
|
return 1; /* to avoid warnings */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
third_party/lua/lua.main.c
vendored
2
third_party/lua/lua.main.c
vendored
|
@ -646,7 +646,7 @@ static int pmain (lua_State *L) {
|
||||||
int main (int argc, char **argv) {
|
int main (int argc, char **argv) {
|
||||||
int status, result;
|
int status, result;
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
if (IsModeDbg()) ShowCrashReports();
|
/* if (IsModeDbg()) ShowCrashReports(); */
|
||||||
L = luaL_newstate(); /* create state */
|
L = luaL_newstate(); /* create state */
|
||||||
if (L == NULL) {
|
if (L == NULL) {
|
||||||
l_message(argv[0], "cannot create state: not enough memory");
|
l_message(argv[0], "cannot create state: not enough memory");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue