From d5730311343fc32d0acd1440a4138d0dafd0d99e Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Fri, 28 Feb 2025 14:41:24 +0300 Subject: [PATCH 1/3] add compact VA layout [#16] --- dj64.mk | 12 +++++++++--- src/djdev64/stub/stub.c | 9 ++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/dj64.mk b/dj64.mk index f3424841..9013a600 100644 --- a/dj64.mk +++ b/dj64.mk @@ -53,8 +53,14 @@ XCPPFLAGS = $(shell pkg-config --variable=xcppflags dj64) ASCPPFLAGS = $(shell pkg-config --variable=cppflags dj64) LD = $(CC) -# stub version 5 -#DJ64_XLDFLAGS = -V 5 + +ifeq ($(DJ64COMPACT_VA),) +LOADADDR = 0x08148000 +else +LOADADDR = 0x08068000 +DJ64_XLDFLAGS += -f 0x20 +endif + # freebsd's dlopen() ignores link order and binds to libc the symbols # defined in libdj64.so. Use static linking as a work-around. ifneq ($(filter freebsd%,$(MACH)),) @@ -99,7 +105,7 @@ ifeq ($(DJ64STATIC),1) XLDFLAGS += $(shell pkg-config --static --libs dj64static) DJ64_XLDFLAGS += -f 0x4000 else -XLDFLAGS += $(shell pkg-config --variable=crt0 dj64) $(XLD_IMB)=0x08148000 +XLDFLAGS += $(shell pkg-config --variable=crt0 dj64) $(XLD_IMB)=$(LOADADDR) endif $(XELF).elf: $(AS_OBJECTS) $(PLT_O) $(XLD) $^ $(XLDFLAGS) -o $@ diff --git a/src/djdev64/stub/stub.c b/src/djdev64/stub/stub.c index f7387cfa..be145e78 100644 --- a/src/djdev64/stub/stub.c +++ b/src/djdev64/stub/stub.c @@ -47,6 +47,7 @@ #define FLG1_OFF STFLAGS_OFF #define FLG2_OFF (STFLAGS_OFF + 1) +#define STFLG1_COMPACT 0x20 // compact 32bit VA layout #define STFLG1_STATIC 0x40 // static linking /* 2 flags below are chosen for compatibility between v4 and v5 stubs. * They can't be set together, and as such, when we have a core payload, @@ -182,6 +183,7 @@ int djstub_main(int argc, char *argv[], char *envp[], _GO32_StubInfo *stubinfo_p; struct ldops *ops = NULL; int STFLAGS_OFF = 0x2c; + int compact_va = 0; uint8_t stub_ver = 0; #define BARE_STUB() (stub_ver == 0) @@ -278,6 +280,9 @@ int djstub_main(int argc, char *argv[], char *envp[], if (stub_ver < 6 || !(buf[FLG2_OFF] & STFLG2_EMBOV)) noffset += coffsize; } + if (buf[FLG1_OFF] & STFLG1_COMPACT) + compact_va = 1; + memcpy(&nsize, &buf[0x20 - moff], sizeof(nsize)); if (nsize) noffset2 = noffset + nsize; @@ -373,7 +378,7 @@ int djstub_main(int argc, char *argv[], char *envp[], if (va_size > MB) exit(EXIT_FAILURE); /* if we load 2 payloads, use larger estimate */ - if (dyn && (pl32 || BARE_STUB())) { + if ((dyn && pl32) || BARE_STUB() || compact_va) { stubinfo.initial_size = VA_SZ; stubinfo.upl_base = va + MB; stubinfo.upl_size = VA_SZ - MB; @@ -408,6 +413,8 @@ int djstub_main(int argc, char *argv[], char *envp[], exit(EXIT_FAILURE); if (va2 < va + va_size || va2 + va_size2 - va > VA_SZ) exit(EXIT_FAILURE); + if (compact_va && va2 + va_size2 - va > MB) + exit(EXIT_FAILURE); ops->read_sections(handle, lin2ptr(mem_base), ifile, coffset); ops->close(handle); unregister_dosops(); From 212c5f3c26585c5d3c13f49e047d0f106783e432 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Fri, 28 Feb 2025 22:25:15 +0300 Subject: [PATCH 2/3] thunks: preparing to support multiple dispatchers [#16] Since this is an ABI-incompatible change, add dynapi versioning. --- include/dj64/thunks_a.inc | 2 +- include/dj64/thunks_c.inc | 2 +- include/dj64/thunks_p.h | 4 +- include/dj64/thunks_p.inc | 5 +- include/dj64/util.h | 9 ++-- src/libc/dj64/plt.S | 2 +- src/libc/dj64/thunks.c | 105 ++++++++++++++++++++++++++++---------- 7 files changed, 91 insertions(+), 38 deletions(-) diff --git a/include/dj64/thunks_a.inc b/include/dj64/thunks_a.inc index 8dca65dc..82624c9a 100644 --- a/include/dj64/thunks_a.inc +++ b/include/dj64/thunks_a.inc @@ -60,6 +60,6 @@ STATIC struct athunks asm_thunks = { __attribute__((constructor)) static void init(void) { - register_athunks(&asm_thunks); + register_athunks(&asm_thunks, DJ64_DYNAPI_VER); } #endif diff --git a/include/dj64/thunks_c.inc b/include/dj64/thunks_c.inc index e147a792..4da89d6d 100644 --- a/include/dj64/thunks_c.inc +++ b/include/dj64/thunks_c.inc @@ -39,7 +39,7 @@ static dj64dispatch_t DJ64_DISPATCH_FN; __attribute__((constructor)) static void init(void) { - register_dispatch_fn(DJ64_DISPATCH_FN); + register_dispatch_fn(DJ64_DISPATCH_FN, DJ64_DYNAPI_VER); } #endif diff --git a/include/dj64/thunks_p.h b/include/dj64/thunks_p.h index 6fe682fa..8955f235 100644 --- a/include/dj64/thunks_p.h +++ b/include/dj64/thunks_p.h @@ -22,8 +22,8 @@ uint64_t dj64_asm_call(int num, uint8_t *sp, uint8_t len, int flags); -uint64_t dj64_asm_call_u(int handle, int num, uint8_t *sp, uint8_t len, - int flags); +uint64_t dj64_asm_call_u(int handle, int libid, int num, uint8_t *sp, + uint8_t len, int flags); uint8_t *dj64_clean_stk(size_t len); uint32_t dj64_obj_init(const void *data, uint16_t len); uint32_t dj64_obj_oinit(const void *data, uint16_t len); diff --git a/include/dj64/thunks_p.inc b/include/dj64/thunks_p.inc index 4e81ee90..3a77d18c 100644 --- a/include/dj64/thunks_p.inc +++ b/include/dj64/thunks_p.inc @@ -44,7 +44,7 @@ #ifdef _IN_DJ64 #define __CALL(n, s, l, f) dj64_asm_call(n, s, l, f) #else -#define __CALL(n, s, l, f) dj64_asm_call_u(_handle, n, s, l, f) +#define __CALL(n, s, l, f) dj64_asm_call_u(_handle, _libid, n, s, l, f) #endif #define __CSTK(l) dj64_clean_stk(l) @@ -82,6 +82,7 @@ #ifndef _IN_DJ64 static int _handle; +static int _libid; #define STATIC static #else #define STATIC @@ -109,6 +110,6 @@ STATIC struct athunks pthunks = { __attribute__((constructor)) static void init(void) { - register_pthunks(&pthunks, &_handle); + register_pthunks(&pthunks, &_handle, &_libid, DJ64_DYNAPI_VER); } #endif diff --git a/include/dj64/util.h b/include/dj64/util.h index a575fc45..d96d93f1 100644 --- a/include/dj64/util.h +++ b/include/dj64/util.h @@ -22,13 +22,15 @@ #include #include +#define DJ64_DYNAPI_VER 2 + #define PRINTF(n) __attribute__((format(printf, n, n + 1))) void djloudprintf(const char *format, ...) PRINTF(1); void djlogprintf(const char *format, ...) PRINTF(1); void djloudvprintf(const char *format, va_list vl); typedef uint32_t (dj64dispatch_t)(int fn, uint8_t *sp, int *r_len); -void register_dispatch_fn(dj64dispatch_t *fn); +void register_dispatch_fn(dj64dispatch_t *fn, int ver); struct athunk { const char *name; @@ -38,8 +40,9 @@ struct athunks { int num; uint32_t *tab; }; -void register_athunks(struct athunks *at); -void register_pthunks(struct athunks *pt, int *handle_p); +void register_athunks(struct athunks *at, int ver); +void register_pthunks(struct athunks *pt, int *handle_p, int *libid_p, + int ver); #define _countof(array) (sizeof(array) / sizeof(array[0])) diff --git a/src/libc/dj64/plt.S b/src/libc/dj64/plt.S index 48e7d664..0d386789 100644 --- a/src/libc/dj64/plt.S +++ b/src/libc/dj64/plt.S @@ -344,7 +344,7 @@ ctrl: movl %esp, %edx movl __plt_handle, %eax movl $0, %ebx - movb $AUX_CORE, %bl + movb $AUX_USER, %bl movb $DL_API_VER, %bh movl 8(%ebp), %ecx movl %cs, %esi diff --git a/src/libc/dj64/thunks.c b/src/libc/dj64/thunks.c index 7eecc648..d833fb8f 100644 --- a/src/libc/dj64/thunks.c +++ b/src/libc/dj64/thunks.c @@ -52,11 +52,12 @@ int __crt0_startup_flags; +#define MAX_DISPS 5 struct udisp { - dj64dispatch_t *disp; + dj64dispatch_t *disp[MAX_DISPS]; const struct elf_ops *eops; - struct athunks *at; - struct athunks *pt; + struct athunks *at[MAX_DISPS]; + struct athunks *pt[MAX_DISPS]; struct athunks core_at; struct athunks core_pt; unsigned cs; @@ -78,6 +79,11 @@ static dj64dispatch_t *disp_fn; static struct athunks *u_athunks; static struct athunks *u_pthunks; static int *u_handle_p; +static int *u_libid_p; + +static int fatalerr; +static int dynapi_mism; +static int req_da_ver; struct ctx_hooks { void (*init)(int); @@ -135,7 +141,7 @@ uint32_t djptr2addr(const uint8_t *ptr) return dj64api->ptr2addr(ptr); } -static int _dj64_call(struct udisp *u, int libid, int fn, dpmi_regs *regs, +static int _dj64_call(struct udisp *u, int fn, dpmi_regs *regs, uint8_t *sp, unsigned esi, dj64dispatch_t *disp, int handle) { int len; @@ -157,7 +163,7 @@ static int _dj64_call(struct udisp *u, int libid, int fn, dpmi_regs *regs, return (rc == ASM_NORET ? DJ64_RET_NORET : DJ64_RET_ABORT); } u->noret_jmp = &noret; - res = (libid ? disp : dj64_thunk_call)(fn, sp, &len); + res = disp(fn, sp, &len); *regs = u->s_regs; switch (len) { case 0: @@ -185,6 +191,7 @@ static int dj64_call(int handle, int libid, int fn, unsigned esi, uint8_t *sp) sp += sizeof(*regs) + 8; // skip regs, ebp, eip to get stack args assert(handle < MAX_HANDLES); + assert(libid < MAX_DISPS); u = &udisps[handle]; assert(u->recur_cnt < MAX_RECUR); u->recur_cnt++; @@ -192,7 +199,7 @@ static int dj64_call(int handle, int libid, int fn, unsigned esi, uint8_t *sp) chooks[i].restore(handle); saved_noret = u->noret_jmp; last_objcnt = u->objcnt; - ret = _dj64_call(u, libid, fn, regs, sp, esi, u->disp, handle); + ret = _dj64_call(u, fn, regs, sp, esi, u->disp[libid], handle); assert(u->objcnt == last_objcnt); // make sure no leaks, esp on NORETURN u->noret_jmp = saved_noret; if (ret == DJ64_RET_OK) { @@ -250,6 +257,8 @@ static int dj64_ctrl(int handle, int libid, int fn, unsigned esi, uint8_t *sp) { dpmi_regs *regs = (dpmi_regs *)sp; int ver = libid >> 8; + libid &= 0xff; + assert(libid < MAX_DISPS); assert(handle < MAX_HANDLES); if (ver != DL_API_VER) { djloudprintf("dj64: API version mismatch, got %i want %i\n", @@ -288,13 +297,13 @@ static int dj64_ctrl(int handle, int libid, int fn, unsigned esi, uint8_t *sp) if (ret) goto err; } - if (u->at) { - ret = process_athunks(u->at, mem_base, u->eops, eh); + if (u->at[libid]) { + ret = process_athunks(u->at[libid], mem_base, u->eops, eh); if (ret) goto err; } - if (u->pt) { - ret = process_pthunks(u->pt, u->eops, eh); + if (u->pt[libid]) { + ret = process_pthunks(u->pt[libid], u->eops, eh); if (ret) goto err; } @@ -343,13 +352,13 @@ static int dj64_ctrl(int handle, int libid, int fn, unsigned esi, uint8_t *sp) size, addr, &entry); if (ret) goto err; - if (u->at) { - ret = process_athunks(u->at, mem_base, u->eops, eh); + if (u->at[libid]) { + ret = process_athunks(u->at[libid], mem_base, u->eops, eh); if (ret) goto err; } - if (u->pt) { - ret = process_pthunks(u->pt, u->eops, eh); + if (u->pt[libid]) { + ret = process_pthunks(u->pt[libid], u->eops, eh); if (ret) goto err; } @@ -374,23 +383,32 @@ dj64cdispatch_t **DJ64_INIT_FN(int handle, const struct elf_ops *ops, { int i; struct udisp *u; + int disp_id = 1; // hard-code assert(handle < MAX_HANDLES); u = &udisps[handle]; - u->disp = disp_fn; + memset(u->disp, 0, sizeof(u->disp)); + u->disp[0] = dj64_thunk_call; + u->disp[disp_id] = disp_fn; disp_fn = NULL; u->eops = ops; u->main = main; u->full_init = full_init; - u->at = u_athunks; + u->at[0] = &u->core_at; + u->pt[0] = &u->core_pt; + + u->at[disp_id] = u_athunks; u_athunks = NULL; - u->pt = u_pthunks; + u->pt[disp_id] = u_pthunks; if (u_handle_p) *u_handle_p = handle; + if (u_libid_p) + *u_libid_p = disp_id; u_pthunks = NULL; u_handle_p = NULL; + u_libid_p = NULL; u->core_at = asm_thunks; u->core_at.tab = dj64api->malloc(sizeof(asm_thunks.tab[0]) * asm_thunks.num); @@ -425,6 +443,13 @@ int DJ64_INIT_ONCE_FN(const struct dj64_api *api, int api_ver) ret++; dj64api = api; dj64api_ver = api_ver; + + if (fatalerr) { + if (dynapi_mism) + djloudprintf("dj64 dynapi version mismatch: need %i got %i\n", + DJ64_DYNAPI_VER, req_da_ver); + return -1; + } return ret; } @@ -475,8 +500,8 @@ uint64_t dj64_asm_call(int num, uint8_t *sp, uint8_t len, int flags) return ret; } -uint64_t dj64_asm_call_u(int handle, int num, uint8_t *sp, uint8_t len, - int flags) +uint64_t dj64_asm_call_u(int handle, int libid, int num, uint8_t *sp, + uint8_t len, int flags) { int i; int ret; @@ -484,13 +509,13 @@ uint64_t dj64_asm_call_u(int handle, int num, uint8_t *sp, uint8_t len, assert(handle < MAX_HANDLES); u = &udisps[handle]; - if (!u->pt) { + if (!u->pt[libid]) { djloudprintf("no user thunks\n"); return ASM_CALL_ABORT; } for (i = 0; i < num_chooks; i++) chooks[i].save(); - ret = do_asm_call(u, u->pt, u->cs, num, sp, len, flags); + ret = do_asm_call(u, u->pt[libid], u->cs, num, sp, len, flags); /* asm call can recursively invoke dj64, so restore context here */ for (i = 0; i < num_chooks; i++) chooks[i].restore(handle); @@ -579,23 +604,43 @@ void dj64_rm_dosobj(const void *data, uint32_t fa) do_rm_dosobj(u, fa); } -void register_dispatch_fn(dj64dispatch_t *fn) +void register_dispatch_fn(dj64dispatch_t *fn, int ver) { + req_da_ver = ver; + if (ver != DJ64_DYNAPI_VER) { + fatalerr++; + dynapi_mism++; + return; + } assert(!disp_fn); disp_fn = fn; } -void register_athunks(struct athunks *at) +void register_athunks(struct athunks *at, int ver) { + req_da_ver = ver; + if (ver != DJ64_DYNAPI_VER) { + fatalerr++; + dynapi_mism++; + return; + } assert(!u_athunks); u_athunks = at; } -void register_pthunks(struct athunks *pt, int *handle_p) +void register_pthunks(struct athunks *pt, int *handle_p, int *libid_p, + int ver) { + req_da_ver = ver; + if (ver != DJ64_DYNAPI_VER) { + fatalerr++; + dynapi_mism++; + return; + } assert(!u_pthunks); u_pthunks = pt; u_handle_p = handle_p; + u_libid_p = libid_p; } void crt1_startup(int handle) @@ -623,15 +668,19 @@ static uint32_t do_thunk_get(const struct athunks *at, const char *name) uint32_t djthunk_get_h(int handle, const char *name) { + int i; struct udisp *u; uint32_t ret = (uint32_t)-1; assert(handle < MAX_HANDLES); u = &udisps[handle]; - if (u->at) - ret = do_thunk_get(u->at, name); - if (ret == (uint32_t)-1) - ret = do_thunk_get(&u->core_at, name); + for (i = 0; i < MAX_DISPS; i++) { + if (u->at[i]) { + ret = do_thunk_get(u->at[i], name); + if (ret != (uint32_t)-1) + break; + } + } assert(ret != (uint32_t)-1); return ret; } From 2eb039d2ac5bc84ceaec18c0647177211a798ff0 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sat, 1 Mar 2025 17:09:40 +0300 Subject: [PATCH 3/3] glue go64 loader with new ELF infra [closes #16] Now it is finally possible to load most of the supported ELF formats (modulo those with compactified layout and with static linking) via go64 API. This is a huge overhaul of the entire ELF infrastructure, but at the same time its a simplest possible approach. If someone wants to expose the remaining ELF formats to go64, then that would be 100 times more work, so not worth the trouble. --- demos/rmcb/asm.S | 4 +- demos/rmcb/asm.inc | 4 +- demos/rmcb/glob_asm.h | 4 +- demos/rmcb/main.c | 2 +- demos/rmcb/mouse.c | 2 +- demos/rmcb/ms.S | 4 +- include/go64.h | 4 ++ include/libc/djthunks.h | 2 + src/djdev64/djdev64.c | 44 ++++++++++++++++-- src/djdev64/djexec.c | 63 +++++++++++++++++++------- src/djdev64/elf.c | 1 - src/djdev64/elf64.c | 31 +++++++++---- src/djdev64/elf_priv.h | 4 ++ src/djdev64/include/djdev64/dj64init.h | 25 ++++++---- src/djdev64/include/djdev64/djdev64.h | 5 +- src/libc/compat/go64/elfexec.c | 49 ++++++++++++++++++-- src/libc/compat/go64/makefile | 2 + src/libc/compat/go64/pltcall32.S | 3 +- src/libc/compat/go64/pltctrl32.S | 24 ++++++++++ src/libc/compat/go64/upltinit32.S | 20 ++++++++ src/libc/dj64/plt.S | 30 ++++++++++-- src/libc/dj64/plt.h | 1 + src/libc/dj64/plt_defs.inc | 11 ----- src/libc/dj64/thunks.c | 55 ++++++++++++++++++---- src/libc/dj64/uplt.S | 11 ++++- 25 files changed, 323 insertions(+), 82 deletions(-) create mode 100644 src/libc/compat/go64/pltctrl32.S create mode 100644 src/libc/compat/go64/upltinit32.S diff --git a/demos/rmcb/asm.S b/demos/rmcb/asm.S index 7b3820a0..47747d8e 100644 --- a/demos/rmcb/asm.S +++ b/demos/rmcb/asm.S @@ -2,8 +2,8 @@ #include "asm.h" .bss -.global __ds -__ds: .long 0 +.global __rmcb_ds +__rmcb_ds: .long 0 .ifndef _DJ64 /* We need emergency stack because __dpmi_int() alters SS in djgpp. * That was eventually fixed in dj64, hence the ifdef. */ diff --git a/demos/rmcb/asm.inc b/demos/rmcb/asm.inc index 7f0beec3..ed1d75c9 100644 --- a/demos/rmcb/asm.inc +++ b/demos/rmcb/asm.inc @@ -1,12 +1,12 @@ .macro handler_prolog len push %ds - mov %cs:__ds, %eax + mov %cs:__rmcb_ds, %eax mov %eax, %ds .ifndef _DJ64 /* djgpp needs emergency stack because of a bug in __dpmi_int() */ mov %ss, %esi mov %esp, %edi - pushl __ds + pushl __rmcb_ds lea _cstack+\len, %edx push %edx lss (%esp), %esp diff --git a/demos/rmcb/glob_asm.h b/demos/rmcb/glob_asm.h index 3277350c..2f3a6578 100644 --- a/demos/rmcb/glob_asm.h +++ b/demos/rmcb/glob_asm.h @@ -1,2 +1,2 @@ -__ASM(unsigned short, _ds) SEMIC -__ASM_FUNC(my_mouse_handler) SEMIC +__ASM(unsigned short, _rmcb_ds) SEMIC +__ASM_FUNC(rmcb_mouse_handler) SEMIC diff --git a/demos/rmcb/main.c b/demos/rmcb/main.c index 4f99d50d..2750a3e2 100644 --- a/demos/rmcb/main.c +++ b/demos/rmcb/main.c @@ -10,7 +10,7 @@ int main() int ok; /* our rm cb needs to know DS */ - _ds = _my_ds(); + _rmcb_ds = _my_ds(); ok = mouse_init(); if (!ok) diff --git a/demos/rmcb/mouse.c b/demos/rmcb/mouse.c index 2a490f62..5edb21ff 100644 --- a/demos/rmcb/mouse.c +++ b/demos/rmcb/mouse.c @@ -113,7 +113,7 @@ int mouse_init(void) #else mouse_regs = (__dpmi_regs *) malloc(sizeof(__dpmi_regs)); #endif - __dpmi_allocate_real_mode_callback(my_mouse_handler, mouse_regs, + __dpmi_allocate_real_mode_callback(rmcb_mouse_handler, mouse_regs, &newm); r.x.ax = 0x14; r.x.cx = MEV_MASK; diff --git a/demos/rmcb/ms.S b/demos/rmcb/ms.S index ac0d9023..8510c863 100644 --- a/demos/rmcb/ms.S +++ b/demos/rmcb/ms.S @@ -3,8 +3,8 @@ .include "asm.inc" .text -.global _my_mouse_handler -_my_mouse_handler: +.global _rmcb_mouse_handler +_rmcb_mouse_handler: pusha handler_prolog SIGSTK_LEN call _do_mouse diff --git a/include/go64.h b/include/go64.h index c8807ba3..a49fae63 100644 --- a/include/go64.h +++ b/include/go64.h @@ -2,7 +2,11 @@ #define GO64_H void pltcall32(__dpmi_regs *regs, __dpmi_paddr addr); +void pltctrl32(__dpmi_regs *regs, int fn, int arg); +void upltinit32(__dpmi_regs *regs); int elfexec(const char *path, int argc, char **argv); int elfload(int num); +#define ELFEXEC_LIBID 2 + #endif diff --git a/include/libc/djthunks.h b/include/libc/djthunks.h index 664231ed..6dc9c452 100644 --- a/include/libc/djthunks.h +++ b/include/libc/djthunks.h @@ -29,5 +29,7 @@ uint32_t djptr2addr(const uint8_t *ptr); uint32_t djthunk_get(const char *name); uint32_t djthunk_get_h(int handle, const char *name); void *djsbrk(int increment); +int djelf_run(int eid); +int djelf_load(int num, int libid, int *r_fd); #endif diff --git a/src/djdev64/djdev64.c b/src/djdev64/djdev64.c index f89886f0..da9e7841 100644 --- a/src/djdev64/djdev64.c +++ b/src/djdev64/djdev64.c @@ -39,17 +39,52 @@ struct dj64handle { dj64cdispatch_t *ctrl; dj64done_t *done; char *path; + const struct djdev64_api *api; }; static struct dj64handle dlhs[HNDL_MAX]; static pthread_mutex_t init_mtx = PTHREAD_MUTEX_INITIALIZER; +static void *do_open_dyn(int handle, int hfd) +{ + int fd; + void *ret; + struct dj64handle *h; + if (handle >= handles) + return NULL; + h = &dlhs[handle]; + fd = h->api->uget(hfd); + if (fd == -1) + return NULL; + ret = djelf_open_dyn(fd); + close(fd); + return ret; +} + +static char *do_elfparse64(int handle, int hfd, uint32_t *r_size) +{ + int fd; + char *ret; + struct dj64handle *h; + if (handle >= handles) + return NULL; + h = &dlhs[handle]; + fd = h->api->uget(hfd); + if (fd == -1) + return NULL; + ret = djelf64_parse_fd(fd, r_size); + close(fd); + return ret; +} + static const struct elf_ops eops = { djelf_open, - djelf_open_dyn, + do_open_dyn, djelf_close, djelf_getsymoff, djelf_reloc, + do_elfparse64, + djelf64_run, }; #define __S(x) #x @@ -137,7 +172,7 @@ static void *emu_dlmopen(int handle, const char *filename, int flags, #define FLG_STATIC 0x40 static int _djdev64_open(const char *path, const struct dj64_api *api, - int api_ver, unsigned flags) + int api_ver, unsigned flags, const struct djdev64_api *devapi) { int rc; dj64init_t *init; @@ -262,6 +297,7 @@ static int _djdev64_open(const char *path, const struct dj64_api *api, h->ctrl = cdisp[1]; h->done = done; h->path = path2; + h->api = devapi; return handles++; err_close: @@ -276,7 +312,7 @@ static int _djdev64_open(const char *path, const struct dj64_api *api, } int djdev64_open(const char *path, const struct dj64_api *api, int api_ver, - unsigned flags) + unsigned flags, const struct djdev64_api *devapi) { int ret; @@ -284,7 +320,7 @@ int djdev64_open(const char *path, const struct dj64_api *api, int api_ver, * register the dispatch fn, which is stored in a global pointer until * init() is called. Also we increment handles non-atomically. */ pthread_mutex_lock(&init_mtx); - ret = _djdev64_open(path, api, api_ver, flags); + ret = _djdev64_open(path, api, api_ver, flags, devapi); pthread_mutex_unlock(&init_mtx); return ret; } diff --git a/src/djdev64/djexec.c b/src/djdev64/djexec.c index 9be0c586..98801fd5 100644 --- a/src/djdev64/djexec.c +++ b/src/djdev64/djexec.c @@ -20,6 +20,7 @@ #include #include #include "djdev64/djdev64.h" +#include "elf_priv.h" struct exec_info { /* volatile because of longjmp() vs auto storage */ @@ -28,35 +29,65 @@ struct exec_info { jmp_buf exit_jmp; }; +struct exec_handle { + void *dlobj; + int (*m)(int, char **); + int (*ae2)(void(*)(void*,int),void*); + int argc; + char **argv; +}; +static struct exec_handle ehands[1]; // expand if more than 1 ever needed + static void exit_exec(void *handle, int rc); -int djdev64_exec(const char *path, unsigned flags, int argc, char **argv) +int djdev64_exec(const char *path, int handle, int libid, unsigned flags, + int argc, char **argv) { - void *dlobj = NULL; - int (*m)(int, char **); - int (*ae2)(void(*)(void*,int),void*); - struct exec_info ei; - int ret = -1, rc; + struct exec_handle *eh = &ehands[0]; + dj64init2_t *i2; #ifdef RTLD_DEEPBIND - dlobj = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND); + eh->dlobj = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND); #endif - if (!dlobj) { + if (!eh->dlobj) { printf("error loading %s: %s\n", path, dlerror()); return -1; } - m = dlsym(dlobj, "main"); - if (!m) { + eh->m = dlsym(eh->dlobj, "main"); + if (!eh->m) { printf("error: can't find \"main\"\n"); goto out; } - ae2 = dlsym(dlobj, "atexit2"); - if (!ae2) { + eh->ae2 = dlsym(eh->dlobj, "atexit2"); + if (!eh->ae2) { printf("error: can't find \"atexit2\"\n"); goto out; } + i2 = dlsym(eh->dlobj, "dj64init2"); + if (!i2) { + printf("error: can't find \"dj64init2\"\n"); + goto out; + } - rc = ae2(exit_exec, &ei); + i2(handle, libid); + eh->argc = argc; + eh->argv = argv; + return 0; +out: + dlclose(eh->dlobj); + return -1; +} + +int djelf64_run(int eid) +{ + struct exec_handle *eh; + struct exec_info ei; + int ret = -1, rc; + + if (eid != 0) + return -1; + eh = &ehands[eid]; + rc = eh->ae2(exit_exec, &ei); if (rc == -1) { printf("error: atexit2() failed\n"); goto out; @@ -64,10 +95,10 @@ int djdev64_exec(const char *path, unsigned flags, int argc, char **argv) if (setjmp(ei.exit_jmp)) ret = ei.exit_code; else - ret = (unsigned char)m(argc, argv); - ae2(NULL, NULL); + ret = (unsigned char)eh->m(eh->argc, eh->argv); + eh->ae2(NULL, NULL); out: - dlclose(dlobj); + dlclose(eh->dlobj); return ret; } diff --git a/src/djdev64/elf.c b/src/djdev64/elf.c index 7d9b0328..c6a851d4 100644 --- a/src/djdev64/elf.c +++ b/src/djdev64/elf.c @@ -118,7 +118,6 @@ void *djelf_open_dyn(int fd) fstat(fd, &st); addr = (char *)mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - close(fd); if (addr == MAP_FAILED) { perror("mmap()"); return NULL; diff --git a/src/djdev64/elf64.c b/src/djdev64/elf64.c index d9263da4..3d93323e 100644 --- a/src/djdev64/elf64.c +++ b/src/djdev64/elf64.c @@ -25,12 +25,12 @@ #include #include #include "djdev64/djdev64.h" +#include "elf_priv.h" static const char *sec_name = ".dj64startup"; -char *djelf64_parse(const char *path, uint32_t *r_size) +static char *do_parse(int fd, uint32_t *r_size) { - int fd; Elf *e; char *ret; char *name; @@ -41,10 +41,8 @@ char *djelf64_parse(const char *path, uint32_t *r_size) if (elf_version(EV_CURRENT) == EV_NONE) return NULL; - if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) - return NULL; if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) - goto err1; + return NULL; if (elf_kind(e) != ELF_K_ELF) goto err2; if (elf_getshdrstrndx(e, &shstrndx) != 0) @@ -59,15 +57,14 @@ char *djelf64_parse(const char *path, uint32_t *r_size) break; } if (!scn) { - fprintf(stderr, "dj64-specific sections not found in %s\n", path); +// fprintf(stderr, "dj64-specific sections not found\n"); goto err2; } data = elf_getdata(scn, NULL); if (!data) { - fprintf(stderr, "failed to get section data for %s\n", path); + fprintf(stderr, "failed to get section data\n"); goto err2; } - close(fd); *r_size = data->d_size; ret = malloc(data->d_size); memcpy(ret, data->d_buf, data->d_size); @@ -76,7 +73,21 @@ char *djelf64_parse(const char *path, uint32_t *r_size) err2: elf_end(e); -err1: - close(fd); return NULL; } + +char *djelf64_parse(const char *path, uint32_t *r_size) +{ + char *ret; + int fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd == -1) + return NULL; + ret = do_parse(fd, r_size); + close(fd); + return ret; +} + +char *djelf64_parse_fd(int fd, uint32_t *r_size) +{ + return do_parse(fd, r_size); +} diff --git a/src/djdev64/elf_priv.h b/src/djdev64/elf_priv.h index 3e12552e..635bab57 100644 --- a/src/djdev64/elf_priv.h +++ b/src/djdev64/elf_priv.h @@ -6,3 +6,7 @@ void *djelf_open(char *addr, uint32_t size); void djelf_close(void *arg); int djelf_reloc(void *arg, uint8_t *addr, uint32_t size, uint32_t va, uint32_t *r_entry); + +char *djelf64_parse_fd(int fd, uint32_t *r_size); + +int djelf64_run(int eid); diff --git a/src/djdev64/include/djdev64/dj64init.h b/src/djdev64/include/djdev64/dj64init.h index 7de66ffa..a4d91d8b 100644 --- a/src/djdev64/include/djdev64/dj64init.h +++ b/src/djdev64/include/djdev64/dj64init.h @@ -25,8 +25,8 @@ typedef int (dj64cdispatch_t)(int handle, int libid, int fn, unsigned esi, uint8_t *sp); -#define DJ64_API_VER 18 -#define DJ64_API_MIN_VER 16 +#define DJ64_API_VER 19 +#define DJ64_API_MIN_VER 19 enum { DJ64_PRINT_LOG, DJ64_PRINT_TERMINAL, DJ64_PRINT_SCREEN }; /* pushal */ @@ -63,28 +63,37 @@ struct dj64_api { void (*exit)(int rc); void *(*malloc)(size_t size); void (*free)(void *ptr); - int (*elfload)(int num); - int (*uget)(int handle); + int (*elfload)(int num, int handle, int libid, int *r_fd); char *(*elfparse64)(int num, uint32_t *r_size); }; + +struct djdev64_api { + int (*uget)(int handle); +}; + #define DJ64_INIT_ONCE_FN dj64init_once typedef int (dj64init_once_t)(const struct dj64_api *api, int api_ver); int DJ64_INIT_ONCE_FN(const struct dj64_api *api, int api_ver); struct elf_ops { void *(*open)(char *addr, uint32_t size); - void *(*open_dyn)(int fd); + void *(*open_dyn)(int handle, int fd); void (*close)(void *arg); uint32_t (*getsym)(void *arg, const char *name); int (*reloc)(void *arg, uint8_t *addr, uint32_t size, uint32_t va, uint32_t *r_entry); + char *(*elfparse64_fd)(int handle, int hfd, uint32_t *r_size); + int (*run64)(int eid); }; -#define DJ64_INIT_FN dj64init typedef dj64cdispatch_t **(dj64init_t)(int handle, const struct elf_ops *ops, void *main, int full_init); -dj64cdispatch_t **DJ64_INIT_FN(int handle, const struct elf_ops *ops, - void *main, int full_init); +#define DJ64_INIT_FN dj64init +dj64init_t DJ64_INIT_FN; + +typedef void (dj64init2_t)(int handle, int disp_id); +#define DJ64_INIT2_FN dj64init2 +dj64init2_t DJ64_INIT2_FN; #define DJ64_DONE_FN dj64done typedef void (dj64done_t)(int handle); diff --git a/src/djdev64/include/djdev64/djdev64.h b/src/djdev64/include/djdev64/djdev64.h index bc3fcbb1..bd8fb61b 100644 --- a/src/djdev64/include/djdev64/djdev64.h +++ b/src/djdev64/include/djdev64/djdev64.h @@ -26,14 +26,15 @@ #define DJ64F_NOMANGLE (1 << 17) int djdev64_open(const char *path, const struct dj64_api *api, int api_ver, - unsigned flags); + unsigned flags, const struct djdev64_api *devapi); int djdev64_call(int handle, int libid, int fn, unsigned esi, unsigned char *sp); int djdev64_ctrl(int handle, int libid, int fn, unsigned esi, unsigned char *sp); void djdev64_close(int handle); -int djdev64_exec(const char *path, unsigned flags, int argc, char **argv); +int djdev64_exec(const char *path, int handle, int libid, unsigned flags, + int argc, char **argv); char *djelf64_parse(const char *path, uint32_t *r_size); diff --git a/src/libc/compat/go64/elfexec.c b/src/libc/compat/go64/elfexec.c index 06f24eeb..5931b410 100644 --- a/src/libc/compat/go64/elfexec.c +++ b/src/libc/compat/go64/elfexec.c @@ -54,7 +54,7 @@ static char *strrpbrk(const char *szString, const char *szChars) int elfexec(const char *path, int argc, char **argv) { - int err, fd, len, errn; + int err, fd, len, errn, eid, ret; const char *p; unsigned fname; __dpmi_paddr api; @@ -80,7 +80,7 @@ int elfexec(const char *path, int argc, char **argv) memset(®s, 0, sizeof(regs)); regs.d.ebx = 3; // get version pltcall32(®s, api); - if (regs.d.eax < 2) { + if (regs.d.eax < 3) { fprintf(stderr, "unsupported DJ64 version %i\n", regs.d.eax); return -1; } @@ -125,12 +125,53 @@ int elfexec(const char *path, int argc, char **argv) dm.size = shmi.size; err = __dpmi_free_physical_address_mapping(&dm); assert(!err); + + regs.d.ebx = 2 | (ELFEXEC_LIBID << 16); // exec + regs.d.ecx = 0; // argc - unsupp + regs.d.edx = 0; // argv - unsupp + regs.x.di = shmi.handle & 0xffff; + regs.x.si = shmi.handle >> 16; + pltcall32(®s, api); + if (regs.x.flags & 1) + return -1; + eid = regs.d.eax; memset(®s, 0, sizeof(regs)); - regs.d.ebx = 2; // exec + regs.d.ebx = 6; // memfd regs.x.di = shmi.handle & 0xffff; regs.x.si = shmi.handle >> 16; pltcall32(®s, api); + // eax == fd + regs.d.ebx = _stubinfo->upl_base; + regs.d.ecx = _stubinfo->upl_size; + regs.d.edx = _stubinfo->mem_base; + pltctrl32(®s, 2, ELFEXEC_LIBID); + if (!(regs.x.flags & 1)) { + // eax == uentry + regs.d.ebx = ELFEXEC_LIBID; + upltinit32(®s); + } + ret = djelf_run(eid); __dpmi_free_shared_memory(shmi.handle); /* returning only 16bit AX allows to distinguish with -1 returns above */ - return regs.x.ax; + return ret; +} + +int elfload(int num) +{ + __dpmi_regs regs; + int fd; + int rc = djelf_load(num, ELFEXEC_LIBID, &fd); + if (rc == -1) + return -1; + regs.d.eax = fd; + regs.d.ebx = _stubinfo->upl_base; + regs.d.ecx = _stubinfo->upl_size; + regs.d.edx = _stubinfo->mem_base; + pltctrl32(®s, 2, ELFEXEC_LIBID); + if (!(regs.x.flags & 1)) { + // eax == uentry + regs.d.ebx = ELFEXEC_LIBID; + upltinit32(®s); + } + return djelf_run(rc); } diff --git a/src/libc/compat/go64/makefile b/src/libc/compat/go64/makefile index e55859cc..bbcc536d 100644 --- a/src/libc/compat/go64/makefile +++ b/src/libc/compat/go64/makefile @@ -2,6 +2,8 @@ TOP=../.. AS_SRC += pltcall32.S +AS_SRC += pltctrl32.S +AS_SRC += upltinit32.S SRC += elfexec.c include $(TOP)/../makefile.inc diff --git a/src/libc/compat/go64/pltcall32.S b/src/libc/compat/go64/pltcall32.S index 059ba994..dab3a8d2 100644 --- a/src/libc/compat/go64/pltcall32.S +++ b/src/libc/compat/go64/pltcall32.S @@ -11,9 +11,10 @@ popal movl __plt_handle, %eax lcalll *ARG2 + pushf pushal movl ARG1, %ebx -.irpc i,01234567 +.irpc i,012345678 popl \i*4(%ebx) .endr popal diff --git a/src/libc/compat/go64/pltctrl32.S b/src/libc/compat/go64/pltctrl32.S new file mode 100644 index 00000000..e01643f0 --- /dev/null +++ b/src/libc/compat/go64/pltctrl32.S @@ -0,0 +1,24 @@ +#include + + FUNC(_pltctrl32) + ENTER + pushal + movl ARG1, %ebx +.irpc i,76543210 + pushl \i*4(%ebx) +.endr + movl %ebp, 8(%esp) // keep ebp untouched + popal + pushl ARG3 + pushl ARG2 + call ctrl + popl %ecx + popl %ecx + pushf + pushal + movl ARG1, %ebx +.irpc i,012345678 + popl \i*4(%ebx) +.endr + popal + LEAVE diff --git a/src/libc/compat/go64/upltinit32.S b/src/libc/compat/go64/upltinit32.S new file mode 100644 index 00000000..d48e968f --- /dev/null +++ b/src/libc/compat/go64/upltinit32.S @@ -0,0 +1,20 @@ +#include + + FUNC(_upltinit32) + ENTER + pushal + movl ARG1, %ebx +.irpc i,76543210 + pushl \i*4(%ebx) +.endr + movl %ebp, 8(%esp) // keep ebp untouched + popal + call uplt_init + pushf + pushal + movl ARG1, %ebx +.irpc i,012345678 + popl \i*4(%ebx) +.endr + popal + LEAVE diff --git a/src/libc/dj64/plt.S b/src/libc/dj64/plt.S index 0d386789..03ae6bae 100644 --- a/src/libc/dj64/plt.S +++ b/src/libc/dj64/plt.S @@ -28,6 +28,8 @@ PLT_OPEN_CMD = 0 PLT_CLOSE_CMD = 1 PLT_ELOAD_CMD = 4 PLT_ECLOSE_CMD = 5 +AUX_CORE = 0 +AUX_USER = 1 __plt_call: .quad 0 __plt_ctrl: .quad 0 .global __plt_handle @@ -78,12 +80,14 @@ err2_str: .asciz "dj64: missing payload\r\n$" .include "plt.inc" +.global uplt_init uplt_init: + pushl %ebx pushl __plt_handle pushl __plt_call + 4 pushl __plt_call - call *%fs:STUBINFO_UENTRY - addl $12, %esp + call *%eax + addl $16, %esp ret .global plt_init @@ -191,6 +195,8 @@ plt_init: movl %fs:STUBINFO_FLAGS, %ecx testw $0x4080, %cx jnz 111f + movl %fs:STUBINFO_UENTRY, %eax + movl $AUX_USER, %ebx call uplt_init 111: movl %fs:STUBINFO_SELF_SIZE, %ecx @@ -252,9 +258,11 @@ plt_init: movl %fs:STUBINFO_SELF_SIZE, %ecx movl %fs:STUBINFO_MEM_BASE, %edx movl %fs:STUBINFO_CPL_FD, %esi + pushl $AUX_USER pushl $DL_SET_SYMTAB call ctrl popl %eax + popl %eax jc 2f /* free mem */ movl $0x502, %eax @@ -287,21 +295,26 @@ plt_init: movl $0, %ecx movl %fs:STUBINFO_MEM_BASE, %edx movl %fs:STUBINFO_CPL_FD, %esi + pushl $AUX_USER pushl $DL_SET_SYMTAB call ctrl popl %eax + popl %eax jc 222f /* resolve upl */ movl %fs:STUBINFO_ELFLOAD_ARG, %eax movl %fs:STUBINFO_UPL_BASE, %ebx movl %fs:STUBINFO_UPL_SIZE, %ecx movl %fs:STUBINFO_MEM_BASE, %edx + pushl $AUX_USER pushl $DL_ELFLOAD call ctrl popl %ecx + popl %ecx // failure is not fatal, just no upl jc 555f - movl %eax, %fs:STUBINFO_UENTRY + // eax has uentry + movl $AUX_USER, %ebx call uplt_init 555: movl $1, elfload @@ -331,12 +344,15 @@ perr: movl $0, %ecx movl %fs:STUBINFO_MEM_BASE, %edx movl %fs:STUBINFO_CPL_FD, %esi + pushl $AUX_USER pushl $DL_SET_SYMTAB call ctrl popl %eax + popl %eax jc 2b jmp 11b +.global ctrl ctrl: pushl %ebp movl %esp, %ebp @@ -344,7 +360,7 @@ ctrl: movl %esp, %edx movl __plt_handle, %eax movl $0, %ebx - movb $AUX_USER, %bl + movb 12(%ebp), %bl movb $DL_API_VER, %bh movl 8(%ebp), %ecx movl %cs, %esi @@ -388,6 +404,12 @@ plt_done: lcalll *__plt_open ret +.global dj64_plt_call +dj64_plt_call: + movl $AUX_USER, %ebx + call_plt + ret + .bss .global _dosobj_page diff --git a/src/libc/dj64/plt.h b/src/libc/dj64/plt.h index 58a50e4b..1d749217 100644 --- a/src/libc/dj64/plt.h +++ b/src/libc/dj64/plt.h @@ -1,4 +1,5 @@ #define DL_SET_SYMTAB 0 #define DL_ELFLOAD 1 +#define DL_ELFLOAD_FD 2 #define DL_API_VER 1 diff --git a/src/libc/dj64/plt_defs.inc b/src/libc/dj64/plt_defs.inc index 526fc940..f6caf32e 100644 --- a/src/libc/dj64/plt_defs.inc +++ b/src/libc/dj64/plt_defs.inc @@ -1,16 +1,5 @@ -AUX_CORE = 0 -AUX_USER = 1 - .macro call_plt movl __plt_handle, %eax movl $0, %esi # reserved lcalll *__plt_call .endm - -.text - -.global dj64_plt_call -dj64_plt_call: - movl $AUX_USER, %ebx - call_plt - ret diff --git a/src/libc/dj64/thunks.c b/src/libc/dj64/thunks.c index d833fb8f..5c815ae5 100644 --- a/src/libc/dj64/thunks.c +++ b/src/libc/dj64/thunks.c @@ -276,8 +276,7 @@ static int dj64_ctrl(int handle, int libid, int fn, unsigned esi, uint8_t *sp) uint32_t addr = regs->ebx; uint32_t size = regs->ecx; uint32_t mem_base = regs->edx; - int32_t cpl_fd = (regs->esi == (uint32_t)-1 ? -1 : - dj64api->uget(regs->esi)); + int32_t cpl_fd = regs->esi; void *eh = NULL; int ret; @@ -314,7 +313,7 @@ static int dj64_ctrl(int handle, int libid, int fn, unsigned esi, uint8_t *sp) if (!have_core) { if (cpl_fd == -1) return -1; - eh = u->eops->open_dyn(cpl_fd); + eh = u->eops->open_dyn(handle, cpl_fd); if (!eh) return -1; ret = process_athunks(&u->core_at, mem_base, u->eops, eh); @@ -333,6 +332,7 @@ static int dj64_ctrl(int handle, int libid, int fn, unsigned esi, uint8_t *sp) break; } + case DL_ELFLOAD_FD: case DL_ELFLOAD: { __label__ err; struct udisp *u = &udisps[handle]; @@ -342,7 +342,12 @@ static int dj64_ctrl(int handle, int libid, int fn, unsigned esi, uint8_t *sp) void *eh = NULL; int ret; uint32_t esize, entry; - char *elf = dj64api->elfparse64(regs->eax, &esize); + char *elf; + + if (fn == DL_ELFLOAD) + elf = dj64api->elfparse64(regs->eax, &esize); + else + elf = u->eops->elfparse64_fd(handle, regs->eax, &esize); if (!elf) return -1; eh = u->eops->open(elf, esize); @@ -390,7 +395,6 @@ dj64cdispatch_t **DJ64_INIT_FN(int handle, const struct elf_ops *ops, memset(u->disp, 0, sizeof(u->disp)); u->disp[0] = dj64_thunk_call; u->disp[disp_id] = disp_fn; - disp_fn = NULL; u->eops = ops; u->main = main; u->full_init = full_init; @@ -399,13 +403,13 @@ dj64cdispatch_t **DJ64_INIT_FN(int handle, const struct elf_ops *ops, u->pt[0] = &u->core_pt; u->at[disp_id] = u_athunks; - u_athunks = NULL; - u->pt[disp_id] = u_pthunks; if (u_handle_p) *u_handle_p = handle; if (u_libid_p) *u_libid_p = disp_id; + disp_fn = NULL; + u_athunks = NULL; u_pthunks = NULL; u_handle_p = NULL; u_libid_p = NULL; @@ -421,6 +425,27 @@ dj64cdispatch_t **DJ64_INIT_FN(int handle, const struct elf_ops *ops, return dops; } +void DJ64_INIT2_FN(int handle, int disp_id) +{ + struct udisp *u; + + assert(handle < MAX_HANDLES); + assert(disp_id > 1 && disp_id < MAX_DISPS); + u = &udisps[handle]; + u->disp[disp_id] = disp_fn; + u->at[disp_id] = u_athunks; + u->pt[disp_id] = u_pthunks; + if (u_handle_p) + *u_handle_p = handle; + if (u_libid_p) + *u_libid_p = disp_id; + disp_fn = NULL; + u_athunks = NULL; + u_pthunks = NULL; + u_handle_p = NULL; + u_libid_p = NULL; +} + void DJ64_DONE_FN(int handle) { int i; @@ -709,9 +734,19 @@ void *djsbrk(int increment) return dj64api->malloc(increment); } -int elfload(int num) +int djelf_load(int num, int libid, int *r_fd) { - if (dj64api_ver < 15) + if (dj64api_ver < 19) + return -1; + return dj64api->elfload(num, dj64api->get_handle(), libid, r_fd); +} + +int djelf_run(int eid) +{ + struct udisp *u; + + if (dj64api_ver < 19) return -1; - return dj64api->elfload(num); + u = &udisps[dj64api->get_handle()]; + return u->eops->run64(eid); } diff --git a/src/libc/dj64/uplt.S b/src/libc/dj64/uplt.S index 1409202a..93aafe8e 100644 --- a/src/libc/dj64/uplt.S +++ b/src/libc/dj64/uplt.S @@ -3,6 +3,7 @@ .bss +AUX_USER: .long 0 __plt_call: .quad 0 __plt_handle: .long 0 @@ -15,5 +16,13 @@ _start: movl 8(%esp), %eax movl %eax, __plt_call + 4 movl 12(%esp), %eax - movl %eax, __plt_handle + movl %eax, __plt_handle + movl 16(%esp), %eax + movl %eax, AUX_USER + ret + +.global dj64_plt_call +dj64_plt_call: + movl AUX_USER, %ebx + call_plt ret