Article View: gnu.gdb.bug
Article #9956[will@nirvana.westford.ccur.com: GDB patches for Concurrent/Masscomp machines.]
From: rms
Date: Wed, 08 Aug 1990 17:47
Date: Wed, 08 Aug 1990 17:47
1427 lines
45829 bytes
45829 bytes
Return-Path: <will@nirvana.westford.ccur.com>
To: rms@ai.mit.edu
Cc: will@nirvana.westford.ccur.com
Subject: GDB patches for Concurrent/Masscomp machines.
Date: Tue, 07 Aug 90 13:48:10 EDT
From: will@nirvana.westford.ccur.com
In-Real-Life: Will Athanasiou (x2647)
--------
These patches will allow GDB to work on our machines up to and including our
current OS RTU v5.0.
Should I post these to the gnu.* news groups as well? What is the most
appropriate group for GDB stuff?
----- cut here -----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# masscomp.chang
# gdb.diffs
# m-mass.h
# mass-dep.c
# This archive created Tue Aug 7 13:42:52 EDT 1990
#
PATH=/bin:$PATH; export PATH
#
echo 'bundle: extracting' masscomp.chang \( 144 Characters\)
if test -f masscomp.chang
then
echo shar: will not overwrite existing file masscomp.chang
else
sed -n -e 's@^X @@p' << \BUNDLE_EOF > masscomp.chang
X Look at:
X Masscomp specific files
X m-mass.h
X mass-dep.c
X Changes were made to
X infrun.c -- marked by #ifdef SOS .. #endif
BUNDLE_EOF
if test 144 -ne "`wc -c <masscomp.chang`"
then
echo shar: error transmitting masscomp.chang \(should have 144 characters\)
fi
fi
#
echo 'bundle: extracting' gdb.diffs \( 2114 Characters\)
if test -f gdb.diffs
then
echo shar: will not overwrite existing file gdb.diffs
else
sed -n -e 's@^X @@p' << \BUNDLE_EOF > gdb.diffs
X diff -c5 dist-gdb/config.gdb rel-gdb/config.gdb
X *** dist-gdb/config.gdb Tue Jan 30 15:35:46 1990
X --- rel-gdb/config.gdb Fri Mar 16 11:46:53 1990
X ***************
X *** 46,55
X $machine=newsos3
X $os=""
X ;;
X esac
X ;;
X sun2)
X case $os in
X os4|sunos4)
X machine=sun2os4
X os=""
X
X --- 46,66 -----
X $machine=newsos3
X $os=""
X ;;
X esac
X ;;
X + mass)
X + case $os in
X + sos|SOS|5.0)
X + machine=massSOS
X + os=""
X + ;;
X + *)
X + machine=mass4.1
X + os="" ;;
X + esac
X + ;;
X sun2)
X case $os in
X os4|sunos4)
X machine=sun2os4
X os=""
X ***************
X *** 245,254
X sun2)
X depfile=sun3-dep.c
X pinsnfile=m68k-pinsn.c
X opcodefile=m68k-opcode.h
X ;;
X sun2os2|sun2-os2)
X depfile=default-dep.c
X paramfile=m-sun2.h
X pinsnfile=m68k-pinsn.c
X opcodefile=m68k-opcode.h
X
X --- 256,280 -----
X sun2)
X depfile=sun3-dep.c
X pinsnfile=m68k-pinsn.c
X opcodefile=m68k-opcode.h
X ;;
X + massSOS)
X + makedefine="-DM_CFLAGS='-DMASSCOMP=700 -DSOS'"
X + depfile=mass-dep.c
X + paramfile=m-mass.h
X + pinsnfile=m68k-pinsn.c
X + opcodefile=m68k-opcode.h
X + ;;
X + mass4.1)
X + makedefine="-DM_CFLAGS='-DMASSCOMP=700'"
X + depfile=mass-dep.c
X + paramfile=m-mass.h
X + pinsnfile=m68k-pinsn.c
X + opcodefile=m68k-opcode.h
X + ;;
X +
X sun2os2|sun2-os2)
X depfile=default-dep.c
X paramfile=m-sun2.h
X pinsnfile=m68k-pinsn.c
X opcodefile=m68k-opcode.h
X diff -c5 dist-gdb/infrun.c rel-gdb/infrun.c
X *** dist-gdb/infrun.c Tue Jan 23 18:10:35 1990
X --- rel-gdb/infrun.c Fri Mar 16 13:29:49 1990
X ***************
X *** 543,552
X #ifdef NO_SINGLE_STEP
X one_stepped = 0;
X #endif
X break;
X }
X
X #ifdef NO_SINGLE_STEP
X if (one_stepped)
X single_step (0); /* This actually cleans up the ss */
X #endif /* NO_SINGLE_STEP */
X
X --- 543,556 -----
X #ifdef NO_SINGLE_STEP
X one_stepped = 0;
X #endif
X break;
X }
X +
X + #ifdef SOS
X + get_initial_thread( pid );
X + #endif
X
X #ifdef NO_SINGLE_STEP
X if (one_stepped)
X single_step (0); /* This actually cleans up the ss */
X #endif /* NO_SINGLE_STEP */
X Only in rel-gdb: m-mass.h
X Only in rel-gdb: mass-dep.c
BUNDLE_EOF
if test 2114 -ne "`wc -c <gdb.diffs`"
then
echo shar: error transmitting gdb.diffs \(should have 2114 characters\)
fi
fi
#
echo 'bundle: extracting' m-mass.h \( 18408 Characters\)
if test -f m-mass.h
then
echo shar: will not overwrite existing file m-mass.h
else
sed -n -e 's@^X @@p' << \BUNDLE_EOF > m-mass.h
X /* Parameters for execution on a MASSCOMP machine, for GDB, the GNU debugger.
X Copyright (C) 1989 Free Software Foundation, Inc.
X
X This file is part of GDB.
X
X GDB is free software; you can redistribute it and/or modify
X it under the terms of the GNU General Public License as published by
X the Free Software Foundation; either version 1, or (at your option)
X any later version.
X
X GDB is distributed in the hope that it will be useful,
X but WITHOUT ANY WARRANTY; without even the implied warranty of
X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X GNU General Public License for more details.
X
X You should have received a copy of the GNU General Public License
X along with GDB; see the file COPYING. If not, write to
X the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X /* Define the bit, byte, and word ordering of the machine. */
X #define BITS_BIG_ENDIAN
X #define BYTES_BIG_ENDIAN
X #define WORDS_BIG_ENDIAN
X
X #define HAVE_WAIT_STRUCT
X
X /* Watch out for NaNs */
X
X #define IEEE_FLOAT
X
X /* Tell user about floating point units. */
X
X #define FLOAT_INFO \
X { \
X printf ("68881 coprocessor available.\n"); \
X }
X
X /* Get rid of any system-imposed stack limit if possible. */
X
X #define SET_STACK_LIMIT_HUGE
X
X /* Define this if the C compiler puts an underscore at the front
X of external names before giving them to the linker. */
X
X #define NAMES_HAVE_UNDERSCORE
X
X /* Debugger information will be in DBX format. */
X
X #define READ_DBX_FORMAT
X
X /* Doesn't have siginterupt. */
X
X #define NO_SIGINTERRUPT
X
X /* Offset from address of function to start of its code.
X Zero on most machines. */
X
X #define FUNCTION_START_OFFSET 0
X
X /* Advance PC across any function entry prologue instructions
X to reach some "real" code. */
X
X #define SKIP_PROLOGUE(pc) \
X { register int op = read_memory_integer (pc, 2); \
X if (op == 0047126) \
X pc += 4; /* Skip link #word */ \
X else if (op == 0044016) \
X pc += 6; /* Skip link #long */ \
X else if (op == 0060000) \
X pc += 4; /* Skip bra #word */ \
X else if (op == 00600377) \
X pc += 6; /* skip bra #long */ \
X else if ((op & 0177400) == 0060000) \
X pc += 2; /* skip bra #char */ \
X }
X
X /* Immediately after a function call, return the saved pc.
X Can't go through the frames for this because on some machines
X the new frame is not set up until the new function executes
X some instructions. */
X
X #define SAVED_PC_AFTER_CALL(frame) \
X read_memory_integer (read_register (SP_REGNUM), 4)
X
X /* Address of end of stack space. */
X
X #define usrstk_300 0x08000000
X #define usrstk_700 0xC0000000
X #if MASSCOMP == 300
X #define STACK_END_ADDR usrstk_300
X #else
X #define STACK_END_ADDR usrstk_700
X #endif
X
X /* Stack grows downward. */
X
X #define INNER_THAN <
X
X /* Data segment starts at etext rounded up to DATAROUND in {N,Z}MAGIC files */
X
X #define DATAROUND 0x1000
X #define N_DATADDR(hdr) (hdr.a_magic != OMAGIC ? \
X (hdr.a_text + DATAROUND) & ~(DATAROUND-1) : hdr.a_text)
X
X /* Sequence of bytes for breakpoint instruction. */
X
X #define BREAKPOINT {0x4e, 0x41}
X
X /* Amount PC must be decremented by after a breakpoint.
X This is often the number of bytes in BREAKPOINT
X but not always. */
X
X #define DECR_PC_AFTER_BREAK 2
X
X /* Nonzero if instruction at PC is a return instruction. */
X /* Allow any of the return instructions, including a trapv and a return
X from interupt. */
X
X #define ABOUT_TO_RETURN(pc) ((read_memory_integer (pc, 2) & ~0x3) == 0x4e74)
X
X /* Return 1 if P points to an invalid floating point value. */
X
X #define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
X
X /* Largest integer type */
X #define LONGEST long
X
X /* Name of the builtin type for the LONGEST type above. */
X #define BUILTIN_TYPE_LONGEST builtin_type_long
X
X /* Say how long (ordinary) registers are. */
X
X #define REGISTER_TYPE long
X
X /* Number of machine registers */
X
X #define NUM_REGS 29
X
X /* Initializer for an array of names of registers.
X There should be NUM_REGS strings in this initializer. */
X
X #define REGISTER_NAMES \
X {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
X "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
X "ps", "pc", \
X "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
X "fpcontrol", "fpstatus", "fpiaddr" }
X
X /* Register numbers of various important registers.
X Note that some of these values are "real" register numbers,
X and correspond to the general registers of the machine,
X and some are "phony" register numbers which are too large
X to be actual register numbers as far as the user is concerned
X but do serve to get the desired values when passed to read_register. */
X
X #define FP_REGNUM 14 /* Contains address of executing stack frame */
X #define SP_REGNUM 15 /* Contains address of top of stack */
X #define PS_REGNUM 16 /* Contains processor status */
X #define PC_REGNUM 17 /* Contains program counter */
X #define FP0_REGNUM 18 /* Floating point register 0 */
X #define FPC_REGNUM 26 /* 68881 control register */
X
X #ifdef SOS
X #define REGISTER_ADDR(blockend, regno) ((int) ¤t_upanel + reg_off[regno])
X #define FP_REGISTER_ADDR(blockend,regno) ((int) ¤t_upanel + reg_off[regno])
X #else
X #define REGISTER_ADDR(blockend, regno) (blockend + regno * 4 + ((regno <= SP_REGNUM) ? 0 : 4))
X
X #define FP_REGISTER_ADDR(blockend, regno) (blockend + ((regno < FPC_REGNUM) ? \
X (regno - FP0_REGNUM) * 12 : 8 * 12 + (regno - FPC_REGNUM) * 4))
X #endif
X
X /* Total amount of space needed to store our copies of the machine's
X register state, the array `registers'. */
X
X #define REGISTER_BYTES (16*4+8*12+2*4+3*4)
X
X /* Index within `registers' of the first byte of the space for
X register N. */
X
X #define REGISTER_BYTE(N) \
X ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
X : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
X : (N) * 4)
X
X /* Number of bytes of storage in the actual machine representation
X for register N. On the 68000, all regs are 4 bytes
X except the floating point regs which are 12 bytes. */
X
X #define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
X
X /* Number of bytes of storage in the program's representation
X for register N. On the 68000, all regs are 4 bytes
X except the floating point regs which are 8-byte doubles. */
X
X #define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
X
X /* Largest value REGISTER_RAW_SIZE can have. */
X
X #define MAX_REGISTER_RAW_SIZE 12
X
X /* Largest value REGISTER_VIRTUAL_SIZE can have. */
X
X #define MAX_REGISTER_VIRTUAL_SIZE 8
X
X /* Nonzero if register N requires conversion
X from raw format to virtual format. */
X
X #define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
X
X /* Convert data from raw format for register REGNUM
X to virtual format for register REGNUM. */
X
X #define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
X { if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
X convert_from_68881 ((FROM), (TO)); \
X else \
X bcopy ((FROM), (TO), 4); }
X
X /* Convert data from virtual format for register REGNUM
X to raw format for register REGNUM. */
X
X #define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
X { if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
X convert_to_68881 ((FROM), (TO)); \
X else \
X bcopy ((FROM), (TO), 4); }
X
X /* Return the GDB type object for the "standard" data type
X of data in register N. */
X
X #define REGISTER_VIRTUAL_TYPE(N) \
X (((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
X
X /* Store the address of the place in which to copy the structure the
X subroutine will return. This is called from call_function. */
X
X #define STORE_STRUCT_RETURN(ADDR, SP) \
X { write_register (9, (ADDR)); }
X
X /* Extract from an array REGBUF containing the (raw) register state
X a function return value of type TYPE, and copy that, in virtual format,
X into VALBUF. */
X
X #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
X bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
X
X /* Write into appropriate registers a function return value
X of type TYPE, given in virtual format. */
X
X #define STORE_RETURN_VALUE(TYPE,VALBUF) \
X write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
X
X /* Extract from an array REGBUF containing the (raw) register state
X the address in which a function should return its structure value,
X as a CORE_ADDR (or an expression that can be used as one). */
X
X #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
X
X /* Compensate for lack of `vprintf' function. */
X
X #define vprintf(format, ap) _doprnt (format, ap, stdout)
X
X /* Do implement the attach and detach commands. */
X
X #define ATTACH_DETACH
X
X /* It is safe to look for symsegs, because ld
X does not screw up with random garbage at end of file. */
X
X #define READ_GDB_SYMSEGS
X
X #define IGNORE_SYMBOL(type) (type == N_RMASK1 || type == N_RMASK2) /* gdb gets these register masks from the text */
X
X /* Describe the pointer in each stack frame to the previous stack frame
X (its caller). */
X
X /* FRAME_CHAIN takes a frame's nominal address
X and produces the frame's chain-pointer.
X
X FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
X and produces the nominal address of the caller frame.
X
X However, if FRAME_CHAIN_VALID returns zero,
X it means the given frame is the outermost one and has no caller.
X In that case, FRAME_CHAIN_COMBINE is not used. */
X
X /* In the case of MASSCOMP, the frame's nominal address
X is the address of a 4-byte word containing the calling frame's address. */
X
X #define FRAME_CHAIN(thisframe) \
X (outside_startup_file ((thisframe)->pc) ? \
X read_memory_integer ((thisframe)->frame, 4) :\
X 0)
X
X #define FRAME_CHAIN_VALID(chain, thisframe) \
X (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
X
X #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
X
X /* Define other aspects of the stack frame. */
X
X /* A macro that tells us whether the function invocation represented
X by FI does not have a frame on the stack associated with it. If it
X does not, FRAMELESS is set to 1, else 0. */
X #define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
X FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
X
X #define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
X
X #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
X
X #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
X
X /* Set VAL to the number of args passed to frame described by FI.
X Can set VAL to -1, meaning no way to tell. */
X
X #define FRAME_NUM_ARGS(val, fi) \
X { register CORE_ADDR pc = FRAME_SAVED_PC (fi); \
X register int insn = 0177777 & read_memory_integer (pc, 2); \
X val = 0; \
X if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
X val = read_memory_integer (pc + 2, 2); \
X else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
X || (insn & 0170777) == 0050117) /* addqw */ \
X { val = (insn >> 9) & 7; if (val == 0) val = 8; } \
X else if (insn == 0157774) /* addal #WW, sp */ \
X val = read_memory_integer (pc + 2, 4); \
X val >>= 2; }
X
X /* Return number of bytes at start of arglist that are not really args. */
X
X #define FRAME_ARGS_SKIP 8
X
X /* Put here the code to store, into a struct frame_saved_regs,
X the addresses of the saved registers of frame described by FRAME_INFO.
X This includes special registers such as pc and fp saved in special
X ways in the stack frame. sp is even more special:
X the address we return for it IS the sp for the next frame. */
X
X #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
X { register int regnum; \
X register int regmask; \
X register CORE_ADDR next_addr; \
X register CORE_ADDR pc; \
X int nextinsn; \
X bzero (&frame_saved_regs, sizeof frame_saved_regs); \
X if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
X && (frame_info)->pc <= (frame_info)->frame) \
X { next_addr = (frame_info)->frame; \
X pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; } \
X else \
X { pc = get_pc_function_start ((frame_info)->pc); \
X /* Verify we have a link a6 instruction next, \
X or a branch followed by a link a6 instruction; \
X if not we lose. If we win, find the address above the saved \
X regs using the amount of storage from the link instruction. */ \
X retry: \
X nextinsn = read_memory_integer (pc, 2); \
X if (nextinsn == 044016) \
X next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \
X else if (nextinsn == 047126) \
X next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \
X else if ((nextinsn & 0177400) == 060000) /* bra insn */ \
X { int offset; \
X offset = nextinsn & 0377; \
X pc += 2; /* advance past bra */ \
X if (offset == 0) /* bra #word */ \
X offset = read_memory_integer (pc, 2), pc += 2; \
X else if (offset == 0377) /* bra #long */ \
X offset = read_memory_integer (pc, 4), pc += 4; \
X pc += offset; \
X goto retry; \
X } else goto lose; \
X /* If have an addal #-n, sp next, adjust next_addr. */ \
X if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
X next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
X } \
X /* Now we can have a series of save type instructions. Most common are
X a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
X for (;;) \
X { \
X nextinsn = read_memory_integer (pc, 2) & 0xffff; \
X regmask = read_memory_integer (pc + 2, 2); \
X /* fmovem. */ \
X if (nextinsn == 0xf227 \
X && (regmask & 0xff00) == 0xe000) \
X { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
X for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
X if (regmask & 1) \
X (frame_saved_regs).regs[regnum] = (next_addr -= 12); } \
X /* movem */ \
X else if (nextinsn == 0044327) \
X { pc += 4; /* Regmask's low bit is for register 0, the first written */ \
X for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
X if (regmask & 1) \
X (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
X else if (nextinsn == 0044347) \
X { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
X for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
X if (regmask & 1) \
X (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
X else if ((nextinsn & 0xfff0) == 0x2f00) \
X { regnum = nextinsn & 0xf; pc += 2; \
X (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
X /* fmovemx to index of sp may follow. */ \
X else if (nextinsn == 0xf236 \
X && (regmask & 0xff00) == 0xf000) \
X { pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
X for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
X if (regmask & 1) \
X (frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; } \
X /* clrw -(sp); movw ccr,-(sp) may follow. */ \
X else if (nextinsn == 041147 \
X && regmask == 041347) \
X { pc += 4; \
X (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); } \
X else break; \
X } \
X lose: ; \
X (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \
X (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \
X (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
X }
X
X /* Things needed for making the inferior call functions. */
X
X /* Push an empty stack frame, to record the current PC, etc. */
X
X #define PUSH_DUMMY_FRAME \
X { register CORE_ADDR sp = read_register (SP_REGNUM); \
X register int regnum; \
X char raw_buffer[12]; \
X sp = push_word (sp, read_register (PC_REGNUM)); \
X sp = push_word (sp, read_register (FP_REGNUM)); \
X write_register (FP_REGNUM, sp); \
X for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
X { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
X sp = push_bytes (sp, raw_buffer, 12); } \
X for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
X sp = push_word (sp, read_register (regnum)); \
X sp = push_word (sp, read_register (PS_REGNUM)); \
X write_register (SP_REGNUM, sp); }
X
X /* Discard from the stack the innermost frame,
X restoring all saved registers. */
X
X #define POP_FRAME \
X { register FRAME frame = get_current_frame (); \
X register CORE_ADDR fp; \
X register int regnum; \
X struct frame_saved_regs fsr; \
X struct frame_info *fi; \
X char raw_buffer[12]; \
X fi = get_frame_info (frame); \
X fp = fi->frame; \
X get_frame_saved_regs (fi, &fsr); \
X for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
X if (fsr.regs[regnum]) \
X { read_memory (fsr.regs[regnum], raw_buffer, 12); \
X write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); } \
X for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
X if (fsr.regs[regnum]) \
X write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
X if (fsr.regs[PS_REGNUM]) \
X write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
X write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
X write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
X write_register (SP_REGNUM, fp + 8); \
X flush_cached_frames (); \
X set_current_frame (create_new_frame (read_register (FP_REGNUM),\
X read_pc ())); }
X
X /* This sequence of words is the instructions
X fmovem 0xff,-(sp)
X moveml 0xfffc,-(sp)
X clrw -(sp)
X movew ccr,-(sp)
X /..* The arguments are pushed at this point by GDB;
X no code is needed in the dummy for this.
X The CALL_DUMMY_START_OFFSET gives the position of
X the following jsr instruction. *../
X jsr @#32323232
X addl #69696969,sp
X trap #1
X nop
X Note this is 28 bytes.
X We actually start executing at the jsr, since the pushing of the
X registers is done by PUSH_DUMMY_FRAME. If this were real code,
X the arguments for the function called by the jsr would be pushed
X between the moveml and the jsr, and we could allow it to execute through.
X But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
X and we cannot allow the moveml to push the registers again lest they be
X taken for the arguments. */
X
X #define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e414e71}
X
X #define CALL_DUMMY_LENGTH 28
X
X #define CALL_DUMMY_START_OFFSET 12
X
X /* Insert the specified number of args and function address
X into a call sequence of the above form stored at DUMMYNAME. */
X
X #define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
X { *(int *)((char *) dummyname + 20) = nargs * 4; \
X *(int *)((char *) dummyname + 14) = fun; }
X
X /*
X ** Missing interface for KDB
X */
BUNDLE_EOF
if test 18408 -ne "`wc -c <m-mass.h`"
then
echo shar: error transmitting m-mass.h \(should have 18408 characters\)
fi
fi
#
echo 'bundle: extracting' mass-dep.c \( 18183 Characters\)
if test -f mass-dep.c
then
echo shar: will not overwrite existing file mass-dep.c
else
sed -n -e 's@^X @@p' << \BUNDLE_EOF > mass-dep.c
X /* Low level interface to ptrace, for GDB when running under Unix.
X Copyright (C) 1989 Free Software Foundation, Inc.
X
X This file is part of GDB.
X
X GDB is free software; you can redistribute it and/or modify
X it under the terms of the GNU General Public License as published by
X the Free Software Foundation; either version 1, or (at your option)
X any later version.
X
X GDB is distributed in the hope that it will be useful,
X but WITHOUT ANY WARRANTY; without even the implied warranty of
X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X GNU General Public License for more details.
X
X You should have received a copy of the GNU General Public License
X along with GDB; see the file COPYING. If not, write to
X the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X #include "defs.h"
X #include "param.h"
X #include "frame.h"
X #include "inferior.h"
X #include <sys/types.h>
X
X #include <stdio.h>
X #include <sys/param.h>
X #include <sys/dir.h>
X #include <signal.h>
X #include <sys/ioctl.h>
X #include <fcntl.h>
X #ifdef SOS
X # include <sys/reg.h>
X #endif
X #include <ptrace.h>
X
X #include <a.out.h>
X #ifndef N_SET_MAGIC
X #define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
X #endif
X
X #include <sys/user.h>
X #include <sys/stat.h>
X
X extern int errno;
X extern int attach_flag;
X
X #ifdef SOS
X /*
X ** Current_upanel added for SOS compatibility. main_tid is the
X ** thread id of the parent (main) thread.
X */
X upanel_t current_upanel;
X int main_tid;
X
X /*
X ** Register offsets from upanel start.
X ** (hard coded because of bug in masscomp c)
X */
X int reg_off[] = {
X /* d0-d7 */
X 24, /* 0 */ 28, /* 1 */ 32, /* 2 */ 36, /* 3 */ 40, /* 4 */
X 44, /* 5 */ 48, /* 6 */ 52, /* 7 */
X
X /* a0-a7,ps,pc */
X 56, /* 8 */ 60, /* 9 */ 64, /* 10 */ 68, /* 11 */ 72, /* 12 */
X 76, /* 13 */ 80, /* 14 */ 84, /* 15 */ 88, /* 16 */ 90, /* 17 */
X
X /* fp0-fp7,fpcontrol,fpstatus,fpiaddr */
X 104, /* 18 */ 116, /* 19 */ 128, /* 20 */ 140, /* 21 */
X 152, /* 22 */ 164, /* 23 */ 176, /* 24 */ 188, /* 25 */ 200, /* 26 */
X 204, /* 27 */ 208, /* 28 */
X
X /* lightning registers (mabye someday?) */
X 212, /* 37 */ 220, /* 38 */ 228, /* 39 */
X 236, /* 40 */ 244, /* 41 */ 252, /* 42 */ 260, /* 43 */ 268, /* 44 */
X 276, /* 45 */ 284, /* 46 */ 292, /* 47 */ 300, /* 48 */ 308, /* 49 */
X 316, /* 50 */ 324, /* 51 */ 332, /* 52 */ 340, /* 53 */ 348, /* 54 */
X 356, /* 55 */ 364, /* 56 */ 372, /* 57 */ 380, /* 58 */ 388, /* 59 */
X 396, /* 60 */ 404, /* 61 */ 412, /* 62 */ 420, /* 63 */ 428, /* 64 */
X 436, /* 65 */ 444, /* 66 */ 452, /* 67 */ 460, /* 68 */ 468, /* 69 */
X 470 /* 70 */
X };
X
X #endif
X
X
X #ifdef SOS
X /*
X ** This function returns the current thread id. This could be expanded
X ** to determine the current thread from the currently active task.
X */
X int
X current_thread()
X {
X return main_tid;
X }
X
X int
X get_initial_thread( pid )
X int pid;
X {
X extern int errno;
X tidlist_t tmp;
X /*
X ** get thread id of main process.
X */
X errno = 0;
X main_tid = 0;
X
X main_tid = ptrace( TIDLIST, pid, &tmp, sizeof( tidlist_t ) );
X if ( errno != 0 && main_tid == -1 ) {
X return -1;
X }
X else {
X main_tid = tmp.tid;
X return 0;
X }
X }
X #endif /* SOS */
X
X /* This function simply calls ptrace with the given arguments.
X It exists so that all calls to ptrace are isolated in this
X machine-dependent file. */
X int
X call_ptrace (request, pid, arg3, arg4)
X int request, pid, arg3, arg4;
X {
X return ptrace (request, pid, arg3, arg4);
X }
X
X kill_inferior ()
X {
X if (remote_debugging)
X return;
X if (inferior_pid == 0)
X return;
X ptrace (PKILL, inferior_pid, 0, 0);
X wait (0);
X inferior_died ();
X }
X
X /* This is used when GDB is exiting. It gives less chance of error.*/
X
X kill_inferior_fast ()
X {
X if (remote_debugging)
X return;
X if (inferior_pid == 0)
X return;
X ptrace (PKILL, inferior_pid, 0, 0);
X wait (0);
X }
X
X /* Resume execution of the inferior process.
X If STEP is nonzero, single-step it.
X If SIGNAL is nonzero, give it that signal. */
X
X void
X resume (step, signal)
X int step;
X int signal;
X {
X errno = 0;
X if (remote_debugging)
X remote_resume (step, signal);
X else
X {
X ptrace (step ? SSTEP : CONT, inferior_pid, 1, signal);
X if (errno)
X perror_with_name ("ptrace");
X }
X }
X
X #ifdef ATTACH_DETACH
X
X /* Start debugging the process whose number is PID. */
X
X attach (pid)
X int pid;
X {
X errno = 0;
X ptrace (ATTACH, pid, 0, 0);
X if (errno)
X perror_with_name ("ptrace");
X attach_flag = 1;
X return pid;
X }
X
X /* Stop debugging the process whose number is PID
X and continue it with signal number SIGNAL.
X SIGNAL = 0 means just continue it. */
X
X void
X detach (signal)
X int signal;
X {
X errno = 0;
X ptrace (DETACH, inferior_pid, 1, signal);
X if (errno)
X perror_with_name ("ptrace");
X attach_flag = 0;
X }
X #endif /* ATTACH_DETACH */
X
X void
X fetch_inferior_registers ()
X {
X extern int errno;
X register int regno;
X register unsigned int regaddr;
X char buf[MAX_REGISTER_RAW_SIZE];
X register int i;
X extern char registers[];
X
X #ifdef SOS
X extern upanel_t current_upanel;
X int tmp;
X #else
X struct user u;
X unsigned int int_offset = (char *) &u.u_ar0 - (char *) &u;
X unsigned int fp_offset = (char *) &u.u_fp_881reg0 - (char *) &u;
X #endif
X
X if (remote_debugging)
X remote_fetch_registers (registers);
X else
X {
X #ifdef SOS
X errno = 0;
X tmp = ptrace( UPREAD, inferior_pid, ¤t_upanel, sizeof( upanel_t ), current_thread() );
X if (errno != 0 && tmp == -1) {
X sprintf (buf, "reading current upanel of thread %d", current_thread());
X perror_with_name (buf);
X }
X #else
X int_offset = ptrace (UREAD, inferior_pid, int_offset, 0) & 0xfff;
X fp_offset = ptrace (UREAD, inferior_pid, fp_offset - 2, 0) & 0xfff; /*fp_offset is a short */
X #endif
X for (regno = 0; regno < NUM_REGS; regno++) {
X #ifdef SOS
X regaddr = (int) ¤t_upanel + reg_off[regno];
X supply_register( regno, regaddr );
X #else
X if (regno < FP0_REGNUM)
X regaddr = REGISTER_ADDR (int_offset, regno);
X else
X regaddr = FP_REGISTER_ADDR (fp_offset, regno);
X
X for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) {
X errno = 0;
X *(int *) &buf[i] = ptrace (UREAD, inferior_pid, regaddr, 0);
X if (errno != 0)
X {
X sprintf (buf, "reading register number %d(%d)", regno, i);
X perror_with_name (buf);
X }
X regaddr += sizeof (int);
X }
X supply_register (regno, buf);
X #endif /* SOS */
X }
X }
X }
X
X /* Store our register values back into the inferior.
X If REGNO is -1, do this for all registers.
X Otherwise, REGNO specifies which register (so we can save time). */
X
X store_inferior_registers (regno)
X int regno;
X {
X register unsigned int regaddr;
X char buf[80];
X extern char registers[];
X register int i;
X
X #ifndef SOS
X struct user u;
X unsigned int int_offset = (char *) &u.u_ar0 - (char *) &u;
X unsigned int fp_offset = (char *) &u.u_fp_881reg0 - (char *) &u;
X #endif
X
X if (remote_debugging)
X remote_store_registers (registers);
X else {
X #ifndef SOS
X int_offset = ptrace (UREAD, inferior_pid, int_offset, 0) & 0xfff;
X fp_offset = ptrace (UREAD, inferior_pid, fp_offset - 2, 0) & 0xfff; /*fp_offset is a short */
X #endif /* SOS */
X if (regno >= 0) {
X #ifdef SOS
X regaddr = reg_off[regno];
X #else
X if (regno < FP0_REGNUM)
X regaddr = REGISTER_ADDR (int_offset, regno);
X else
X regaddr = FP_REGISTER_ADDR (fp_offset, regno);
X #endif
X for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) {
X errno = 0;
X #ifdef SOS
X ptrace (UPWRITE, inferior_pid, regaddr,
X *((int *) ®isters[REGISTER_BYTE (regno) + i]), current_thread());
X #else
X ptrace (UWRITE, inferior_pid, regaddr,
X *(int *) ®isters[REGISTER_BYTE (regno) + i]);
X #endif /* SOS */
X if (errno != 0)
X {
X sprintf (buf, "writing register number %d(%d)", regno, i);
X perror_with_name (buf);
X }
X regaddr += sizeof(int);
X }
X }
X else
X for (regno = 0; regno < NUM_REGS; regno++) {
X #ifdef SOS
X regaddr = reg_off[regno];
X #else
X if (regno < FP0_REGNUM)
X regaddr = REGISTER_ADDR (int_offset, regno);
X else
X regaddr = FP_REGISTER_ADDR (fp_offset, regno);
X #endif
X for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) {
X errno = 0;
X #ifdef SOS
X ptrace (UPWRITE, inferior_pid, regaddr,
X * ((int *) ®isters[REGISTER_BYTE (regno) + i]), current_thread());
X #else
X ptrace (UWRITE, inferior_pid, regaddr,
X *(int *) ®isters[REGISTER_BYTE (regno) + i]);
X #endif
X if (errno != 0) {
X sprintf (buf, "writing all regs, number %d(%d)", regno, i);
X perror_with_name (buf);
X }
X regaddr += sizeof(int);
X }
X }
X }
X }
X
X /* Virtual addresses of bounds of the two areas of memory in the core file. */
X
X extern CORE_ADDR data_start;
X extern CORE_ADDR data_end;
X extern CORE_ADDR stack_start;
X extern CORE_ADDR stack_end;
X
X /* Virtual addresses of bounds of two areas of memory in the exec file.
X Note that the data area in the exec file is used only when there is no core file. */
X
X extern CORE_ADDR text_start;
X extern CORE_ADDR text_end;
X
X extern CORE_ADDR exec_data_start;
X extern CORE_ADDR exec_data_end;
X
X /* Address in executable file of start of text area data. */
X
X extern int text_offset;
X
X /* Address in executable file of start of data area data. */
X
X extern int exec_data_offset;
X
X /* Address in core file of start of data area data. */
X
X extern int data_offset;
X
X /* Address in core file of start of stack area data. */
X
X extern int stack_offset;
X
X /* Copy LEN bytes from inferior's memory starting at MEMADDR
X to debugger memory starting at MYADDR.
X On failure (cannot read from inferior, usually because address is out
X of bounds) returns the value of errno. */
X
X int
X read_inferior_memory (memaddr, myaddr, len)
X CORE_ADDR memaddr;
X char *myaddr;
X int len;
X {
X register int i;
X /* Round starting address down to longword boundary. */
X register CORE_ADDR addr = memaddr & - sizeof (int);
X /* Round ending address up; get number of longwords that makes. */
X register int count
X = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
X /* Allocate buffer of that many longwords. */
X register int *buffer = (int *) alloca (count * sizeof (int));
X extern int errno;
X
X /* Read all the longwords */
X for (i = 0; i < count; i++, addr += sizeof (int))
X {
X errno = 0;
X if (remote_debugging)
X buffer[i] = remote_fetch_word (addr);
X else
X buffer[i] = ptrace (TREAD, inferior_pid, addr, 0);
X if (errno)
X return errno;
X }
X
X /* Copy appropriate bytes out of the buffer. */
X bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
X return 0;
X }
X
X /* Copy LEN bytes of data from debugger memory at MYADDR
X to inferior's memory at MEMADDR.
X On failure (cannot write the inferior)
X returns the value of errno. */
X
X int
X write_inferior_memory (memaddr, myaddr, len)
X CORE_ADDR memaddr;
X char *myaddr;
X int len;
X {
X register int i;
X /* Round starting address down to longword boundary. */
X register CORE_ADDR addr = memaddr & - sizeof (int);
X /* Round ending address up; get number of longwords that makes. */
X register int count
X = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
X /* Allocate buffer of that many longwords. */
X register int *buffer = (int *) alloca (count * sizeof (int));
X extern int errno;
X
X /* Fill start and end extra bytes of buffer with existing memory data. */
X
X if (remote_debugging)
X buffer[0] = remote_fetch_word (addr);
X else
X buffer[0] = ptrace (TREAD, inferior_pid, addr, 0);
X
X if (count > 1)
X {
X if (remote_debugging)
X buffer[count - 1]
X = remote_fetch_word (addr + (count - 1) * sizeof (int));
X else
X buffer[count - 1]
X = ptrace (TREAD, inferior_pid,
X addr + (count - 1) * sizeof (int), 0);
X }
X
X /* Copy data to be written over corresponding part of buffer */
X
X bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
X
X /* Write the entire buffer. */
X
X for (i = 0; i < count; i++, addr += sizeof (int))
X {
X errno = 0;
X if (remote_debugging)
X remote_store_word (addr, buffer[i]);
X else
X ptrace ((addr >= data_start) ? DWRITE : TWRITE,
X inferior_pid, addr, buffer[i]);
X if (errno)
X return errno;
X }
X
X return 0;
X }
X
X /* Work with core dump and executable files, for GDB.
X This code would be in core.c if it weren't machine-dependent. */
X
X #ifndef N_TXTADDR
X #define N_TXTADDR(hdr) 0
X #endif /* no N_TXTADDR */
X
X #ifndef N_DATADDR
X #define N_DATADDR(hdr) hdr.a_text
X #endif /* no N_DATADDR */
X
X /* Make COFF and non-COFF names for things a little more compatible
X to reduce conditionals later. */
X
X #ifdef COFF_FORMAT
X #define a_magic magic
X #endif
X
X #ifndef COFF_FORMAT
X #ifndef AOUTHDR
X #define AOUTHDR struct exec
X #endif
X #endif
X
X extern char *sys_siglist[];
X
X
X /* Hook for `exec_file_command' command to call. */
X
X extern void (*exec_file_display_hook) ();
X
X /* File names of core file and executable file. */
X
X extern char *corefile;
X extern char *execfile;
X
X /* Descriptors on which core file and executable file are open.
X Note that the execchan is closed when an inferior is created
X and reopened if the inferior dies or is killed. */
X
X extern int corechan;
X extern int execchan;
X
X /* Last modification time of executable file.
X Also used in source.c to compare against mtime of a source file. */
X
X extern int exec_mtime;
X
X #ifdef COFF_FORMAT
X /* various coff data structures */
X
X extern FILHDR file_hdr;
X extern SCNHDR text_hdr;
X extern SCNHDR data_hdr;
X
X #endif /* not COFF_FORMAT */
X
X /* a.out header saved in core file. */
X
X extern AOUTHDR core_aouthdr;
X
X /* a.out header of exec file. */
X
X extern AOUTHDR exec_aouthdr;
X
X extern void validate_files ();
X
X extern int maxstkaddr; /* machine dependent values */
X extern short cpu_type; /* determines machine & cpu type */
X extern short fpu_exist; /* determines presence of Lightning*/
X extern short fpp_type; /* determines floating point processor type
X /* (ie. Lightning); this is used in
X /* conjunction with fpu_exist */
X
X core_file_command (filename, from_tty)
X char *filename;
X int from_tty;
X {
X int val;
X extern char registers[];
X
X /* Discard all vestiges of any previous core file
X and mark data and stack spaces as empty. */
X
X if (corefile)
X free (corefile);
X corefile = 0;
X
X if (corechan >= 0)
X close (corechan);
X corechan = -1;
X
X data_start = 0;
X data_end = 0;
X stack_start = STACK_END_ADDR;
X stack_end = STACK_END_ADDR;
X
X /* Now, if a new core file was specified, open it and digest it. */
X
X if (filename)
X {
X if (have_inferior_p ())
X error ("To look at a core file, you must kill the inferior with \"kill\".");
X corechan = open (filename, O_RDONLY, 0);
X if (corechan < 0)
X perror_with_name (filename);
X /* 4.2-style (and perhaps also sysV-style) core dump file. */
X {
X struct user u;
X
X unsigned int int_reg_offset;
X unsigned int fp_reg_offset;
X
X val = myread (corechan, &u, sizeof u);
X if (val < 0)
X perror_with_name ("Not a core file: reading upage");
X if (val != sizeof u)
X error ("Not a core file: could only read %d bytes", val);
X data_start = exec_data_start;
X
X data_end = data_start + NBPG * u.u_dsize;
X stack_start = stack_end - NBPG * u.u_ssize;
X data_offset = NBPG * UPAGES;
X stack_offset = NBPG * (UPAGES + u.u_dsize);
X int_reg_offset = (int) u.u_ar0 & 0xfff;
X fp_reg_offset = u.u_fp_881reg0 & 0xfff;
X
X /* I don't know where to find this info.
X So, for now, mark it as not available. */
X N_SET_MAGIC (core_aouthdr, 0);
X
X /* Read the register values out of the core file and store
X them where `read_register' will find them. */
X
X {
X register int regno;
X
X for (regno = 0; regno < NUM_REGS; regno++)
X {
X char buf[MAX_REGISTER_RAW_SIZE];
X
X if (regno < FP0_REGNUM)
X val = lseek (corechan, REGISTER_ADDR (int_reg_offset, regno), 0);
X else
X val = lseek (corechan, FP_REGISTER_ADDR (fp_reg_offset, regno), 0);
X if (val < 0
X || (val = myread (corechan, buf, sizeof buf)) < 0)
X {
X char * buffer = (char *) alloca (strlen (reg_names[regno])
X + 30);
X strcpy (buffer, "Reading register ");
X strcat (buffer, reg_names[regno]);
X
X perror_with_name (buffer);
X }
X
X supply_register (regno, buf);
X }
X }
X }
X if (filename[0] == '/')
X corefile = savestring (filename, strlen (filename));
X else
X {
X corefile = concat (current_directory, "/", filename);
X }
X
X set_current_frame ( create_new_frame (read_register (FP_REGNUM),
X read_pc ()));
X select_frame (get_current_frame (), 0);
X validate_files ();
X }
X else if (from_tty)
X printf ("No core file now.\n");
X }
X
X exec_file_command (filename, from_tty)
X char *filename;
X int from_tty;
X {
X int val;
X
X /* Eliminate all traces of old exec file.
X Mark text segment as empty. */
X
X if (execfile)
X free (execfile);
X execfile = 0;
X data_start = 0;
X data_end -= exec_data_start;
X text_start = 0;
X text_end = 0;
X exec_data_start = 0;
X exec_data_end = 0;
X if (execchan >= 0)
X close (execchan);
X execchan = -1;
X
X /* Now open and digest the file the user requested, if any. */
X
X if (filename)
X {
X execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
X &execfile);
X if (execchan < 0)
X perror_with_name (filename);
X
X {
X struct stat st_exec;
X
X #ifdef HEADER_SEEK_FD
X HEADER_SEEK_FD (execchan);
X #endif
X
X val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
X
X if (val < 0)
X perror_with_name (filename);
X
X text_start = N_TXTADDR (exec_aouthdr);
X exec_data_start = N_DATADDR (exec_aouthdr);
X
X text_offset = N_TXTOFF (exec_aouthdr);
X exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
X
X text_end = text_start + exec_aouthdr.a_text;
X exec_data_end = exec_data_start + exec_aouthdr.a_data;
X data_start = exec_data_start;
X data_end += exec_data_start;
X
X fstat (execchan, &st_exec);
X exec_mtime = st_exec.st_mtime;
X }
X
X validate_files ();
X }
X else if (from_tty)
X printf ("No exec file now.\n");
X
X /* Tell display code (if any) about the changed file name. */
X if (exec_file_display_hook)
X (*exec_file_display_hook) (filename);
X }
BUNDLE_EOF
if test 18183 -ne "`wc -c <mass-dep.c`"
then
echo shar: error transmitting mass-dep.c \(should have 18183 characters\)
fi
fi
Technical Details
Message-ID:
<9008081747.AA01046@sugar-bombs.ai.mit.edu>Path:
arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!AI.MIT.EDU!rmsShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: f5053,a1dd611f8af67d25,start X-Google-Attributes: gidf5053,public X-Google-ArrivalTime: 1990-08-09 04:35:17 PST Path: arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!AI.MIT.EDU!rms From: rms@AI.MIT.EDU Newsgroups: gnu.gdb.bug Subject: [will@nirvana.westford.ccur.com: GDB patches for Concurrent/Masscomp machines.] Message-ID: <9008081747.AA01046@sugar-bombs.ai.mit.edu> Date: 8 Aug 90 17:47:22 GMT Sender: quinlan@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 1427 Posted: Wed Aug 8 18:47:22 1990