Beispiel #1
0
int
_read5(Biobuf *bp, Prog *p)
{
	int as, n;
	Addr a;

	as = BGETC(bp);			/* as */
	if(as < 0)
		return 0;
	p->kind = aNone;
	p->sig = 0;
	if(as == ANAME || as == ASIGNAME){
		if(as == ASIGNAME){
			Bread(bp, &p->sig, 4);
			p->sig = leswal(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;
	skip(bp, 6);		/* scond(1), reg(1), lineno(4) */
	a = 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;
}
Beispiel #2
0
static int
machdotout(int fd, Fhdr *fp, ExecHdr *hp)
{
	uvlong (*swav)(uvlong);
	uint32 (*swal)(uint32);
	ushort (*swab)(ushort);
	Machhdr *mp;
	MachCmd **cmd;
	MachSymSeg *symtab;
	MachSymSeg *pclntab;
	MachSeg64 *seg;
	MachSect64 *sect;
	MachSeg32 *seg32;
	MachSect32 *sect32;
	uvlong textsize, datasize, bsssize;
	uchar *cmdbuf;
	uchar *cmdp;
	int i, hdrsize;
	uint32 textva, textoff, datava, dataoff;

	mp = &hp->e.machhdr;
	if (leswal(mp->filetype) != MACH_EXECUTABLE_TYPE) {
		werrstr("bad MACH executable type %#ux", leswal(mp->filetype));
		return 0;
	}

	swab = leswab;
	swal = leswal;
	swav = leswav;

	mp->magic = swal(mp->magic);
	mp->cputype = swal(mp->cputype);
	mp->cpusubtype = swal(mp->cpusubtype);
	mp->filetype = swal(mp->filetype);
	mp->ncmds = swal(mp->ncmds);
	mp->sizeofcmds = swal(mp->sizeofcmds);
	mp->flags = swal(mp->flags);
	mp->reserved = swal(mp->reserved);
	hdrsize = 0;

	switch(mp->magic) {
	case 0xFEEDFACE:	// 32-bit mach
		if (mp->cputype != MACH_CPU_TYPE_X86) {
			werrstr("bad MACH cpu type - not 386");
			return 0;
		}
		if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) {
			werrstr("bad MACH cpu subtype - not 386");
			return 0;
		}
		if (mp->filetype != MACH_EXECUTABLE_TYPE) {
			werrstr("bad MACH executable type");
			return 0;
		}
		mach = &mi386;
		fp->type = FI386;
		hdrsize = 28;
		break;

	case 0xFEEDFACF:	// 64-bit mach
		if (mp->cputype != MACH_CPU_TYPE_X86_64) {
			werrstr("bad MACH cpu type - not amd64");
			return 0;
		}

		if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) {
			werrstr("bad MACH cpu subtype - not amd64");
			return 0;
		}
		mach = &mamd64;
		fp->type = FAMD64;
		hdrsize = 32;
		break;

	default:
		werrstr("not mach %#ux", mp->magic);
		return 0;
	}

	cmdbuf = malloc(mp->sizeofcmds);
	seek(fd, hdrsize, 0);
	if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) {
		free(cmdbuf);
		return 0;
	}
	cmd = malloc(mp->ncmds * sizeof(MachCmd*));
	cmdp = cmdbuf;
	textva = 0;
	textoff = 0;
	dataoff = 0;
	datava = 0;
	symtab = 0;
	pclntab = 0;
	textsize = datasize = bsssize = 0;
	for (i = 0; i < mp->ncmds; i++) {
		MachCmd *c;

		cmd[i] = (MachCmd*)cmdp;
		c = cmd[i];
		c->type = swal(c->type);
		c->size = swal(c->size);
		switch(c->type) {
		case MACH_SEGMENT_32:
			if(mp->magic != 0xFEEDFACE) {
				werrstr("segment 32 in mach 64");
				goto bad;
			}
			seg32 = (MachSeg32*)c;
			seg32->vmaddr = swav(seg32->vmaddr);
			seg32->vmsize = swav(seg32->vmsize);
			seg32->fileoff = swav(seg32->fileoff);
			seg32->filesize = swav(seg32->filesize);
			seg32->maxprot = swal(seg32->maxprot);
			seg32->initprot = swal(seg32->initprot);
			seg32->nsects = swal(seg32->nsects);
			seg32->flags = swal(seg32->flags);
			if (strcmp(seg32->segname, "__TEXT") == 0) {
				textva = seg32->vmaddr;
				textoff = seg32->fileoff;
				sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
				if (strcmp(sect32->sectname, "__text") == 0) {
					textsize = swal(sect32->size);
				} else {
					werrstr("no text section");
					goto bad;
				}
			}
			if (strcmp(seg32->segname, "__DATA") == 0) {
				datava = seg32->vmaddr;
				dataoff = seg32->fileoff;
				sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
				if (strcmp(sect32->sectname, "__data") == 0) {
					datasize = swal(sect32->size);
				} else {
					werrstr("no data section");
					goto bad;
				}
				sect32++;
				if (strcmp(sect32->sectname, "__nl_symbol_ptr") == 0)
					sect32++;
				if (strcmp(sect32->sectname, "__bss") == 0) {
					bsssize = swal(sect32->size);
				} else {
					werrstr("no bss section");
					goto bad;
				}
			}
			break;

		case MACH_SEGMENT_64:
			if(mp->magic != 0xFEEDFACF) {
				werrstr("segment 32 in mach 64");
				goto bad;
			}
			seg = (MachSeg64*)c;
			seg->vmaddr = swav(seg->vmaddr);
			seg->vmsize = swav(seg->vmsize);
			seg->fileoff = swav(seg->fileoff);
			seg->filesize = swav(seg->filesize);
			seg->maxprot = swal(seg->maxprot);
			seg->initprot = swal(seg->initprot);
			seg->nsects = swal(seg->nsects);
			seg->flags = swal(seg->flags);
			if (strcmp(seg->segname, "__TEXT") == 0) {
				textva = seg->vmaddr;
				textoff = seg->fileoff;
				sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
				if (strcmp(sect->sectname, "__text") == 0) {
					textsize = swav(sect->size);
				} else {
					werrstr("no text section");
					goto bad;
				}
			}
			if (strcmp(seg->segname, "__DATA") == 0) {
				datava = seg->vmaddr;
				dataoff = seg->fileoff;
				sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
				if (strcmp(sect->sectname, "__data") == 0) {
					datasize = swav(sect->size);
				} else {
					werrstr("no data section");
					goto bad;
				}
				sect++;
				if (strcmp(sect->sectname, "__bss") == 0) {
					bsssize = swav(sect->size);
				} else {
					werrstr("no bss section");
					goto bad;
				}
			}
			break;
		case MACH_UNIXTHREAD:
			break;
		case MACH_SYMSEG:
			if (symtab == 0)
				symtab = (MachSymSeg*)c;
			else if (pclntab == 0)
				pclntab = (MachSymSeg*)c;
			break;
		}
		cmdp += c->size;
	}
	if (textva == 0 || datava == 0) {
		free(cmd);
		free(cmdbuf);
		return 0;
	}
	/* compute entry by taking address after header - weird - BUG? */
	settext(fp, textva+sizeof(Machhdr) + mp->sizeofcmds, textva, textsize, textoff);
	setdata(fp, datava, datasize, dataoff, bsssize);
	if(symtab != 0)
		setsym(fp, symtab->filesize, 0, pclntab? pclntab->filesize : 0, symtab->fileoff);
	free(cmd);
	free(cmdbuf);
	return 1;
bad:
	free(cmd);
	free(cmdbuf);
	return 0;
}
Beispiel #3
0
static int
machdotout(int fd, Fhdr *fp, ExecHdr *hp)
{
	uvlong (*swav)(uvlong);
	uint32 (*swal)(uint32);
	Machhdr *mp;
	MachCmd **cmd;
	MachSymSeg *symtab;
	MachSymSeg *pclntab;
	MachSeg64 *seg;
	MachSect64 *sect;
	MachSeg32 *seg32;
	MachSect32 *sect32;
	uvlong textsize, datasize, bsssize;
	uchar *cmdbuf;
	uchar *cmdp;
	int i, j, hdrsize;
	uint32 textva, textoff, datava, dataoff, symoff, symsize, pclnoff, pclnsize;

	mp = &hp->e.machhdr;
	if (leswal(mp->filetype) != MACH_EXECUTABLE_TYPE) {
		werrstr("bad MACH executable type %#ux", leswal(mp->filetype));
		return 0;
	}

	swal = leswal;
	swav = leswav;

	mp->magic = swal(mp->magic);
	mp->cputype = swal(mp->cputype);
	mp->cpusubtype = swal(mp->cpusubtype);
	mp->filetype = swal(mp->filetype);
	mp->ncmds = swal(mp->ncmds);
	mp->sizeofcmds = swal(mp->sizeofcmds);
	mp->flags = swal(mp->flags);
	mp->reserved = swal(mp->reserved);

	switch(mp->magic) {
	case 0xFEEDFACE:	// 32-bit mach
		if (mp->cputype != MACH_CPU_TYPE_X86) {
			werrstr("bad MACH cpu type - not 386");
			return 0;
		}
		if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) {
			werrstr("bad MACH cpu subtype - not 386");
			return 0;
		}
		if (mp->filetype != MACH_EXECUTABLE_TYPE) {
			werrstr("bad MACH executable type");
			return 0;
		}
		mach = &mi386;
		fp->type = FI386;
		hdrsize = 28;
		break;

	case 0xFEEDFACF:	// 64-bit mach
		werrstr("64 bit mach NOT SUPPORTED");
		return 0;
		//if (mp->cputype != MACH_CPU_TYPE_X86_64) {
		//	werrstr("bad MACH cpu type - not amd64");
		//	return 0;
		//}
        //
		//if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86 && mp->cpusubtype != MACH_CPU_SUBTYPE_X86_64) {
		//	werrstr("bad MACH cpu subtype - not amd64");
		//	return 0;
		//}
		//mach = &mamd64;
		//fp->type = FAMD64;
		//hdrsize = 32;
		//break;

	default:
		werrstr("not mach %#ux", mp->magic);
		return 0;
	}

	cmdbuf = malloc(mp->sizeofcmds);
	if(!cmdbuf) {
		werrstr("out of memory");
		return 0;
	}
	seek(fd, hdrsize, 0);
	if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) {
		free(cmdbuf);
		return 0;
	}
	cmd = malloc(mp->ncmds * sizeof(MachCmd*));
	if(!cmd) {
		free(cmdbuf);
		werrstr("out of memory");
		return 0;
	}
	cmdp = cmdbuf;
	textva = 0;
	textoff = 0;
	dataoff = 0;
	datava = 0;
	symtab = 0;
	pclntab = 0;
	textsize = 0;
	datasize = 0;
	bsssize = 0;
	symoff = 0;
	symsize = 0;
	pclnoff = 0;
	pclnsize = 0;
	for (i = 0; i < mp->ncmds; i++) {
		MachCmd *c;

		cmd[i] = (MachCmd*)cmdp;
		c = cmd[i];
		c->type = swal(c->type);
		c->size = swal(c->size);
		switch(c->type) {
		case MACH_SEGMENT_32:
			if(mp->magic != 0xFEEDFACE) {
				werrstr("segment 32 in mach 64");
				goto bad;
			}
			seg32 = (MachSeg32*)c;
			seg32->vmaddr = swav(seg32->vmaddr);
			seg32->vmsize = swav(seg32->vmsize);
			seg32->fileoff = swav(seg32->fileoff);
			seg32->filesize = swav(seg32->filesize);
			seg32->maxprot = swal(seg32->maxprot);
			seg32->initprot = swal(seg32->initprot);
			seg32->nsects = swal(seg32->nsects);
			seg32->flags = swal(seg32->flags);
			if (strcmp(seg32->segname, "__TEXT") == 0) {
				textva = seg32->vmaddr;
				textoff = seg32->fileoff;
				textsize = seg32->vmsize;
				sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
				for(j = 0; j < seg32->nsects; j++, sect32++) {
					if (strcmp(sect32->sectname, "__gosymtab") == 0) {
						symoff = swal(sect32->offset);
						symsize = swal(sect32->size);
					}
					if (strcmp(sect32->sectname, "__gopclntab") == 0) {
						pclnoff = swal(sect32->offset);
						pclnsize = swal(sect32->size);
					}
				}
			}
			if (strcmp(seg32->segname, "__DATA") == 0) {
				datava = seg32->vmaddr;
				dataoff = seg32->fileoff;
				datasize = seg32->filesize;
				bsssize = seg32->vmsize - seg32->filesize;
			}
			break;

		case MACH_SEGMENT_64:
			werrstr("MACH SEGMENT 64 NOT SUPPORTED");
				goto bad;
			//if(mp->magic != 0xFEEDFACF) {
			//	werrstr("segment 32 in mach 64");
			//	goto bad;
			//}
			//seg = (MachSeg64*)c;
			//seg->vmaddr = swav(seg->vmaddr);
			//seg->vmsize = swav(seg->vmsize);
			//seg->fileoff = swav(seg->fileoff);
			//seg->filesize = swav(seg->filesize);
			//seg->maxprot = swal(seg->maxprot);
			//seg->initprot = swal(seg->initprot);
			//seg->nsects = swal(seg->nsects);
			//seg->flags = swal(seg->flags);
			//if (strcmp(seg->segname, "__TEXT") == 0) {
			//	textva = seg->vmaddr;
			//	textoff = seg->fileoff;
			//	textsize = seg->vmsize;
			//	sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
			//	for(j = 0; j < seg->nsects; j++, sect++) {
			//		if (strcmp(sect->sectname, "__gosymtab") == 0) {
			//			symoff = swal(sect->offset);
			//			symsize = swal(sect->size);
			//		}
			//		if (strcmp(sect->sectname, "__gopclntab") == 0) {
			//			pclnoff = swal(sect->offset);
			//			pclnsize = swal(sect->size);
			//		}
			//	}
			//}
			//if (strcmp(seg->segname, "__DATA") == 0) {
			//	datava = seg->vmaddr;
			//	dataoff = seg->fileoff;
			//	datasize = seg->filesize;
			//	bsssize = seg->vmsize - seg->filesize;
			//}
			break;
		case MACH_UNIXTHREAD:
			break;
		case MACH_SYMSEG:
			if (symtab == 0) {
				symtab = (MachSymSeg*)c;
				symoff = swal(symtab->fileoff);
				symsize = swal(symtab->filesize);
			} else if (pclntab == 0) {
				pclntab = (MachSymSeg*)c;
				pclnoff = swal(pclntab->fileoff);
				pclnsize = swal(pclntab->filesize);
			}
			break;
		}
		cmdp += c->size;
	}
	if (textva == 0 || datava == 0) {
		free(cmd);
		free(cmdbuf);
		return 0;
	}
	/* compute entry by taking address after header - weird - BUG? */
	settext(fp, textva+sizeof(Machhdr) + mp->sizeofcmds, textva, textsize, textoff);
	setdata(fp, datava, datasize, dataoff, bsssize);
	if(symoff > 0)
		setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsize);
	free(cmd);
	free(cmdbuf);
	return 1;
bad:
	free(cmd);
	free(cmdbuf);
	return 0;
}
Beispiel #4
0
/*
 * Read from Windows PE/COFF .exe file image.
 */
static int
pedotout(int fd, Fhdr *fp, ExecHdr *hp)
{
	uint32 start, magic;
	uint32 symtab, esymtab, pclntab, epclntab;
	IMAGE_FILE_HEADER fh;
	IMAGE_SECTION_HEADER sh;
	IMAGE_OPTIONAL_HEADER oh;
	PE64_IMAGE_OPTIONAL_HEADER oh64;
	uint8 sym[18];
	uint32 *valp, ib, entry;
	int i, ohoffset;

	USED(hp);
	seek(fd, 0x3c, 0);
	if (readn(fd, &start, sizeof(start)) != sizeof(start)) {
		werrstr("crippled PE MSDOS header");
		return 0;
	}
	start = leswal(start);

	seek(fd, start, 0);
	if (readn(fd, &magic, sizeof(magic)) != sizeof(magic)) {
		werrstr("no PE magic number found");
		return 0;
	}
	if (beswal(magic) != 0x50450000) {  /* "PE\0\0" */
		werrstr("incorrect PE magic number");
		return 0;
	}

	if (readn(fd, &fh, sizeof(fh)) != sizeof(fh)) {
		werrstr("crippled PE File Header");
		return 0;
	}
	if (fh.PointerToSymbolTable == 0) {
		werrstr("zero pointer to COFF symbol table");
		return 0;
	}

	ohoffset = seek(fd, 0, 1);
	if (readn(fd, &oh, sizeof(oh)) != sizeof(oh)) {
		werrstr("crippled PE Optional Header");
		return 0;
	}

	switch(oh.Magic) {
	case 0x10b:	// PE32
		fp->type = FI386;
		ib = leswal(oh.ImageBase);
		entry = leswal(oh.AddressOfEntryPoint);
		break;
	case 0x20b:	// PE32+
		fp->type = FAMD64;
		seek(fd, ohoffset, 0);
		if (readn(fd, &oh64, sizeof(oh64)) != sizeof(oh64)) {
			werrstr("crippled PE32+ Optional Header");
			return 0;
		}
		ib = leswal(oh64.ImageBase);
		entry = leswal(oh64.AddressOfEntryPoint);
		break;
	default:
		werrstr("invalid PE Optional Header magic number");
		return 0;
	}

	fp->txtaddr = 0;
	fp->dataddr = 0;
	for (i=0; i<leswab(fh.NumberOfSections); i++) {
		if (readn(fd, &sh, sizeof(sh)) != sizeof(sh)) {
			werrstr("could not read Section Header %d", i+1);
			return 0;
		}
		if (match8(sh.Name, ".text"))
			settext(fp, ib+entry, ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
		if (match8(sh.Name, ".data"))
			setdata(fp, ib+leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
	}
	if (fp->txtaddr==0 || fp->dataddr==0) {
		werrstr("no .text or .data");
		return 0;
	}

	seek(fd, leswal(fh.PointerToSymbolTable), 0);
	symtab = esymtab = pclntab = epclntab = 0;
	for (i=0; i<leswal(fh.NumberOfSymbols); i++) {
		if (readn(fd, sym, sizeof(sym)) != sizeof(sym)) {
			werrstr("crippled COFF symbol %d", i);
			return 0;
		}
		valp = (uint32 *)&sym[8];
		if (match8(sym, "symtab"))
			symtab = leswal(*valp);
		if (match8(sym, "esymtab"))
			esymtab = leswal(*valp);
		if (match8(sym, "pclntab"))
			pclntab = leswal(*valp);
		if (match8(sym, "epclntab"))
			epclntab = leswal(*valp);
	}
	if (symtab==0 || esymtab==0 || pclntab==0 || epclntab==0) {
		werrstr("no symtab or esymtab or pclntab or epclntab in COFF symbol table");
		return 0;
	}
	setsym(fp, symtab, esymtab-symtab, 0, 0, pclntab, epclntab-pclntab);

	return 1;
}