/* * 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"); } }