Plan 9 from Bell Labs’s /usr/web/sources/contrib/rminnich/bgp/machcnk.c

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


/*
 * elf2cnk
 * Copyright (C) 2008 Ronald G. Minnich
 *
 * derived from: 
 *
 * lar - lightweight archiver
 *
 * This includes code from previous versions of the LAR utility,
 * including create.c, list.c, extract.c and bootblock.c
 *
 * Copyright (C) 2006-2007 coresystems GmbH
 * (Written by Stefan Reinauer <[email protected]> for coresystems GmbH)
 * Copyright (C) 2007 Patrick Georgi <[email protected]>
 * Copyright (C) 2007 Advanced Micro Devices, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
 */

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <mach.h>
#include "elf.h"

int
verbose(void){
	return 1;
}
void errexit(char *s)
{
	fprint(2, smprint("%s\n", s));
	exits("life sucks");
}
void ssize(int fd, u32int va, u32int size)
{
	char *cmd;
	/* round size up to nearest MB */
	size += 0xfffff;
	size &= ~0xfffff;
	cmd = smprint("va %#x %#x", va, size);
	if (write(fd, cmd, strlen(cmd)) < 0)
		errexit("Setting size");
}

unsigned char *makeseg(char *name, u32int addr, u32int size, int markheap)
{
	char *segname = smprint("/n/cnk/%s", name);
	char *ctl = smprint("/n/cnk/%s/ctl", name);
	int ctlfd;
	unsigned char *ptr;

	remove(segname);

	if (create(segname, 0, DMDIR|0777)<0)
		errexit(segname);

	if ((ctlfd = open(ctl, ORDWR)) < 0) errexit(ctl);	
	ssize(ctlfd, addr, size);

	if (markheap) {
		if (write(ctlfd, "heap", 4) < 0)
			errexit("Setting heap");
	}

	ptr = segattach(0, name, (void *)addr,size);
	if (ptr == (unsigned char *)-1)
		errexit("segattach");
	memset(ptr, 0, size);
	return ptr;
}

/* aux vector structure. Can NOT be null.  */
typedef struct
{
  u32int a_type;              /* Entry type */
  union
    {
      u32int a_val;           /* Integer value */
      /* We use to have pointer elements added here.  We cannot do that,
         though, since it does not work when using 32-bit definitions
         on 64-bit platforms and vice versa.  */
    } a_un;
} Elf32_auxv_t;


/*
 *	All a.out header types.  The dummy entry allows canonical
 *	processing of the union as a sequence of longs
 */

typedef struct {
	union{
		Ehdr;			/* elf.h */
	} e;
	long dummy;			/* padding to ensure extra long */
} ExecHdr;

extern void *exechdr(void);
extern void *phdr(void);
/* we need an array of these. Cheese it out and just make 32 of them. 
 * they will start out empty (zero'd) and we'll just add what we need. 
 */
int auxc = 0;
Elf32_auxv_t aux[32];

void naux(int type, u32int val) 
{
	aux[auxc].a_type = type;
	aux[auxc].a_un.a_val = val;
	auxc++;
}

/*
 * Elf32 binaries.
 */
Phdr *
hdr(int fd)
{
	Ehdr *ep;
	Phdr *ph;
	int i;
	ep = exechdr();
	ph = phdr();
	fprint(2,"elf add %d entries at %p\n", ep->phnum, ph);
	for(i = 0; i < ep->phnum; i++)
		fprint(2,"%d: type %d va %p pa %p \n", i, ph[i].type, ph[i].vaddr, ph[i].paddr);
	/* GNU ELF is weird. GNUSTACK is the last phdr and it's confusing libmach. */
	naux(AT_PHNUM, ep->phnum-1);
	naux(AT_PHDR, (u32int)ph);

	return ph;
}

void
usage(void)
{
	errexit(smprint("usage: machcnk [-b] [breakpoint] [a]rgstosyscall [s]yscall [u]regsbefore [U]uregsafter [f]aultpower [F]aultpowerregs elf\n"));
}

main(int argc, char *argv[])
{
	char *ctlpath = "#P/cnk";
	void callcnk(void (*f)(int, char **), int, char **, char **);
	int fd, ctl;
	unsigned char  *textp, *datap, *bssp;
	void (*f)(int argc, char *argv[]);
	Fhdr fp;
	Map *map;
	int textseg, dataseg;
	int i;
	u32int breakpoint = 0;
	char *av[256];
	int cnk = 2;
	char cmd[2];

	ARGBEGIN{
	case 'b':	breakpoint = strtoul(EARGF(usage()), 0, 0); break;
	case 'f':	cnk |= 4; break;
	case 'F':	cnk |= 8; break;
	case 's':	cnk |= 16; break;
	case 'u':	cnk |= 32; break;
	case 'U':	cnk |= 64; break;
	case 'a':	cnk |= 128; break;
	default:	usage(); break;
	}ARGEND

	if (argc < 1)
		errexit("usage: elfcnk filename");

	fd = open(argv[0], OREAD);
	if (fd < 0)
		errexit(smprint("Can't open %s\n", argv[1]));

	if (crackhdr(fd, &fp) < 0)
		errexit("crackhdr failed");

	map = loadmap(nil, fd, &fp);

	if (! map)
		errexit("loadmap failed");

	textseg = findseg(map, "text");
	if (textseg < 0)
		errexit("no text segment");
	dataseg = findseg(map, "data");
	if (dataseg < 0)
		errexit("no data segment");

	naux(AT_DCACHEBSIZE, 0x20);
	naux(AT_PAGESZ, 0x1000);
	naux(AT_UID, 0x17be);
	naux(AT_EUID, 0x17be);
	naux(AT_GID, 0x64);
	naux(AT_EGID, 0x64);
	naux(AT_HWCAP, 0x4);
	hdr(fd); 


	fprint(2, "textseg is %d and dataseg is %d\n", textseg, dataseg);
	fprint(2, "base %#llx end %#llx off %#llx \n", map->seg[0].b, map->seg[0].e, map->seg[2].f);
	fprint(2, "base %#llx end %#llx off %#llx \n", map->seg[1].b, map->seg[1].e, map->seg[1].f);
	fprint(2, "txtaddr %#llx dataaddr %#llx entry %#llx txtsz %#lx datasz %#lx bsssz %#lx\n", 
		fp.txtaddr, fp.dataddr, fp.entry, fp.txtsz, fp.datsz, fp.bsssz);
	if (dirstat("/n/cnk") == nil)
	if (create("/n/cnk", 0, DMDIR|0777)<0)
		errexit("/n/cnk");

	/* let's make us some seggies */
	if (bind("#g", "/n/cnk", MREPL|MCREATE) < 0)
		errexit("bind segdriver");

	textp = makeseg("0", fp.txtaddr, fp.txtsz, 0);
	datap = makeseg("1", fp.dataddr, fp.datsz + fp.bsssz, 0);
	bssp = makeseg("3",512*1024*1024, 0x1000, 1);
	print("bssp is %p\n", bssp);

	/* now the big fun. Just copy it out */
	pread(fd, textp, fp.txtsz, fp.txtoff);
	pread(fd, datap, fp.datsz, fp.datoff);
	/*
	hangpath = smprint("/proc/%d/ctl", getpid());

	fprint(2, "Open %s\n", hangpath);
	hang = open(hangpath, OWRITE);
	if (hang < 0){
		errexit(smprint("%s: %r", hangpath));
	}
	if (write(hang, "hang", 4) < 4){
		errexit(smprint("write cnk: %r"));
	}

	*/

	/* gnu is odd. they start out knowing args are on stack (sort of) */
	/* av is going to become the start of the stack. */
	/* this is where argc goes. */
	av[0] = (char *)argc;
	for(i = 0; i < argc; i++)
		av[i+1] = argv[i];
	i++;
	av[i++] = nil;
	av[i++] = "LANG=C";
	av[i++] = nil;
	/* now just copy the aux array over av */
	memcpy(&av[i], aux, sizeof(aux));
	fprint(2, "env %p *env %p\n", &av[argc+2], av[argc+2]);
	/* set the breakpoint */
	if (breakpoint){
		*(u32int *)breakpoint = 0;
		fprint(2, "Breakpoint set at %#x\n", breakpoint);
	}
	fprint(2, "Open %s\n", ctlpath);
	ctl = open(ctlpath, OWRITE);
	if (ctl < 0){
		errexit(smprint("%s: %r", ctlpath));
	}
	sprint(cmd, "%1x", cnk);
	fprint(2, "write cnk cmd (%s)\n", cmd);	
	if (write(ctl, cmd, 1) < 1){
		errexit(smprint("write cnk: %r"));
	}

//	callcnk(f, argc, argv);

	f = (void *)fp.entry;
	callcnk(f, argc, &av[1], av);
	return 0;

}
/* qc -wF machcnk.c; ql -o machcnk machcnk.q */
/* 8c -wF  machcnk.c; 8l -o machcnk machcnk.8 */

/* fcp q.out /mnt/term/tmp/machcnk */

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].