Browse Source
* gnu-nat.c, gnu-nat.h, msg.defs, exc_request.defs, i386gnu-nat.c,
msg_reply.defs, notify.defs, process_reply.defs, reply_mig_hack.awk,
config/nm-gnu.h, config/i386/{i386gnu.mh, i386gnu.mt, nm-gnu.h,
m-i386gnu.h, xm-i386gnu.h}: New files for GNU hurd.
gdb-4_18-branch
17 changed files with 3594 additions and 1 deletions
@ -0,0 +1,22 @@ |
|||
/* Native-dependent definitions for Intel 386 running the GNU Hurd
|
|||
Copyright 1994, 1995 Free Software Foundation, Inc. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|||
|
|||
/* Include the generic hurd definitions. */ |
|||
|
|||
#include "nm-gnu.h" |
|||
@ -0,0 +1,48 @@ |
|||
/* Macro definitions for i386, GNU Hurd
|
|||
Copyright (C) 1992 Free Software Foundation, Inc. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|||
|
|||
/* Include common definitions for gnu systems */ |
|||
#include "nm-gnu.h" |
|||
|
|||
/* Thread flavors used in re-setting the T bit.
|
|||
* @@ this is also bad for cross debugging. |
|||
*/ |
|||
#define THREAD_STATE_FLAVOR i386_THREAD_STATE |
|||
#define THREAD_STATE_SIZE i386_THREAD_STATE_COUNT |
|||
#define THREAD_STATE_SET_TRACED(state) \ |
|||
((struct i386_thread_state *)state)->efl |= 0x100 |
|||
#define THREAD_STATE_CLEAR_TRACED(state) \ |
|||
((((struct i386_thread_state *)state)->efl &= ~0x100), 1) |
|||
|
|||
/* we can do it */ |
|||
#define ATTACH_DETACH 1 |
|||
|
|||
/* Sigh. There should be a file for i386 but no sysv stuff in it */ |
|||
#include "i386/tm-i386v.h" |
|||
|
|||
/* I want to test this float info code. See comment in tm-i386v.h */ |
|||
#undef FLOAT_INFO |
|||
#define FLOAT_INFO { i386_mach3_float_info (); } |
|||
|
|||
/* Address of end of stack space.
|
|||
* for MACH, see <machine/vmparam.h> |
|||
* @@@ I don't know what is in the 5 ints... |
|||
*/ |
|||
#undef STACK_END_ADDR |
|||
#define STACK_END_ADDR (0xc0000000-sizeof(int [5])) |
|||
@ -0,0 +1,23 @@ |
|||
/* Definitions to make GDB run on the GNU Hurd on an Intel 386
|
|||
Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|||
|
|||
#define HOST_BYTE_ORDER LITTLE_ENDIAN |
|||
|
|||
/* Do implement the attach and detach commands. */ |
|||
#define ATTACH_DETACH 1 |
|||
@ -0,0 +1,46 @@ |
|||
/* Common declarations for the GNU Hurd
|
|||
|
|||
Copyright (C) 1995 Free Software Foundation, Inc. |
|||
|
|||
Written by Miles Bader <miles@gnu.ai.mit.edu> |
|||
|
|||
The GNU Hurd is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU General Public License as |
|||
published by the Free Software Foundation; either version 2, or (at |
|||
your option) any later version. |
|||
|
|||
The GNU Hurd is distributed in the hope that it will be useful, but |
|||
WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|||
|
|||
#ifndef __NM_GNU_H__ |
|||
#define __NM_GNU_H__ |
|||
|
|||
#include <unistd.h> |
|||
#include <mach.h> |
|||
#include <mach/exception.h> |
|||
|
|||
#include "solib.h" /* Support for shared libraries. */ |
|||
|
|||
#undef target_pid_to_str |
|||
#define target_pid_to_str(pid) gnu_target_pid_to_str(pid) |
|||
extern char *gnu_target_pid_to_str (int pid); |
|||
|
|||
/* Before storing, we need to read all the registers. */ |
|||
#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES) |
|||
|
|||
/* Don't do wait_for_inferior on attach. */ |
|||
#define ATTACH_NO_WAIT |
|||
|
|||
/* Use SVR4 style shared library support */ |
|||
#define SVR4_SHARED_LIBS |
|||
#define NO_CORE_OPS |
|||
|
|||
#define MAINTENANCE_CMDS 1 |
|||
|
|||
#endif /* __NM_GNU_H__ */ |
|||
@ -0,0 +1,51 @@ |
|||
/* |
|||
* Mach Operating System |
|||
* Copyright (c) 1993,1991,1990,1989,1988,1987 Carnegie Mellon University |
|||
* All Rights Reserved. |
|||
* |
|||
* Permission to use, copy, modify and distribute this software and its |
|||
* documentation is hereby granted, provided that both the copyright |
|||
* notice and this permission notice appear in all copies of the |
|||
* software, derivative works or modified versions, and any portions |
|||
* thereof, and that both notices appear in supporting documentation. |
|||
* |
|||
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
|||
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR |
|||
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
|||
* |
|||
* Carnegie Mellon requests users of this software to return to |
|||
* |
|||
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
|||
* School of Computer Science |
|||
* Carnegie Mellon University |
|||
* Pittsburgh PA 15213-3890 |
|||
* |
|||
* any improvements or extensions that they make and grant Carnegie Mellon |
|||
* the rights to redistribute these changes. |
|||
*/ |
|||
|
|||
/* |
|||
* Abstract: |
|||
* MiG definitions file for Mach exception interface (request half). |
|||
*/ |
|||
|
|||
subsystem exc 2400; |
|||
|
|||
#include <mach/std_types.defs> |
|||
|
|||
#ifdef USERPREFIX |
|||
userprefix USERPREFIX; |
|||
#endif |
|||
|
|||
#ifdef SERVERPREFIX |
|||
serverprefix SERVERPREFIX; |
|||
#endif |
|||
|
|||
simpleroutine exception_raise_request ( |
|||
exception_port : mach_port_t; |
|||
replyport reply : mach_port_send_once_t; |
|||
thread : mach_port_t; |
|||
task : mach_port_t; |
|||
exception : integer_t; |
|||
code : integer_t; |
|||
subcode : integer_t); |
|||
File diff suppressed because it is too large
@ -0,0 +1,91 @@ |
|||
/* Common things used by the various *gnu-nat.c files
|
|||
|
|||
Copyright (C) 1995 Free Software Foundation, Inc. |
|||
|
|||
Written by Miles Bader <miles@gnu.ai.mit.edu> |
|||
|
|||
The GNU Hurd is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU General Public License as |
|||
published by the Free Software Foundation; either version 2, or (at |
|||
your option) any later version. |
|||
|
|||
The GNU Hurd is distributed in the hope that it will be useful, but |
|||
WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|||
|
|||
#ifndef __GNU_NAT_H__ |
|||
#define __GNU_NAT_H__ |
|||
|
|||
#include <unistd.h> |
|||
#include <mach.h> |
|||
|
|||
struct inf; |
|||
|
|||
extern struct inf *current_inferior; |
|||
|
|||
/* Converts a GDB pid to a struct proc. */ |
|||
struct proc *inf_tid_to_thread (struct inf *inf, int tid); |
|||
|
|||
/* A proc is either a thread, or the task (there can only be one task proc
|
|||
because it always has the same TID, PROC_TID_TASK). */ |
|||
struct proc |
|||
{ |
|||
thread_t port; /* The task or thread port. */ |
|||
int tid; /* The GDB pid (actually a thread id). */ |
|||
int num; /* An id number for threads, to print. */ |
|||
|
|||
mach_port_t saved_exc_port; /* The task/thread's real exception port. */ |
|||
mach_port_t exc_port; /* Our replacement, which for. */ |
|||
|
|||
int sc; /* Desired suspend count. */ |
|||
int cur_sc; /* Implemented suspend count. */ |
|||
int run_sc; /* Default sc when the program is running. */ |
|||
int pause_sc; /* Default sc when gdb has control. */ |
|||
int resume_sc; /* Sc resulting form the last resume. */ |
|||
|
|||
thread_state_data_t state; /* Registers, &c. */ |
|||
int state_valid : 1; /* True if STATE is up to date. */ |
|||
int state_changed : 1; |
|||
|
|||
int aborted : 1; /* True if thread_abort has been called. */ |
|||
|
|||
/* Bit mask of registers fetched by gdb. This is used when we re-fetch
|
|||
STATE after aborting the thread, to detect that gdb may have out-of-date |
|||
information. */ |
|||
unsigned long fetched_regs; |
|||
|
|||
struct inf *inf; /* Where we come from. */ |
|||
|
|||
struct proc *next; |
|||
}; |
|||
|
|||
/* The task has a thread entry with this TID. */ |
|||
#define PROC_TID_TASK (-1) |
|||
|
|||
#define proc_is_task(proc) ((proc)->tid == PROC_TID_TASK) |
|||
#define proc_is_thread(proc) ((proc)->tid != PROC_TID_TASK) |
|||
|
|||
extern int __proc_pid (struct proc *proc); |
|||
|
|||
extern thread_state_t proc_get_state (struct proc *proc, int will_modify); |
|||
|
|||
#define proc_debug(_proc, msg, args...) \ |
|||
do { struct proc *__proc = (_proc); \ |
|||
debug ("{proc %d/%d %p}: " msg, \ |
|||
__proc_pid (__proc), __proc->tid, __proc , ##args); } while (0) |
|||
|
|||
#if MAINTENANCE_CMDS |
|||
extern int gnu_debug_flag; |
|||
#define debug(msg, args...) \ |
|||
do { if (gnu_debug_flag) \ |
|||
fprintf (stderr, "%s: " msg "\r\n", __FUNCTION__ , ##args); } while (0) |
|||
#else |
|||
#define debug(msg, args...) (void)0 |
|||
#endif |
|||
|
|||
#endif /* __GNU_NAT_H__ */ |
|||
@ -0,0 +1,348 @@ |
|||
/* Low level interface to I386 running the GNU Hurd
|
|||
Copyright (C) 1992 Free Software Foundation, Inc. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|||
|
|||
#include "defs.h" |
|||
#include "inferior.h" |
|||
#include "floatformat.h" |
|||
|
|||
#include <stdio.h> |
|||
|
|||
#include <mach.h> |
|||
#include <mach/message.h> |
|||
#include <mach/exception.h> |
|||
#include <mach_error.h> |
|||
|
|||
#include "gnu-nat.h" |
|||
|
|||
/* Hmmm... Should this not be here?
|
|||
* Now for i386_float_info() target_has_execution |
|||
*/ |
|||
#include <target.h> |
|||
|
|||
/* @@@ Should move print_387_status() to i387-tdep.c */ |
|||
extern void print_387_control_word (); /* i387-tdep.h */ |
|||
extern void print_387_status_word (); |
|||
|
|||
/* Find offsets to thread states at compile time.
|
|||
* If your compiler does not grok this, calculate offsets |
|||
* offsets yourself and use them (or get a compatible compiler :-) |
|||
*/ |
|||
|
|||
#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg) |
|||
|
|||
/* at reg_offset[i] is the offset to the i386_thread_state
|
|||
* location where the gdb registers[i] is stored. |
|||
*/ |
|||
|
|||
static int reg_offset[] = |
|||
{ |
|||
REG_OFFSET(eax), REG_OFFSET(ecx), REG_OFFSET(edx), REG_OFFSET(ebx), |
|||
REG_OFFSET(uesp), REG_OFFSET(ebp), REG_OFFSET(esi), REG_OFFSET(edi), |
|||
REG_OFFSET(eip), REG_OFFSET(efl), REG_OFFSET(cs), REG_OFFSET(ss), |
|||
REG_OFFSET(ds), REG_OFFSET(es), REG_OFFSET(fs), REG_OFFSET(gs) |
|||
}; |
|||
|
|||
#define REG_ADDR(state,regnum) ((char *)(state)+reg_offset[regnum]) |
|||
|
|||
/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
|
|||
* Caller knows that the regs handled in one transaction are of same size. |
|||
*/ |
|||
#define FETCH_REGS(state, regnum, count) \ |
|||
memcpy (®isters[REGISTER_BYTE (regnum)], \ |
|||
REG_ADDR (state, regnum), \ |
|||
count * REGISTER_RAW_SIZE (regnum)) |
|||
|
|||
/* Store COUNT contiguous registers to thread STATE starting from REGNUM */ |
|||
#define STORE_REGS(state, regnum, count) \ |
|||
memcpy (REG_ADDR (state, regnum), \ |
|||
®isters[REGISTER_BYTE (regnum)], \ |
|||
count * REGISTER_RAW_SIZE (regnum)) |
|||
|
|||
/*
|
|||
* Fetch inferiors registers for gdb. |
|||
* REG specifies which (as gdb views it) register, -1 for all. |
|||
*/ |
|||
void |
|||
gnu_fetch_registers (int reg) |
|||
{ |
|||
thread_state_t state; |
|||
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid); |
|||
|
|||
if (!thread) |
|||
error ("fetch inferior registers: %d: Invalid thread", inferior_pid); |
|||
|
|||
state = proc_get_state (thread, 0); |
|||
|
|||
if (! state) |
|||
warning ("Couldn't fetch register %s.", reg_names[reg]); |
|||
else if (reg >= 0) |
|||
{ |
|||
proc_debug (thread, "fetching register: %s", reg_names[reg]); |
|||
supply_register (reg, REG_ADDR(state, reg)); |
|||
thread->fetched_regs |= (1 << reg); |
|||
} |
|||
else |
|||
{ |
|||
proc_debug (thread, "fetching all registers"); |
|||
for (reg = 0; reg < NUM_REGS; reg++) |
|||
supply_register (reg, REG_ADDR(state, reg)); |
|||
thread->fetched_regs = ~0; |
|||
} |
|||
} |
|||
|
|||
/* Store our register values back into the inferior.
|
|||
* If REG is -1, do this for all registers. |
|||
* Otherwise, REG specifies which register |
|||
* |
|||
* On mach3 all registers are always saved in one call. |
|||
*/ |
|||
void |
|||
gnu_store_registers (reg) |
|||
int reg; |
|||
{ |
|||
int was_aborted, was_valid; |
|||
thread_state_t state; |
|||
thread_state_data_t old_state; |
|||
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid); |
|||
|
|||
if (! thread) |
|||
error ("store inferior registers: %d: Invalid thread", inferior_pid); |
|||
|
|||
proc_debug (thread, "storing register %s.", reg_names[reg]); |
|||
|
|||
was_aborted = thread->aborted; |
|||
was_valid = thread->state_valid; |
|||
if (! was_aborted && was_valid) |
|||
bcopy (&thread->state, &old_state, sizeof (old_state)); |
|||
|
|||
state = proc_get_state (thread, 1); |
|||
|
|||
if (! state) |
|||
warning ("Couldn't store register %s.", reg_names[reg]); |
|||
else |
|||
{ |
|||
if (! was_aborted && was_valid) |
|||
/* See which registers have changed after aborting the thread. */ |
|||
{ |
|||
int check_reg; |
|||
for (check_reg = 0; check_reg < NUM_REGS; check_reg++) |
|||
if ((thread->fetched_regs & (1 << check_reg)) |
|||
&& bcmp (REG_ADDR (&old_state, check_reg), |
|||
REG_ADDR (state, check_reg), |
|||
REGISTER_RAW_SIZE (check_reg))) |
|||
/* Register CHECK_REG has changed! Ack! */ |
|||
{ |
|||
warning ("Register %s changed after thread was aborted.", |
|||
reg_names [check_reg]); |
|||
if (reg >= 0 && reg != check_reg) |
|||
/* Update gdb's copy of the register. */ |
|||
supply_register (check_reg, REG_ADDR (state, check_reg)); |
|||
else |
|||
warning ("... also writing this register! Suspicious..."); |
|||
} |
|||
} |
|||
|
|||
if (reg >= 0) |
|||
{ |
|||
proc_debug (thread, "storing register: %s", reg_names[reg]); |
|||
STORE_REGS (state, reg, 1); |
|||
} |
|||
else |
|||
{ |
|||
proc_debug (thread, "storing all registers"); |
|||
for (reg = 0; reg < NUM_REGS; reg++) |
|||
STORE_REGS (state, reg, 1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* jtv@hut.fi: I copied and modified this 387 code from
|
|||
* gdb/i386-xdep.c. Modifications for Mach 3.0. |
|||
* |
|||
* i387 status dumper. See also i387-tdep.c |
|||
*/ |
|||
struct env387 |
|||
{ |
|||
unsigned short control; |
|||
unsigned short r0; |
|||
unsigned short status; |
|||
unsigned short r1; |
|||
unsigned short tag; |
|||
unsigned short r2; |
|||
unsigned long eip; |
|||
unsigned short code_seg; |
|||
unsigned short opcode; |
|||
unsigned long operand; |
|||
unsigned short operand_seg; |
|||
unsigned short r3; |
|||
unsigned char regs[8][10]; |
|||
}; |
|||
/* This routine is machine independent?
|
|||
* Should move it to i387-tdep.c but you need to export struct env387 |
|||
*/ |
|||
static |
|||
print_387_status (status, ep) |
|||
unsigned short status; |
|||
struct env387 *ep; |
|||
{ |
|||
int i; |
|||
int bothstatus; |
|||
int top; |
|||
int fpreg; |
|||
unsigned char *p; |
|||
|
|||
bothstatus = ((status != 0) && (ep->status != 0)); |
|||
if (status != 0) |
|||
{ |
|||
if (bothstatus) |
|||
printf_unfiltered ("u: "); |
|||
print_387_status_word (status); |
|||
} |
|||
|
|||
if (ep->status != 0) |
|||
{ |
|||
if (bothstatus) |
|||
printf_unfiltered ("e: "); |
|||
print_387_status_word (ep->status); |
|||
} |
|||
|
|||
print_387_control_word (ep->control); |
|||
printf_unfiltered ("last exception: "); |
|||
printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode)); |
|||
printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg)); |
|||
printf_unfiltered ("%s; ", local_hex_string(ep->eip)); |
|||
printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg)); |
|||
printf_unfiltered (":%s\n", local_hex_string(ep->operand)); |
|||
|
|||
top = (ep->status >> 11) & 7; |
|||
|
|||
printf_unfiltered ("regno tag msb lsb value\n"); |
|||
for (fpreg = 7; fpreg >= 0; fpreg--) |
|||
{ |
|||
double val; |
|||
|
|||
printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg); |
|||
|
|||
switch ((ep->tag >> (fpreg * 2)) & 3) |
|||
{ |
|||
case 0: printf_unfiltered ("valid "); break; |
|||
case 1: printf_unfiltered ("zero "); break; |
|||
case 2: printf_unfiltered ("trap "); break; |
|||
case 3: printf_unfiltered ("empty "); break; |
|||
} |
|||
for (i = 9; i >= 0; i--) |
|||
printf_unfiltered ("%02x", ep->regs[fpreg][i]); |
|||
|
|||
floatformat_to_double (&floatformat_i387_ext, (char *)ep->regs[fpreg], |
|||
&val); |
|||
printf_unfiltered (" %g\n", val); |
|||
} |
|||
if (ep->r0) |
|||
printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string(ep->r0)); |
|||
if (ep->r1) |
|||
printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string(ep->r1)); |
|||
if (ep->r2) |
|||
printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string(ep->r2)); |
|||
if (ep->r3) |
|||
printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string(ep->r3)); |
|||
} |
|||
|
|||
/*
|
|||
* values that go into fp_kind (from <i386/fpreg.h>) |
|||
*/ |
|||
#define FP_NO 0 /* no fp chip, no emulator (no fp support) */ |
|||
#define FP_SW 1 /* no fp chip, using software emulator */ |
|||
#define FP_HW 2 /* chip present bit */ |
|||
#define FP_287 2 /* 80287 chip present */ |
|||
#define FP_387 3 /* 80387 chip present */ |
|||
|
|||
typedef struct fpstate { |
|||
#if 1 |
|||
unsigned char state[FP_STATE_BYTES]; /* "hardware" state */ |
|||
#else |
|||
struct env387 state; /* Actually this */ |
|||
#endif |
|||
int status; /* Duplicate status */ |
|||
} *fpstate_t; |
|||
|
|||
/* Mach 3 specific routines.
|
|||
*/ |
|||
static int |
|||
get_i387_state (fstate) |
|||
struct fpstate *fstate; |
|||
{ |
|||
error_t err; |
|||
thread_state_data_t state; |
|||
unsigned int fsCnt = i386_FLOAT_STATE_COUNT; |
|||
struct i386_float_state *fsp; |
|||
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid); |
|||
|
|||
if (!thread) |
|||
error ("get_i387_state: Invalid thread"); |
|||
|
|||
proc_abort (thread, 0); /* Make sure THREAD's in a reasonable state. */ |
|||
|
|||
err = thread_get_state (thread->port, i386_FLOAT_STATE, state, &fsCnt); |
|||
if (err) |
|||
{ |
|||
warning ("Can not get live floating point state: %s", |
|||
mach_error_string (err)); |
|||
return 0; |
|||
} |
|||
|
|||
fsp = (struct i386_float_state *)state; |
|||
/* The 387 chip (also 486 counts) or a software emulator? */ |
|||
if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW)) |
|||
return 0; |
|||
|
|||
/* Clear the target then copy thread's float state there.
|
|||
Make a copy of the status word, for some reason? |
|||
*/ |
|||
memset (fstate, 0, sizeof (struct fpstate)); |
|||
|
|||
fstate->status = fsp->exc_status; |
|||
|
|||
memcpy (fstate->state, (char *)&fsp->hw_state, FP_STATE_BYTES); |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
/*
|
|||
* This is called by "info float" command |
|||
*/ |
|||
void |
|||
i386_mach3_float_info() |
|||
{ |
|||
char buf [sizeof (struct fpstate) + 2 * sizeof (int)]; |
|||
int valid = 0; |
|||
fpstate_t fps; |
|||
|
|||
if (target_has_execution) |
|||
valid = get_i387_state (buf); |
|||
|
|||
if (!valid) |
|||
{ |
|||
warning ("no floating point status saved"); |
|||
return; |
|||
} |
|||
|
|||
fps = (fpstate_t) buf; |
|||
|
|||
print_387_status (fps->status, (struct env387 *)fps->state); |
|||
} |
|||
@ -0,0 +1 @@ |
|||
#include <hurd/msg.defs> |
|||
@ -0,0 +1 @@ |
|||
#include <hurd/msg_reply.defs> |
|||
@ -0,0 +1 @@ |
|||
#include <mach/notify.defs> |
|||
@ -0,0 +1 @@ |
|||
#include <hurd/process_reply.defs> |
|||
@ -0,0 +1,123 @@ |
|||
# Reply server mig-output massager |
|||
# |
|||
# Copyright (C) 1995 Free Software Foundation, Inc. |
|||
# |
|||
# Written by Miles Bader <miles@gnu.ai.mit.edu> |
|||
# |
|||
# This program is free software; you can redistribute it and/or |
|||
# modify it under the terms of the GNU General Public License as |
|||
# published by the Free Software Foundation; either version 2, or (at |
|||
# your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, but |
|||
# WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
# General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License |
|||
# along with this program; if not, write to the Free Software |
|||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|||
# |
|||
# This awk script hacks the output of mig-generated reply server code |
|||
# so that it allows replies with just the error-code in them (as this is |
|||
# how mig returns errors). |
|||
# |
|||
# It is highly, highly, dependent on the exact format of mig output. Ick. |
|||
# |
|||
|
|||
BEGIN { parse_phase = 0; } |
|||
|
|||
/^}/ { parse_phase = 0; } |
|||
|
|||
parse_phase == 0 && /^mig_internal void _X[a-zA-Z0-9_]*_reply/ { |
|||
# The start of a mig server routine. Reset everything. Note that we only |
|||
# mess with rpcs that have the suffix `_reply'. |
|||
num_args = 0; |
|||
num_checks = 0; |
|||
parse_phase = 1; |
|||
print; next; |
|||
} |
|||
|
|||
parse_phase == 1 && /^[\t ]*typedef struct/ { |
|||
# The first structure in the server routine should describe the arguments |
|||
parse_phase = 2; |
|||
print; next; |
|||
} |
|||
|
|||
parse_phase == 2 { |
|||
# The message header field in the args structure, which skip. |
|||
parse_phase = 3; |
|||
print; next; |
|||
} |
|||
|
|||
parse_phase == 3 && /}/ { |
|||
# The args structure is over. |
|||
if (num_args > 1) |
|||
parse_phase = 5; |
|||
else |
|||
# There's no extra args that could screw up the normal mechanism for |
|||
# error returns, so we don't have to insert any new code. |
|||
parse_phase = 0; |
|||
print; next; |
|||
} |
|||
|
|||
parse_phase == 3 { |
|||
# The type field for an argument. |
|||
arg_type_code_name[num_args] = $2; |
|||
sub (/;$/, "", arg_type_code_name[num_args]) # Get rid of the semi-colon |
|||
parse_phase = 4; |
|||
print; next; |
|||
} |
|||
|
|||
parse_phase == 4 { |
|||
# The value field for an argument. |
|||
arg_name[num_args] = $2; |
|||
sub (/;$/, "", arg_name[num_args]) # Get rid of the semi-colon |
|||
arg_type[num_args] = $1; |
|||
num_args++; |
|||
parse_phase = 3; |
|||
print; next; |
|||
} |
|||
|
|||
parse_phase == 5 && /^[ \t]*static const mach_msg_type_t/ { |
|||
# The type check structure for an argument. |
|||
arg_check_name[num_checks] = $4; |
|||
num_checks++; |
|||
print; next; |
|||
} |
|||
|
|||
parse_phase == 5 && /^[ \t]*mig_external kern_return_t/ { |
|||
# The declaration of the user server function for this rpc. |
|||
user_function_name = $3; |
|||
print; next; |
|||
} |
|||
|
|||
parse_phase == 5 && /^#if[ \t]TypeCheck/ { |
|||
# The first args type checking statement; we need to insert our chunk of |
|||
# code that bypasses all the type checks if this is an error return, after |
|||
# which we're done until we get to the next function. Handily, the size |
|||
# of mig's Reply structure is also the size of the alternate Request |
|||
# structure that we want to check for. |
|||
print "\tif (In0P->Head.msgh_size == sizeof (Reply)"; |
|||
print "\t && ! (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)"; |
|||
print "\t && *(int *)&In0P->" arg_type_code_name[0] " == *(int *)&" arg_check_name[0]; |
|||
print "\t && In0P->" arg_name[0] " != 0)"; |
|||
print "\t /* Error return, only the error code argument is passed. */"; |
|||
print "\t {"; |
|||
# Force the function into a type that only takes the first two args, via |
|||
# the temp variable SFUN (is there another way to correctly do this cast?). |
|||
# This is possibly bogus, but easier than supplying bogus values for all |
|||
# the other args (we can't just pass 0 for them, as they might not be scalar). |
|||
printf ("\t kern_return_t (*sfun)(mach_port_t"); |
|||
for (i = 0; i < num_args; i++) |
|||
printf (", %s", arg_type[i]); |
|||
printf (") = %s;\n", user_function_name); |
|||
print "\t OutP->RetCode = (*(kern_return_t (*)(mach_port_t, kern_return_t))sfun) (In0P->Head.msgh_request_port, In0P->" arg_name[0] ");"; |
|||
print "\t return;"; |
|||
print "\t }"; |
|||
print ""; |
|||
parse_phase = 0; |
|||
print; next; |
|||
} |
|||
|
|||
{ print; } |
|||
Loading…
Reference in new issue