🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

1 total messages Started by Kevin Boyes Mon, 26 Jun 1989 13:52
(none)
#53
Author: Kevin Boyes
Date: Mon, 26 Jun 1989 13:52
1222 lines
35889 bytes
A bug report for gdb 3.1.1.  See the enclosed shar,
in particular what.happened.

#! /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:
#	what.happened
#	blockframe.c
#	inflow.c
# This archive created: Mon Jun 26 09:49:44 1989
export PATH; PATH=/bin:$PATH
if test -f 'what.happened'
then
	echo shar: will not over-write existing file "'what.happened'"
else
cat << \SHAR_EOF > 'what.happened'
Hello,

While installing gdb on our Sun4/280 I came across a bug.
It involves dereferencing a NULL pointer in get_frame_block
in the file blockframe.c
What follows is a log of the compile and dbx (sorry) run
on gdb.  I will also include the file blockframe.c
and the file inflow.c where I got a complaint and made a fix.
The fix provided for blockframe.c is a hack as I do not have
time to spend with the code.

As I said above I am running on a Sun4/280 with SunOS Release 4.0.1_Export

If anymore information is required just ask.

Maybe gcc should recognize -sun4 or -msun4 option ???

						Kevin Boyes
===============================================================================

Script started on Fri Jun 23 16:27:09 1989
/u0/staff/kevinb/tmp/gnu/gdb/3.1.1 [1]] config.gdb
Usage: config.gdb machine [operating-system]
Available machine types:
hp9k320 i386 i386gas isi merlin news npl pn sparc sun2 sun2os4 sun3 sun3os4 sun4os4 umax vax
/u0/staff/kevinb/tmp/gnu/gdb/3.1.1 [2]] config.gdb sparc sunos4
Linked `param.h' to `m-sparc.h'.
Linked `pinsn.c' to `sparc-pinsn.c'.
Linked `opcode.h' to `sparc-opcode.h'.
Linked `dep.c' to `sparc-dep.c'.
Links are now set up for use with a sparc.
/u0/staff/kevinb/tmp/gnu/gdb/3.1.1 [3]] make
gcc -I. -g  -sun4 -c  main.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  blockframe.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  breakpoint.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  findvar.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  stack.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  source.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  values.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  eval.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  valops.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  valarith.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  valprint.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  printcmd.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  symtab.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  symmisc.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  coffread.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  dbxread.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  infcmd.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  infrun.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  remote.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  command.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  utils.c
gcc: unrecognized option `-sun4'
gcc -c -I. -g expread.tab.c
mv expread.tab.o expread.o
gcc -I. -g  -sun4 -c  expprint.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  pinsn.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  environ.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  version.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  core.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  inflow.c
inflow.c: In function terminal_ours_1:
inflow.c:204: warning: assignment between incompatible pointer types
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  dep.c
gcc: unrecognized option `-sun4'
gcc -I. -g  -sun4 -c  obstack.c
gcc: unrecognized option `-sun4'
rm init.c
rm: init.c: No such file or directory
*** Error code 1 (ignored)
./munch main.o blockframe.o breakpoint.o findvar.o stack.o source.o  values.o eval.o valops.o valarith.o valprint.o printcmd.o  symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o  command.o utils.o expread.o expprint.o pinsn.o environ.o version.o core.o inflow.o dep.o > init.c
gcc -g -o gdb init.c main.o blockframe.o breakpoint.o findvar.o stack.o source.o  values.o eval.o valops.o valarith.o valprint.o printcmd.o  symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o  command.o utils.o expread.o expprint.o pinsn.o environ.o version.o core.o inflow.o dep.o obstack.o  
/u0/staff/kevinb/tmp/gnu/gdb/3.1.1 [4]] exit

script done on Fri Jun 23 16:31:34 1989
=======================================
after fixing inflow.c
^^^^^^^^^^^^^^^^^^^^^

gcc -I. -g  -sun4 -c  inflow.c
gcc: unrecognized option `-sun4'
rm init.c
./munch main.o blockframe.o breakpoint.o findvar.o stack.o source.o  values.o eval.o valops.o valarith.o valprint.o printcmd.o  symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o  command.o utils.o expread.o expprint.o pinsn.o environ.o version.o core.o inflow.o dep.o > init.c
gcc -g -o gdb init.c main.o blockframe.o breakpoint.o findvar.o stack.o source.o  values.o eval.o valops.o valarith.o valprint.o printcmd.o  symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o  command.o utils.o expread.o expprint.o pinsn.o environ.o version.o core.o inflow.o dep.o obstack.o  
=======================================

Script started on Fri Jun 23 16:40:14 1989
/u0/staff/kevinb/tmp/gnu/gdb/3.1.1 [1]] dbx gdb
Reading symbolic information...
Read 19494 symbols
(dbx) run
Running: gdb 
GDB 3.1.1, Copyright (C) 1988 Free Software Foundation, Inc.
There is ABSOLUTELY NO WARRANTY for GDB; type "info warranty" for details.
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "info copying" to see the conditions.
Function fatal not defined.
Type "help" for a list of commands.
(gdb) info args
signal SEGV (segmentation violation) in get_frame_block at line 357 in file "/blockframe.c"
  357     return block_for_pc (fi->pc);
(dbx) where
get_frame_block(frame = (nil)), line 357 in "blockframe.c"
get_frame_function(frame = (nil)), line 389 in "blockframe.c"
print_frame_arg_vars(), line 500 in "stack.c"
args_info(), line 530 in "stack.c"
execute_command(p = 0x69df1 "", from_tty = 1), line 423 in "main.c"
command_loop(), line 447 in "main.c"
main(argc = 1, argv = 0xf7fffe24, envp = 0xf7fffe2c), line 376 in "main.c"
(dbx) print fi
`blockframe`get_frame_block`fi = (nil)
(dbx) quit
/u0/staff/kevinb/tmp/gnu/gdb/3.1.1 [2]] exit

script done on Fri Jun 23 16:42:17 1989

SHAR_EOF
fi # end of overwriting check
if test -f 'blockframe.c'
then
	echo shar: will not over-write existing file "'blockframe.c'"
else
cat << \SHAR_EOF > 'blockframe.c'
/* Get info from stack frames;
   convert between frames, blocks, functions and pc values.
   Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.

GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY.  No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.

Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License.  A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities.  It
should be in a file named COPYING.  Among other things, the copyright
notice and this notice must be preserved on all copies.

In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther.  Help stamp out software hoarding!
*/

#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"

/* Address of end of first object file.
   This file is assumed to be a startup file
   and frames with pc's inside it
   are treated as nonexistent.  */

CORE_ADDR first_object_file_end;

/* Address of innermost stack frame (contents of FP register) */

static FRAME current_frame;

struct block *block_for_pc ();
CORE_ADDR get_pc_function_start ();

/*
 * Cache for frame addresses already read by gdb.  Valid only while
 * inferior is stopped.  Control variables for the frame cache should
 * be local to this module.
 */
struct obstack frame_cache_obstack;

/* Return the innermost (currently executing) stack frame.  */

FRAME
get_current_frame ()
{
  /* We assume its address is kept in a general register;
     param.h says which register.  */

  return current_frame;
}

void
set_current_frame (frame)
     FRAME frame;
{
  current_frame = frame;
}

FRAME
create_new_frame (addr, pc)
     FRAME_ADDR addr;
     CORE_ADDR pc;
{
  struct frame_info *fci;	/* Same type as FRAME */

  fci = (struct frame_info *)
    obstack_alloc (&frame_cache_obstack,
		   sizeof (struct frame_info));

  /* Arbitrary frame */
  fci->next = (struct frame_info *) 0;
  fci->prev = (struct frame_info *) 0;
  fci->frame = addr;
  fci->next_frame = 0;		/* Since arbitrary */
  fci->pc = pc;

#ifdef INIT_EXTRA_FRAME_INFO
  INIT_EXTRA_FRAME_INFO (fci);
#endif

  return fci;
}

/* Return the frame that called FRAME.
   If FRAME is the original frame (it has no caller), return 0.  */

FRAME
get_prev_frame (frame)
     FRAME frame;
{
  /* We're allowed to know that FRAME and "struct frame_info *" are
     the same */
  return get_prev_frame_info (frame);
}

/*
 * Flush the entire frame cache.
 */
void
flush_cached_frames ()
{
  /* Since we can't really be sure what the first object allocated was */
  obstack_free (&frame_cache_obstack, 0);
  obstack_init (&frame_cache_obstack);
  
  current_frame = (struct frame_info *) 0; /* Invalidate cache */
}

/* Return a structure containing various interesting information
   about a specified stack frame.  */
/* How do I justify including this function?  Well, the FRAME
   identifier format has gone through several changes recently, and
   it's not completely inconceivable that it could happen again.  If
   it does, have this routine around will help */

struct frame_info *
get_frame_info (frame)
     FRAME frame;
{
  return frame;
}

/* Return a structure containing various interesting information
   about the frame that called NEXT_FRAME.  */

struct frame_info *
get_prev_frame_info (next_frame)
     FRAME next_frame;
{
  FRAME_ADDR address;
  struct frame_info *prev;
  int fromleaf = 0;

  /* If we are within "start" right now, don't go any higher.  */
  if (next_frame && next_frame->pc < first_object_file_end)
    return 0;

  /* If the requested entry is in the cache, return it.
     Otherwise, figure out what the address should be for the entry
     we're about to add to the cache. */

  if (!next_frame)
    {
      if (!current_frame)
	fatal ("get_prev_frame_info: Called before cache primed");

      return current_frame;
    }
  else
    {
      /* If we have the prev one, return it */
      if (next_frame->prev)
	return next_frame->prev;

      /* There is a questionable, but probably always correct
	 assumption being made here.  The assumption is that if
	 functions on a specific machine has a FUNCTION_START_OFFSET,
	 then this is used by the function call instruction for some
	 purpose.  If the function call instruction has this much hair
	 in it, it probably also sets up the frame pointer
	 automatically (ie.  we'll never have what I am calling a
	 "leaf node", one which shares a frame pointer with it's
	 calling function).  This is true on a vax.  The only other
	 way to find this out would be to setup a seperate macro
	 "FUNCTION_HAS_FRAME_POINTER", which would often be equivalent
	 to SKIP_PROLOGUE modifying a pc value.  */

#if FUNCTION_START_OFFSET == 0
      if (!(next_frame->next))
	{
	  /* Innermost */
	  CORE_ADDR func_start, after_prologue;

	  func_start = (get_pc_function_start (next_frame->pc) +
			FUNCTION_START_OFFSET);
	  after_prologue = func_start;
	  SKIP_PROLOGUE (after_prologue);
	  if (after_prologue == func_start)
	    {
	      fromleaf = 1;
	      address = next_frame->frame;
	    }
	}
#endif

      if (!fromleaf)
	{
	  /* Two macros defined in param.h specify the machine-dependent
	     actions to be performed here.  */
	  /* First, get the frame's chain-pointer.
	     If that is zero, the frame is the outermost frame.  */
	  address = FRAME_CHAIN (next_frame);
	  if (!FRAME_CHAIN_VALID (address, next_frame))
	    return 0;

	  /* If frame has a caller, combine the chain pointer and
	     the frame's own address to get the address of the caller.  */
	  address = FRAME_CHAIN_COMBINE (address, next_frame);
	}
    }

  prev = (struct frame_info *)
    obstack_alloc (&frame_cache_obstack,
		   sizeof (struct frame_info));

  if (next_frame)
    next_frame->prev = prev;
  prev->next = next_frame;
  prev->prev = (struct frame_info *) 0;
  prev->frame = address;
  prev->next_frame = prev->next ? prev->next->frame : 0;

#ifdef INIT_EXTRA_FRAME_INFO
  INIT_EXTRA_FRAME_INFO(prev);
#endif

  /* This entry is in the frame queue now, which is good since
     FRAME_SAVED_PC may use that queue to figure out it's value
     (see m-sparc.h).  We want the pc saved in the inferior frame. */
  prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (next_frame) :
	      next_frame ? FRAME_SAVED_PC (next_frame) : read_pc ());

  return prev;
}

CORE_ADDR
get_frame_pc (frame)
     FRAME frame;
{
  struct frame_info *fi;
  fi = get_frame_info (frame);
  return fi->pc;
}

/* Find the addresses in which registers are saved in FRAME.  */

void
get_frame_saved_regs (frame_info_addr, saved_regs_addr)
     struct frame_info *frame_info_addr;
     struct frame_saved_regs *saved_regs_addr;
{
#if 1
  FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr);
#else
  {
    register int regnum;							
    register int regmask;							
    register CORE_ADDR next_addr;						
    register CORE_ADDR pc;						
    int nextinsn;								
    bzero (&*saved_regs_addr, sizeof *saved_regs_addr);			
    if ((frame_info_addr)->pc >= ((frame_info_addr)->frame
			     - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4)
	&& (frame_info_addr)->pc <= (frame_info_addr)->frame)				
      {
	next_addr = (frame_info_addr)->frame;					
	pc = (frame_info_addr)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4;
      }
    else   								
      {
	pc = get_pc_function_start ((frame_info_addr)->pc); 			
	/* Verify we have a link a6 instruction next;			
	   if not we lose.  If we win, find the address above the saved   
	   regs using the amount of storage from the link instruction.  */
	if (044016 == read_memory_integer (pc, 2))			
	  {
	    next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 4);
	    pc += 4;
	  }
	else if (047126 == read_memory_integer (pc, 2))
	  {
	    next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 2);
	    pc+=2;
	  }
	else goto lose;							
	
	/* If have an addal #-n, sp next, adjust next_addr.  */		
	if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
	  {
	    next_addr += read_memory_integer (pc += 2, 4);
	    pc += 4;
	  }
      }									
    /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */	
    regmask = read_memory_integer (pc + 2, 2);				
    
    /* But before that can come an fmovem.  Check for it.  */		
    nextinsn = 0xffff & read_memory_integer (pc, 2);			
    if (0xf227 == nextinsn						
	&& (regmask & 0xff00) == 0xe000)					
      {
	pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ 
	for (regnum = FP0_REGNUM + 7;
	     regnum >= FP0_REGNUM;
	     regnum--, regmask >>= 1)		
	  if (regmask & 1)						
	    (*saved_regs_addr).regs[regnum] = (next_addr -= 12);		
	regmask = read_memory_integer (pc + 2, 2);
      }			
    if (0044327 == read_memory_integer (pc, 2))				
      {
	pc += 4; /* Regmask's low bit is for register 0, the first written */ 
	for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)		
	  if (regmask & 1)						
	    (*saved_regs_addr).regs[regnum] = (next_addr += 4) - 4;
      }	
    else if (0044347 == read_memory_integer (pc, 2))			
      { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ 
	for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)		
	  if (regmask & 1)						
	    (*saved_regs_addr).regs[regnum] = (next_addr -= 4); }		
    else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))		
      { regnum = 0xf & read_memory_integer (pc, 2); pc += 2;		
	(*saved_regs_addr).regs[regnum] = (next_addr -= 4); }		
    /* fmovemx to index of sp may follow.  */				
    regmask = read_memory_integer (pc + 2, 2);				
    nextinsn = 0xffff & read_memory_integer (pc, 2);			
    if (0xf236 == nextinsn						
	&& (regmask & 0xff00) == 0xf000)					
      {
	pc += 10; /* Regmask's low bit is for register fp0, the first written */ 
	for (regnum = FP0_REGNUM + 7;
	     regnum >= FP0_REGNUM;
	     regnum--, regmask >>= 1)		
	  if (regmask & 1)						
	    (*saved_regs_addr).regs[regnum] = (next_addr += 12) - 12;	
	regmask = read_memory_integer (pc + 2, 2);
      }			
    /* clrw -(sp); movw ccr,-(sp) may follow.  */				
    if (0x426742e7 == read_memory_integer (pc, 4))			
      (*saved_regs_addr).regs[PS_REGNUM] = (next_addr -= 4);		
  lose: ;								
    (*saved_regs_addr).regs[SP_REGNUM] = (frame_info_addr)->frame + 8;		
    (*saved_regs_addr).regs[FP_REGNUM] = (frame_info_addr)->frame;		
    (*saved_regs_addr).regs[PC_REGNUM] = (frame_info_addr)->frame + 4;		
  }
#endif
}

/* Return the innermost lexical block in execution
   in a specified stack frame.  The frame address is assumed valid.  */

struct block *
get_frame_block (frame)
     FRAME frame;
{
  struct frame_info *fi;

  fi = get_frame_info (frame);
/* -- bug --
** when gdb is first run frame is not initialized
** and is NULL.  Dereferencing it is a no-no and causes core
** -- fix -- (hack)
** check fi here and if NULL return zero
** because that is what block_for_pc returns on failure
*/
  if (fi == (struct frame_info *)0)
	return(0);
  return block_for_pc (fi->pc);
}

struct block *
get_current_block ()
{
  return block_for_pc (read_pc ());
}

CORE_ADDR
get_pc_function_start (pc)
     CORE_ADDR pc;
{
  register struct block *bl = block_for_pc (pc);
  register struct symbol *symbol;
  if (bl == 0 || (symbol = block_function (bl)) == 0)
    {
      register int misc_index = find_pc_misc_function (pc);
      if (misc_index >= 0)
	return misc_function_vector[misc_index].address;
      return 0;
    }
  bl = SYMBOL_BLOCK_VALUE (symbol);
  return BLOCK_START (bl);
}

/* Return the symbol for the function executing in frame FRAME.  */

struct symbol *
get_frame_function (frame)
     FRAME frame;
{
  register struct block *bl = get_frame_block (frame);
  if (bl == 0)
    return 0;
  return block_function (bl);
}

/* Return the innermost lexical block containing the specified pc value,
   or 0 if there is none.  */

extern struct symtab *psymtab_to_symtab ();

struct block *
block_for_pc (pc)
     register CORE_ADDR pc;
{
  register struct block *b;
  register int bot, top, half;
  register struct symtab *s;
  register struct partial_symtab *ps;
  struct blockvector *bl;

  /* First search all symtabs for one whose file contains our pc */

  for (s = symtab_list; s; s = s->next)
    {
      bl = BLOCKVECTOR (s);
      b = BLOCKVECTOR_BLOCK (bl, 0);
      if (BLOCK_START (b) <= pc
	  && BLOCK_END (b) > pc)
	break;
    }

  if (s == 0)
    for (ps = partial_symtab_list; ps; ps = ps->next)
      {
	if (ps->textlow <= pc
	    && ps->texthigh > pc)
	  {
	    s = psymtab_to_symtab (ps);
	    bl = BLOCKVECTOR (s);
	    b = BLOCKVECTOR_BLOCK (bl, 0);
	    break;
	  }
      }

  if (s == 0)
    return 0;

  /* Then search that symtab for the smallest block that wins.  */
  /* Use binary search to find the last block that starts before PC.  */

  bot = 0;
  top = BLOCKVECTOR_NBLOCKS (bl);

  while (top - bot > 1)
    {
      half = (top - bot + 1) >> 1;
      b = BLOCKVECTOR_BLOCK (bl, bot + half);
      if (BLOCK_START (b) <= pc)
	bot += half;
      else
	top = bot + half;
    }

  /* Now search backward for a block that ends after PC.  */

  while (bot >= 0)
    {
      b = BLOCKVECTOR_BLOCK (bl, bot);
      if (BLOCK_END (b) > pc)
	return b;
      bot--;
    }

  return 0;
}

/* Return the function containing pc value PC.
   Returns 0 if function is not known.  */

struct symbol *
find_pc_function (pc)
     CORE_ADDR pc;
{
  register struct block *b = block_for_pc (pc);
  if (b == 0)
    return 0;
  return block_function (b);
}

/* Find the misc function whose address is the largest
   while being less than PC.  Return its index in misc_function_vector.
   Returns -1 if PC is not in suitable range.  */

int
find_pc_misc_function (pc)
     register CORE_ADDR pc;
{
  register int lo = 0;
  register int hi = misc_function_count-1;
  register int new;
  register int distance;

  /* Note that the last thing in the vector is always _etext.  */

  /* Above statement is not *always* true - fix for case where there are */
  /* no misc functions at all (ie no symbol table has been read). */
  if (hi < 0) return -1;        /* no misc functions recorded */

  /* trivial reject range test */
  if (pc < misc_function_vector[0].address ||
      pc > misc_function_vector[hi].address)
    return -1;

  do {
    new = (lo + hi) >> 1;
    distance = misc_function_vector[new].address - pc;
    if (distance == 0)
      return new;		/* an exact match */
    else if (distance > 0)
      hi = new;
    else
      lo = new;
  } while (hi-lo != 1);

  /* if here, we had no exact match, so return the lower choice */
  return lo;
}

/* Return the innermost stack frame executing inside of the specified block,
   or zero if there is no such frame.  */

FRAME
block_innermost_frame (block)
     struct block *block;
{
  struct frame_info *fi;
  register FRAME frame;
  register CORE_ADDR start = BLOCK_START (block);
  register CORE_ADDR end = BLOCK_END (block);

  frame = 0;
  while (1)
    {
      frame = get_prev_frame (frame);
      if (frame == 0)
	return 0;
      fi = get_frame_info (frame);
      if (fi->pc >= start && fi->pc < end)
	return frame;
    }
}

void
_initialize_blockframe ()
{
  obstack_init (&frame_cache_obstack);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'inflow.c'
then
	echo shar: will not over-write existing file "'inflow.c'"
else
cat << \SHAR_EOF > 'inflow.c'
/* Low level interface to ptrace, for GDB when running under Unix.
   Copyright (C) 1986, 1987 Free Software Foundation, Inc.

GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY.  No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.

Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License.  A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities.  It
should be in a file named COPYING.  Among other things, the copyright
notice and this notice must be preserved on all copies.

In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther.  Help stamp out software hoarding!
*/
#include "defs.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"

#ifdef USG
#include <sys/types.h>
#include <sys/fcntl.h>
#endif

#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>

/* May be unnecessary since many parts of inflow.c 
   have migrated to *-infdep.c */
#ifdef USG
#include <sys/user.h>
#endif

#ifdef HAVE_TERMIO
#include <termio.h>
#undef TIOCGETP
#define TIOCGETP TCGETA
#undef TIOCSETN
#define TIOCSETN TCSETA
#undef TIOCSETP
#define TIOCSETP TCSETAF
#define TERMINAL struct termio
#else
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sgtty.h>
#define TERMINAL struct sgttyb
#endif

#ifdef SET_STACK_LIMIT_HUGE
#include <sys/time.h>
#include <sys/resource.h>
extern int original_stack_limit;
#endif /* SET_STACK_LIMIT_HUGE */

extern int errno;

/* Nonzero if we are debugging an attached outside process
   rather than an inferior.  */

int attach_flag;


/* Record terminal status separately for debugger and inferior.  */

static TERMINAL sg_inferior;
static TERMINAL sg_ours;

static int tflags_inferior;
static int tflags_ours;

#ifdef TIOCGLTC
static struct tchars tc_inferior;
static struct tchars tc_ours;
static struct ltchars ltc_inferior;
static struct ltchars ltc_ours;
static int lmode_inferior;
static int lmode_ours;
#endif /* TIOCGLTC */

#ifdef TIOCGPGRP
static int pgrp_inferior;
static int pgrp_ours;
#else
static int (*sigint_ours) ();
static int (*sigquit_ours) ();
#endif /* TIOCGPGRP */

/* Copy of inferior_io_terminal when inferior was last started.  */
static char *inferior_thisrun_terminal;

static void terminal_ours_1 ();

/* Nonzero if our terminal settings are in effect.
   Zero if the inferior's settings are in effect.  */
static int terminal_is_ours;

/* Initialize the terminal settings we record for the inferior,
   before we actually run the inferior.  */

void
terminal_init_inferior ()
{
  if (remote_debugging)
    return;

  sg_inferior = sg_ours;
  tflags_inferior = tflags_ours;

#ifdef TIOCGLTC
  tc_inferior = tc_ours;
  ltc_inferior = ltc_ours;
  lmode_inferior = lmode_ours;
#endif /* TIOCGLTC */

#ifdef TIOCGPGRP
  pgrp_inferior = inferior_pid;
#endif /* TIOCGPGRP */

  terminal_is_ours = 1;
}

/* Put the inferior's terminal settings into effect.
   This is preparation for starting or resuming the inferior.  */

void
terminal_inferior ()
{
  if (remote_debugging)
    return;

  if (terminal_is_ours)   /*  && inferior_thisrun_terminal == 0) */
    {
      fcntl (0, F_SETFL, tflags_inferior);
      fcntl (0, F_SETFL, tflags_inferior);
      ioctl (0, TIOCSETN, &sg_inferior);
#ifdef TIOCGLTC
      ioctl (0, TIOCSETC, &tc_inferior);
      ioctl (0, TIOCSLTC, &ltc_inferior);
      ioctl (0, TIOCLSET, &lmode_inferior);
#endif /* TIOCGLTC */

#ifdef TIOCGPGRP
      ioctl (0, TIOCSPGRP, &pgrp_inferior);
#else
      sigint_ours = (int (*) ()) signal (SIGINT, SIG_IGN);
      sigquit_ours = (int (*) ()) signal (SIGQUIT, SIG_IGN);
#endif /* TIOCGPGRP */
    }
  terminal_is_ours = 0;
}

/* Put some of our terminal settings into effect,
   enough to get proper results from our output,
   but do not change into or out of RAW mode
   so that no input is discarded.

   After doing this, either terminal_ours or terminal_inferior
   should be called to get back to a normal state of affairs.  */

void
terminal_ours_for_output ()
{
  if (remote_debugging)
    return;

  terminal_ours_1 (1);
}

/* Put our terminal settings into effect.
   First record the inferior's terminal settings
   so they can be restored properly later.  */

void
terminal_ours ()
{
  if (remote_debugging)
    return;

  terminal_ours_1 (0);
}

static void
terminal_ours_1 (output_only)
     int output_only;
{
#ifdef TIOCGPGRP
  /* Ignore this signal since it will happen when we try to set the pgrp.  */
/* was
  int (*osigttou) ();
** but signal wants a pointer to a function returning void
*/
  void (*osigttou) ();
#endif /* TIOCGPGRP */

  if (!terminal_is_ours)  /*   && inferior_thisrun_terminal == 0)  */
    {
      terminal_is_ours = 1;

#ifdef TIOCGPGRP
      osigttou = signal (SIGTTOU, SIG_IGN);

      ioctl (0, TIOCGPGRP, &pgrp_inferior);
      ioctl (0, TIOCSPGRP, &pgrp_ours);

      signal (SIGTTOU, osigttou);
#else
      signal (SIGINT, sigint_ours);
      signal (SIGQUIT, sigquit_ours);
#endif /* TIOCGPGRP */

      tflags_inferior = fcntl (0, F_GETFL, 0);
      ioctl (0, TIOCGETP, &sg_inferior);

#ifdef TIOCGLTC
      ioctl (0, TIOCGETC, &tc_inferior);
      ioctl (0, TIOCGLTC, &ltc_inferior);
      ioctl (0, TIOCLGET, &lmode_inferior);
#endif /* TIOCGLTC */
    }

#ifdef HAVE_TERMIO
  sg_ours.c_lflag |= ICANON;
  if (output_only && !(sg_inferior.c_lflag & ICANON))
    sg_ours.c_lflag &= ~ICANON;
#else /* not HAVE_TERMIO */
  sg_ours.sg_flags &= ~RAW & ~CBREAK;
  if (output_only)
    sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
#endif /* not HAVE_TERMIO */

  fcntl (0, F_SETFL, tflags_ours);
  fcntl (0, F_SETFL, tflags_ours);
  ioctl (0, TIOCSETN, &sg_ours);

#ifdef TIOCGLTC
  ioctl (0, TIOCSETC, &tc_ours);
  ioctl (0, TIOCSLTC, &ltc_ours);
  ioctl (0, TIOCLSET, &lmode_ours);
#endif /* TIOCGLTC */


#ifdef HAVE_TERMIO
  sg_ours.c_lflag |= ICANON;
#else /* not HAVE_TERMIO */
  sg_ours.sg_flags &= ~RAW & ~CBREAK;
#endif /* not HAVE_TERMIO */
}

static void
term_status_command ()
{
  register int i;

  if (remote_debugging)
    {
      printf ("No terminal status when remote debugging.\n");
      return;
    }

  printf ("Inferior's terminal status (currently saved by GDB):\n");

#ifdef HAVE_TERMIO

  printf ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n",
	  tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag);
  printf ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
	  sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line);
  printf ("c_cc: ");
  for (i = 0; (i < NCC); i += 1)
    printf ("0x%x ", sg_inferior.c_cc[i]);
  printf ("\n");

#else /* not HAVE_TERMIO */

  printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n",
	  tflags_inferior, lmode_inferior,
	  sg_inferior.sg_flags, pgrp_inferior);
  printf ("tchars: ");
  for (i = 0; i < sizeof (struct tchars); i++)
    printf ("0x%x ", ((char *)&tc_inferior)[i]);
  printf ("\n");
  printf ("ltchars: ");
  for (i = 0; i < sizeof (struct ltchars); i++)
    printf ("0x%x ", ((char *)&ltc_inferior)[i]);
  printf ("\n");

#endif /* not HAVE_TERMIO */
}

static void
new_tty (ttyname)
     char *ttyname;
{
  register int tty;
  register int fd;

#ifdef TIOCNOTTY
  /* Disconnect the child process from our controlling terminal.  */
  tty = open("/dev/tty", O_RDWR);
  if (tty > 0)
    {
      ioctl(tty, TIOCNOTTY, 0);
      close(tty);
    }
#endif

  /* Now open the specified new terminal.  */

  tty = open(ttyname, O_RDWR);
  if (tty == -1)
    _exit(1);

  dup2(tty, 0);
  dup2(tty, 1);
  dup2(tty, 2);
  close(tty);
}

/* Start an inferior process and returns its pid.
   ALLARGS is a string containing shell command to run the program.
   ENV is the environment vector to pass.  */

#ifndef SHELL_FILE
#define SHELL_FILE "/bin/sh"
#endif

int
create_inferior (allargs, env)
     char *allargs;
     char **env;
{
  int pid;
  char *shell_command;
  extern int sys_nerr;
  extern char *sys_errlist[];
  extern int errno;

  /* If desired, concat something onto the front of ALLARGS.
     SHELL_COMMAND is the result.  */
#ifdef SHELL_COMMAND_CONCAT
  shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1);
  strcpy (shell_command, SHELL_COMMAND_CONCAT);
  strcat (shell_command, allargs);
#else
  shell_command = allargs;
#endif

  /* exec is said to fail if the executable is open.  */
  close_exec_file ();

  pid = vfork ();
  if (pid < 0)
    perror_with_name ("vfork");

  if (pid == 0)
    {
#ifdef TIOCGPGRP
      /* Run inferior in a separate process group.  */
      setpgrp (getpid (), getpid ());
#endif /* TIOCGPGRP */

#ifdef SET_STACK_LIMIT_HUGE
      /* Reset the stack limit back to what it was.  */
      {
	struct rlimit rlim;

	getrlimit (RLIMIT_STACK, &rlim);
	rlim.rlim_cur = original_stack_limit;
	setrlimit (RLIMIT_STACK, &rlim);
      }
#endif /* SET_STACK_LIMIT_HUGE */


      inferior_thisrun_terminal = inferior_io_terminal;
      if (inferior_io_terminal != 0)
	new_tty (inferior_io_terminal);

/* Not needed on Sun, at least, and loses there
   because it clobbers the superior.  */
/*???      signal (SIGQUIT, SIG_DFL);
      signal (SIGINT, SIG_DFL);  */

      call_ptrace (0);
      execle (SHELL_FILE, "sh", "-c", shell_command, 0, env);

      fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE,
	       errno < sys_nerr ? sys_errlist[errno] : "unknown error");
      fflush (stderr);
      _exit (0177);
    }
  return pid;
}

/* Kill the inferior process.  Make us have no inferior.  */

static void
kill_command ()
{
  if (remote_debugging)
    return;
  if (inferior_pid == 0)
    error ("The program is not being run.");
  if (!query ("Kill the inferior process? "))
    error ("Not confirmed.");
  kill_inferior ();
}

void
inferior_died ()
{
  inferior_pid = 0;
  attach_flag = 0;
  mark_breakpoints_out ();
  reopen_exec_file ();
  if (have_core_file_p ())
    set_current_frame ( create_new_frame (read_register (FP_REGNUM),
					  read_pc ()));
}

static void
try_writing_regs_command ()
{
  register int i;
  register int value;
  extern int errno;

  if (inferior_pid == 0)
    error ("There is no inferior process now.");

  for (i = 0; ; i += 2)
    {
      QUIT;
      errno = 0;
      value = call_ptrace (3, inferior_pid, i, 0);
      call_ptrace (6, inferior_pid, i, value);
      if (errno == 0)
	{
	  printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
		  i, value, value);
	}
      else if ((i & 0377) == 0)
	printf (" Failed at 0x%x.\n", i);
    }
}

void
_initialize_inflow ()
{
  add_com ("term-status", class_obscure, term_status_command,
	   "Print info on inferior's saved terminal status.");

  add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
	   "Try writing all locations in inferior's system block.\n\
Report which ones can be written.");

  add_com ("kill", class_run, kill_command,
	   "Kill execution of program being debugged.");

  inferior_pid = 0;

  ioctl (0, TIOCGETP, &sg_ours);
  fcntl (0, F_GETFL, tflags_ours);

#ifdef TIOCGLTC
  ioctl (0, TIOCGETC, &tc_ours);
  ioctl (0, TIOCGLTC, &ltc_ours);
  ioctl (0, TIOCLGET, &lmode_ours);
#endif /* TIOCGLTC */

#ifdef TIOCGPGRP
  ioctl (0, TIOCGPGRP, &pgrp_ours);
#endif /* TIOCGPGRP */

  terminal_is_ours = 1;
}

SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0

-- 
Kevin Boyes                                     kevinb@sparkles.dcss.McMaster.CA
McMaster University                         ...!uunet!utai!utgpu!sparkles!kevinb
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads