Plan 9 from Bell Labs’s /usr/web/sources/contrib/rsc/linuxemu/linuxemu.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <ureg.h>
#include "linux.h"
#include "linuxsys.h"

typedef struct Ureg Ureg;

static void	maincall(ulong, ulong, char**, ulong);
static int	linuxnote(void*, char*);
void*	mmap(char*);
void*	mmapfd(int);

void	*bss;
int	debug;

void
usage(void)
{
	fprint(2, "usage: %s [-d] linuxprog args...\n", argv0);
	exits("usage");
}

void
main(int argc, char **argv)
{
	long entry = 0;
	void *file;

	ARGBEGIN{
	case 'd':
		debug = 1;
		break;
	default:
		usage();
	}ARGEND

	if(argc < 1)
		usage();

	if((file = mmap(argv[0])) == nil) {
		fprint(2, "mmap failed: %r\n");
		exits("mmap");
	}

	if(memcmp(file, "\x7fELF", 4) == 0)
		entry = elfload(file);
	else {
		fprint(2, "cannot identify binary\n");
		exits("binary type");
	}

	if(entry <= 0) {
		fprint(2, "error loading binary\n");
		exits("binary load");
	}

	DPRINT("entry=%lux\n", entry);
	maincall(entry, argc, argv, 0);
	abort();	// not reached
}

/*
 * set up the argument stack 
 * for linux and do the jmp.
 * this should not return, since 
 * what we're jumping to is supposed
 * to call exit.
 *
 * we use jumpstack, provided by stack.s
 *
 * it expects 
 *
 *	| envp
 *	| 
 *	|----
 *	| 
 *	| argv
 *	|
 *	|----
 *	| argc
 *	|---- ← sp
 *
 */
static void
maincall(ulong entry, ulong argc, char **argv, ulong depth)
{
	ulong buf[1024/4], *p;
	int i, n;

	/* BUG do environment */
	n = 8;	// padding
	n += (argc+1)*4;	// argv
	n += 4;	// argc

	/*
	 * here's a kludge: we need some room on the
	 * stack.  rather than try to assemble "SP -= n",
	 * since that will confuse the compiler, we just
	 * call ourselves lots of times to bring the stack
	 * depth down to what we want, giving us enough
	 * room.  we have no intention of returning.
	 */
	depth++;
	if(depth * sizeof buf < n)
		maincall(entry, argc, argv, depth);

	/* install ``syscall'' handler */
	atnotify(linuxnote, 1);

	p = (ulong*) buf;

	*p++ = argc;

	for(i=0; i<argc; i++)
		*p++ = (ulong) argv[i];
	*p++ = 0;

	*p++ = 0;
	*p = 0;
	
	jumpstack(entry, buf);
	abort();	// not reached.
}

static int
linuxnote(void *v, char *msg)
{
	ulong n;
	uchar *x;
	Syscall f;
	Ureg *ureg;

	ureg = v;
	if(strstr(msg, "general protection") == nil)
		return 0;

	x = (uchar*) ureg->pc;
	if(x[0] != 0xCD || x[1] != 0x80)	/* INT $0x80 */
		return 0;

	n = ureg->ax;
	DPRINT("SYSCALL %d\n", n);
	if(n >= LMAXSYSCALL || (f=syscalltab[ureg->ax]) == 0) {
		print("wants unimplemented function %lux (%s) pc=%lux\n", n, 
			n < LMAXSYSCALL ? syscallname[n] : "(?)", ureg->pc);
		ureg->ax = -1;
	} else {
		(*f)(ureg);
		DPRINT("returns %lud=0x%lux...\n", ureg->ax, ureg->ax);
	}
	ureg->pc += 2;
	return 1;
}

/*
 * mmap, if it were handled by the kernel
 *
void*
_mmap(char *name)
{
	void *v;
	Dir *d;
	char *buf;
	vlong len;

	if((d = dirstat(name)) == nil || d->length == 0){
		free(d);
		return nil;
	}
	len = d->length;
	free(d);
	buf = malloc(strlen(name)+10);
	if(buf == nil)
		return nil;

	sprint(buf, "file!%s", name);
	v = (void*)segattach(0, buf, nil, len);
	print("v=%lx file=%s len=%ld\n", v, name, len);
	free(buf);
	if(v == (void*)-1)
		return nil;
	return v;
}

void*
_mmapfd(int fd)
{
	void *v;
	Dir d;
	char buf[30];

	if(dirfstat(fd, &d) < 0 || d.length == 0)
		return nil;
	snprint(buf, sizeof buf, "file!/fd/%d", fd);
	v = (void*)segattach(0, buf, nil, 4096);
	if(v == (void*)-1)
		return nil;
	return v;
}
*/

/*
 * crummy mmap.  should be handled by kernel.
 */
void*
mmap(char *name)
{
	void *v;
	int fd;

	if((fd = open(name, OREAD)) < 0)
		return nil;

	v = mmapfd(fd);
	close(fd);
	return v;
}

void*
mmapfd(int fd)
{
	void *v;
	Dir *d;
	vlong len;

	if((d = dirfstat(fd)) == nil)
		return nil;
	len = d->length;
	free(d);
	if(len == 0)
		return nil;
	v = malloc(len);
	if(v == nil)
		return nil;

	if(readn(fd, v, len) != len) {
		free(v);
		return nil;
	}
	return v;
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].