Ejemplo n.º 1
0
/*
 * Loads an ELF 32 executable.
 */
PRIVATE addr_t load_elf32(struct inode *inode)
{
	int i;                  /* Loop index.                    */
	addr_t addr;            /* Region address.                */
	addr_t entry;           /* Program entry point.           */
	struct elf32_fhdr *elf; /* ELF file header.               */
	struct elf32_phdr *seg; /* ELF Program header.            */
	block_t blk;            /* Working block number.          */
	buffer_t header;        /* File headers block buffer.     */
	struct region *reg;     /* Working memory region.         */
	struct pregion *preg;   /* Working process memory region. */
	
	blk = block_map(inode, 0, 0);
	
	/* Empty file. */
	if (blk == BLOCK_NULL)
	{
		curr_proc->errno = -ENOEXEC;
		return (0);
	}
	
	/* Read ELF file header. */
	header = bread(inode->dev, blk);
	elf = buffer_data(header);
	
	/* Bad ELF file. */
	if (!is_elf(elf))
	{
		brelse(header);
		curr_proc->errno = -ENOEXEC;
		return (0);
	}
	
	/* Bad ELF file. */
	if (elf->e_phoff + elf->e_phnum*elf->e_phentsize > BLOCK_SIZE)
	{
		brelse(header);
		curr_proc->errno = -ENOEXEC;
		return (0);
	}
	
	seg = (struct elf32_phdr *)((char *)buffer_data(header) + elf->e_phoff);
	
	/* Load segments. */
	for (i = 0; i < elf->e_phnum; i++)
	{
		/* Not loadable. */
		if (seg[i].p_type != PT_LOAD)
			continue;
		
		/* Broken executable. */
		if (seg[i].p_filesz > seg[i].p_memsz)
		{
			kprintf("broken executable");
			
			brelse(header);
			curr_proc->errno = -ENOEXEC;
			return (0);
		}
		
		addr = ALIGN(seg[i].p_vaddr, seg[i].p_align);
		
		/* Text section. */
		if (!(seg[i].p_flags ^ (PF_R | PF_X)))
		{
			preg = TEXT(curr_proc);
			reg = allocreg(S_IRUSR | S_IXUSR, seg[i].p_memsz, 0);
		}
		
		/* Data section. */
		else
		{
			preg = DATA(curr_proc);
			reg = allocreg(S_IRUSR | S_IWUSR, seg[i].p_memsz, 0);
		}
		
		/* Failed to allocate region. */
		if (reg == NULL)
		{
			brelse(header);
			curr_proc->errno = -ENOMEM;
			return (0);
		}
		
		/* Attach memory region. */
		if (attachreg(curr_proc, preg, addr, reg))
		{
			freereg(reg);
			brelse(header);
			curr_proc->errno = -ENOMEM;
			return (0);
		}
		
		loadreg(inode, reg, seg[i].p_offset, seg[i].p_filesz);
		
		unlockreg(reg);	
	}
	
	entry = elf->e_entry;
	
	brelse(header);
	
	return (entry);
}
void transquad(context* ctx, assembly* casm, int quadnum)
{
	operand o = {0}, o1 = {0}, o2 = {0};
	int local, temp;	/* this frame's (caller) size */
	int dlocal, dtemp;	/* next frame's (callee) size, used by calls */
	quadruple* quad;
	symbol* s = getquadfunc(ctx, quadnum);
	local = (s==0?0:s->localsize);
	temp = (s==0?0:s->tempsize);
	quad = &ctx->prog->quadruples[quadnum];
	s = getquadfunc(ctx, quad->opdest.entity.entity.ival);
	dlocal = (s==0?0:s->localsize);
	dtemp = (s==0?0:s->tempsize);
	switch (quad->op)
	{
	case opAssign:
		loadreg(ctx, casm, &quad->op1, ra, local, temp);
		storereg(ctx, casm, &quad->opdest, ra, local, temp);
		break;
	case opNeg:			case opNot:			case opBitcom: case opFact:
		loadreg(ctx, casm, &quad->op1, ra, local, temp);
		o.ival = ra;
		emit(ctx, casm, quad->op, &o, &o, &o);
		storereg(ctx, casm, &quad->opdest, ra, local, temp);
		break;
	case opLogand:		case opLogor:		case opBitand:	case opBitor:
	case opBitxor:		case opLshift:		case opRshift:	case opAdd:
	case opMinus:		case opMultiply:	case opDivide:	case opMod:
	case opEqual:		case opNeq:			case opGreater:	case opGeq:
	case opLess:		case opLeq:			case opConcat: case opPower:
	case opClass:       case opTEqual:		case opTNeq:
		loadreg(ctx, casm, &quad->op1, ra, local, temp);
		loadreg(ctx, casm, &quad->op2, rb, local, temp);
		o.ival = ra;	o1.ival = rb;
		emit(ctx, casm, quad->op, &o, &o1, &o);
		storereg(ctx, casm, &quad->opdest, ra, local, temp);
		break;
	case opPush:
		loadreg(ctx, casm, &quad->opdest, ra, local, temp);
		o.ival = ra;
		emit(ctx, casm, quad->op, 0, 0, &o);
		break;
	case opPop:
		o.ival = quad->op2.entity.entity.ival+1;		/* shrink offset */
		o1.ival = quad->opdest.entity.entity.offset;/* pop target temporary offset */
		o2.ival = local+temp;	/* frame size */
		emit(ctx, casm, quad->op, &o, &o1, &o2);
		break;
	case opJz:			case opJnz:
		loadreg(ctx, casm, &quad->op1, ra, local, temp);
		o.ival = ra;	o2.ival = quad->opdest.entity.entity.ival;
		emit(ctx, casm, quad->op, &o, &o1, &o2);
		break;
	case opJmp:		case opHalt:	case opCall:	case opCallhost:
	case opTRCall:
		o.ival = quad->op2.entity.entity.ival;
		o1.ival = dlocal+dtemp;	/* for opCall to grow the stack */
		o2.ival = quad->opdest.entity.entity.ival;
		emit(ctx, casm, quad->op, &o, &o1, &o2);
		break;
	case opCallin:
		loadreg(ctx, casm, &quad->opdest, rb, local, temp);
		o1.ival = dlocal+dtemp;	/* for opCall to grow the stack */
		o2.ival = rb;
		emit(ctx, casm, quad->op, &o, &o1, &o2);
		break;
	case opRet:
		loadreg(ctx, casm, &quad->opdest, ra, local, temp);
		o.ival = rf;	o1.ival = 1;	o2.ival = ra;
		emit(ctx, casm, opST, &o, &o1, &o2);	/* [rf+1] = ret val */
		emit(ctx, casm, quad->op, NULL, NULL, NULL);
		break;
	case opYield:
		loadreg(ctx, casm, &quad->opdest, ra, local, temp);
		o.ival = rs;	o1.ival = 0;	o2.ival = ra;
		emit(ctx, casm, opST, &o, &o1, &o2);	/* [rs] = ret val */
		emit(ctx, casm, quad->op, NULL, NULL, NULL);
		break;
	case opSaveexc:
		storereg(ctx, casm, &quad->opdest, re, local, temp);
		break;
	case opThrow:
		loadreg(ctx, casm, &quad->opdest, ra, local, temp);
		o.ival = ra;
		emit(ctx, casm, quad->op, NULL, NULL, &o);
		break;
	case opStart:
		emit(ctx, casm, quad->op, NULL, NULL, &o);
		break;
	case opUpdate:
		loadreg(ctx, casm, &quad->op1, ra, local, temp);
		o.ival = ra; o1.ival = rb;
		emit(ctx, casm, quad->op, &o, NULL, &o1);
		storereg(ctx, casm, &quad->opdest, rb, local, temp);
		break;
	case opCopy:
		emit(ctx, casm, quad->op, 0, 0, 0);
		storereg(ctx, casm, &quad->op1, ra, local, temp);
		storereg(ctx, casm, &quad->op2, rb, local, temp);
		break;
	case opSave:
		emit(ctx, casm, quad->op, 0, 0, 0);
		storereg(ctx, casm, &quad->op1, ra, local, temp);
		storereg(ctx, casm, &quad->op2, rb, local, temp);
		break;
	case opRestore:
		loadreg(ctx, casm, &quad->op1, ra, local, temp);
		loadreg(ctx, casm, &quad->op2, rb, local, temp);
		emit(ctx, casm, quad->op, 0, 0, 0);
		break;
	case opNewtable:
		o2.ival = ra;
		emit(ctx, casm, quad->op, NULL, NULL, &o2);
		storereg(ctx, casm, &quad->opdest, ra, local, temp);
		break;
	case opIR:
		loadreg(ctx, casm, &quad->op1, ra, local, temp);
		loadreg(ctx, casm, &quad->op2, rb, local, temp);
		o.ival = ra;	o1.ival = rb;	o2.ival = ra;
		emit(ctx, casm, quad->op, &o, &o1, &o2);
		storereg(ctx, casm, &quad->opdest, ra, local, temp);
		break;
	case opIA:
		loadreg(ctx, casm, &quad->op1, ra, local, temp);
		loadreg(ctx, casm, &quad->op2, rb, local, temp);
		loadreg(ctx, casm, &quad->opdest, rc, local, temp);
		o.ival = ra;	o1.ival = rb;	o2.ival = rc;
		emit(ctx, casm, quad->op, &o, &o1, &o2);
		break;
	default:
		error("Unknown quadruple.\n");
	}
}