mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +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);
|
||||
const char *GetSiCodeName(int, int);
|
||||
void AppendResourceReport(char **, struct rusage *, const char *);
|
||||
char *GetSymbolByAddr(int64_t);
|
||||
void PrintGarbage(FILE *);
|
||||
void PrintGarbageNumeric(FILE *);
|
||||
|
||||
#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.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].arg = (intptr_t)arg;
|
||||
__garbage.p[__garbage.i].ret = frame->addr;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/notice.inc"
|
||||
|
||||
#define INITIAL_CAPACITY 4
|
||||
|
||||
// Invokes deferred function calls.
|
||||
|
@ -44,19 +45,17 @@ __gc: decq __garbage(%rip)
|
|||
// </LIMBO>
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
sub $0x20,%rsp
|
||||
sub $16,%rsp
|
||||
push %rax
|
||||
push %rdx
|
||||
movdqa %xmm0,-0x20(%rbp)
|
||||
movdqa %xmm1,-0x10(%rbp)
|
||||
movdqa %xmm0,-16(%rbp)
|
||||
call *%r9
|
||||
movdqa -0x10(%rbp),%xmm1
|
||||
movdqa -0x20(%rbp),%xmm0
|
||||
movdqa -16(%rbp),%xmm0
|
||||
pop %rdx
|
||||
pop %rax
|
||||
leave
|
||||
ret
|
||||
9: call abort
|
||||
9: hlt
|
||||
.endfn __gc,globl,hidden
|
||||
.source __FILE__
|
||||
|
||||
|
|
|
@ -30,29 +30,27 @@
|
|||
// @see examples/ctrlc.c
|
||||
// @noreturn
|
||||
_gclongjmp:
|
||||
.leafprologue
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
.weak __garbage
|
||||
lea __garbage(%rip),%r12
|
||||
test %r12,%r12
|
||||
mov (%r12),%r13 # garbage.i
|
||||
test %r13,%r13
|
||||
jnz .L.unwind.destructors
|
||||
0: jmp longjmp
|
||||
.L.unwind.destructors:
|
||||
push %rdi
|
||||
push %rsi
|
||||
mov (%r12),%r13 # garbage.i
|
||||
mov 16(%r12),%r14 # garbage.p
|
||||
mov (%rdi),%r15 # jmp_buf[0] is new %rsp
|
||||
shl $5,%r13
|
||||
1: test %r13,%r13
|
||||
jz 2f
|
||||
sub $32,%r13
|
||||
cmp (%r14,%r13),%r15
|
||||
ja 2f
|
||||
mov 8(%r14,%r13),%rax # garbage.p[𝑖].fn
|
||||
shl $5,%r13 # log2(sizeof(struct Garbage))
|
||||
1: sub $32,%r13 # 𝑖--
|
||||
js 2f
|
||||
cmp (%r14,%r13),%r15 # new %rsp > garbage.p[𝑖].frame
|
||||
jbe 2f
|
||||
mov 16(%r14,%r13),%rdi # garbage.p[𝑖].arg
|
||||
call *%rax
|
||||
decq (%r12)
|
||||
callq *8(%r14,%r13) # garbage.p[𝑖].fn
|
||||
decq (%r12) # garbage.i--
|
||||
jmp 1b
|
||||
2: pop %rsi
|
||||
pop %rdi
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
// @assume system five nexgen32e abi conformant
|
||||
// @note code built w/ microsoft abi compiler can't call this
|
||||
// @see _gclongjmp() unwinds _gc() destructors
|
||||
longjmp:mov %esi,%eax
|
||||
longjmp:
|
||||
mov %esi,%eax
|
||||
test %eax,%eax
|
||||
jnz 1f
|
||||
inc %eax
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
#include "libc/runtime/gc.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define gc(THING) _gc(THING)
|
||||
#define defer(FN, ARG) _defer(FN, ARG)
|
||||
#define gc(THING) _gc(THING)
|
||||
#define defer(FN, ARG) _defer(FN, ARG)
|
||||
#define gclongjmp(JB, ARG) _gclongjmp(JB, ARG)
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#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);
|
||||
lua_pop(L, 1); /* remove 'Aux' struct */
|
||||
runC(b->L, L, b->paniccode); /* run optional panic code */
|
||||
longjmp(b->jb, 1);
|
||||
_gclongjmp(b->jb, 1);
|
||||
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 status, result;
|
||||
lua_State *L;
|
||||
if (IsModeDbg()) ShowCrashReports();
|
||||
/* if (IsModeDbg()) ShowCrashReports(); */
|
||||
L = luaL_newstate(); /* create state */
|
||||
if (L == NULL) {
|
||||
l_message(argv[0], "cannot create state: not enough memory");
|
||||
|
|
Loading…
Reference in a new issue