Example #1
0
int32_t
pcollgnextoff(int32_t fromoff)
{
	int c, state = 0, defoff = -1;

	if(Bseek(bdict, fromoff, 0) < 0)
		return -1;
	while((c = Bgetc(bdict)) >= 0){
		if(c == '\r')
			defoff = Boffset(bdict);
		switch(state){
		case 0:
			if(c == 0x05)
				state = 1;
			break;
		case 1:
			if(c == 'h')
				state = 2;
			else
				state = 0;
			break;
		case 2:
			if(c == 0x06)
				return (Boffset(bdict)-3);
			else
				state = 0;
			break;
		}
	}
	return defoff;
}
Example #2
0
void
join(int seekf)
{
	int cmp, less;
	int n[NIN];
	int64_t top, bot;

	less = seekf == F2;
	top = 0;
	bot = Boffset(f[seekf]);
	readboth(n);
	while((n[F1]>0 && n[F2]>0) || ((a1||a2) && n[F1]+n[F2]>0)) {
		cmp = comp();
		if((n[F1]>0 && n[F2]>0 && cmp>0) || n[F1]==0) {
			if(a2)
				output(0, n[F2]);
			if (seekf == F2)
				bot = Boffset(f[seekf]);
			n[F2] = input(F2);
		} else if((n[F1]>0 && n[F2]>0 && cmp<0) || n[F2]==0) {
			if(a1)
				output(n[F1], 0);
			if (seekf == F1)
				bot = Boffset(f[seekf]);
			n[F1] = input(F1);
		} else {
			/* n[F1]>0 && n[F2]>0 && cmp==0 */
			while(n[F2]>0 && cmp==0) {
				output(n[F1], n[F2]);
				top = Boffset(f[seekf]);
				n[seekf] = input(seekf);
				cmp = comp();
			}
			seekbotreadboth(seekf, bot, n);
			for(;;) {
				cmp = comp();
				if(n[F1]>0 && n[F2]>0 && cmp==0) {
					output(n[F1], n[F2]);
					n[seekf] = input(seekf);
				} else if((n[F1]>0 && n[F2]>0 &&
				    (less? cmp<0 :cmp>0)) || n[seekf]==0)
					seekbotreadboth(seekf, bot, n);
				else {
					/*
					 * n[F1]>0 && n[F2]>0 &&
					 * (less? cmp>0 :cmp<0) ||
					 * n[seekf==F1? F2: F1]==0
					 */
					Bseek(f[seekf], top, 0);
					bot = top;
					n[seekf] = input(seekf);
					break;
				}
			}
		}
	}
}
Example #3
0
vlong
Bseek(Biobufhdr *bp, vlong offset, int base)
{
	vlong n, d;

	switch(bp->state) {
	default:
		fprint(2, "Bseek: unknown state %d\n", bp->state);
		return Beof;

	case Bracteof:
		bp->state = Bractive;
		bp->icount = 0;
		bp->gbuf = bp->ebuf;

	case Bractive:
		n = offset;
		if(base == 1) {
			n += Boffset(bp);
			base = 0;
		}

		/*
		 * try to seek within buffer
		 */
		if(base == 0) {
			/*
			 * if d is too large for an int, icount may wrap,
			 * so we need to ensure that icount hasn't wrapped
			 * and points within the buffer's valid data.
			 */
			d = n - Boffset(bp);
			bp->icount += d;
			if(d <= bp->bsize && bp->icount <= 0 &&
			    bp->ebuf - bp->gbuf >= -bp->icount)
				return n;
		}

		/*
		 * reset the buffer
		 */
		n = seek(bp->fid, n, base);
		bp->icount = 0;
		bp->gbuf = bp->ebuf;
		break;

	case Bwactive:
		Bflush(bp);
		n = seek(bp->fid, offset, base);
		break;
	}
	bp->offset = n;
	return n;
}
Example #4
0
/*
 * CD image buffering routines.
 */
void
Cputc(Cdimg *cd, int c)
{
	assert(Boffset(&cd->bwr) >= 16*Blocksize || c == 0);

if(Boffset(&cd->bwr) == 0x9962)
if(c >= 256) abort();
	if(Bputc(&cd->bwr, c) < 0)
		sysfatal("Bputc: %r");
	Bflush(&cd->brd);
}
Example #5
0
File: bseek.c Project: 8l/inferno
long
Bseek(Biobuf *bp, long offset, int base)
{
	long n, d;

	switch(bp->state) {
	default:
		fprint(2, "Bseek: unknown state %d\n", bp->state);
		return Beof;

	case Bracteof:
		bp->state = Bractive;
		bp->icount = 0;
		bp->gbuf = bp->ebuf;

	case Bractive:
		n = offset;
		if(base == 1) {
			n += Boffset(bp);
			base = 0;
		}

		/*
		 * try to seek within buffer
		 */
		if(base == 0) {
			d = n - Boffset(bp);
			bp->icount += d;
			if(d >= 0) {
				if(bp->icount <= 0)
					return n;
			} else {
				if(bp->ebuf - bp->gbuf >= -bp->icount)
					return n;
			}
		}

		/*
		 * reset the buffer
		 */
		n = seek(bp->fid, n, base);
		bp->icount = 0;
		bp->gbuf = bp->ebuf;
		break;

	case Bwactive:
		Bflush(bp);
		n = seek(bp->fid, offset, base);
		break;
	}
	bp->offset = n;
	return n;
}
Example #6
0
static
int
marker(Header *h)
{
	int c;

	while((c=readbyte(h)) == 0)
		fprint(2, "ReadJPG: skipping zero byte at offset %lld\n", Boffset(h->fd));
	if(c != 0xFF)
		jpgerror(h, "ReadJPG: expecting marker; found 0x%x at offset %lld\n", c, Boffset(h->fd));
	while(c == 0xFF)
		c = readbyte(h);
	return c;
}
Example #7
0
File: pgw.c Project: aberg001/plan9
/*
 * Return offset into bdict where next webster entry after fromoff starts.
 * Webster entries start with <p><hw>
 */
long
pgwnextoff(long fromoff)
{
    long a, n;
    int c;

    a = Bseek(bdict, fromoff, 0);
    if(a != fromoff)
        return -1;
    n = 0;
    for(;;) {
        c = Bgetc(bdict);
        if(c < 0)
            break;
        if(c == '<' && Bgetc(bdict) == 'p' && Bgetc(bdict) == '>') {
            c = Bgetc(bdict);
            if(c == '<') {
                if (Bgetc(bdict) == 'h' && Bgetc(bdict) == 'w'
                        && Bgetc(bdict) == '>')
                    n = 7;
            } else if (c == '{')
                n = 4;
            if(n)
                break;
        }
    }
    return (Boffset(bdict)-n);
}
Example #8
0
File: ar.c Project: CoryXie/nix-os
/*
 *	read the header for the next archive member
 */
Armember *
getdir(Biobuf *b)
{
	Armember *bp;
	char *cp;
	static char name[ARNAMESIZE+1];

	bp = newmember();
	if(HEADER_IO(Bread, b, bp->hdr)) {
		free(bp);
		return 0;
	}
	if(strncmp(bp->hdr.fmag, ARFMAG, sizeof(bp->hdr.fmag)) != 0)
		phaseerr(Boffset(b));
	strncpy(name, bp->hdr.name, sizeof(bp->hdr.name));
	cp = name+sizeof(name)-1;
	*cp = '\0';
	/* skip trailing spaces and (gnu-produced) slashes */
	while(*--cp == ' ' || *cp == '/')
		;
	cp[1] = '\0';
	file = name;
	bp->date = strtol(bp->hdr.date, 0, 0);
	bp->size = strtol(bp->hdr.size, 0, 0);
	return bp;
}
Example #9
0
File: unzip.c Project: aahud/harvey
static int
header(Biobuf *bin, ZipHead *zh)
{
	uint32_t v;
	int flen, xlen;

	v = get4(bin);
	if(v != ZHeader){
		if(v == ZCHeader)
			return 0;
		error("bad magic number %lx at %lld", v, Boffset(bin)-4);
	}
	zh->extvers = get1(bin);
	zh->extos = get1(bin);
	zh->flags = get2(bin);
	zh->meth = get2(bin);
	zh->modtime = get2(bin);
	zh->moddate = get2(bin);
	zh->crc = get4(bin);
	zh->csize = get4(bin);
	zh->uncsize = get4(bin);
	flen = get2(bin);
	xlen = get2(bin);

	zh->file = getname(bin, flen);

	while(xlen-- > 0)
		get1(bin);

	return 1;
}
Example #10
0
static void
doar(Biobuf *bp, char *file)
{
	int offset, size, obj;
	char membername[SARNAME];
	char symname[]="__.SYMDEF";	/* table of contents file name */

	for (offset = Boffset(bp);;offset += size) {
		size = nextar(bp, offset, membername);
		if (size < 0) {
			fprint(2, "%s: phase error on ar header %ld",
				file, offset);
			return;
		}
		if (size == 0)
			return;
		if (strcmp(membername, symname) == 0)
			continue;
		obj = objtype(bp, 0);
		if (obj < 0) {
			fprint(2, "%s: %s inconsistent file",
				file, membername);
			return;
		}
		if (!readar(bp, obj, offset+size, 1)) {
			fprint(2, "%s: %s invalid symbol reference in file",
					file, membername);
			return;
		}
		objtraverse(addfunc, 0);
	}
}
Example #11
0
File: nm.c Project: rminnich/harvey
/*
 * read an archive file,
 * processing the symbols for each intermediate file in it.
 */
void
doar(Biobuf *bp)
{
	int offset, size, obj;
	char membername[SARNAME];

	multifile = 1;
	for (offset = Boffset(bp);;offset += size) {
		size = nextar(bp, offset, membername);
		if (size < 0) {
			error("phase error on ar header %ld", offset);
			return;
		}
		if (size == 0)
			return;
		if (strcmp(membername, symname) == 0)
			continue;
		obj = objtype(bp, 0);
		if (obj < 0) {
			error("inconsistent file %s in %s",
					membername, filename);
			return;
		}
		if (!readar(bp, obj, offset+size, 1)) {
			error("invalid symbol reference in file %s",
					membername);
			return;
		}
		filename = membername;
		nsym=0;
		objtraverse(psym, 0);
		printsyms(symptr, nsym);
	}
}
Example #12
0
void
Cwrite(Cdimg *cd, void *buf, int n)
{
	assert(Boffset(&cd->bwr) >= 16*Blocksize);

	if(Bwrite(&cd->bwr, buf, n) != n)
		sysfatal("Bwrite: %r");
	Bflush(&cd->brd);
}
Example #13
0
void
stringit(char *str)
{
	long posn, start;
	int cnt = 0;
	long c;

	Rune buf[BUFSIZE];

	if ((fin = Bopen(str, OREAD)) == 0) {
		perror("open");
		return;
	}

	start = 0;
	posn = Boffset(fin);
	while((c = Bgetrune(fin)) >= 0) {
		if(isprint(c)) {
			if(start == 0)
				start = posn;
			buf[cnt++] = c;
			if(cnt == BUFSIZE-1) {
				buf[cnt] = 0;
				Bprint(&fout, "%8ld: %S ...\n", start, buf);
				start = 0;
				cnt = 0;
			}
		} else {
			 if(cnt >= minspan) {
				buf[cnt] = 0;
				Bprint(&fout, "%8ld: %S\n", start, buf);
			}
			start = 0;
			cnt = 0;
		}	
		posn = Boffset(fin);
	}

	if(cnt >= minspan){
		buf[cnt] = 0;
		Bprint(&fout, "%8ld: %S\n", start, buf);
	}
	Bterm(fin);
}
Example #14
0
int
locate(void)
{
	vlong top, bot, mid;
	long c;
	int n;

	bot = 0;
	top = Bseek(dfile, 0, 2);
	for(;;) {
		mid = (top+bot) / 2;
		Bseek(dfile, mid, 0);
		do
			c = Bgetrune(dfile);
		while(c>=0 && c!='\n');
		mid = Boffset(dfile);
		if(!getword(dfile, entry, sizeof(entry)/sizeof(entry[0])))
			break;
		rcanon(entry, word);
		n = compare(key, word);
		switch(n) {
		case -2:
		case -1:
		case 0:
			if(top <= mid)
				break;
			top = mid;
			continue;
		case 1:
		case 2:
			bot = mid;
			continue;
		}
		break;
	}
	Bseek(dfile, bot, 0);
	while(getword(dfile, entry, sizeof(entry)/sizeof(entry[0]))) {
		rcanon(entry, word);
		n = compare(key, word);
		switch(n) {
		case -2:
			return 0;
		case -1:
			if(exact)
				return 0;
		case 0:
			return 1;
		case 1:
		case 2:
			continue;
		}
	}
	return 0;
}
Example #15
0
Link_Data::Link_Data (int link) : Class_Index (link)
{
	Anode (0);
	Bnode (0);
	Length (0);
	Aoffset (0);
	Boffset (0);
	Use (0);
	Type (0);
	AB_Dir (0);
	BA_Dir (0);
	Shape (0);
}
Example #16
0
void
thumbpctab(Biobuf *b, Fhdr *fp)
{
	int n, o, ta;
	uchar c[8];
	pcentry *tab;

	Bseek(b, fp->lnpcoff+fp->lnpcsz, 0);
	o = (int)Boffset(b);
	Bseek(b, 0, 2);
	n = (int)Boffset(b)-o;
	pctab = (pcentry*)malloc(n);
	if(pctab == 0)
		return;
	ta = fp->txtaddr;
	tab = pctab;
	Bseek(b, fp->lnpcoff+fp->lnpcsz, 0);
	while(Bread(b, c, sizeof(c)) == sizeof(c)){
		tab->start = ta + (c[0]<<24)|(c[1]<<16)|(c[2]<<8)|c[3];
		tab->stop = ta + (c[4]<<24)|(c[5]<<16)|(c[6]<<8)|c[7];
		tab++;
	}
	npctab = n/sizeof(c);
}
Example #17
0
File: unzip.c Project: aahud/harvey
/*
 * extract files using the info in the central directory structure
 */
static int
unzip(Biobuf *bin, char *file)
{
	ZipHead zh;
	int64_t off;
	int ok, eok, entries;

	entries = findCDir(bin, file);
	if(entries < 0)
		return 0;

	ok = 1;
	while(entries-- > 0){
		if(setjmp(zjmp)){
			free(zh.file);
			return 0;
		}
		memset(&zh, 0, sizeof(zh));
		if(!cheader(bin, &zh))
			return ok;


		off = Boffset(bin);
		if(wantFile(zh.file)){
			if(Bseek(bin, zh.off, 0) < 0){
				fprint(2, "unzip: can't seek to start of %s, skipping\n", zh.file);
				ok = 0;
			}else{
				eok = unzipEntry(bin, &zh);
				if(eok <= 0){
					fprint(2, "unzip: skipping %s\n", zh.file);
					ok = 0;
				}
			}
		}

		free(zh.file);
		zh.file = nil;

		if(Bseek(bin, off, 0) < 0){
			fprint(2, "unzip: can't seek to start of next entry, terminating extraction\n");
			return 0;
		}
	}

	return ok;
}
Example #18
0
static int
gunzip(int ofd, char *ofile, Biobuf *bin)
{
	Dir *d;
	GZHead h;
	int err;

	h.file = nil;
	gzok = 0;
	for(;;){
		if(Bgetc(bin) < 0)
			return 1;
		Bungetc(bin);

		if(setjmp(zjmp))
			return 0;
		header(bin, &h);
		gzok = 0;

		wlen = 0;
		crc = 0;

		if(!table && verbose)
			fprint(2, "extracting %s to %s\n", h.file, ofile);

		err = inflate((void*)ofd, crcwrite, bin, (int(*)(void*))Bgetc);
		if(err != FlateOk)
			error("inflate failed: %s", flateerr(err));

		trailer(bin, wlen);

		if(table){
			if(verbose)
				print("%-32s %10ld %s", h.file, wlen, ctime(h.mtime));
			else
				print("%s\n", h.file);
		}else if(settimes && h.mtime && (d=dirfstat(ofd)) != nil){
			d->mtime = h.mtime;
			dirfwstat(ofd, d);
			free(d);
		}

		free(h.file);
		h.file = nil;
		gzok = Boffset(bin);
	}
}
Example #19
0
long
pcollnextoff(long fromoff)
{
	long a;
	char *p;

	a = Bseek(bdict, fromoff, 0);
	if(a < 0)
		return -1;
	for(;;) {
		p = Brdline(bdict, '\n');
		if(!p)
			break;
		if(p[0] == '>' && p[1] == 'H' && p[2] == '<')
			return (Boffset(bdict)-Blinelen(bdict));
	}
	return -1;
}
Example #20
0
void
rl(int fd)
{

    Biobuf b;
    char *cp;
    struct ar_hdr a;
    long len;

    Binit(&b, fd, OWRITE);
    Bseek(&b,seek(fd,0,1), 0);

    len = symdefsize;
    if(len&01)
        len++;
    sprint(a.date, "%-12ld", time(0));
    sprint(a.uid, "%-6d", 0);
    sprint(a.gid, "%-6d", 0);
    sprint(a.mode, "%-8o", 0644);
    sprint(a.size, "%-10ld", len);
    strncpy(a.fmag, ARFMAG, 2);
    strcpy(a.name, symdef);
    for (cp = strchr(a.name, 0);		/* blank pad on right */
            cp < a.name+sizeof(a.name); cp++)
        *cp = ' ';
    if(HEADER_IO(Bwrite, &b, a))
        wrerr();

    len += Boffset(&b);
    if (astart) {
        wrsym(&b, len, astart->sym);
        len += astart->size;
    }
    if(amiddle) {
        wrsym(&b, len, amiddle->sym);
        len += amiddle->size;
    }
    if(aend)
        wrsym(&b, len, aend->sym);

    if(symdefsize&0x01)
        Bputc(&b, 0);
    Bterm(&b);
}
Example #21
0
void
ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64 len, char *pn, char *file)
{
	int i, isinternal;
	Hostobj *h;

	isinternal = 0;
	for(i=0; i<nelem(internalpkg); i++) {
		if(strcmp(pkg, internalpkg[i]) == 0) {
			isinternal = 1;
			break;
		}
	}

	// DragonFly declares errno with __thread, which results in a symbol
	// type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not
	// currently know how to handle TLS relocations, hence we have to
	// force external linking for any libraries that link in code that
	// uses errno. This can be removed if the Go linker ever supports
	// these relocation types.
	if(HEADTYPE == Hdragonfly)
	if(strcmp(pkg, "net") == 0 || strcmp(pkg, "os/user") == 0)
		isinternal = 0;

	if(!isinternal)
		externalobj = 1;

	if(nhostobj >= mhostobj) {
		if(mhostobj == 0)
			mhostobj = 16;
		else
			mhostobj *= 2;
		hostobj = erealloc(hostobj, mhostobj*sizeof hostobj[0]);
	}
	h = &hostobj[nhostobj++];
	h->ld = ld;
	h->pkg = estrdup(pkg);
	h->pn = estrdup(pn);
	h->file = estrdup(file);
	h->off = Boffset(f);
	h->len = len;
}
Example #22
0
/*
 *	extract the symbol references from an object file
 */
void
scanobj(Biobuf *b, Arfile *ap, int size)
{
    int obj;
    long offset;
    Dir *d;
    static int lastobj = -1;

    if (!allobj)			/* non-object file encountered */
        return;
    offset = Boffset(b);
    obj = objtype(b, 0);
    if (obj < 0) {			/* not an object file */
        allobj = 0;
        d = dirfstat(Bfildes(b));
        if (d != nil && d->length == 0)
            fprint(2, "ar: zero length file %s\n", file);
        free(d);
        Bseek(b, offset, 0);
        return;
    }
    if (lastobj >= 0 && obj != lastobj) {
        fprint(2, "ar: inconsistent object file %s\n", file);
        allobj = 0;
        Bseek(b, offset, 0);
        return;
    }
    lastobj = obj;
    if (!readar(b, obj, offset+size, 0)) {
        fprint(2, "ar: invalid symbol reference in file %s\n", file);
        allobj = 0;
        Bseek(b, offset, 0);
        return;
    }
    Bseek(b, offset, 0);
    objtraverse(objsym, ap);
}
Example #23
0
/*
 *	read the header for the next archive member
 */
Armember *
getdir(Biobuf *b)
{
    Armember *bp;
    char *cp;
    static char name[ARNAMESIZE+1];

    bp = newmember();
    if(HEADER_IO(Bread, b, bp->hdr)) {
        free(bp);
        return 0;
    }
    if(strncmp(bp->hdr.fmag, ARFMAG, sizeof(bp->hdr.fmag)))
        phaseerr(Boffset(b));
    strncpy(name, bp->hdr.name, sizeof(bp->hdr.name));
    cp = name+sizeof(name)-1;
    while(*--cp==' ')
        ;
    cp[1] = '\0';
    file = name;
    bp->date = atol(bp->hdr.date);
    bp->size = atol(bp->hdr.size);
    return bp;
}
Example #24
0
ulong
writeBlock(uchar *b, int type)
{
	uchar *cb, *ob;
	int n;
	PaqBlock bh;
	uchar buf[BlockSize];
	ulong offset;

	offset = Boffset(out);

	bh.magic = BlockMagic;
	bh.size = blocksize;	
	bh.type = type;
	bh.encoding = NoEnc;
	bh.adler32 = adler32(0, b, blocksize);
	ob = b;

	if(!uflag) {
		cb = emallocz(blocksize);
		n = deflateblock(cb, blocksize, b, blocksize, 6, 0);
		if(n > 0 && n < blocksize) {
			bh.encoding = DeflateEnc;
			bh.size = n;
			ob = cb;
		}	
	}

	putBlock(buf, &bh);
	outWrite(buf, sizeof(buf));
	outWrite(ob, bh.size);
	
	if(ob != b)
		free(ob);
	return offset;
}
Example #25
0
File: ps.c Project: 00001/plan9port
Document*
initps(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
{
	Document *d;
	PSInfo *ps;
	char *p;
	char *q, *r;
	char eol;
	char *nargv[1];
	char fdbuf[20];
	char tmp[32];
	int fd;
	int i;
	int incomments;
	int cantranslate;
	int trailer=0;
	int nesting=0;
	int dumb=0;
	int landscape=0;
	long psoff;
	long npage, mpage;
	Page *page;
	Rectangle bbox = Rect(0,0,0,0);

	if(argc > 1) {
		fprint(2, "can only view one ps file at a time\n");
		return nil;
	}

	fprint(2, "reading through postscript...\n");
	if(b == nil){	/* standard input; spool to disk (ouch) */
		fd = spooltodisk(buf, nbuf, nil);
		sprint(fdbuf, "/dev/fd/%d", fd);
		b = Bopen(fdbuf, OREAD);
		if(b == nil){
			fprint(2, "cannot open disk spool file\n");
			wexits("Bopen temp");
		}
		nargv[0] = fdbuf;
		argv = nargv;
	}

	/* find %!, perhaps after PCL nonsense */
	Bseek(b, 0, 0);
	psoff = 0;
	eol = 0;
	for(i=0; i<16; i++){
		psoff = Boffset(b);
		if(!(p = Brdline(b, eol='\n')) && !(p = Brdline(b, eol='\r'))) {
			fprint(2, "cannot find end of first line\n");
			wexits("initps");
		}
		if(p[0]=='\x1B')
			p++, psoff++;
		if(p[0] == '%' && p[1] == '!')
			break;
	}
	if(i == 16){
		werrstr("not ps");
		return nil;
	}

	/* page counting */
	npage = 0;
	mpage = 16;
	page = emalloc(mpage*sizeof(*page));
	memset(page, 0, mpage*sizeof(*page));

	cantranslate = goodps;
	incomments = 1;
Keepreading:
	while(p = Brdline(b, eol)) {
		if(p[0] == '%')
			if(chatty) fprint(2, "ps %.*s\n", utfnlen(p, Blinelen(b)-1), p);
		if(npage == mpage) {
			mpage *= 2;
			page = erealloc(page, mpage*sizeof(*page));
			memset(&page[npage], 0, npage*sizeof(*page));
		}

		if(p[0] != '%' || p[1] != '%')
			continue;

		if(prefix(p, "%%BeginDocument")) {
			nesting++;
			continue;
		}
		if(nesting > 0 && prefix(p, "%%EndDocument")) {
			nesting--;
			continue;
		}
		if(nesting)
			continue;

		if(prefix(p, "%%EndComment")) {
			incomments = 0;
			continue;
		}
		if(reverse == -1 && prefix(p, "%%PageOrder")) {
			/* glean whether we should reverse the viewing order */
			p[Blinelen(b)-1] = 0;
			if(strstr(p, "Ascend"))
				reverse = 0;
			else if(strstr(p, "Descend"))
				reverse = 1;
			else if(strstr(p, "Special"))
				dumb = 1;
			p[Blinelen(b)-1] = '\n';
			continue;
		} else if(prefix(p, "%%Trailer")) {
			incomments = 1;
			page[npage].offset = Boffset(b)-Blinelen(b);
			trailer = 1;
			continue;
		} else if(incomments && prefix(p, "%%Orientation")) {
			if(strstr(p, "Landscape"))
				landscape = 1;
		} else if(incomments && Dx(bbox)==0 && prefix(p, q="%%BoundingBox")) {
			bbox = rdbbox(p+strlen(q)+1);
			if(chatty)
				/* can't use %R because haven't initdraw() */
				fprint(2, "document bbox [%d %d %d %d]\n",
					RECT(bbox));
			continue;
		}

		/*
		 * If they use the initgraphics command, we can't play our translation tricks.
		 */
		p[Blinelen(b)-1] = 0;
		if((q=strstr(p, "initgraphics")) && ((r=strchr(p, '%'))==nil || r > q))
			cantranslate = 0;
		p[Blinelen(b)-1] = eol;

		if(!prefix(p, "%%Page:"))
			continue;

		/* 
		 * figure out of the %%Page: line contains a page number
		 * or some other page description to use in the menu bar.
		 * 
		 * lines look like %%Page: x y or %%Page: x
		 * we prefer just x, and will generate our
		 * own if necessary.
		 */
		p[Blinelen(b)-1] = 0;
		if(chatty) fprint(2, "page %s\n", p);
		r = p+7;
		while(*r == ' ' || *r == '\t')
			r++;
		q = r;
		while(*q && *q != ' ' && *q != '\t')
			q++;
		free(page[npage].name);
		if(*r) {
			if(*r == '"' && *q == '"')
				r++, q--;
			if(*q)
				*q = 0;
			page[npage].name = estrdup(r);
			*q = 'x';
		} else {
			snprint(tmp, sizeof tmp, "p %ld", npage+1);
			page[npage].name = estrdup(tmp);
		}

		/*
		 * store the offset info for later viewing
		 */
		trailer = 0;
		p[Blinelen(b)-1] = eol;
		page[npage++].offset = Boffset(b)-Blinelen(b);
	}
	if(Blinelen(b) > 0){
		fprint(2, "page: linelen %d\n", Blinelen(b));
		Bseek(b, Blinelen(b), 1);
		goto Keepreading;
	}

	if(Dx(bbox) == 0 || Dy(bbox) == 0)
		bbox = Rect(0,0,612,792);	/* 8½×11 */
	/*
	 * if we didn't find any pages, assume the document
	 * is one big page
	 */
	if(npage == 0) {
		dumb = 1;
		if(chatty) fprint(2, "don't know where pages are\n");
		reverse = 0;
		goodps = 0;
		trailer = 0;
		page[npage].name = "p 1";
		page[npage++].offset = 0;
	}

	if(npage+2 > mpage) {
		mpage += 2;
		page = erealloc(page, mpage*sizeof(*page));
		memset(&page[mpage-2], 0, 2*sizeof(*page));
	}

	if(!trailer)
		page[npage].offset = Boffset(b);

	Bseek(b, 0, 2); /* EOF */
	page[npage+1].offset = Boffset(b);

	d = emalloc(sizeof(*d));
	ps = emalloc(sizeof(*ps));
	ps->page = page;
	ps->npage = npage;
	ps->bbox = bbox;
	ps->psoff = psoff;

	d->extra = ps;
	d->npage = ps->npage;
	d->b = b;
	d->drawpage = psdrawpage;
	d->pagename = pspagename;

	d->fwdonly = ps->clueless = dumb;
	d->docname = argv[0];
	/*
	 * "tag" the doc as an image for now since there still is the "blank page"
	 * problem for ps files.
	 */
	d->type = Tgfx;

	if(spawngs(&ps->gs, "-dSAFER") < 0)
		return nil;

	if(!cantranslate)
		bbox.min = ZP;
	setdim(&ps->gs, bbox, ppi, landscape);

	if(goodps){
		/*
		 * We want to only send the page (i.e. not header and trailer) information
	 	 * for each page, so initialize the device by sending the header now.
		 */
		pswritepage(d, ps->gs.gsfd, -1);
		waitgs(&ps->gs);
	}

	if(dumb) {
		fprint(ps->gs.gsfd, "(%s) run\n", argv[0]);
		fprint(ps->gs.gsfd, "(/dev/fd/3) (w) file dup (THIS IS NOT A PLAN9 BITMAP 01234567890123456789012345678901234567890123456789\\n) writestring flushfile\n");
	}

	ps->bbox = bbox;

	return d;
}
Example #26
0
File: obj.c Project: machinaut/go
void
ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
{
	int32 ipc;
	Prog *p;
	int v, o, r, skip;
	Sym *h[NSYM], *s;
	uint32 sig;
	int ntext;
	int32 eof;
	char *name, *x;
	char src[1024];
	Prog *lastp;

	lastp = nil;
	ntext = 0;
	eof = Boffset(f) + len;
	src[0] = 0;


newloop:
	memset(h, 0, sizeof(h));
	version++;
	histfrogp = 0;
	ipc = pc;
	skip = 0;

loop:
	if(f->state == Bracteof || Boffset(f) >= eof)
		goto eof;
	o = Bgetc(f);
	if(o == Beof)
		goto eof;
	o |= Bgetc(f) << 8;
	if(o <= AXXX || o >= ALAST) {
		if(o < 0)
			goto eof;
		diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o);
		print("	probably not a .%c file\n", thechar);
		errorexit();
	}

	if(o == ANAME || o == ASIGNAME) {
		sig = 0;
		if(o == ASIGNAME)
			sig = Bget4(f);
		v = Bgetc(f);	/* type */
		o = Bgetc(f);	/* sym */
		r = 0;
		if(v == D_STATIC)
			r = version;
		name = Brdline(f, '\0');
		if(name == nil) {
			if(Blinelen(f) > 0) {
				fprint(2, "%s: name too long\n", pn);
				errorexit();
			}
			goto eof;
		}
		x = expandpkg(name, pkg);
		s = lookup(x, r);
		if(x != name)
			free(x);

		if(debug['S'] && r == 0)
			sig = 1729;
		if(sig != 0){
			if(s->sig != 0 && s->sig != sig)
				diag("incompatible type signatures"
					"%ux(%s) and %ux(%s) for %s",
					s->sig, s->file, sig, pn, s->name);
			s->sig = sig;
			s->file = pn;
		}

		if(debug['W'])
			print("	ANAME	%s\n", s->name);
		if(o < 0 || o >= nelem(h))
			mangle(pn);
		h[o] = s;
		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
			s->type = SXREF;
		if(v == D_FILE) {
			if(s->type != SFILE) {
				histgen++;
				s->type = SFILE;
				s->value = histgen;
			}
			if(histfrogp < MAXHIST) {
				histfrog[histfrogp] = s;
				histfrogp++;
			} else
				collapsefrog(s);
			dwarfaddfrag(s->value, s->name);
		}
		goto loop;
	}

	p = mal(sizeof(*p));
	p->as = o;
	p->line = Bget4(f);
	p->back = 2;
	p->ft = 0;
	p->tt = 0;
	zaddr(pn, f, &p->from, h);
	fromgotype = adrgotype;
	zaddr(pn, f, &p->to, h);

	if(debug['W'])
		print("%P\n", p);

	switch(p->as) {
	case AHISTORY:
		if(p->to.offset == -1) {
			addlib(src, pn);
			histfrogp = 0;
			goto loop;
		}
		if(src[0] == '\0')
			copyhistfrog(src, sizeof src);
		addhist(p->line, D_FILE);		/* 'z' */
		if(p->to.offset)
			addhist(p->to.offset, D_FILE1);	/* 'Z' */
		histfrogp = 0;
		goto loop;

	case AEND:
		histtoauto();
		if(cursym != nil && cursym->text)
			cursym->autom = curauto;
		curauto = 0;
		cursym = nil;
		if(Boffset(f) == eof)
			return;
		goto newloop;

	case AGLOBL:
		s = p->from.sym;
		if(s->type == 0 || s->type == SXREF) {
			s->type = SBSS;
			s->size = 0;
		}
		if(s->type != SBSS && !s->dupok) {
			diag("%s: redefinition: %s in %s",
				pn, s->name, TNAME);
			s->type = SBSS;
			s->size = 0;
		}
		if(p->to.offset > s->size)
			s->size = p->to.offset;
		if(p->from.scale & DUPOK)
			s->dupok = 1;
		if(p->from.scale & RODATA)
			s->type = SRODATA;
		goto loop;

	case ADATA:
		// Assume that AGLOBL comes after ADATA.
		// If we've seen an AGLOBL that said this sym was DUPOK,
		// ignore any more ADATA we see, which must be
		// redefinitions.
		s = p->from.sym;
		if(s->dupok) {
//			if(debug['v'])
//				Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
			goto loop;
		}
		if(s->file == nil)
			s->file = pn;
		else if(s->file != pn) {
			diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
			errorexit();
		}
		savedata(s, p, pn);
		unmal(p, sizeof *p);
		goto loop;

	case AGOK:
		diag("%s: GOK opcode in %s", pn, TNAME);
		pc++;
		goto loop;

	case ATEXT:
		s = p->from.sym;
		if(s->text != nil) {
			diag("%s: %s: redefinition", pn, s->name);
			return;
		}
		if(ntext++ == 0 && s->type != 0 && s->type != SXREF) {
			/* redefinition, so file has probably been seen before */
			if(debug['v'])
				diag("skipping: %s: redefinition: %s", pn, s->name);
			return;
		}
		if(cursym != nil && cursym->text) {
			histtoauto();
			cursym->autom = curauto;
			curauto = 0;
		}
		skip = 0;
		if(etextp)
			etextp->next = s;
		else
			textp = s;
		etextp = s;
		s->text = p;
		cursym = s;
		if(s->type != 0 && s->type != SXREF) {
			if(p->from.scale & DUPOK) {
				skip = 1;
				goto casdef;
			}
			diag("%s: redefinition: %s\n%P", pn, s->name, p);
		}
		s->type = STEXT;
		s->value = pc;
		lastp = p;
		p->pc = pc++;
		goto loop;

	case AFMOVF:
	case AFADDF:
	case AFSUBF:
	case AFSUBRF:
	case AFMULF:
	case AFDIVF:
	case AFDIVRF:
	case AFCOMF:
	case AFCOMFP:
		if(skip)
			goto casdef;
		if(p->from.type == D_FCONST) {
			/* size sb 9 max */
			sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
			s = lookup(literal, 0);
			if(s->type == 0) {
				s->type = SDATA;
				adduint32(s, ieeedtof(&p->from.ieee));
				s->reachable = 0;
			}
			p->from.type = D_EXTERN;
			p->from.sym = s;
			p->from.offset = 0;
		}
		goto casdef;

	case AFMOVD:
	case AFADDD:
	case AFSUBD:
	case AFSUBRD:
	case AFMULD:
	case AFDIVD:
	case AFDIVRD:
	case AFCOMD:
	case AFCOMDP:
		if(skip)
			goto casdef;
		if(p->from.type == D_FCONST) {
			/* size sb 18 max */
			sprint(literal, "$%ux.%ux",
				p->from.ieee.l, p->from.ieee.h);
			s = lookup(literal, 0);
			if(s->type == 0) {
				s->type = SDATA;
				adduint32(s, p->from.ieee.l);
				adduint32(s, p->from.ieee.h);
				s->reachable = 0;
			}
			p->from.type = D_EXTERN;
			p->from.sym = s;
			p->from.offset = 0;
		}
		goto casdef;

	casdef:
	default:
		if(skip)
			nopout(p);
		p->pc = pc;
		pc++;

		if(p->to.type == D_BRANCH)
			p->to.offset += ipc;
		if(lastp == nil) {
			if(p->as != ANOP)
				diag("unexpected instruction: %P", p);
			goto loop;
		}
		lastp->link = p;
		lastp = p;
		goto loop;
	}

eof:
	diag("truncated object file: %s", pn);
}
Example #27
0
void
ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence)
{
	char *line;
	int n, c1, c2, c3, c4;
	uint32 magic;
	vlong import0, import1, eof;
	char *t;

	eof = Boffset(f) + len;

	pn = estrdup(pn);

	c1 = BGETC(f);
	c2 = BGETC(f);
	c3 = BGETC(f);
	c4 = BGETC(f);
	Bungetc(f);
	Bungetc(f);
	Bungetc(f);
	Bungetc(f);

	magic = c1<<24 | c2<<16 | c3<<8 | c4;
	if(magic == 0x7f454c46) {	// \x7F E L F
		ldhostobj(ldelf, f, pkg, len, pn, file);
		return;
	}
	if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
		ldhostobj(ldmacho, f, pkg, len, pn, file);
		return;
	}
	if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
		ldhostobj(ldpe, f, pkg, len, pn, file);
		return;
	}

	/* check the header */
	line = Brdline(f, '\n');
	if(line == nil) {
		if(Blinelen(f) > 0) {
			diag("%s: not an object file", pn);
			return;
		}
		goto eof;
	}
	n = Blinelen(f) - 1;
	line[n] = '\0';
	if(strncmp(line, "go object ", 10) != 0) {
		if(strlen(pn) > 3 && strcmp(pn+strlen(pn)-3, ".go") == 0) {
			print("%cl: input %s is not .%c file (use %cg to compile .go files)\n", thechar, pn, thechar, thechar);
			errorexit();
		}
		if(strcmp(line, thestring) == 0) {
			// old header format: just $GOOS
			diag("%s: stale object file", pn);
			return;
		}
		diag("%s: not an object file", pn);
		free(pn);
		return;
	}
	
	// First, check that the basic goos, string, and version match.
	t = smprint("%s %s %s ", goos, thestring, getgoversion());
	line[n] = ' ';
	if(strncmp(line+10, t, strlen(t)) != 0 && !debug['f']) {
		line[n] = '\0';
		diag("%s: object is [%s] expected [%s]", pn, line+10, t);
		free(t);
		free(pn);
		return;
	}
	
	// Second, check that longer lines match each other exactly,
	// so that the Go compiler and write additional information
	// that must be the same from run to run.
	line[n] = '\0';
	if(n-10 > strlen(t)) {
		if(theline == nil)
			theline = estrdup(line+10);
		else if(strcmp(theline, line+10) != 0) {
			line[n] = '\0';
			diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
			free(t);
			free(pn);
			return;
		}
	}
	free(t);
	line[n] = '\n';

	/* skip over exports and other info -- ends with \n!\n */
	import0 = Boffset(f);
	c1 = '\n';	// the last line ended in \n
	c2 = BGETC(f);
	c3 = BGETC(f);
	while(c1 != '\n' || c2 != '!' || c3 != '\n') {
		c1 = c2;
		c2 = c3;
		c3 = BGETC(f);
		if(c3 == Beof)
			goto eof;
	}
	import1 = Boffset(f);

	Bseek(f, import0, 0);
	ldpkg(f, pkg, import1 - import0 - 2, pn, whence);	// -2 for !\n
	Bseek(f, import1, 0);

	ldobjfile(ctxt, f, pkg, eof - Boffset(f), pn);
	free(pn);
	return;

eof:
	diag("truncated object file: %s", pn);
	free(pn);
}
Example #28
0
void
objfile(char *file, char *pkg)
{
	vlong off, l;
	Biobuf *f;
	char magbuf[SARMAG];
	char pname[150];
	struct ar_hdr arhdr;

	pkg = smprint("%i", pkg);

	if(debug['v'] > 1)
		Bprint(&bso, "%5.2f ldobj: %s (%s)\n", cputime(), file, pkg);
	Bflush(&bso);
	f = Bopen(file, 0);
	if(f == nil) {
		diag("cannot open file: %s", file);
		errorexit();
	}
	l = Bread(f, magbuf, SARMAG);
	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
		/* load it as a regular file */
		l = Bseek(f, 0L, 2);
		Bseek(f, 0L, 0);
		ldobj(f, pkg, l, file, file, FileObj);
		Bterm(f);
		free(pkg);
		return;
	}
	
	/* skip over optional __.GOSYMDEF and process __.PKGDEF */
	off = Boffset(f);
	l = nextar(f, off, &arhdr);
	if(l <= 0) {
		diag("%s: short read on archive file symbol header", file);
		goto out;
	}
	if(strncmp(arhdr.name, symname, strlen(symname)) == 0) {
		off += l;
		l = nextar(f, off, &arhdr);
		if(l <= 0) {
			diag("%s: short read on archive file symbol header", file);
			goto out;
		}
	}

	if(strncmp(arhdr.name, pkgname, strlen(pkgname))) {
		diag("%s: cannot find package header", file);
		goto out;
	}
	off += l;

	if(debug['u'])
		ldpkg(f, pkg, atolwhex(arhdr.size), file, Pkgdef);

	/*
	 * load all the object files from the archive now.
	 * this gives us sequential file access and keeps us
	 * from needing to come back later to pick up more
	 * objects.  it breaks the usual C archive model, but
	 * this is Go, not C.  the common case in Go is that
	 * we need to load all the objects, and then we throw away
	 * the individual symbols that are unused.
	 *
	 * loading every object will also make it possible to
	 * load foreign objects not referenced by __.GOSYMDEF.
	 */
	for(;;) {
		l = nextar(f, off, &arhdr);
		if(l == 0)
			break;
		if(l < 0) {
			diag("%s: malformed archive", file);
			goto out;
		}
		off += l;

		l = SARNAME;
		while(l > 0 && arhdr.name[l-1] == ' ')
			l--;
		snprint(pname, sizeof pname, "%s(%.*s)", file, utfnlen(arhdr.name, l), arhdr.name);
		l = atolwhex(arhdr.size);
		ldobj(f, pkg, l, pname, file, ArchiveObj);
	}

out:
	Bterm(f);
	free(pkg);
}
Example #29
0
void
ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
{
	char *name;
	int32 base;
	int i, j, l, numaux;
	PeObj *obj;
	PeSect *sect, *rsect;
	IMAGE_SECTION_HEADER sh;
	uchar symbuf[18];
	Sym *s;
	Reloc *r, *rp;
	PeSym *sym;

	USED(len);
	USED(pkg);
	if(debug['v'])
		Bprint(&bso, "%5.2f ldpe %s\n", cputime(), pn);
	
	sect = nil;
	version++;
	base = Boffset(f);
	
	obj = mal(sizeof *obj);
	obj->f = f;
	obj->base = base;
	obj->name = pn;
	// read header
	if(Bread(f, &obj->fh, sizeof obj->fh) != sizeof obj->fh)
		goto bad;
	// load section list
	obj->sect = mal(obj->fh.NumberOfSections*sizeof obj->sect[0]);
	obj->nsect = obj->fh.NumberOfSections;
	for(i=0; i < obj->fh.NumberOfSections; i++) {
		if(Bread(f, &obj->sect[i].sh, sizeof sh) != sizeof sh)
			goto bad;
		obj->sect[i].size = obj->sect[i].sh.SizeOfRawData;
		obj->sect[i].name = (char*)obj->sect[i].sh.Name;
		// TODO return error if found .cormeta
	}
	// load string table
	Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
	if(Bread(f, &l, sizeof l) != sizeof l) 
		goto bad;
	obj->snames = mal(l);
	Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
	if(Bread(f, obj->snames, l) != l)
		goto bad;
	// read symbols
	obj->pesym = mal(obj->fh.NumberOfSymbols*sizeof obj->pesym[0]);
	obj->npesym = obj->fh.NumberOfSymbols;
	Bseek(f, base+obj->fh.PointerToSymbolTable, 0);
	for(i=0; i<obj->fh.NumberOfSymbols; i+=numaux+1) {
		Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*i, 0);
		if(Bread(f, symbuf, sizeof symbuf) != sizeof symbuf)
			goto bad;
		
		if((symbuf[0] == 0) && (symbuf[1] == 0) &&
			 (symbuf[2] == 0) && (symbuf[3] == 0)) {
			l = le32(&symbuf[4]);
			obj->pesym[i].name = (char*)&obj->snames[l];
		} else { // sym name length <= 8
			obj->pesym[i].name = mal(9);
			strncpy(obj->pesym[i].name, (char*)symbuf, 8);
			obj->pesym[i].name[8] = 0;
		}
		obj->pesym[i].value = le32(&symbuf[8]);
		obj->pesym[i].sectnum = le16(&symbuf[12]);
		obj->pesym[i].sclass = symbuf[16];
		obj->pesym[i].aux = symbuf[17];
		obj->pesym[i].type = le16(&symbuf[14]);
		numaux = obj->pesym[i].aux; 
		if (numaux < 0) 
			numaux = 0;
	}
	// create symbols for mapped sections
	for(i=0; i<obj->nsect; i++) {
		sect = &obj->sect[i];
		if(sect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE)
			continue;
		if(map(obj, sect) < 0)
			goto bad;
		
		name = smprint("%s(%s)", pn, sect->name);
		s = lookup(name, version);
		free(name);
		switch(sect->sh.Characteristics&(IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_CNT_INITIALIZED_DATA|
			IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE)) {
			case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ: //.rdata
				s->type = SRODATA;
				break;
			case IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.bss
				s->type = SBSS;
				break;
			case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.data
				s->type = SDATA;
				break;
			case IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ: //.text
				s->type = STEXT;
				break;
			default:
				werrstr("unexpected flags for PE section %s", sect->name);
				goto bad;
		}
		s->p = sect->base;
		s->np = sect->size;
		s->size = sect->size;
		if(s->type == STEXT) {
			if(etextp)
				etextp->next = s;
			else
				textp = s;
			etextp = s;
		}
		sect->sym = s;
		if(strcmp(sect->name, ".rsrc") == 0)
			setpersrc(sect->sym);
	}
	
	// load relocations
	for(i=0; i<obj->nsect; i++) {
		rsect = &obj->sect[i];
		if(rsect->sym == 0 || rsect->sh.NumberOfRelocations == 0)
			continue;
		if(rsect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE)
			continue;
		r = mal(rsect->sh.NumberOfRelocations*sizeof r[0]);
		Bseek(f, obj->base+rsect->sh.PointerToRelocations, 0);
		for(j=0; j<rsect->sh.NumberOfRelocations; j++) {
			rp = &r[j];
			if(Bread(f, symbuf, 10) != 10)
				goto bad;
			
			uint32 rva, symindex;
			uint16 type;
			rva = le32(&symbuf[0]);
			symindex = le32(&symbuf[4]);
			type = le16(&symbuf[8]);
			if(readsym(obj, symindex, &sym) < 0)
				goto bad;
			if(sym->sym == nil) {
				werrstr("reloc of invalid sym %s idx=%d type=%d", sym->name, symindex, sym->type);
				goto bad;
			}
			rp->sym = sym->sym;
			rp->siz = 4;
			rp->off = rva;
			switch(type) {
				default:
					diag("%s: unknown relocation type %d;", pn, type);
				case IMAGE_REL_I386_REL32:
				case IMAGE_REL_AMD64_REL32:
				case IMAGE_REL_AMD64_ADDR32: // R_X86_64_PC32
				case IMAGE_REL_AMD64_ADDR32NB:
					rp->type = D_PCREL;
					rp->add = le32(rsect->base+rp->off);
					break;
				case IMAGE_REL_I386_DIR32NB:
				case IMAGE_REL_I386_DIR32:
					rp->type = D_ADDR;
					// load addend from image
					rp->add = le32(rsect->base+rp->off);
					break;
				case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64
					rp->siz = 8;
					rp->type = D_ADDR;
					// load addend from image
					rp->add = le64(rsect->base+rp->off);
					break;
			}
		}
		qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff);
		
		s = rsect->sym;
		s->r = r;
		s->nr = rsect->sh.NumberOfRelocations;
	}
	
	// enter sub-symbols into symbol table.
	for(i=0; i<obj->npesym; i++) {
		if(obj->pesym[i].name == 0)
			continue;
		if(obj->pesym[i].name[0] == '.') //skip section
			continue;
		if(obj->pesym[i].sectnum > 0) {
			sect = &obj->sect[obj->pesym[i].sectnum-1];
			if(sect->sym == 0)
				continue;
		}
		if(readsym(obj, i, &sym) < 0)
			goto bad;
	
		s = sym->sym;
		if(sym->sectnum == 0) {// extern
			if(s->type == SDYNIMPORT)
				s->plt = -2; // flag for dynimport in PE object files.
			if (s->type == SXREF && sym->value > 0) {// global data
				s->type = SDATA; 
				s->size = sym->value;
			}
			continue;
		} else if (sym->sectnum > 0) {
			sect = &obj->sect[sym->sectnum-1];
			if(sect->sym == 0)
				diag("%s: %s sym == 0!", pn, s->name);
		} else {
			diag("%s: %s sectnum < 0!", pn, s->name);
		}

		if(sect == nil) 
			return;
		s->sub = sect->sym->sub;
		sect->sym->sub = s;
		s->type = sect->sym->type | SSUB;
		s->value = sym->value;
		s->size = 4;
		s->outer = sect->sym;
		if(sect->sym->type == STEXT) {
			Prog *p;
	
			if(s->text != P)
				diag("%s: duplicate definition of %s", pn, s->name);
			// build a TEXT instruction with a unique pc
			// just to make the rest of the linker happy.
			p = prg();
			p->as = ATEXT;
			p->from.type = D_EXTERN;
			p->from.sym = s;
			p->textflag = 7;
			p->to.type = D_CONST;
			p->link = nil;
			p->pc = pc++;
			s->text = p;
	
			etextp->next = s;
			etextp = s;
		}
	}

	return;
bad:
	diag("%s: malformed pe file: %r", pn);
}
Example #30
0
void
dumpobj(void)
{
	NodeList *externs, *tmp;
	char arhdr[ArhdrSize];
	vlong startobj, size;
	Sym *zero;

	bout = Bopen(outfile, OWRITE);
	if(bout == nil) {
		flusherrors();
		print("can't create %s: %r\n", outfile);
		errorexit();
	}

	startobj = 0;
	if(writearchive) {
		Bwrite(bout, "!<arch>\n", 8);
		memset(arhdr, 0, sizeof arhdr);
		Bwrite(bout, arhdr, sizeof arhdr);
		startobj = Boffset(bout);
	}
	Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
	dumpexport();
	
	if(writearchive) {
		Bflush(bout);
		size = Boffset(bout) - startobj;
		if(size&1)
			Bputc(bout, 0);
		Bseek(bout, startobj - ArhdrSize, 0);
		formathdr(arhdr, "__.PKGDEF", size);
		Bwrite(bout, arhdr, ArhdrSize);
		Bflush(bout);

		Bseek(bout, startobj + size + (size&1), 0);
		memset(arhdr, 0, ArhdrSize);
		Bwrite(bout, arhdr, ArhdrSize);
		startobj = Boffset(bout);
		Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
	}

	Bprint(bout, "\n!\n");

	externs = nil;
	if(externdcl != nil)
		externs = externdcl->end;

	dumpglobls();
	dumptypestructs();

	// Dump extra globals.
	tmp = externdcl;
	if(externs != nil)
		externdcl = externs->next;
	dumpglobls();
	externdcl = tmp;

	zero = pkglookup("zerovalue", runtimepkg);
	ggloblsym(zero, zerosize, 1, 1);

	dumpdata();
	writeobj(ctxt, bout);

	if(writearchive) {
		Bflush(bout);
		size = Boffset(bout) - startobj;
		if(size&1)
			Bputc(bout, 0);
		Bseek(bout, startobj - ArhdrSize, 0);
		snprint(namebuf, sizeof namebuf, "_go_.%c", thechar);
		formathdr(arhdr, namebuf, size);
		Bwrite(bout, arhdr, ArhdrSize);
	}
	Bterm(bout);
}