void do_pending_stack_adjust (void) { if (inhibit_defer_pop == 0) { if (pending_stack_adjust != 0) adjust_stack (GEN_INT (pending_stack_adjust)); pending_stack_adjust = 0; } }
void load(int r, SValue* sv) { int fr,ft,fc; int length; int align; int v,sign,t; SValue v1; pr("; load %d\n",r); pr("; type %d reg 0x%x extra 0x%x\n",sv->type.t,sv->r,sv->type.extra); fr = sv->r; ft = sv->type.t; fc = sv->c.ul; length = type_size(&sv->type, &align); if((ft & VT_BTYPE) == VT_LLONG) length = 2; // long longs are handled word-wise if(ll_workaround) length = 4; //pr("; load r 0x%x fr 0x%x ft 0x%x fc 0x%x\n",r,fr,ft,fc); #if 0 // FIXME: Does that make sense? if(fc>0) sign=0; else { sign = 1; fc = -fc; } #endif int base = -1; v = fr & VT_VALMASK; if(fr & VT_LVAL) { if(v == VT_LLOCAL) { v1.type.t = VT_PTR; v1.r = VT_LOCAL | VT_LVAL; v1.c.ul = sv->c.ul; load(base=10 /* lr */, &v1); fc=sign=0; v=VT_LOCAL; } else if(v == VT_CONST) { if(fr & VT_SYM) { // deref symbol + displacement char* sy = get_sym_str(sv->sym); if(is_float(ft)) { pr("; fld%d [%s + %d], tcc__f%d\n", length, sy, fc, r - TREG_F0); switch(length) { case 4: pr("lda.l %s + %d\nsta.b tcc__f%d\nlda.l %s + %d + 2\nsta.b tcc__f%dh\n", sy, fc, r - TREG_F0, sy, fc, r - TREG_F0); break; default: error("ICE 1"); } } else { pr("; ld%d [%s + %d], tcc__r%d\n", length, sy, fc, r); // FIXME: This implementation is moronic if(fc > 65535) error("index too big"); switch(length) { case 1: pr("lda.w #0\nsep #$20\nlda.l %s + %d\nrep #$20\n", sy, fc); if(!(ft & VT_UNSIGNED)) pr("xba\nxba\nbpl +\nora.w #$ff00\n+\n"); pr("sta.b tcc__r%d\n", r); break; //case 2: pr("stz.b tcc__r%dh\nldx #%d\nlda.l %s,x\nsta.b tcc__r%d\n", r, fc, sy, r); break; case 2: pr("lda.l %s + %d\nsta.b tcc__r%d\n", sy, fc, r); break; case 4: pr("lda.l %s + %d\nsta.b tcc__r%d\nlda.l %s + %d + 2\nsta.b tcc__r%dh\n", sy, fc, r, sy, fc, r); break; default: error("ICE 1"); } } } else { // deref constant pointer //error("ld [%d],tcc__r%d\n",fc,r); pr("; deref constant ptr ld [%d],tcc__r%d\n", fc, r); if(is_float(ft)) { error("dereferencing constant float pointers unimplemented\n"); } else { switch(length) { case 1: pr("lda.w #0\nsep #$20\nlda.l %d\nrep #$20\n", fc); if(!(ft & VT_UNSIGNED)) pr("xba\nxba\nbpl +\nora.w #$ff00\n+\n"); pr("sta.b tcc__r%d\n", r); break; case 2: pr("lda.l %d\nsta.b tcc__r%d\n", fc, r); break; case 4: pr("lda.l %d\nsta.b tcc__r%d\nlda.l %d + 2\nsta.b tcc__r%dh\n", fc, r, fc, r); break; default: error("ICE 1"); } } } return; } else if(v < VT_CONST) { // deref pointer in register base = v; fc = sign = 0; v = VT_LOCAL; } if(v == VT_LOCAL) { if(is_float(ft)) { if(base == -1) { pr("; fld%d [sp,%d],tcc__f%d\n", length, fc, r - TREG_F0); if(length != 4) error("ICE 2f"); fc = adjust_stack(fc, args_size + 2); pr("lda %d + __%s_locals + 1,s\nsta.b tcc__f%d\nlda %d + __%s_locals + 1,s\nsta.b tcc__f%dh\n", fc+args_size, current_fn, r - TREG_F0, fc+args_size+2, current_fn, r - TREG_F0); fc = restore_stack(fc); } else { pr("; fld%d [tcc__r%d,%d],tcc__f%d\n", length, base, fc, r - TREG_F0); if(length != 4) error("ICE 3f"); pr("ldy #%d\nlda.b [tcc__r%d],y\nsta.b tcc__f%d\niny\niny\nlda.b [tcc__r%d], y\nsta.b tcc__f%dh\n", fc, base, r - TREG_F0, base, r - TREG_F0); } } else { if(base == -1) { // value of local at fc pr("; ld%d [sp,%d],tcc__r%d\n",length,fc,r); //if(length == 2 && fc == -88 && r == 0) asm("int $3"); fc = adjust_stack(fc, args_size + 2); switch(length) { case 1: pr("lda.w #0\nsep #$20\nlda %d + __%s_locals + 1,s\nrep #$20\n", fc+args_size, current_fn); if(!(ft & VT_UNSIGNED)) pr("xba\nxba\nbpl +\nora.w #$ff00\n+\n"); pr("sta.b tcc__r%d\n", r); break; //case 2: pr("stz.b tcc__r%dh\nlda %d + __%s_locals + 1,s\nsta.b tcc__r%d\n", r, fc+args_size, current_fn, r); break; case 2: pr("lda %d + __%s_locals + 1,s\nsta.b tcc__r%d\n", fc+args_size, current_fn, r); break; case 4: pr("lda %d + __%s_locals + 1,s\nsta.b tcc__r%d\nlda %d + __%s_locals + 1,s\nsta.b tcc__r%dh\n", fc+args_size, current_fn, r, fc+args_size + 2, current_fn, r); break; default: error("ICE 2"); break; } fc = restore_stack(fc); } else { // value of array member r[fc] pr("; ld%d [tcc__r%d,%d],tcc__r%d\n",length, base, fc, r); switch(length) { case 1: pr("lda.w #0\n"); if(!fc) pr("sep #$20\nlda.b [tcc__r%d]\nrep #$20\n", base); else pr("ldy #%d\nsep #$20\nlda.b [tcc__r%d],y\nrep #$20\n", fc, base); if(!(ft & VT_UNSIGNED)) pr("xba\nxba\nbpl +\nora.w #$ff00\n+\n"); pr("sta.b tcc__r%d\n", r); break; //case 2: pr("stz.b tcc__r%dh\nldy #%d\nlda.b [tcc__r%d],y\nsta.b tcc__r%d\n", r, fc, base, r); break; case 2: if(!fc) pr("lda.b [tcc__r%d]\nsta.b tcc__r%d\n", base, r); else pr("ldy #%d\nlda.b [tcc__r%d],y\nsta.b tcc__r%d\n", fc, base, r); break; case 4: pr("ldy #%d\nlda.b [tcc__r%d],y\nsta.b tcc__r%d\niny\niny\nlda.b [tcc__r%d],y\nsta.b tcc__r%dh\n", fc, base, r, base, r); break; default: error("ICE 3"); break; } } } return; } } else { // VT_LVAL if(v == VT_CONST) { if(fr & VT_SYM) { // symbolic constant //greloc(cur_text_section, sv->sym, ind, R_DATA_32); char* sy = get_sym_str(sv->sym); pr("; ld%d #%s + %d, tcc__r%d (type 0x%x)\n", length,sy, fc, r, ft); if(length != PTR_SIZE) pr("; FISHY! length <> PTR_SIZE! (may be an array)\n"); pr("lda.w #:%s\nsta.b tcc__r%dh\nlda.w #%s + %d\nsta.b tcc__r%d\n", sy, r, sy, fc, r); } else { // numeric constant pr("; ld%d #%d,tcc__r%d\n",length,sv->c.ul,r); if((ft & VT_BTYPE) == VT_BOOL) { sv->c.ul = sv->c.ul? 1: 0; } switch(length) { case 1: if (ft & VT_UNSIGNED) { pr("lda.w #%d\n", sv->c.ul & 0xff); } else { pr("lda.w #%d\n", ((short)((sv->c.ul & 0xff) << 8)) >> 8); } pr("sta.b tcc__r%d\n", r); break; //case 2: pr("stz.b tcc__r%dh\nlda.w #%d\nsta.b tcc__r%d\n", r, sv->c.ul & 0xffff, r); break; case 2: pr("lda.w #%d\nsta.b tcc__r%d\n", sv->c.ul & 0xffff, r); break; case 4: pr("lda.w #%d\nsta.b tcc__r%d\nlda.w #%d\nsta.b tcc__r%dh\n", sv->c.ul & 0xffff, r, sv->c.ul >> 16, r); break; default: error("ICE 4"); } } return; } else if(v == VT_LOCAL) { if(fr & VT_SYM) { error("symbol"); char* sy = get_sym_str(sv->sym); pr("; LOCAL ld%d #%s, tcc__r%d (type 0x%x)\n", length,sy, r, ft); } else { // local pointer pr("; ld%d #(sp) + %d,tcc__r%d (fr 0x%x ft 0x%x fc 0x%x)\n",length,sv->c.ul,r,fr,ft,fc); // pointer; have to ensure the upper word is correct (page 0) pr("stz.b tcc__r%dh\ntsa\nclc\nadc #(%d + __%s_locals + 1)\nsta.b tcc__r%d\n", r, sv->c.ul + args_size, current_fn, r); } return; } else if(v == VT_CMP) { error("cmp"); return; } else if(v == VT_JMP || v == VT_JMPI) { t = v & 1; // inverted or not pr("; jmpr(i) v 0x%x r 0x%x fc 0x%x\n",v,r,fc); pr("lda #%d\nbra +\n", t); gsym(fc); //pr("lda #%d\n+ stz tcc__r%dh\nsta tcc__r%d\n", t^1, r,r); pr("lda #%d\n+\nsta.b tcc__r%d\n", t^1, r); // stz rXh seems to be unnecessary (we only look at the lower word) return; } else if(v < VT_CONST) { // register value if(is_float(ft)) { //error("float 1"); v -= TREG_F0; r -= TREG_F0; pr("; fmov tcc__f%d, tcc__f%d\n", v, r); pr("lda.b tcc__f%d\nsta.b tcc__f%d\nlda.b tcc__f%dh\nsta.b tcc__f%dh\n", v, r, v, r); } else { pr("; mov tcc__r%d, tcc__r%d\n",v,r); pr("lda.b tcc__r%d\nsta.b tcc__r%d\nlda.b tcc__r%dh\nsta.b tcc__r%dh\n", v, r, v, r); } return; } }
int dumpcore(pid_t pid) { int r, seg, fd; vir_bytes len; off_t off, seg_off; long data; struct mem_map segs[NR_LOCAL_SEGS]; struct proc procentry; ssize_t w; char core_name[PATH_MAX]; /* Get the process table entry for this process. */ len = sizeof(struct proc) / sizeof(long); for (off = 0; off < len; off++) { errno = 0; data = ptrace(T_GETUSER, pid, off * sizeof(long), 0); if (data == -1 && errno != 0) { perror("ptrace(T_GETUSER)"); return 1; } ((long *) &procentry)[off] = data; } memcpy(segs, procentry.p_memmap, sizeof(segs)); /* Correct and reduce the stack segment. */ r = adjust_stack(pid, &segs[S]); if (r != 0) goto error; /* Create a core file with a temporary, unique name. */ sprintf(core_name, "core.%d", pid); if((fd = open(core_name, O_CREAT|O_EXCL|O_WRONLY, 0600)) < 0) { fprintf(stderr, "couldn't open %s (%s)\n", core_name, strerror(errno)); return 1; } /* Write out the process's segments. */ if((w=write(fd, segs, sizeof(segs))) != sizeof(segs)) { if(w < 0) printf("write error: %s\n", strerror(errno)); printf( "segs write failed: %d/%d\n", w, sizeof(segs)); goto error; } /* Write out the whole kernel process table entry to get the regs. */ if((w=write(fd, &procentry, sizeof(procentry))) != sizeof(procentry)) { if(w < 0) printf("write error: %s\n", strerror(errno)); printf( "proc write failed: %d/%d\n", w, sizeof(procentry)); goto error; } /* Loop through segments and write the segments themselves out. */ for (seg = 0; seg < NR_LOCAL_SEGS; seg++) { len= segs[seg].mem_len << CLICK_SHIFT; seg_off= segs[seg].mem_vir << CLICK_SHIFT; r= write_seg(fd, pid, seg, seg_off, len); if (r != 0) goto error; } /* Give the core file its final name. */ if (rename(core_name, "core")) { perror("rename"); goto error; } close(fd); return 0; error: close(fd); unlink(core_name); return 1; }