Skip to content

Commit

Permalink
started implementing go64 [closes #12]
Browse files Browse the repository at this point in the history
It can load elf files directly.
  • Loading branch information
stsp committed Oct 21, 2024
1 parent da9457b commit 640be87
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 0 deletions.
7 changes: 7 additions & 0 deletions include/go64.h
Original file line number Diff line number Diff line change
@@ -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
125 changes: 125 additions & 0 deletions src/libc/compat/go64/elfexec.c
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <sys/segments.h>
#include <io.h>
#include <dpmi.h>
#include <crt0.h>
#include <go64.h>

#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(&regs, 0, sizeof(regs));
regs.d.ebx = 3; // get version
pltcall32(&regs, 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(&regs, 0, sizeof(regs));
regs.d.ebx = 2; // exec
regs.x.di = shmi.handle & 0xffff;
regs.x.si = shmi.handle >> 16;
pltcall32(&regs, api);
__dpmi_free_shared_memory(shmi.handle);
return regs.d.eax;
}
7 changes: 7 additions & 0 deletions src/libc/compat/go64/makefile
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions src/libc/compat/go64/pltcall32.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <libc/asmdefs.h>

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

0 comments on commit 640be87

Please sign in to comment.