This is NeXT-tdep.m in view mode; [Download] [Up]
#import "gdb.h" #import <mach/thread_status.h> extern thread_t current_thread; extern RegionManager *regionManager; /* * GDB and MACH have different ideas on the order which registers should * be stored. * * IU registers: * GDB order: * eax, ecx, edx, ebx, ebp, esp, esi, edi, eip, ps, cs, ss, ds, es, fs, gs * MACH order: * eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags, eip, * cs, ds, es, fs, gs * * FP registers: * GDB order: * fst0, fst1, fst2, fst3, fst4, fst5, fst6, fst7, fctrl, fstat, ftag, * fip, fcs, fopoff, fopsel * * MACH order: * (uses the structure defined in mach/i386/thread_status.h) */ /* * IU register ordering */ static int offset[] = { 0, 2, 3, 1, 7, 6, 5, 4, 10, 9, 11, 8, 12, 13, 14, 15 }; void copy_registers_in(regsState) i386_thread_state_t *regsState; { unsigned int *r = (unsigned int *) registers; unsigned int *rs = (unsigned int *) regsState; int i; for (i = 0; i < FP0_REGNUM; i++) r[i] = rs[offset[i]]; return; } void copy_registers_out(regsState) i386_thread_state_t *regsState; { unsigned int *r = (unsigned int *) registers; unsigned int *rs = (unsigned int *) regsState; int i; for (i = 0; i < FP0_REGNUM; i++) rs[offset[i]] = r[i]; return; } void copy_fp_registers_in(fpState) i386_thread_fpstate_t *fpState; { /* fp stack */ memcpy((char *) ®isters[REGISTER_BYTE(FP0_REGNUM)], (char *) &fpState->stack, sizeof(fp_stack_t)); /* fctrl, fstat, ftag */ *(unsigned short *)®isters[REGISTER_BYTE(FPC_REGNUM)] = *((unsigned short *) &fpState->environ.control); *(unsigned short *)®isters[REGISTER_BYTE(FPC_REGNUM+1)] = *((unsigned short *) &fpState->environ.status); *(unsigned short *)®isters[REGISTER_BYTE(FPC_REGNUM+2)] = *((unsigned short *) &fpState->environ.tag); /* fip */ *(unsigned *)®isters[REGISTER_BYTE(FPC_REGNUM+3)] = fpState->environ.ip; /* fcs, fdp, fds - don't copy opcode */ *(unsigned short *)®isters[REGISTER_BYTE(FPC_REGNUM+4)] = *((unsigned short *) &fpState->environ.cs); *(unsigned short *)®isters[REGISTER_BYTE(FPC_REGNUM+5)] = fpState->environ.dp; *(unsigned short *)®isters[REGISTER_BYTE(FPC_REGNUM+6)] = *((unsigned short *) &fpState->environ.ds); return; } void copy_fp_registers_out(fpState) i386_thread_fpstate_t *fpState; { /* fp stack */ memcpy((char *) &fpState->stack, (char *) ®isters[REGISTER_BYTE(FP0_REGNUM)], sizeof(fp_stack_t)); /* fctrl, fstat, ftag, fip */ *((unsigned short *) &fpState->environ.control) = *((unsigned short *) ®isters[REGISTER_BYTE(FPC_REGNUM)]); *((unsigned short *) &fpState->environ.status) = *((unsigned short *) ®isters[REGISTER_BYTE(FPC_REGNUM+1)]); *((unsigned short *) &fpState->environ.tag) = *((unsigned short *) ®isters[REGISTER_BYTE(FPC_REGNUM+2)]); /* fip */ fpState->environ.ip = *((unsigned int *) ®isters[REGISTER_BYTE(FPC_REGNUM+3)]); /* fcs, opcode, fdp, fds */ *((unsigned short *) &fpState->environ.cs) = *((unsigned short *) ®isters[REGISTER_BYTE(FPC_REGNUM + 4)]); fpState->environ.opcode = 0; fpState->environ.dp = *((unsigned int *) ®isters[REGISTER_BYTE(FPC_REGNUM + 5)]); *((unsigned short *) &fpState->environ.ds) = *(unsigned short *) ®isters[REGISTER_BYTE(FPC_REGNUM + 6)]; return; } void fetch_inferior_registers (regno) { int i; extern char registers[]; extern char register_valid[]; if (current_thread) { if (regno < FP0_REGNUM || regno == -1) { i386_thread_state_t regsState; unsigned regsCount = i386_THREAD_STATE_COUNT; mach_call(thread_get_state(current_thread, i386_THREAD_STATE, (thread_state_t)®sState, ®sCount), "thread_get_state", "fetch_inferior_registers"); copy_registers_in(®sState); for (i = 0; i < FP0_REGNUM; i++) register_valid[i] = 1; } /* get FP registers only if we have to */ if (regno >= FP0_REGNUM || regno == -1) { i386_thread_fpstate_t fpState; unsigned fpCount = i386_THREAD_FPSTATE_COUNT; mach_call(thread_get_state(current_thread, i386_THREAD_FPSTATE, (thread_state_t)&fpState, &fpCount), "thread_get_state", "fetch_inferior_registers"); copy_fp_registers_in(&fpState); for (i = FP0_REGNUM; i < NUM_REGS; i++) register_valid[i] = 1; } } } /* Store our register values back into the inferior. If REGNO is -1, do this for all registers. Otherwise, REGNO specifies which register (so we can save time). */ void store_inferior_registers(regno) { i386_thread_state_t regsState; i386_thread_fpstate_t fpState; unsigned regsCount = i386_THREAD_STATE_COUNT; unsigned fpCount = i386_THREAD_FPSTATE_COUNT; extern char registers[]; if (current_thread) { validateRegister(regno); if (!stopped_in_ptrace) mach_call(thread_abort(current_thread), "thread_abort", "store_inferior_registers"); if (regno < FP0_REGNUM || regno == -1) { i386_thread_state_t regsState; unsigned regsCount = i386_THREAD_STATE_COUNT; copy_registers_out(®sState); mach_call(thread_set_state(current_thread, i386_THREAD_STATE, (thread_state_t)®sState, regsCount), "thread_set_state", "store_inferior_registers"); } /* set FP registers only if we have to */ if (regno >= FP0_REGNUM || regno == -1) { i386_thread_fpstate_t fpState; unsigned fpCount = i386_THREAD_FPSTATE_COUNT; copy_fp_registers_out(&fpState); mach_call(thread_set_state(current_thread, i386_THREAD_FPSTATE, (thread_state_t)&fpState, fpCount), "thread_set_state", "store_inferior_registers"); } } } struct type * i386_register_virtual_type(regno) { switch (regno) { /* eax, ecx, edx, ebx, esi, edi, eflags */ case 0: case 1: case 2: case 3: case 6: case 7: case 9: return builtin_type_int; /* cs, ss, ds, es, fs, gs, fctrl, fstat, ftag, fcs, fds */ case 10: case 11: case 12: case 13: case 14: case 15: case 24: case 25: case 26: case 28: case 30: return builtin_type_unsigned_short; /* eip, ebp, esp, fip, fdp */ case 4: case 5: case 8: case 27: case 29: return lookup_pointer_type(builtin_type_void); /* fst0 - fst7 */ case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: return builtin_type_double; } } int getFirstTwoIntArgs(first, second) unsigned *first, *second; { unsigned *sp = (unsigned *)read_register(SP_REGNUM); unsigned *argsPtr = [regionManager pointerFor: sp + 1 withSize: 2 * sizeof(CORE_ADDR)]; if (argsPtr) { *first = *(argsPtr); *second = *(argsPtr + 1); return YES; } else { return NO; } } CORE_ADDR getBranch(pc) CORE_ADDR pc; { unsigned char *jmpSlot; jmpSlot = [regionManager pointerFor: (void *)pc withSize: 5]; return pc + 5 + *(CORE_ADDR *)(jmpSlot + 1); } #define JMPTABLEOFFSET 0x54 #define JMPOPCODE_I386 0xe9 #define TRAPOPCODE_I386 0xf4 void * jmpTableEnd(sectAddr, sect) CORE_ADDR sectAddr; struct section *sect; { struct _JmpSlot { unsigned char opcode; unsigned int arg; } *jmpSlot; void *endOfText; BOOL foundEnd = NO; for (jmpSlot = (struct _JmpSlot *)(sectAddr + JMPTABLEOFFSET), endOfText = (void *)(sectAddr + sect->size); !foundEnd && (jmpSlot < (struct _JmpSlot *)endOfText); ((char *)jmpSlot)+=5) { if ((jmpSlot->opcode != JMPOPCODE_I386) && (jmpSlot->opcode != TRAPOPCODE_I386)) foundEnd = YES; } return (void *) (sect->addr + (((void *) jmpSlot - 5)- sectAddr)); } cpu_type_t cpuType() { return CPU_TYPE_I386; } #pragma CC_OPT_OFF float convertRealToFloat(real) struct fp_data_reg *real; { float dst; asm ("fldtl %0" : : "g" (*real) : "st"); asm ("fsts %0" : "=m" (dst)); return dst; } double convertRealToDouble(real) struct fp_data_reg *real; { double dst; asm ("fldtl %0" : : "g" (*real) : "st"); asm ("fstl %0" : "=m" (dst)); return dst; } #pragma CC_OPT_ON void extractReturnValue(type, regBuf, valBuf) struct type *type; const char *regBuf; char *valBuf; { if (type->code == TYPE_CODE_FLT) { fp_status_t status = *(fp_status_t *) ®isters[REGISTER_BYTE(FPC_REGNUM+1)]; struct fp_data_reg *reg = (struct fp_data_reg *) ®Buf[REGISTER_BYTE(FP0_REGNUM)]; reg += ((status.tos + 1) % 8); if (TYPE_LENGTH(type) == 4) { *(float *) valBuf = convertRealToFloat(reg); } else { *(double *) valBuf = convertRealToDouble(reg); } } else if ((type->code == TYPE_CODE_STRUCT) && (type->length == 8)) { *(unsigned int *) valBuf = *(unsigned int *) regBuf; *(unsigned int *)(valBuf + 4) = *(unsigned int *)(regBuf + 8); } else { bcopy (regBuf, valBuf, TYPE_LENGTH (type)); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.