154 lines · 2.8 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * qobj.c - identify and parse a PowerPC object file *	forsyth@terzarima.net */#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#include "qc/q.out.h"#include "obj.h" typedef struct Addr	Addr;struct Addr{	char	type;	char	sym;	char	name;};static Addr addr(Biobuf*);static char type2char(int);static void skip(Biobuf*, int); int_isq(char *s){	return  (s[0]&0377) == ANAME			/* ANAME */		&& (s[1]&0377) == ANAME>>8		&& s[2] == D_FILE			/* type */		&& s[3] == 1				/* sym */		&& s[4] == '<';				/* name of file */} int_readq(Biobuf *bp, Prog *p){	int as, n, c;	Addr a; 	as = Bgetc(bp);			/* as(low) */	if(as < 0)		return 0;	c = Bgetc(bp);		/* as(high) */	if(c < 0)		return 0;	as |= ((c & 0xff) << 8);	p->kind = aNone;	p->sig = 0;	if(as == ANAME || as == ASIGNAME){		if(as == ASIGNAME){			Bread(bp, &p->sig, 4);			p->sig = beswal(p->sig);		}		p->kind = aName;		p->type = type2char(Bgetc(bp));		/* type */		p->sym = Bgetc(bp);			/* sym */		n = 0;		for(;;) {			as = Bgetc(bp);			if(as < 0)				return 0;			n++;			if(as == 0)				break;		}		p->id = malloc(n);		if(p->id == 0)			return 0;		Bseek(bp, -n, 1);		if(Bread(bp, p->id, n) != n)			return 0;		return 1;	}	if(as == ATEXT)		p->kind = aText;	else if(as == AGLOBL)		p->kind = aData;	n = Bgetc(bp);	/* reg and flag */	skip(bp, 4);		/* lineno(4) */	a = addr(bp);	if(n & 0x40)		addr(bp);	addr(bp);	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)		p->kind = aNone;	p->sym = a.sym;	return 1;} static Addraddr(Biobuf *bp){	Addr a;	long off; 	a.type = Bgetc(bp);	/* a.type */	skip(bp,1);		/* reg */	a.sym = Bgetc(bp);	/* sym index */	a.name = Bgetc(bp);	/* sym type */	switch(a.type){	default:	case D_NONE: case D_REG: case D_FREG: case D_CREG:	case D_FPSCR: case D_MSR: case D_SREG:		break;	case D_SPR:	case D_OREG:	case D_DCR:	case D_CONST:	case D_BRANCH:		off = Bgetc(bp);		off |= Bgetc(bp) << 8;		off |= Bgetc(bp) << 16;		off |= Bgetc(bp) << 24;		if(off < 0)			off = -off;		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))			_offset(a.sym, off);		break;	case D_SCONST:		skip(bp, NSNAME);		break;	case D_FCONST:		skip(bp, 8);		break;	}	return a;} static chartype2char(int t){	switch(t){	case D_EXTERN:		return 'U';	case D_STATIC:		return 'b';	case D_AUTO:		return 'a';	case D_PARAM:		return 'p';	default:		return UNKNOWN;	}} static voidskip(Biobuf *bp, int n){	while (n-- > 0)		Bgetc(bp);}