From 640be8786128f86140b7cb38f238c2d10eb35856 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sun, 20 Oct 2024 22:27:34 +0300 Subject: [PATCH] started implementing go64 [closes #12] It can load elf files directly. --- include/go64.h | 7 ++ src/libc/compat/go64/elfexec.c | 125 +++++++++++++++++++++++++++++++ src/libc/compat/go64/makefile | 7 ++ src/libc/compat/go64/pltcall32.S | 20 +++++ 4 files changed, 159 insertions(+) create mode 100644 include/go64.h create mode 100644 src/libc/compat/go64/elfexec.c create mode 100644 src/libc/compat/go64/makefile create mode 100644 src/libc/compat/go64/pltcall32.S diff --git a/include/go64.h b/include/go64.h new file mode 100644 index 00000000..bf4acc6b --- /dev/null +++ b/include/go64.h @@ -0,0 +1,7 @@ +#ifndef GO64_H +#define GO64_H + +void pltcall32(__dpmi_regs *regs, __dpmi_paddr addr); +int elfexec(const char *path, int argc, char **argv); + +#endif diff --git a/src/libc/compat/go64/elfexec.c b/src/libc/compat/go64/elfexec.c new file mode 100644 index 00000000..d24c154a --- /dev/null +++ b/src/libc/compat/go64/elfexec.c @@ -0,0 +1,125 @@ +/* + * dj64 - 64bit djgpp-compatible tool-chain + * Copyright (C) 2021-2024 @stsp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif +#define _PAGE_MASK (~(PAGE_SIZE-1)) +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&_PAGE_MASK) + +// https://github.com/vonj/snippets.org/blob/master/strrpbrk.c +static char *strrpbrk(const char *szString, const char *szChars) +{ + const char *p; + char *p0, *p1; + + for (p = szChars, p0 = p1 = NULL; p && *p; ++p) + { + p1 = strrchr(szString, *p); + if (p1 && p1 > p0) + p0 = p1; + } + return p0; +} + +int elfexec(const char *path, int argc, char **argv) +{ + int err, fd, len, errn; + const char *p; + unsigned fname; + __dpmi_paddr api; + __dpmi_shminfo shmi; + __dpmi_meminfo dm; + __dpmi_regs regs; + int en_dis = !(_crt0_startup_flags & _CRT0_FLAG_NEARPTR); + + err = __dpmi_get_vendor_specific_api_entry_point("DJ64", &api); + if (err) { + fprintf(stderr, "DJ64 support missing\n"); + return -1; + } + memset(®s, 0, sizeof(regs)); + regs.d.ebx = 3; // get version + pltcall32(®s, api); + if (regs.d.eax < 2) { + fprintf(stderr, "unsupported DJ64 version %i\n", regs.d.eax); + return -1; + } + fd = open(path, O_RDONLY | O_BINARY); + if (fd == -1) { + fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno)); + return -1; + } + len = filelength(fd); + p = strrpbrk(path, "/\\"); + if (!p) + p = path; + fname = malloc32(strlen(p) + 1); + strcpy(DATA_PTR(fname), p); + shmi.size_requested = len; + shmi.name_offset = fname; + shmi.name_selector = _my_ds(); + err = __dpmi_allocate_shared_memory(&shmi); + free32(fname); + if (err) { + close(fd); + fprintf(stderr, "Can't allocate shmem for %s\n", p); + return -1; + } + if (en_dis) + __djgpp_nearptr_enable(); + err = read(fd, djaddr2ptr(shmi.address), len); + errn = errno; + if (en_dis) + __djgpp_nearptr_disable(); + close(fd); + if (err == -1) { + fprintf(stderr, "error reading %s: %s\n", path, strerror(errn)); + return -1; + } + if (err != len) { + fprintf(stderr, "read returned %i, need %i\n", err, len); + return -1; + } + dm.handle = shmi.handle; + dm.address = shmi.address; + dm.size = shmi.size; + err = __dpmi_free_physical_address_mapping(&dm); + assert(!err); + memset(®s, 0, sizeof(regs)); + regs.d.ebx = 2; // exec + regs.x.di = shmi.handle & 0xffff; + regs.x.si = shmi.handle >> 16; + pltcall32(®s, api); + __dpmi_free_shared_memory(shmi.handle); + return regs.d.eax; +} diff --git a/src/libc/compat/go64/makefile b/src/libc/compat/go64/makefile new file mode 100644 index 00000000..e55859cc --- /dev/null +++ b/src/libc/compat/go64/makefile @@ -0,0 +1,7 @@ +# Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details +TOP=../.. + +AS_SRC += pltcall32.S +SRC += elfexec.c + +include $(TOP)/../makefile.inc diff --git a/src/libc/compat/go64/pltcall32.S b/src/libc/compat/go64/pltcall32.S new file mode 100644 index 00000000..059ba994 --- /dev/null +++ b/src/libc/compat/go64/pltcall32.S @@ -0,0 +1,20 @@ +#include + + FUNC(_pltcall32) + ENTER + pushal + movl ARG1, %ebx +.irpc i,76543210 + pushl \i*4(%ebx) +.endr + movl %ebp, 8(%esp) // keep ebp untouched + popal + movl __plt_handle, %eax + lcalll *ARG2 + pushal + movl ARG1, %ebx +.irpc i,01234567 + popl \i*4(%ebx) +.endr + popal + LEAVE