1
0
mirror of https://github.com/golang/go synced 2024-11-18 12:14:42 -07:00

darwin support for 32-bit debugging

R=r
DELTA=129  (78 added, 1 deleted, 50 changed)
OCL=29411
CL=29413
This commit is contained in:
Russ Cox 2009-05-26 17:20:57 -07:00
parent 5273868f67
commit 7d73075511

View File

@ -29,10 +29,17 @@
#include <libc.h>
#include <bio.h>
#include <mach_amd64.h>
#define Ureg Ureg32
#include <ureg_x86.h>
#undef Ureg
#define Ureg Ureg64
#include <ureg_amd64.h>
typedef struct Ureg Ureg;
#undef Ureg
#undef waitpid /* want Unix waitpid, not Plan 9 */
typedef struct Ureg32 Ureg32;
typedef struct Ureg64 Ureg64;
extern mach_port_t mach_reply_port(void); // should be in system headers, is not
// Mach-error wrapper.
@ -423,67 +430,105 @@ machsegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
}
}
// Convert Ureg offset to x86_thread_state64_t offset.
// Convert Ureg offset to x86_thread_state32_t offset.
static int
go2darwin(uvlong addr)
go2darwin32(uvlong addr)
{
switch(addr){
case offsetof(Ureg, ax):
case offsetof(Ureg32, ax):
return offsetof(x86_thread_state32_t, eax);
case offsetof(Ureg32, bx):
return offsetof(x86_thread_state32_t, ebx);
case offsetof(Ureg32, cx):
return offsetof(x86_thread_state32_t, ecx);
case offsetof(Ureg32, dx):
return offsetof(x86_thread_state32_t, edx);
case offsetof(Ureg32, si):
return offsetof(x86_thread_state32_t, esi);
case offsetof(Ureg32, di):
return offsetof(x86_thread_state32_t, edi);
case offsetof(Ureg32, bp):
return offsetof(x86_thread_state32_t, ebp);
case offsetof(Ureg32, fs):
return offsetof(x86_thread_state32_t, fs);
case offsetof(Ureg32, gs):
return offsetof(x86_thread_state32_t, gs);
case offsetof(Ureg32, pc):
return offsetof(x86_thread_state32_t, eip);
case offsetof(Ureg32, cs):
return offsetof(x86_thread_state32_t, cs);
case offsetof(Ureg32, flags):
return offsetof(x86_thread_state32_t, eflags);
case offsetof(Ureg32, sp):
return offsetof(x86_thread_state32_t, esp);
}
return -1;
}
// Convert Ureg offset to x86_thread_state64_t offset.
static int
go2darwin64(uvlong addr)
{
switch(addr){
case offsetof(Ureg64, ax):
return offsetof(x86_thread_state64_t, rax);
case offsetof(Ureg, bx):
case offsetof(Ureg64, bx):
return offsetof(x86_thread_state64_t, rbx);
case offsetof(Ureg, cx):
case offsetof(Ureg64, cx):
return offsetof(x86_thread_state64_t, rcx);
case offsetof(Ureg, dx):
case offsetof(Ureg64, dx):
return offsetof(x86_thread_state64_t, rdx);
case offsetof(Ureg, si):
case offsetof(Ureg64, si):
return offsetof(x86_thread_state64_t, rsi);
case offsetof(Ureg, di):
case offsetof(Ureg64, di):
return offsetof(x86_thread_state64_t, rdi);
case offsetof(Ureg, bp):
case offsetof(Ureg64, bp):
return offsetof(x86_thread_state64_t, rbp);
case offsetof(Ureg, r8):
case offsetof(Ureg64, r8):
return offsetof(x86_thread_state64_t, r8);
case offsetof(Ureg, r9):
case offsetof(Ureg64, r9):
return offsetof(x86_thread_state64_t, r9);
case offsetof(Ureg, r10):
case offsetof(Ureg64, r10):
return offsetof(x86_thread_state64_t, r10);
case offsetof(Ureg, r11):
case offsetof(Ureg64, r11):
return offsetof(x86_thread_state64_t, r11);
case offsetof(Ureg, r12):
case offsetof(Ureg64, r12):
return offsetof(x86_thread_state64_t, r12);
case offsetof(Ureg, r13):
case offsetof(Ureg64, r13):
return offsetof(x86_thread_state64_t, r13);
case offsetof(Ureg, r14):
case offsetof(Ureg64, r14):
return offsetof(x86_thread_state64_t, r14);
case offsetof(Ureg, r15):
case offsetof(Ureg64, r15):
return offsetof(x86_thread_state64_t, r15);
case offsetof(Ureg, fs):
case offsetof(Ureg64, fs):
return offsetof(x86_thread_state64_t, fs);
case offsetof(Ureg, gs):
case offsetof(Ureg64, gs):
return offsetof(x86_thread_state64_t, gs);
case offsetof(Ureg, ip):
case offsetof(Ureg64, ip):
return offsetof(x86_thread_state64_t, rip);
case offsetof(Ureg, cs):
case offsetof(Ureg64, cs):
return offsetof(x86_thread_state64_t, cs);
case offsetof(Ureg, flags):
case offsetof(Ureg64, flags):
return offsetof(x86_thread_state64_t, rflags);
case offsetof(Ureg, sp):
case offsetof(Ureg64, sp):
return offsetof(x86_thread_state64_t, rsp);
}
return -1;
}
extern Mach mi386;
// Read/write from fake register segment.
static int
machregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
{
uint nn;
uint nn, count, state;
mach_port_t thread;
int reg;
char buf[100];
union {
x86_thread_state64_t regs;
x86_thread_state64_t reg64;
x86_thread_state32_t reg32;
uchar p[1];
} u;
uchar *p;
@ -499,21 +544,36 @@ machregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
return -1;
}
if((reg = go2darwin(addr)) < 0 || reg+n > sizeof u){
if(isr){
memset(v, 0, n);
return 0;
if(mach == &mi386) {
count = x86_THREAD_STATE32_COUNT;
state = x86_THREAD_STATE32;
if((reg = go2darwin32(addr)) < 0 || reg+n > sizeof u){
if(isr){
memset(v, 0, n);
return 0;
}
werrstr("register %llud not available", addr);
return -1;
}
} else {
count = x86_THREAD_STATE64_COUNT;
state = x86_THREAD_STATE64;
if((reg = go2darwin64(addr)) < 0 || reg+n > sizeof u){
if(isr){
memset(v, 0, n);
return 0;
}
werrstr("register %llud not available", addr);
return -1;
}
werrstr("register %llud not available", addr);
return -1;
}
if(!isr && me(thread_suspend(thread)) < 0){
werrstr("thread suspend %#x: %r", thread);
return -1;
}
nn = x86_THREAD_STATE64_COUNT;
if(me(thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&u.regs, &nn)) < 0){
nn = count;
if(me(thread_get_state(thread, state, (void*)u.p, &nn)) < 0){
if(!isr)
thread_resume(thread);
rerrstr(buf, sizeof buf);
@ -529,8 +589,8 @@ machregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
memmove(v, p, n);
else{
memmove(p, v, n);
nn = x86_THREAD_STATE64_COUNT;
if(me(thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&u.regs, nn)) < 0){
nn = count;
if(me(thread_set_state(thread, state, (void*)u.p, nn)) < 0){
thread_resume(thread);
werrstr("thread_set_state: %r");
return -1;
@ -546,7 +606,7 @@ machregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
enum
{
RFLAGS_TF = 0x100 // x86 single-step processor flag
FLAGS_TF = 0x100 // x86 single-step processor flag
};
// Is thread t suspended?
@ -572,25 +632,42 @@ threadstart(Thread *t, int singlestep)
int i;
uint n;
struct thread_basic_info info;
x86_thread_state64_t regs;
if(!threadstopped(t))
return 0;
// Set or clear the processor single-step flag, as appropriate.
n = x86_THREAD_STATE64_COUNT;
if(me(thread_get_state(t->thread, x86_THREAD_STATE64,
(thread_state_t)&regs,
&n)) < 0)
return -1;
if(singlestep)
regs.rflags |= RFLAGS_TF;
else
regs.rflags &= ~RFLAGS_TF;
if(me(thread_set_state(t->thread, x86_THREAD_STATE64,
(thread_state_t)&regs,
x86_THREAD_STATE64_COUNT)) < 0)
return -1;
if(mach == &mi386) {
x86_thread_state32_t regs;
n = x86_THREAD_STATE32_COUNT;
if(me(thread_get_state(t->thread, x86_THREAD_STATE32,
(thread_state_t)&regs,
&n)) < 0)
return -1;
if(singlestep)
regs.eflags |= FLAGS_TF;
else
regs.eflags &= ~FLAGS_TF;
if(me(thread_set_state(t->thread, x86_THREAD_STATE32,
(thread_state_t)&regs,
x86_THREAD_STATE32_COUNT)) < 0)
return -1;
} else {
x86_thread_state64_t regs;
n = x86_THREAD_STATE64_COUNT;
if(me(thread_get_state(t->thread, x86_THREAD_STATE64,
(thread_state_t)&regs,
&n)) < 0)
return -1;
if(singlestep)
regs.rflags |= FLAGS_TF;
else
regs.rflags &= ~FLAGS_TF;
if(me(thread_set_state(t->thread, x86_THREAD_STATE64,
(thread_state_t)&regs,
x86_THREAD_STATE64_COUNT)) < 0)
return -1;
}
// Run.
n = sizeof info;