[comp.unix.xenix] GDB for Xenix 386 with GCC

Steve.Bleazard@RoboBar.Co.UK (05/08/90)

This is part one of a coordinated set of 4 patches for Xenix GCC, GAS and GDB.
GCC and GAS will need to be ALREADY PATCHED with ALL my Xenix 386 patches.
Please collect all parts before you start hacking :-)

No, I haven't made up the complete patch kit for sources.misc yet, but
that's because I'd like to share gdb with you first :-)

This is a preliminary release of a port to SCO Xenix of gdb support for
gcc.  The gdb work is partly based on Ron Kuris <ron@rdk386.UUCP>'s work,
but I've severely mangled it.

	* It no longer attempts to be compatible with SCO's sdb.
	  Trying to do that seems to be like hitting your head against
	  a <name your favourite immovable object> because the debugging
	  info format is both undocumented and CHANGES FROM RELEASE TO
	  RELEASE of SCO's compiler, or so it would seem.  So I gave
	  up and used dbx debugging info instead, which is much
	  better supported by the GNUfolk anyway.  So you can't mix and
	  match cc and gcc -g compiled programs for debugging, but ...

	* The GDB port is nearly a full one, structure types, all seem
	  to work fine, but I haven't got a 387 (you could donate one,
	  of course :-) so I can't test the floating point status support.
	  I can't hack the emulator at the moment--it doesn't seem to use
	  387 format.

	* The gdb fast initial partial-symbol-table read is supported,
	  as is incremental symbol loading.

This is part 1 which patches GCC, say |patch -p -d /usr/local/src/gcc-1.37.1
or whatever.  BTW it fixes the bug reported by bob@dhw68k.cts.com where
gcc didn't give the linker -l libraries in the right place.

As usual, all bug reports concerning these hacks are gratefully received.
Please send them to me, steve@robobar.co.uk or uunet!mcsun!ukc!robobar!steve.

#! /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:
#	gcc-dbxpch.01
# This archive created: Tue May  8 09:32:38 1990
export PATH; PATH=/bin:$PATH
echo shar: extracting "'gcc-dbxpch.01'" '(8164 characters)'
if test -f 'gcc-dbxpch.01'
then
	echo shar: will not over-write existing file "'gcc-dbxpch.01'"
else
sed 's/^X//' << \SHAR_EOF > 'gcc-dbxpch.01'
X*** gcc.c.old	Mon May  7 15:42:23 1990
X--- gcc.c	Mon May  7 17:13:16 1990
X***************
X*** 96,104 ****
X   %{|S:X} like %{S:X}, but if no S switch, substitute `-'.
X   %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
X- *ifdef M_XENIX
X-  %Z	substitute the names of the libraries specified with -l, each
X- 	name is prefixed with 'Slib'and has .a appended; the resultant
X- 	name is searched for in the standard list of directories.
X- *endif
X  
X  The conditional text X in a %{S:X} or %{!S:X} construct may contain
X--- 96,99 ----
X***************
X*** 249,256 ****
X  
X  #ifdef M_XENIX
X  /* Microsoft C 5.1 (Beta) and earlier (and probaly latter!) do not
X   * grok very long strings.  So here is the .c compilation spec
X   * string in a form it does grok!  The only difference between this
X!  * and the standard one is 'as' is replaced with 'gas'.
X   */
X  static char c_string[] = {
X--- 244,253 ----
X  
X  #ifdef M_XENIX
X+ #ifndef __GNUC__
X  /* Microsoft C 5.1 (Beta) and earlier (and probaly latter!) do not
X   * grok very long strings.  So here is the .c compilation spec
X   * string in a form it does grok!  The only difference between this
X!  * and the standard one is 'as' is replaced with 'gas' and %{gg:...}
X!  * with %{g}.
X   */
X  static char c_string[] = {
X***************
X*** 325,341 ****
X  	0x20,0x25,0x7b,0x6a,0x7d,0x20,0x25,0x7b,0x4a,0x7d,
X  	0x20,0x25,0x7b,0x68,0x7d,0x20,0x25,0x7b,0x64,0x32,
X! 	0x7d,0x20,0x25,0x61,0x20,0x25,0x7b,0x67,0x67,0x3a,
X! 	0x2d,0x47,0x20,0x25,0x67,0x2e,0x73,0x79,0x6d,0x7d,
X! 	0x9,0x9,0x20,0x20,0x20,0x20,0x20,0x20,0x25,0x7b,
X! 	0x63,0x3a,0x25,0x7b,0x6f,0x2a,0x7d,0x25,0x7b,0x21,
X! 	0x6f,0x2a,0x3a,0x2d,0x6f,0x20,0x25,0x77,0x25,0x62,
X! 	0x2e,0x6f,0x7d,0x7d,0x25,0x7b,0x21,0x63,0x3a,0x2d,
X! 	0x6f,0x20,0x25,0x64,0x25,0x77,0x25,0x62,0x2e,0x6f,
X! 	0x7d,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
X  	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
X! 	0x20,0x20,0x20,0x25,0x7b,0x21,0x70,0x69,0x70,0x65,
X! 	0x3a,0x25,0x67,0x2e,0x73,0x7d,0xa,0x20,0x7d,0x7d,
X! 	0x7d,0x0
X  };
X  #endif /* M_XENIX */
X  
X--- 322,338 ----
X  	0x20,0x25,0x7b,0x6a,0x7d,0x20,0x25,0x7b,0x4a,0x7d,
X  	0x20,0x25,0x7b,0x68,0x7d,0x20,0x25,0x7b,0x64,0x32,
X! 	0x7d,0x20,0x25,0x61,0x20,0x25,0x7b,0x67,0x7d,0x9,
X! 	0x9,0x20,0x20,0x20,0x20,0x20,0x20,0x25,0x7b,0x63,
X! 	0x3a,0x25,0x7b,0x6f,0x2a,0x7d,0x25,0x7b,0x21,0x6f,
X! 	0x2a,0x3a,0x2d,0x6f,0x20,0x25,0x77,0x25,0x62,0x2e,
X! 	0x6f,0x7d,0x7d,0x25,0x7b,0x21,0x63,0x3a,0x2d,0x6f,
X! 	0x20,0x25,0x64,0x25,0x77,0x25,0x62,0x2e,0x6f,0x7d,
X  	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
X! 	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
X! 	0x20,0x20,0x25,0x7b,0x21,0x70,0x69,0x70,0x65,0x3a,
X! 	0x25,0x67,0x2e,0x73,0x7d,0xa,0x20,0x7d,0x7d,0x7d,
X! 	0x0
X  };
X+ #endif /* __GNUC__ */
X  #endif /* M_XENIX */
X  
X***************
X*** 359,363 ****
X--- 356,377 ----
X                        %{!pipe:%g.s}\n }}}"
X  #else /* M_XENIX */
X+ #ifdef __GNUC__
X+   "cpp %{nostdinc} %{C} %{v} %{D*} %{U*} %{I*} %{M*} %{i*} %{trigraphs} -undef \
X+         -D__GNUC__ %{ansi:-trigraphs -$ -D__STRICT_ANSI__} %{!ansi:%p} %P\
X+         %c %{O:-D__OPTIMIZE__} %{traditional} %{pedantic}\
X+ 	%{Wcomment*} %{Wtrigraphs} %{Wall} %C\
X+         %i %{!M*:%{!E:%{!pipe:%g.cpp}}}%{E:%{o*}}%{M*:%{o*}} |\n\
X+     %{!M*:%{!E:cc1 %{!pipe:%g.cpp} %1 \
X+ 		   %{!Q:-quiet} -dumpbase %i %{Y*} %{d*} %{m*} %{f*} %{a}\
X+ 		   %{g} %{O} %{W*} %{w} %{pedantic} %{ansi} %{traditional}\
X+ 		   %{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\
X+ 		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
X+ 		   %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
X+               %{!S:gas %{R} %{j} %{J} %{h} %{d2} %a %{g}\
X+ 		      %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\
X+                       %{!pipe:%g.s}\n }}}"
X+ #else /* __GNUC__ */
X     c_string
X+ #endif /* __GNUC__ */
X  #endif /* not M_XENIX */
X    },
X***************
X*** 392,396 ****
X  	%{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\
X  	%{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
X!     %{!S:gas %{R} %{j} %{J} %{h} %{d2} %a %{gg:-G %g.sym}\
X              %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o} %{!pipe:%g.s}\n }"},
X  #endif /* not M_XENIX */
X--- 406,410 ----
X  	%{v:-version} %{gg:-symout %g.sym} %{pg:-p} %{p}\
X  	%{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
X!     %{!S:gas %{R} %{j} %{J} %{h} %{d2} %a %{g}\
X              %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o} %{!pipe:%g.s}\n }"},
X  #endif /* not M_XENIX */
X***************
X*** 400,404 ****
X              %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o} %i\n }"},
X  #else /* M_XENIX */
X!    "%{!S:gas %{R} %{j} %{J} %{h} %{d2} %a \
X              %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o} %i\n }"},
X  #endif /* not M_XENIX */
X--- 414,418 ----
X              %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o} %i\n }"},
X  #else /* M_XENIX */
X!    "%{!S:gas %{R} %{j} %{J} %{h} %{d2} %a %{g}\
X              %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o} %i\n }"},
X  #endif /* not M_XENIX */
X***************
X*** 419,423 ****
X  	%{Wcomment*} %{Wtrigraphs} %{Wall} %C\
X          %i %{!M*:%{!E:%{!pipe:%g.s}}}%{E:%{o*}}%{M*:%{o*}} |\n\
X!     %{!M*:%{!E:%{!S:gas %{R} %{j} %{J} %{h} %{d2} %a \
X                      %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\
X  		    %{!pipe:%g.s}\n }}}"},
X--- 433,437 ----
X  	%{Wcomment*} %{Wtrigraphs} %{Wall} %C\
X          %i %{!M*:%{!E:%{!pipe:%g.s}}}%{E:%{o*}}%{M*:%{o*}} |\n\
X!     %{!M*:%{!E:%{!S:gas %{R} %{j} %{J} %{h} %{d2} %a %{g}\
X                      %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\
X  		    %{!pipe:%g.s}\n }}}"},
X***************
X*** 431,435 ****
X  char *link_spec = "%{!c:%{!M*:%{!E:%{!S:ld %{o*} %l %{g:-g} \
X   %{A} %{F} %{r} %{s} %{u*} \
X!  %{!nostdlib:%S} %{!o:-o a.out} %o %Z %{!nostdlib:gnulib%s %L }\n }}}}";
X  #else /* not M_XENIX */
X  char *link_spec = "%{!c:%{!M*:%{!E:%{!S:ld %{o*} %l\
X--- 445,449 ----
X  char *link_spec = "%{!c:%{!M*:%{!E:%{!S:ld %{o*} %l %{g:-g} \
X   %{A} %{F} %{r} %{s} %{u*} \
X!  %{!nostdlib:%S} %{!o:-o a.out} %o %{!nostdlib:gnulib%s %L }\n }}}}";
X  #else /* not M_XENIX */
X  char *link_spec = "%{!c:%{!M*:%{!E:%{!S:ld %{o*} %l\
X***************
X*** 1071,1084 ****
X  char **outfiles;
X  
X- #ifdef M_XENIX
X- 
X- /* A vector of library files (from -llibrary) */
X- 
X- char **libraries;
X- 
X- int n_libraries;
X- 
X- #endif /* M_XENIX */
X- 
X  /* Create the vector `switches' and its contents.
X     Store its length in `n_switches'.  */
X--- 1085,1088 ----
X***************
X*** 1093,1099 ****
X    n_switches = 0;
X    n_infiles = 0;
X- #ifdef M_XENIX
X-   n_libraries = 0;
X- #endif /* M_XENIX */
X  
X    env_exec_prefix = getenv ("GCC_EXEC_PREFIX");
X--- 1097,1100 ----
X***************
X*** 1105,1113 ****
X    for (i = 1; i < argc; i++)
X      {
X- #ifdef M_XENIX
X-       if (argv[i][0] == '-' && argv[i][1] == 'l')
X- 	n_libraries++;
X-       else
X- #endif /* M_XENIX */
X        if (argv[i][0] == '-' && argv[i][1] != 'l')
X  	{
X--- 1106,1109 ----
X***************
X*** 1147,1154 ****
X    switches = ((struct switchstr *)
X  	      xmalloc ((n_switches + 1) * sizeof (struct switchstr)));
X- #ifdef M_XENIX
X-   libraries = (char **) xmalloc ((n_libraries + 1) * sizeof (char *));
X-   n_libraries = 0;
X- #endif /* M_XENIX */
X    infiles = (char **) xmalloc ((n_infiles + 1) * sizeof (char *));
X    n_switches = 0;
X--- 1143,1146 ----
X***************
X*** 1161,1169 ****
X    for (i = 1; i < argc; i++)
X      {
X- #ifdef M_XENIX
X-       if (argv[i][0] == '-' && argv[i][1] == 'l')
X- 	libraries[n_libraries++] = &argv[i][2];
X-       else
X- #endif /* M_XENIX */
X        if (argv[i][0] == '-' && argv[i][1] != 'l')
X  	{
X--- 1153,1156 ----
X***************
X*** 1183,1186 ****
X--- 1170,1178 ----
X  	}
X        else
X+ #ifdef M_XENIX
X+       if (argv[i][0] == '-' && argv[i][1] == 'l')
X+ 	infiles[n_infiles++] = find_lib(&argv[i][2]);
X+       else
X+ #endif /* M_XENIX */
X  	infiles[n_infiles++] = argv[i];
X      }
X***************
X*** 1432,1445 ****
X  	    obstack_1grow (&obstack, '%');
X  	    break;
X- 
X- #ifdef M_XENIX
X- 	  case 'Z':
X- 	    {
X- 	      register int f;
X- 	      for (f = 0; f < n_libraries; f++)
X- 		store_arg (find_lib(libraries[f]), 0, 0);
X- 	    }
X- 	    break;
X- #endif /* M_XENIX */
X  
X  
X--- 1424,1427 ----
SHAR_EOF
if test 8164 -ne "`wc -c < 'gcc-dbxpch.01'`"
then
	echo shar: error transmitting "'gcc-dbxpch.01'" '(should have been 8164 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

Steve.Bleazard@RoboBar.Co.UK (05/08/90)

This is part two of a coordinated set of 4 patches for Xenix GCC, GAS and GDB.
Please collect all parts before you start hacking :-)

This is part 2 which patches GAS, say |patch -p -d /usr/local/src/gas-1.35
or whatever.   Please ensure that ALL my patches for GAS under Xenix 386
(original + 1 bugfix == 2 prior patches) have already been applied.

#! /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:
#	gas-dbxpch.01
# This archive created: Tue May  8 09:39:30 1990
export PATH; PATH=/bin:$PATH
echo shar: extracting "'gas-dbxpch.01'" '(13414 characters)'
if test -f 'gas-dbxpch.01'
then
	echo shar: will not over-write existing file "'gas-dbxpch.01'"
else
sed 's/^X//' << \SHAR_EOF > 'gas-dbxpch.01'
X*** ../gas-1.35.old/i386.c	Mon Mar  5 20:11:07 1990
X--- ./i386.c	Mon May  7 17:29:27 1990
X***************
X*** 1042,1046 ****
X  	/* I caught it failing with obstack_room == 6,
X  	   so I changed to <=   pace */
X! 	if (obstack_room (&frags) <= 6) frag_new (0);
X  	p = frag_more (1);
X  	p[0] = t->base_opcode;
X--- 1042,1046 ----
X  	/* I caught it failing with obstack_room == 6,
X  	   so I changed to <=   pace */
X! 	if (obstack_room (&frags) <= 6) { frag_wane(frag_now);  frag_new (0); }
X  	p = frag_more (1);
X  	p[0] = t->base_opcode;
X*** ../gas-1.35.old/msomf.h	Mon May  7 17:26:26 1990
X--- ./msomf.h	Tue May  1 10:01:23 1990
X***************
X*** 6,10 ****
X--- 6,13 ----
X  #define SDEF_CONST	3
X  #define SDEF_BSS	4
X+ #define SDEF_SYMBOLS	5
X+ #define SDEF_TYPES	6
X  #define SDEF_SIZE	4
X+ #define SDEF_G_SIZE	6
X  
X  #define GDEF_DGROUP	1
X*** ../gas-1.35.old/write.c	Mon May  7 17:28:28 1990
X--- ./write.c	Tue May  1 16:45:59 1990
X***************
X*** 48,51 ****
X--- 48,57 ----
X  #endif /* M_XENIX */
X  
X+ #if __STDC__
X+ #include <stddef.h>
X+ #else
X+ #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
X+ #endif
X+ 
X  void	append();
X  
X***************
X*** 87,90 ****
X--- 93,99 ----
X  
X  static long int string_byte_count;
X+ #ifdef M_XENIX
X+ static long int stab_symbol_count;
X+ #endif /* M_XENIX */
X  
X  static char *		the_object_file;
X***************
X*** 154,157 ****
X--- 163,195 ----
X  }
X  
X+ #ifdef M_XENIX
X+ threads(type, trgt_thrd, frm_thrd)
X+ int type;
X+ int *trgt_thrd, *frm_thrd;
X+ {
X+ 	  switch (type)
X+ 	  {
X+ 	    case PRIVDATA:	*trgt_thrd = DATA_TGT_THREAD;
X+ 				*frm_thrd = DGROUP_FRAME_THREAD;
X+ 				break;
X+ 	    case PRIVBSS:	*trgt_thrd = BSS_TGT_THREAD;
X+ 				*frm_thrd = DGROUP_FRAME_THREAD;
X+ 				break;
X+ 	    case PRIVTEXT:	*trgt_thrd = TEXT_TGT_THREAD;
X+ 				*frm_thrd = TEXT_FRAME_THREAD;
X+ 				break;
X+ 	    case PUBLICDATA:	*trgt_thrd = DATA_TGT_THREAD;
X+ 				*frm_thrd = DGROUP_FRAME_THREAD;
X+ 				break;
X+ 	    case PUBLICTEXT:	*trgt_thrd = TEXT_TGT_THREAD;
X+ 				*frm_thrd = TEXT_FRAME_THREAD;
X+ 				break;
X+ 	    default:		*trgt_thrd = CONST_TGT_THREAD;
X+ 				*frm_thrd = DGROUP_FRAME_THREAD;
X+ 				break;
X+ 	  }
X+ }
X+ #endif /* M_XENIX */
X+ 
X  void
X  write_object_file()
X***************
X*** 377,381 ****
X      symbol_number = 0;
X  #else /* M_XENIX */
X!     symbol_number = 1;
X  #endif /* M_XENIX */
X  
X--- 415,419 ----
X      symbol_number = 0;
X  #else /* M_XENIX */
X!     symbol_number = 1;  stab_symbol_count = 0;
X  #endif /* M_XENIX */
X  
X***************
X*** 409,418 ****
X  	    else
X  	    	symbolP -> sy_number = 0;
X  #else /* M_XENIX */
X  	    symbolP -> sy_number = symbol_number ++;
X  #endif /* M_XENIX */
X- #ifndef M_XENIX
X  #ifndef	VMS
X  	    if (name)
X  	      {			/* Ordinary case. */
X  		symbolP -> sy_name_offset = string_byte_count;
X--- 447,461 ----
X  	    else
X  	    	symbolP -> sy_number = 0;
X+ 	    if (symbolP->sy_nlist.n_type&N_STAB)
X+ 		stab_symbol_count++;
X  #else /* M_XENIX */
X  	    symbolP -> sy_number = symbol_number ++;
X  #endif /* M_XENIX */
X  #ifndef	VMS
X+ #ifndef M_XENIX
X  	    if (name)
X+ #else /* M_XENIX */
X+ 	    if (name && symbolP->sy_nlist.n_type&N_STAB)
X+ #endif /* M_XENIX */
X  	      {			/* Ordinary case. */
X  		symbolP -> sy_name_offset = string_byte_count;
X***************
X*** 421,425 ****
X  	    else			/* .Stabd case. */
X  #endif	/* not VMS */
X- #endif /* not M_XENIX */
X  		symbolP -> sy_name_offset = 0;
X  	    symbolPP = & (symbolP -> sy_next);
X--- 464,467 ----
X***************
X*** 757,761 ****
X    output_file_create (out_file_name);
X    omf_initialize_a_out(output_file_desc(), module_name, text_siz, data_siz,
X! 		       (long) local_bss_counter, 0L);
X  
X  /*  Traverse the symbol chain emitting external symbol definitions
X--- 799,805 ----
X    output_file_create (out_file_name);
X    omf_initialize_a_out(output_file_desc(), module_name, text_siz, data_siz,
X! 		       (long) local_bss_counter, 0L,
X! 		       flagseen['g'], stab_symbol_count * sizeof(struct nlist),
X! 		       string_byte_count);
X  
X  /*  Traverse the symbol chain emitting external symbol definitions
X***************
X*** 783,787 ****
X    for (   symbolP = symbol_rootP;   symbolP;   symbolP = symbolP -> sy_next   )
X    {
X!       if (PUBLIC(symbolP->sy_type))
X      {
X          unsigned int group = 0, segment = 0;
X--- 827,831 ----
X    for (   symbolP = symbol_rootP;   symbolP;   symbolP = symbolP -> sy_next   )
X    {
X!     if (PUBLIC(symbolP->sy_type))
X      {
X          unsigned int group = 0, segment = 0;
X***************
X*** 867,891 ****
X  		  int external = EXTDEF(symbolP->sy_type);
X  
X! 		  switch (symbolP->sy_type)
X! 		  {
X! 		    case PRIVDATA:	trgt_thrd = DATA_TGT_THREAD;
X! 					frm_thrd = DGROUP_FRAME_THREAD;
X! 					break;
X! 		    case PRIVBSS:	trgt_thrd = BSS_TGT_THREAD;
X! 					frm_thrd = DGROUP_FRAME_THREAD;
X! 					break;
X! 		    case PRIVTEXT:	trgt_thrd = TEXT_TGT_THREAD;
X! 					frm_thrd = TEXT_FRAME_THREAD;
X! 					break;
X! 		    case PUBLICDATA:	trgt_thrd = DATA_TGT_THREAD;
X! 					frm_thrd = DGROUP_FRAME_THREAD;
X! 					break;
X! 		    case PUBLICTEXT:	trgt_thrd = TEXT_TGT_THREAD;
X! 					frm_thrd = TEXT_FRAME_THREAD;
X! 					break;
X! 		    default:		trgt_thrd = CONST_TGT_THREAD;
X! 					frm_thrd = DGROUP_FRAME_THREAD;
X! 					break;
X! 		  }
X  		  if (fixP->fx_pcrel)
X  			frm_thrd = TEXT_FRAME_THREAD;
X--- 911,915 ----
X  		  int external = EXTDEF(symbolP->sy_type);
X  
X! 		  threads(symbolP->sy_type, &trgt_thrd, &frm_thrd);
X  		  if (fixP->fx_pcrel)
X  			frm_thrd = TEXT_FRAME_THREAD;
X***************
X*** 959,983 ****
X  		  int external = EXTDEF(symbolP->sy_type);
X  
X! 		  switch (symbolP->sy_type)
X! 		  {
X! 		    case PRIVDATA:	trgt_thrd = DATA_TGT_THREAD;
X! 					frm_thrd = DGROUP_FRAME_THREAD;
X! 					break;
X! 		    case PRIVBSS:	trgt_thrd = BSS_TGT_THREAD;
X! 					frm_thrd = DGROUP_FRAME_THREAD;
X! 					break;
X! 		    case PRIVTEXT:	trgt_thrd = TEXT_TGT_THREAD;
X! 					frm_thrd = TEXT_FRAME_THREAD;
X! 					break;
X! 		    case PUBLICDATA:	trgt_thrd = DATA_TGT_THREAD;
X! 					frm_thrd = DGROUP_FRAME_THREAD;
X! 					break;
X! 		    case PUBLICTEXT:	trgt_thrd = TEXT_TGT_THREAD;
X! 					frm_thrd = TEXT_FRAME_THREAD;
X! 					break;
X! 		    default:		trgt_thrd = CONST_TGT_THREAD;
X! 					frm_thrd = DGROUP_FRAME_THREAD;
X! 					break;
X! 		  }
X  		  if (fixP->fx_pcrel)
X  			frm_thrd = TEXT_FRAME_THREAD;
X--- 983,987 ----
X  		  int external = EXTDEF(symbolP->sy_type);
X  
X! 		  threads(symbolP->sy_type, &trgt_thrd, &frm_thrd);
X  		  if (fixP->fx_pcrel)
X  			frm_thrd = TEXT_FRAME_THREAD;
X***************
X*** 1004,1007 ****
X--- 1008,1140 ----
X        }
X    }
X+ 
X+ /*  Traverse the symbol chain emitting stabs.
X+  */
X+ 
X+ #define VAL_OFF offsetof(struct nlist, n_value)
X+ 
X+   if (flagseen['g'] && stab_symbol_count)
X+   {   
X+       long count = 0, ncount = 0;
X+       symbolS *last_startP;
X+       char *temp;
X+       symbolS *fsymP;
X+       int i;
X+       int start_fixup = 0;
X+ 
X+       omf_start_ledata(I386, SDEF_SYMBOLS, 0);
X+       last_startP = symbol_rootP;
X+       for (symbolP = symbol_rootP; symbolP; symbolP = symbolP -> sy_next)
X+       {
X+ 	 if (symbolP->sy_nlist.n_type & N_STAB)
X+ 	 {
X+             if ((ncount + 1) * sizeof(struct nlist) >= 1016)
X+             {
X+                omf_end_ledata();
X+ 
X+                /* emit relocations */
X+ 
X+                start_fixup = 0;
X+ 	       for (i = 0, fsymP=last_startP; i < ncount; fsymP=fsymP->sy_next)
X+ 	       {
X+ 	          if (fsymP->sy_nlist.n_type & N_STAB)
X+ 		  {
X+                      if (fsymP->sy_type & N_TYPE) /* if relocation required */
X+ 		     {
X+ 		       int trgt_thrd, frm_thrd;
X+ 		       int external = EXTDEF(fsymP->sy_type & N_TYPE);
X+ 
X+ 		       threads(fsymP->sy_type & N_TYPE,&trgt_thrd,&frm_thrd);
X+ 		       if (!start_fixup)
X+ 		       {
X+                            omf_start_fixup(I386);
X+ 			   start_fixup++;
X+ 		       }
X+ 		       omf_fixup(I386, 1, /* segment relative */
X+ 		          LOC_OFFSET32, i * sizeof(struct nlist) + VAL_OFF,
X+     			  external ? 0 : 1,
X+     			  external ? FRM_TRGT : frm_thrd,
X+     			  external ? 0 : 1,
X+     			  external ? TGT_EI : trgt_thrd,
X+     			  1, /* No offset */
X+ 			  0, /* No frame required */
X+     			  external ? fsymP->sy_number : 0,
X+ 			  0);
X+ 		     }
X+ 		     i++;
X+ 		  }
X+ 	       }
X+ 	       if (start_fixup)
X+                   omf_end_fixup();
X+ 
X+                /* start new segment */
X+ 
X+                ncount = 0;  last_startP = symbolP;
X+                omf_start_ledata(I386, SDEF_SYMBOLS, count*sizeof(struct nlist));
X+             }
X+             temp = symbolP->sy_nlist.n_un.n_name;
X+             symbolP->sy_nlist.n_un.n_strx = symbolP->sy_name_offset;
X+             omf_ledata(&(symbolP->sy_nlist), sizeof(struct nlist));
X+             symbolP->sy_nlist.n_un.n_name = temp;
X+    	    ncount++;  count++;
X+ 	 }
X+       }
X+       omf_end_ledata();
X+       start_fixup = 0;
X+       for (i = 0, fsymP = last_startP; i < ncount; fsymP = fsymP->sy_next)
X+       {
X+          if (fsymP->sy_nlist.n_type & N_STAB)
X+ 	 {
X+             if (fsymP->sy_type & N_TYPE) /* if relocation required */
X+ 	    {
X+ 	      int trgt_thrd, frm_thrd;
X+ 	      int external = EXTDEF(fsymP->sy_type & N_TYPE);
X+ 
X+ 	      threads(fsymP->sy_type & N_TYPE,&trgt_thrd,&frm_thrd);
X+ 	      if (!start_fixup)
X+               {
X+                  omf_start_fixup(I386);
X+                  start_fixup++;
X+               }
X+ 	      omf_fixup(I386, 1, /* segment relative */
X+ 	         LOC_OFFSET32, i * sizeof(struct nlist) + VAL_OFF,
X+    		  external ? 0 : 1,
X+    		  external ? FRM_TRGT : frm_thrd,
X+    		  external ? 0 : 1,
X+    		  external ? TGT_EI : trgt_thrd,
X+    		  1, /* No offset */
X+                   0, /* No frame required */
X+    		  external ? fsymP->sy_number : 0,
X+ 		  0);
X+ 	    }
X+ 	    i++;
X+ 	 }
X+       }
X+       if (start_fixup)
X+          omf_end_fixup();
X+ 
X+       count = sizeof(string_byte_count);  ncount = count;
X+       omf_start_ledata(I386, SDEF_TYPES, 0);
X+       omf_ledata(&string_byte_count, sizeof(string_byte_count));
X+       for (symbolP = symbol_rootP; symbolP; symbolP = symbolP -> sy_next)
X+       {
X+          if (symbolP->sy_nlist.n_type & N_STAB && symbolP -> sy_name)
X+ 	 {
X+ 	    int len = strlen(symbolP -> sy_name) + 1;
X+ 
X+ 	    if (ncount + len > 1016)
X+ 	    {
X+ 	       omf_end_ledata();
X+                omf_start_ledata(I386, SDEF_TYPES, count);
X+ 	       ncount = 0;
X+ 	    }
X+             omf_ledata(symbolP->sy_name, len);
X+ 	    count += len;  ncount += len;
X+ 	 }
X+       }
X+       omf_end_ledata();
X+   }
X+   
X+ 
X    omf_modend(I386);
X    output_file_close (out_file_name);
X*** ../gas-1.35.old/xenixomf.c	Mon May  7 17:26:26 1990
X--- ./xenixomf.c	Wed May  2 11:03:47 1990
X***************
X*** 544,548 ****
X--- 544,553 ----
X  #define L_UBSS		8
X  #define L_BSS		9
X+ #define L_TYPES		10
X+ #define L_DEBTYP	11
X+ #define L_SYMBOLS	12
X+ #define L_DEBSYM	13
X  #define L_TSIZE		9
X+ #define L_G_TSIZE	13
X  
X  char *lnames_tab[] = {
X***************
X*** 556,560 ****
X  	"CONST",
X  	"_BSS",
X! 	"BSS"
X  };
X  
X--- 561,569 ----
X  	"CONST",
X  	"_BSS",
X! 	"BSS",
X! 	"$$TYPES",
X! 	"DEBTYP",
X! 	"$$SYMBOLS",
X! 	"DEBSYM"
X  };
X  
X***************
X*** 573,577 ****
X  	{SD_DWORD|SD_PUBLIC|SD_PGRES, 0, L_UDATA, L_DATA},
X  	{SD_DWORD|SD_PUBLIC|SD_PGRES, 0, L_CONST, L_CONST},
X! 	{SD_DWORD|SD_PUBLIC|SD_PGRES, 0, L_UBSS, L_BSS}
X  };
X  
X--- 582,588 ----
X  	{SD_DWORD|SD_PUBLIC|SD_PGRES, 0, L_UDATA, L_DATA},
X  	{SD_DWORD|SD_PUBLIC|SD_PGRES, 0, L_CONST, L_CONST},
X! 	{SD_DWORD|SD_PUBLIC|SD_PGRES, 0, L_UBSS, L_BSS},
X! 	{SD_BYTE|SD_PGRES, 0, L_SYMBOLS, L_DEBSYM},
X! 	{SD_BYTE|SD_PGRES, 0, L_TYPES, L_DEBTYP}
X  };
X  
X***************
X*** 592,596 ****
X  #define NUMFIXEDCOMMENTS 4
X  
X! static unsigned char gas_comment[] = "gas-1.34";
X  static unsigned char lib_comment[] = "SLIBCE";
X  static unsigned char model_comment[] = "3s";
X--- 603,607 ----
X  #define NUMFIXEDCOMMENTS 4
X  
X! static unsigned char gas_comment[] = "gas-1.35c";
X  static unsigned char lib_comment[] = "SLIBCE";
X  static unsigned char model_comment[] = "3s";
X***************
X*** 604,611 ****
X  };
X  
X! void omf_initialize_a_out(fd, name, text_size, data_size, bss_size, const_size)
X  int fd;
X  unsigned char *name;
X  long text_size, data_size, bss_size, const_size;
X  {
X  	int i;
X--- 615,625 ----
X  };
X  
X! void omf_initialize_a_out(fd, name, text_size, data_size, bss_size, const_size,
X! 			  gdb, syms_size, str_size)
X  int fd;
X  unsigned char *name;
X  long text_size, data_size, bss_size, const_size;
X+ int gdb;
X+ long syms_size, str_size;
X  {
X  	int i;
X***************
X*** 622,626 ****
X  
X  	omf_start_lnames();
X! 	for (i = 1; i <= L_TSIZE; i++)
X  		omf_lnames(lnames_tab[i]);
X  	omf_end_lnames();
X--- 636,640 ----
X  
X  	omf_start_lnames();
X! 	for (i = 1; i <= (gdb ? L_G_TSIZE : L_TSIZE); i++)
X  		omf_lnames(lnames_tab[i]);
X  	omf_end_lnames();
X***************
X*** 632,636 ****
X  	segt[SDEF_BSS].length = bss_size;
X  	segt[SDEF_CONST].length = const_size;
X! 	for (i = 1; i <= SDEF_SIZE; i++)
X  		omf_segdef(I386, segt[i].attrib, 0, 0L, segt[i].length,
X  			   segt[i].nameindex, segt[i].classindex);
X--- 646,655 ----
X  	segt[SDEF_BSS].length = bss_size;
X  	segt[SDEF_CONST].length = const_size;
X! 	if (gdb)
X! 	{
X! 		segt[SDEF_SYMBOLS].length = syms_size;
X! 		segt[SDEF_TYPES].length = str_size;
X! 	}
X! 	for (i = 1; i <= (gdb ? SDEF_G_SIZE : SDEF_SIZE); i++)
X  		omf_segdef(I386, segt[i].attrib, 0, 0L, segt[i].length,
X  			   segt[i].nameindex, segt[i].classindex);
SHAR_EOF
if test 13414 -ne "`wc -c < 'gas-dbxpch.01'`"
then
	echo shar: error transmitting "'gas-dbxpch.01'" '(should have been 13414 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

Steve.Bleazard@RoboBar.Co.UK (05/08/90)

This is part three of a coordinated set of 4 patches for Xenix GCC, GAS and GDB.
Please collect all parts before you start hacking :-)

This is part 3 which patches GDB, say |patch -p -d /usr/local/src/dist-gdb
or whatever.  PLEASE APPLY THIS PATCH TO A FRESH UNSULLIED DISTRIBUTION
OF GDB 3.5 FROM THE FREE SOFTWARE FOUNDATION.  In particular, the
Xenix patches from rdk386!ron MUST NOT be already applied.  I've merged
his changes into this patch.  Part 4 will also patch GDB.

GDB will DEFINITELY need to be compiled with gcc, it requires GCC specific
enhancements.

#! /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:
#	gdb-x386.01
# This archive created: Tue May  8 12:35:10 1990
export PATH; PATH=/bin:$PATH
echo shar: extracting "'gdb-x386.01'" '(39436 characters)'
if test -f 'gdb-x386.01'
then
	echo shar: will not over-write existing file "'gdb-x386.01'"
else
sed 's/^X//' << \SHAR_EOF > 'gdb-x386.01'
X*** dist-gdb/Makefile.dist	Wed Jan 31 03:42:57 1990
X--- ./Makefile.dist	Tue May  8 12:33:40 1990
X***************
X*** 19,24 ****
X   will be incorrectly compiled.  The "fixincludes" script in the gcc
X   distribution will fix your include files up. */
X! /* CC=gcc -traditional */
X! CC=cc
X  
X  /* It is also possible that you will need to add -I/usr/include/sys to the
X--- 19,24 ----
X   will be incorrectly compiled.  The "fixincludes" script in the gcc
X   distribution will fix your include files up. */
X! CC=gcc -traditional
X! /* CC=cc */
X  
X  /* It is also possible that you will need to add -I/usr/include/sys to the
X***************
X*** 26,31 ****
X   is where it should be according to Posix).  */
X  
X! YACC=bison -y -v
X! /* YACC=yacc */
X  SHELL=/bin/sh
X  MAKE=make
X--- 26,31 ----
X   is where it should be according to Posix).  */
X  
X! /* YACC=bison -y -v */
X! YACC=yacc
X  SHELL=/bin/sh
X  MAKE=make
X***************
X*** 43,51 ****
X  /* M_CFLAGS, if defined, has system-dependent CFLAGS.  */
X  #if !defined(M_CFLAGS)
X! #define M_CFLAGS
X  #endif
X  
X  /* CFLAGS for both GDB and readline.  */
X! GLOBAL_CFLAGS = -g M_CFLAGS
X  CFLAGS = -I. ${HAVE_VPRINTF_DEFINE} ${GLOBAL_CFLAGS}
X  /* None of the things in CFLAGS will do any harm, and on some systems
X--- 43,51 ----
X  /* M_CFLAGS, if defined, has system-dependent CFLAGS.  */
X  #if !defined(M_CFLAGS)
X! #define M_CFLAGS -DM_SYSV
X  #endif
X  
X  /* CFLAGS for both GDB and readline.  */
X! GLOBAL_CFLAGS = M_CFLAGS
X  CFLAGS = -I. ${HAVE_VPRINTF_DEFINE} ${GLOBAL_CFLAGS}
X  /* None of the things in CFLAGS will do any harm, and on some systems
X***************
X*** 67,72 ****
X  REGEX1 = M_REGEX
X  #else
X! REGEX = 
X! REGEX1 = 
X  #endif
X  
X--- 67,72 ----
X  REGEX1 = M_REGEX
X  #else
X! REGEX = regex.o
X! REGEX1 = regex.o
X  #endif
X  
X***************
X*** 113,117 ****
X   For example, -lPW for System V to get alloca().  */
X  #ifndef M_CLIBS
X! #define M_CLIBS
X  #endif
X  CLIBS = ${ADD_FILES} ${TERMCAP} M_CLIBS
X--- 113,117 ----
X   For example, -lPW for System V to get alloca().  */
X  #ifndef M_CLIBS
X! #define M_CLIBS -lx
X  #endif
X  CLIBS = ${ADD_FILES} ${TERMCAP} M_CLIBS
X***************
X*** 125,129 ****
X  	 remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \
X  	 utils.c valarith.c valops.c valprint.c values.c version.c expread.y \
X! 	 xgdb.c
X  
X  DEPFILES = umax-dep.c gould-dep.c default-dep.c sun3-dep.c \
X--- 125,129 ----
X  	 remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \
X  	 utils.c valarith.c valops.c valprint.c values.c version.c expread.y \
X! 	 x386dbx.c xgdb.c
X  
X  DEPFILES = umax-dep.c gould-dep.c default-dep.c sun3-dep.c \
X***************
X*** 174,178 ****
X  OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
X      values.o eval.o valops.o valarith.o valprint.o printcmd.o \
X!     symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o \
X      command.o utils.o expread.o expprint.o pinsn.o environ.o version.o \
X      copying.o ${READLINEOBS}
X--- 174,178 ----
X  OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
X      values.o eval.o valops.o valarith.o valprint.o printcmd.o \
X!     symtab.o symmisc.o coffread.o dbxread.o x386dbx.o infcmd.o infrun.o remote.o \
X      command.o utils.o expread.o expprint.o pinsn.o environ.o version.o \
X      copying.o ${READLINEOBS}
X***************
X*** 259,265 ****
X  	rm -f gdb.tar
X  	mkdir dist-gdb
X! 	cd dist-gdb ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
X  	mkdir dist-gdb/readline
X! 	cd dist-gdb/readline ; for i in ${READLINE} ; do ln -s ../../readline/$$i . ; done
X  	tar chf gdb.tar dist-gdb
X  	rm -rf dist-gdb
X--- 259,265 ----
X  	rm -f gdb.tar
X  	mkdir dist-gdb
X! 	cd dist-gdb ; for i in ${TARFILES} ; do ln -s "../$$i" . ; done
X  	mkdir dist-gdb/readline
X! 	cd dist-gdb/readline ; for i in ${READLINE} ; do ln -s "../../readline/$$i" . ; done
X  	tar chf gdb.tar dist-gdb
X  	rm -rf dist-gdb
X*** dist-gdb.old/breakpoint.c	Wed Jan 10 23:49:07 1990
X--- breakpoint.c	Sat May  5 14:59:30 1990
X***************
X*** 1108,1112 ****
X  	if (b->number == num)
X  	  {
X! 	    function (b);
X  	    goto win;
X  	  }
X--- 1108,1112 ----
X  	if (b->number == num)
X  	  {
X! 	    (*function)(b);
X  	    goto win;
X  	  }
X*** dist-gdb.old/config.gdb	Tue Jan 30 20:35:46 1990
X--- config.gdb	Mon May  7 15:33:32 1990
X***************
X*** 327,330 ****
X--- 327,336 ----
X  	opcodefile=four
X  	;;
X+ xenix386)
X+ 	pinsnfile=i386-pinsn.c
X+ # The following is a lie, but a necessary one.  See comment at beginning
X+ # of this file about unneeded files.
X+ 	opcodefile=m-xenix386.h
X+ 	;;
X  *)
X  	echo "Unknown machine type: \`$machine'"
X***************
X*** 370,375 ****
X  echo "Editing Makefile"
X  cp Makefile.dist tmp.c
X! cc -E >Makefile tmp.c $makedefine -DM_MAKEDEFINE="$makedefine"
X! rm -f tmp.c
X  
X  echo "GDB is now set up for use with a $machine." \
X--- 376,381 ----
X  echo "Editing Makefile"
X  cp Makefile.dist tmp.c
X! gcc -E >Makefile $makedefine -DM_MAKEDEFINE="$makedefine" tmp.c
X! #rm -f tmp.c
X  
X  echo "GDB is now set up for use with a $machine." \
X*** dist-gdb.old/core.c	Wed Jan 10 23:55:17 1990
X--- core.c	Sat May  5 14:59:31 1990
X***************
X*** 50,53 ****
X--- 50,57 ----
X  #include <sys/ptrace.h>
X  #else
X+ #ifdef M_XENIX
X+ #include <sys/page.h>
X+ #include <sys/seg.h>
X+ #endif
X  #include <sys/user.h>
X  #endif
X***************
X*** 63,69 ****
X--- 67,77 ----
X  #ifndef COFF_FORMAT
X  #ifndef AOUTHDR
X+ #ifdef M_XENIX
X+ #define AOUTHDR		struct xexec
X+ #else
X  #define AOUTHDR		struct exec
X  #endif
X  #endif
X+ #endif
X  
X  extern char *sys_siglist[];
X***************
X*** 201,208 ****
X  	return;
X  
X        if (N_MAGIC (core_aouthdr) != 0
X  	  && bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
X  	printf ("Warning: core file does not match specified executable file.\n");
X!       else if (exec_mtime > st_core.st_mtime)
X  	printf ("Warning: exec file is newer than core file.\n");
X      }
X--- 209,220 ----
X  	return;
X  
X+ /* cannot validate core file against executable file on xenix */
X+ #ifndef M_XENIX
X        if (N_MAGIC (core_aouthdr) != 0
X  	  && bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
X  	printf ("Warning: core file does not match specified executable file.\n");
X!       else
X! #endif
X!       if (exec_mtime > st_core.st_mtime)
X  	printf ("Warning: exec file is newer than core file.\n");
X      }
X*** dist-gdb.old/dbxread.c	Sat Jan 27 07:30:54 1990
X--- dbxread.c	Sat May  5 15:44:39 1990
X***************
X*** 41,44 ****
X--- 41,59 ----
X  #endif
X  
X+ #ifdef M_XENIX
X+ #include <sys/relsym.h>
X+ #define nlist xenix_nlist	/* the system nlist is broken */
X+ #include <a.out.h>
X+ #undef nlist
X+ #define nlist gas_nlist
X+ #include "stab.gnu.h"
X+ #include "gas-nlist.h"
X+ 
X+ #define STRING_SEG 4
X+ #define SYMS_SEG   5
X+ #define AOUTHDR    struct xexec
X+ 
X+ #else /* M_XENIX */
X+ 
X  #ifdef COFF_ENCAPSULATE
X  #include "a.out.encap.h"
X***************
X*** 48,51 ****
X--- 63,68 ----
X  #include <stab.h>
X  #endif
X+ #endif /* M_XENIX */
X+ 
X  #include <ctype.h>
X  
X***************
X*** 168,171 ****
X--- 185,190 ----
X  static struct type **read_args ();
X  
X+ #ifndef M_XENIX
X+ 
X  /* Macro to determine which symbols to ignore when reading the first symbol
X     of a file.  Some machines override this definition. */
X***************
X*** 284,287 ****
X--- 303,413 ----
X  #define BELIEVE_PCC_PROMOTION 0
X  #endif
X+ 
X+ #else	/* M_XENIX */
X+ 
X+ /* Macro to determine which symbols to ignore when reading the first symbol
X+    of a file.  Some machines override this definition. */
X+ 
X+ extern struct xseg *find_segment();
X+ 
X+ #ifndef IGNORE_SYMBOL
X+ /* Don't ignore any symbols. */
X+ #define IGNORE_SYMBOL(type) (0)
X+ #endif 
X+ 
X+ /* Macro for number of symbol table entries (in usual a.out format).
X+    Some machines override this definition.  */
X+ #ifndef NUMBER_OF_SYMBOLS
X+ #define NUMBER_OF_SYMBOLS \
X+   ({ struct xseg *cseg; long z;\
X+      cseg = find_segment(XS_TSYMS, SYMS_SEG); \
X+      z = cseg ? cseg->xs_psize / sizeof(struct nlist) : 0; z;})
X+ #endif
X+ 
X+ /* Macro for file-offset of symbol table (in usual a.out format).  */
X+ #ifndef SYMBOL_TABLE_OFFSET
X+ #define SYMBOL_TABLE_OFFSET \
X+   ({ struct xseg *cseg; long z;\
X+      cseg = find_segment(XS_TSYMS, SYMS_SEG); \
X+      z = cseg ? cseg->xs_filpos : 0; z;})
X+ #endif
X+ 
X+ /* Macro for file-offset of string table (in usual a.out format).  */
X+ #ifndef STRING_TABLE_OFFSET
X+ #define STRING_TABLE_OFFSET \
X+   ({ struct xseg *cseg; long z;\
X+      cseg = find_segment(XS_TSYMS, STRING_SEG); \
X+      z = cseg ? cseg->xs_filpos : 0; z; })
X+ #endif
X+ 
X+ /* Macro to store the length of the string table data in INTO.  */
X+ #ifndef READ_STRING_TABLE_SIZE
X+ #define READ_STRING_TABLE_SIZE(INTO)		\
X+   { struct xseg *cseg; \
X+      cseg = find_segment(XS_TSYMS, STRING_SEG); \
X+      INTO = cseg ? cseg->xs_psize : 0; }
X+ #endif
X+ 
X+ /* Macro to declare variables to hold the file's header data.  */
X+ #ifndef DECLARE_FILE_HEADERS
X+ #define DECLARE_FILE_HEADERS  AOUTHDR hdr
X+ #endif
X+ 
X+ #define N_BADMAG(hdr)\
X+   (hdr.x_magic != X_MAGIC && (hdr.x_cpu & XC_CPU) != XC_386 \
X+    && (hdr.x_renv & XE_SEG) == 0  && (hdr.x_renv & XE_EXEC) == 0)
X+ 
X+ /* Macro to read the header data from descriptor DESC and validate it.
X+    NAME is the file name, for error messages.  */
X+ #ifndef READ_FILE_HEADERS
X+ #define READ_FILE_HEADERS(DESC, NAME)		\
X+ { val = myread (DESC, &hdr, sizeof hdr);	\
X+   if (val < 0) perror_with_name (NAME);		\
X+   if (N_BADMAG (hdr))				\
X+     error ("File \"%s\" not in executable format.", NAME);\
X+   process_a_out(DESC, NAME); }
X+ #endif
X+ 
X+ #ifndef IS_OBJECT_FILE
X+ #define IS_OBJECT_FILE 0
X+ #endif
X+ 
X+ /* Macro for size of text segment */
X+ #ifndef SIZE_OF_TEXT_SEGMENT
X+ #define SIZE_OF_TEXT_SEGMENT hdr.x_text
X+ #endif
X+ 
X+ /* Get the address in debugged memory of the start
X+    of the text segment.  */
X+ #if !defined (ADDR_OF_TEXT_SEGMENT)
X+ #define ADDR_OF_TEXT_SEGMENT 0
X+ #endif /* no ADDR_OF_TEXT_SEGMENT */
X+ 
X+ /* Macro to get entry point from headers.  */
X+ #ifndef ENTRY_POINT
X+ #define ENTRY_POINT hdr.x_entry
X+ #endif
X+ 
X+ /* Macro for name of symbol to indicate a file compiled with gcc. */
X+ #ifndef GCC_COMPILED_FLAG_SYMBOL
X+ #define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled."
X+ #endif
X+ 
X+ /* Convert stab register number (from `r' declaration) to a gdb REGNUM.  */
X+ 
X+ #ifndef STAB_REG_TO_REGNUM
X+ #define STAB_REG_TO_REGNUM(VALUE) (VALUE)
X+ #endif
X+ 
X+ /* Define this as 1 if a pcc declaration of a char or short argument
X+    gives the correct address.  Otherwise assume pcc gives the
X+    address of the corresponding int, which is not the same on a
X+    big-endian machine.  */
X+ 
X+ #ifndef BELIEVE_PCC_PROMOTION
X+ #define BELIEVE_PCC_PROMOTION 0
X+ #endif
X+ 
X+ #endif /* !M_XENIX */
X  
X  /* Nonzero means give verbose info on gdb action.  From main.c.  */
X***************
X*** 1628,1631 ****
X--- 1754,1763 ----
X    make_cleanup (free_current_contents, &name);
X  
X+ #ifdef M_XENIX
X+ /* On xenix (with gcc) READ_FILE_HEADER reads the segment table,
X+  * fileinfo table and global symbol table as well. 
X+  */
X+ #endif /* M_XENIX */
X+ 
X    READ_FILE_HEADERS (desc, name);
X  
X***************
X*** 1677,1680 ****
X--- 1809,1816 ----
X    if (val < 0)
X      perror_with_name (name);
X+ #ifdef X_DEBUG
X+     printf("\nstring table offset = %d, size = %d, start = %s\n",
X+ 	    STRING_TABLE_OFFSET, buffer, stringtab);
X+ #endif
X    
X    /* Throw away the old symbol table.  */
X***************
X*** 1721,1725 ****
X--- 1857,1865 ----
X    /* Go over the misc functions and install them in vector.  */
X  
X+ #ifndef M_XENIX /* This has already been done at header read time */
X    condense_misc_bunches (0);
X+ #else
X+   process_global_symbol_table(desc, name);
X+ #endif /* M_XENIX */
X  
X    /* Don't allow char * to have a typename (else would get caddr_t.)  */
X***************
X*** 1938,1941 ****
X--- 2078,2091 ----
X  #endif
X  
X+ #ifdef M_XENIX
X+   long lsym_count = 0;
X+   long flsym_count = 0;
X+   long file_string_base = 0;
X+   long stringtab_offset = 0;
X+   long symtab_pos = 0;
X+   long filadd = 0;
X+   int file_count = 0;
X+ #endif /* M_XENIX */
X+ 
X    /* Current partial symtab */
X    struct partial_symtab *pst;
X***************
X*** 1990,1993 ****
X--- 2140,2148 ----
X    symbuf_end = symbuf_idx = 0;
X  
X+ #ifdef M_XENIX
X+   init_fileinfo_processing();   /* start processing the list of files */
X+   nlistlen += 10; 		/* force the hack code to terminate the loop */
X+ #endif /* M_XENIX */
X+ 
X    for (symnum = 0; symnum < nlistlen; symnum++)
X      {
X***************
X*** 1994,1997 ****
X--- 2149,2194 ----
X        /* Get the symbol for this run and pull out some info */
X        QUIT;	/* allow this to be interruptable */
X+ #ifdef M_XENIX
X+ 
X+       /* This is a gross hack.  Xenix places pointers to each files $$SYMBOLS
X+        * (containing the symbols for DBX) and $$TYPES (containing the strings
X+        * for DBX) in the file name table.  There is also a partial symbol
X+        * table record for each file produced by the loader - this is ignored
X+        * at present.
X+        */
X+        if (lsym_count == 0)
X+        {
X+      try_next_file:
X+ 	 if (!get_next_fileinfo(&stringtab_offset, &flsym_count, &filadd,
X+ 	                        &symtab_pos))
X+ 	 {			/* all files proccessed */
X+ 	   symnum = nlistlen;
X+ 	   continue;
X+ 	 }
X+ 	 else
X+ 	 {
X+ 	   lseek(desc, symtab_pos, 0);
X+   	   stringtab_global = stringtab + stringtab_offset;
X+ 	   symbuf_idx = symbuf_end;  /* force symbol reading */
X+ 	   lsym_count = flsym_count;
X+ 	 }
X+ 	 
X+ 	 file_count++;
X+ 
X+ 	 if (file_count == 2)
X+            startup_file_start = filadd;
X+ 
X+ 	 if (file_count == 3)
X+            startup_file_end = filadd;
X+ 
X+          if (lsym_count == 0)    /* skip this file if no symbols in it */
X+ 	   goto try_next_file;
X+ 
X+        }
X+ 
X+        
X+        lsym_count--;
X+ 
X+ #endif /* M_XENIX */
X        if (symbuf_idx == symbuf_end)
X  	fill_symbuf ();
X***************
X*** 2024,2028 ****
X      error ("Invalid symbol data: bad string table offset: %d",       \
X  	   bufp->n_un.n_strx);                                       \
X!   namestring = bufp->n_un.n_strx + stringtab
X  
X  #define	ADD_PSYMBOL_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE)\
X--- 2221,2225 ----
X      error ("Invalid symbol data: bad string table offset: %d",       \
X  	   bufp->n_un.n_strx);                                       \
X!   namestring = bufp->n_un.n_strx + stringtab + stringtab_offset
X  
X  #define	ADD_PSYMBOL_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE)\
X***************
X*** 2052,2057 ****
X    } while (0);
X  
X  
X!       switch (bufp->n_type)
X  	{
X  	  /*
X--- 2249,2259 ----
X    } while (0);
X  
X+ #ifdef X_DEBUG
X+ printf("%s = (%#x, %d, %#x)\n",
X+   bufp->n_un.n_strx ? bufp->n_un.n_strx+stringtab+stringtab_offset : "<NONE>",
X+   (unsigned char)bufp->n_type, bufp->n_desc, bufp->n_value);
X+ #endif /* X_DEBUG */
X  
X!       switch ((unsigned char)bufp->n_type)
X  	{
X  	  /*
X***************
X*** 2058,2061 ****
X--- 2260,2264 ----
X  	   * Standard, non-debugger, symbols
X  	   */
X+ #ifndef M_XENIX			/* these are not present with Xenix / GCC */
X  
X  	case N_TEXT | N_EXT:
X***************
X*** 2177,2180 ****
X--- 2380,2385 ----
X  #endif
X  
X+ #endif /* M_XENIX */
X+ 
X  	  /* Keep going . . .*/
X  
X***************
X*** 2210,2213 ****
X--- 2415,2419 ----
X  	  if (pst && past_first_source_file)
X  	    {
X+ #ifndef M_XENIX
X  	      end_psymtab (pst, psymtab_include_list, includes_used,
X  			   symnum * sizeof (struct nlist), bufp->n_value,
X***************
X*** 2214,2217 ****
X--- 2420,2429 ----
X  			   dependency_list, dependencies_used,
X  			   global_psymbols.next, static_psymbols.next);
X+ #else
X+ 	      end_psymtab (pst, psymtab_include_list, includes_used,
X+ 			   symtab_pos + flsym_count * sizeof (struct nlist),
X+ 			   bufp->n_value, dependency_list, dependencies_used,
X+ 			   global_psymbols.next, static_psymbols.next);
X+ #endif
X  	      pst = (struct partial_symtab *) 0;
X  	      includes_used = 0;
X***************
X*** 2221,2227 ****
X--- 2433,2445 ----
X  	    past_first_source_file = 1;
X  
X+ #ifndef M_XENIX
X  	  pst = start_psymtab (namestring, bufp->n_value,
X  			       symnum * sizeof (struct nlist),
X  			       global_psymbols.next, static_psymbols.next);
X+ #else
X+ 	  pst = start_psymtab (namestring, bufp->n_value, symtab_pos,
X+ 			       global_psymbols.next, static_psymbols.next,
X+ 			       stringtab_offset, flsym_count);
X+ #endif /* M_XENIX */
X  
X  	  continue;
X***************
X*** 2592,2595 ****
X--- 2810,2814 ----
X  
X    /* If there's stuff to be cleaned up, clean it up.  */
X+ #ifndef M_XENIX
X    if (entry_point < bufp->n_value
X        && entry_point >= last_o_file_start)
X***************
X*** 2598,2604 ****
X--- 2817,2825 ----
X        startup_file_end = bufp->n_value;
X      }
X+ #endif /* M_XENIX */
X  
X    if (pst)
X      {
X+ #ifndef M_XENIX
X        end_psymtab (pst, psymtab_include_list, includes_used,
X  		   symnum * sizeof (struct nlist), end_of_text_addr,
X***************
X*** 2605,2608 ****
X--- 2826,2835 ----
X  		   dependency_list, dependencies_used,
X  		   global_psymbols.next, static_psymbols.next);
X+ #else /* M_XENIX */
X+       end_psymtab (pst, psymtab_include_list, includes_used,
X+ 		   symtab_pos + flsym_count * sizeof (struct nlist),
X+ 		   end_of_text_addr, dependency_list, dependencies_used,
X+ 		   global_psymbols.next, static_psymbols.next);
X+ #endif /* M_XENIX */
X        includes_used = 0;
X        dependencies_used = 0;
X***************
X*** 2654,2657 ****
X--- 2881,2885 ----
X   */
X  static struct partial_symtab *
X+ #ifndef M_XENIX
X  start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms)
X       char *filename;
X***************
X*** 2660,2663 ****
X--- 2888,2902 ----
X       struct partial_symbol *global_syms;
X       struct partial_symbol *static_syms;
X+ #else
X+ start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms, stroffset,
X+ 	       symcount)
X+      char *filename;
X+      int textlow;
X+      int ldsymoff;
X+      struct partial_symbol *global_syms;
X+      struct partial_symbol *static_syms;
X+      int stroffset;
X+      int symcount;
X+ #endif
X  {
X    struct partial_symtab *result =
X***************
X*** 2672,2676 ****
X    result->textlow = textlow;
X    result->ldsymoff = ldsymoff;
X! 
X    result->readin = 0;
X  
X--- 2911,2917 ----
X    result->textlow = textlow;
X    result->ldsymoff = ldsymoff;
X! #ifdef M_XENIX
X!   result->ldsymlen = symcount * sizeof(struct nlist);
X! #endif
X    result->readin = 0;
X  
X***************
X*** 2680,2683 ****
X--- 2921,2925 ----
X    result->n_global_syms = 0;
X    result->n_static_syms = 0;
X+   result->stringtab_off = stroffset;
X  
X    return result;
X***************
X*** 2723,2727 ****
X--- 2965,2971 ----
X    int i;
X  
X+ #ifndef M_XENIX
X    pst->ldsymlen = capping_symbol_offset - pst->ldsymoff;
X+ #endif /* M_XENIX */
X    pst->texthigh = capping_text;
X  
X***************
X*** 2831,2835 ****
X--- 3075,3081 ----
X  
X        /* Read in this files symbols */
X+ #ifndef M_XENIX
X        lseek (desc, sym_offset, L_SET);
X+ 
X        read_ofile_symtab (desc, stringtab, stringtab_size,
X  			 pst->ldsymoff,
X***************
X*** 2836,2839 ****
X--- 3082,3092 ----
X  			 pst->ldsymlen, pst->textlow,
X  			 pst->texthigh - pst->textlow, 0);
X+ #else  /* M_XENIX */
X+       read_ofile_symtab (desc, stringtab + pst->stringtab_off,
X+ 			 stringtab_size - pst->stringtab_off,
X+ 			 pst->ldsymoff,
X+ 			 pst->ldsymlen, pst->textlow,
X+ 			 pst->texthigh - pst->textlow, 0);
X+ #endif  /* M_XENIX */
X        sort_symtab_syms (symtab_list); /* At beginning since just added */
X  
X***************
X*** 2904,2908 ****
X--- 3157,3163 ----
X  	error("Symbol file not readable");
X  
X+ #ifndef M_XENIX	
X        READ_FILE_HEADERS (desc, name);
X+ #endif /* M_XENIX */
X  
X        /* Read in the string table */
X***************
X*** 3059,3062 ****
X--- 3314,3318 ----
X    symbuf_end = symbuf_idx = 0;
X  
X+ #ifndef M_XENIX
X    /* It is necessary to actually read one symbol *before* the start
X       of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL
X***************
X*** 3065,3068 ****
X--- 3321,3325 ----
X       Detecting this in read_dbx_symtab
X       would slow down initial readin, so we look for it here instead.  */
X+ 
X    if (sym_offset >= sizeof (struct nlist))
X      {
X***************
X*** 3088,3091 ****
X--- 3345,3355 ----
X        processing_gcc_compilation = 0;
X      }
X+ #else /* M_XENIX */
X+     lseek(desc, sym_offset, L_SET);
X+     processing_gcc_compilation = 0;
X+ #ifdef X_DEBUG
X+     printf("sym_offset = %d,  sym_size = %d\n", sym_offset, sym_size);
X+ #endif /* X_DEBUG */
X+ #endif /* M_XENIX */
X  
X    if (symbuf_idx == symbuf_end)
X***************
X*** 3095,3098 ****
X--- 3359,3368 ----
X      fatal("First symbol in segment of executable not a source symbol");
X  
X+ #ifdef X_DEBUG
X+ printf("%s = (%#x, %d, %#x)\n",
X+   bufp->n_un.n_strx ? bufp->n_un.n_strx+stringtab : "<NONE>",
X+   (unsigned char)bufp->n_type, bufp->n_desc, bufp->n_value);
X+ #endif /* X_DEBUG */
X+ 
X    for (symnum = 0;
X         symnum < sym_size / sizeof(struct nlist);
X***************
X*** 3104,3107 ****
X--- 3374,3382 ----
X        bufp = &symbuf[symbuf_idx++];
X        type = bufp->n_type;
X+ #ifdef X_DEBUG
X+ printf("%s = (%#x, %d, %#x)\n",
X+   bufp->n_un.n_strx ? bufp->n_un.n_strx+stringtab : "<NONE>",
X+   (unsigned char)bufp->n_type, bufp->n_desc, bufp->n_value);
X+ #endif /* X_DEBUG */
X  
X        if (offset &&
X***************
X*** 3477,3480 ****
X--- 3752,3757 ----
X  /* Read in another .o file and create a symtab entry for it.*/
X  
X+ #ifndef M_XENIX /* Xenix can't do incremental loads */
X+ 
X  static void
X  read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
X***************
X*** 3773,3776 ****
X--- 4050,4054 ----
X    fflush (stdout);
X  }
X+ #endif /* M_XENIX */
X  
X  /* Read a number by which a type is referred to in dbx data,
X***************
X*** 5466,5475 ****
X    undef_types = (struct type **) xmalloc (undef_types_allocated *
X  					  sizeof (struct type *));
X- 
X    add_com ("symbol-file", class_files, symbol_file_command,
X  	   "Load symbol table (in dbx format) from executable file FILE.");
X  
X    add_com ("add-file", class_files, add_file_command,
X             "Load the symbols from FILE, assuming its code is at TEXT_START.") ;
X  }
X  
X--- 5744,5754 ----
X    undef_types = (struct type **) xmalloc (undef_types_allocated *
X  					  sizeof (struct type *));
X    add_com ("symbol-file", class_files, symbol_file_command,
X  	   "Load symbol table (in dbx format) from executable file FILE.");
X  
X+ #ifndef M_XENIX
X    add_com ("add-file", class_files, add_file_command,
X             "Load the symbols from FILE, assuming its code is at TEXT_START.") ;
X+ #endif /* M_XENIX */
X  }
X  
X*** dist-gdb.old/eval.c	Sun Nov  5 18:01:52 1989
X--- eval.c	Sat May  5 14:59:35 1990
X***************
X*** 412,419 ****
X  	goto nosideret;
X        if (noside == EVAL_AVOID_SIDE_EFFECTS)
X! 	return value_zero (lookup_struct_elt_type (TYPE_TARGET_TYPE
X! 						   (VALUE_TYPE (arg1)),
X! 						   &exp->elts[pc + 1].string),
X! 			   lval_memory);
X        else
X  	return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0,
X--- 412,419 ----
X  	goto nosideret;
X        if (noside == EVAL_AVOID_SIDE_EFFECTS)
X! 	return value_zero (lookup_struct_elt_type
X! 		(TYPE_TARGET_TYPE(VALUE_TYPE (arg1)),
X! 	        &exp->elts[pc + 1].string),
X! 	        lval_memory);
X        else
X  	return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0,
X*** dist-gdb.old/gas-nlist.h	Thu Jan  1 00:00:00 1970
X--- gas-nlist.h	Sat May  5 14:59:35 1990
X***************
X*** 0 ****
X--- 1,13 ----
X+ #define N_STAB 0340
X+ 
X+ struct gas_nlist {
X+ 	union {
X+ 		char	*n_name;
X+ 		struct gas_nlist *n_next;
X+ 		long	n_strx;
X+ 	} n_un;
X+ 	char	n_type;
X+ 	char	n_other;
X+ 	short	n_desc;
X+ 	unsigned n_value;
X+ };
X*** dist-gdb.old/inflow.c	Wed Jan 10 23:55:38 1990
X--- inflow.c	Sat May  5 14:59:36 1990
X***************
X*** 30,33 ****
X--- 30,34 ----
X  /* Some USG-esque systems (some of which are BSD-esque enough so that USG
X     is not defined) want this header, and it won't do any harm.  */
X+ /* rk@unify.UUCP: yes it will if you include it twice (line removed below) */
X  #include <fcntl.h>
X  
X***************
X*** 47,51 ****
X  #else
X  #include <sys/ioctl.h>
X- #include <fcntl.h>
X  #include <sgtty.h>
X  #define TERMINAL struct sgttyb
X--- 48,51 ----
X***************
X*** 299,303 ****
X--- 299,307 ----
X  
X    printf_filtered ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n",
X+ #ifdef TIOCGPGRP
X  	  tflags_inferior, sg_inferior.sg_flags, pgrp_inferior);
X+ #else
X+ 	  tflags_inferior, sg_inferior.sg_flags, 0);
X+ #endif
X  
X  #endif /* not HAVE_TERMIO */
X*** dist-gdb.old/infrun.c	Tue Jan 23 23:10:35 1990
X--- infrun.c	Sat May  5 14:59:36 1990
X***************
X*** 147,150 ****
X--- 147,154 ----
X  #include <sys/param.h>
X  /* Needed by IN_SIGTRAMP on some machines (e.g. vax).  */
X+ #ifdef M_XENIX
X+ #include <sys/page.h>
X+ #include <sys/seg.h>
X+ #endif
X  #include <sys/user.h>
X  
X*** dist-gdb.old/m-xenix386.h	Thu Jan  1 00:00:00 1970
X--- m-xenix386.h	Sat May  5 14:59:38 1990
X***************
X*** 0 ****
X--- 1,350 ----
X+ /* Macro defintions for i386.
X+    Copyright (C) 1986, 1987, 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+ /*
X+  * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
X+  * July 1988
X+  */
X+ 
X+ 
X+ #ifndef i386
X+ #define i386
X+ #endif
X+ 
X+ /* This machine doesn't have the siginterrupt call.  */
X+ #define NO_SIGINTERRUPT
X+ 
X+ #define ALIGN_STACK_ON_STARTUP
X+ 
X+ /* define USG if you are using sys5 /usr/include's */
X+ #define USG
X+ 
X+ /* USG systems need these */
X+ #define vfork() fork()
X+ #define MAXPATHLEN 500
X+ 
X+ /* define this if you don't have the extension to coff that allows
X+  * file names to appear in the string table
X+  * (aux.x_file.x_foff)
X+  */
X+ #define COFF_NO_LONG_FILE_NAMES
X+ 
X+ /* turn this on when rest of gdb is ready */
X+ /* #define IEEE_FLOAT */
X+ 
X+ #define NBPG NBPC
X+ #define UPAGES USIZE
X+ 
X+ /* #define HAVE_TERMIO */
X+ 
X+ /* Get rid of any system-imposed stack limit if possible.  */
X+ 
X+ /* #define SET_STACK_LIMIT_HUGE not in sys5 */
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+ /* Specify debugger information format (only one)  */
X+ 
X+ #define READ_DBX_FORMAT
X+ #undef COFF_FORMAT
X+ 
X+ /* number of traps that happen between exec'ing the shell 
X+  * to run an inferior, and when we finally get to 
X+  * the inferior code.  This is 2 on most implementations.
X+  */
X+ #define START_INFERIOR_TRAPS_EXPECTED 2
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(frompc)   {(frompc) = i386_skip_prologue((frompc));}
X+ 
X+ /* Immediately after a function call, return the saved pc.
X+    Can't always 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+ /* This is the amount to subtract from u.u_ar0
X+    to get the offset in the core file of the register values.  */
X+ 
X+ #define KERNEL_U_ADDR 0x06000000
X+ 
X+ /* Address of end of stack space.  */
X+ 
X+ #define STACK_END_ADDR 0x80000000
X+ 
X+ /* Stack grows downward.  */
X+ 
X+ #define INNER_THAN <
X+ 
X+ /* Sequence of bytes for breakpoint instruction.  */
X+ 
X+ #define BREAKPOINT {0xcc}
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 1
X+ 
X+ /* Nonzero if instruction at PC is a return instruction.  */
X+ 
X+ #define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc3)
X+ 
X+ /* Return 1 if P points to an invalid floating point value.
X+    LEN is the length in bytes -- not relevant on the 386.  */
X+ 
X+ #define INVALID_FLOAT(p, len) (0)
X+ 
X+ /* code to execute to print interesting information about the
X+  * floating point processor (if any)
X+  * No need to define if there is nothing to do.
X+  */
X+ #define FLOAT_INFO { i386_float_info (); }
X+ 
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 16
X+ 
X+ /* Initializer for an array of names of registers.
X+    There should be NUM_REGS strings in this initializer.  */
X+ 
X+ /* the order of the first 8 registers must match the compiler's 
X+  * numbering scheme (which is the same as the 386 scheme)
X+  * also, this table must match regmap in i386-pinsn.c.
X+  */
X+ #define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
X+ 			 "esp", "ebp", "esi", "edi", \
X+ 			 "eip", "ps", "cs", "ss", \
X+ 			 "ds", "es", "fs", "gs", \
X+ 			 }
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 5		/* Contains address of executing stack frame */
X+ #define SP_REGNUM 4		/* Contains address of top of stack */
X+ 
X+ #define PC_REGNUM 8
X+ #define PS_REGNUM 9
X+ 
X+ #define REGISTER_U_ADDR(addr, blockend, regno) \
X+ 	(addr) = i386_register_u_addr ((blockend),(regno));
X+ 
X+ /* Total amount of space needed to store our copies of the machine's
X+    register state, the array `registers'.  */
X+ #define REGISTER_BYTES (NUM_REGS * 4)
X+ 
X+ /* Index within `registers' of the first byte of the space for
X+    register N.  */
X+ 
X+ #define REGISTER_BYTE(N) ((N)*4)
X+ 
X+ /* Number of bytes of storage in the actual machine representation
X+    for register N.  */
X+ 
X+ #define REGISTER_RAW_SIZE(N) (4)
X+ 
X+ /* Number of bytes of storage in the program's representation
X+    for register N. */
X+ 
X+ #define REGISTER_VIRTUAL_SIZE(N) (4)
X+ 
X+ /* Largest value REGISTER_RAW_SIZE can have.  */
X+ 
X+ #define MAX_REGISTER_RAW_SIZE 4
X+ 
X+ /* Largest value REGISTER_VIRTUAL_SIZE can have.  */
X+ 
X+ #define MAX_REGISTER_VIRTUAL_SIZE 4
X+ 
X+ /* Nonzero if register N requires conversion
X+    from raw format to virtual format.  */
X+ 
X+ #define REGISTER_CONVERTIBLE(N) (0)
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) {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) {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) (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+   { (SP) -= sizeof (ADDR);		\
X+     write_memory ((SP), &(ADDR), sizeof (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+ 
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+ #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+ /* Return number of args passed to a frame.
X+    Can return -1, meaning no way to tell.  */
X+ 
X+ #define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
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+ { i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
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 { i386_push_dummy_frame (); }
X+ 
X+ /* Discard from the stack the innermost frame, restoring all registers.  */
X+ 
X+ #define POP_FRAME  { i386_pop_frame (); }
X+ 
X+ /* this is 
X+  *   call 11223344 (32 bit relative)
X+  *   int3
X+  */
X+ 
X+ #define CALL_DUMMY { 0x223344e8, 0xcc11 }
X+ 
X+ #define CALL_DUMMY_LENGTH 8
X+ 
X+ #define CALL_DUMMY_START_OFFSET 0  /* Start execution at beginning of dummy */
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+ { \
X+ 	int from, to, delta, loc; \
X+ 	loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
X+ 	from = loc + 5; \
X+ 	to = (int)(fun); \
X+ 	delta = to - from; \
X+ 	*(int *)((char *)(dummyname) + 1) = delta; \
X+ }
X+ 
X+ #define CANNOT_EXECUTE_STACK
X+ 
X+ /* missing stuff from SCO */
X+ #define X_OK 1			/* for access(2) */
X+ #define W_OK 2			/* for access(2) */
X+ #define R_OK 4			/* for access(2) */
X*** dist-gdb.old/munch	Wed Jul  5 19:46:28 1989
X--- munch	Sat May  5 14:59:38 1990
X***************
X*** 6,11 ****
X  echo 'void initialize_all_files () {'
X  
X! if test "$1" = "-DSYSV" ; then
X      shift;
X      nm $* | egrep '^(.*[^a-zA-Z_]_|_)initialize_' | \
X  	sed -e 's/^.*\(_initialize_[a-zA-Z0-9_]*\)[^a-zA-Z0-9_].*$/   \1 ();/'
X--- 6,15 ----
X  echo 'void initialize_all_files () {'
X  
X! if [ -f /xenix ]; then
X      shift;
X+     nm $* | egrep 'A *__initialize_' | \
X+ 	sed -e 's/^.*A *_*\(.*\)/    _\1 ();/'
X+ else if test "$1" = "-DSYSV" ; then
X+     shift;
X      nm $* | egrep '^(.*[^a-zA-Z_]_|_)initialize_' | \
X  	sed -e 's/^.*\(_initialize_[a-zA-Z0-9_]*\)[^a-zA-Z0-9_].*$/   \1 ();/'
X***************
X*** 13,16 ****
X--- 17,21 ----
X      nm -p $* | egrep 'T *__initialize_' | \
X  	sed -e 's/^.*T *_*\(.*\)/    _\1 ();/'
X+ fi
X  fi
X  
X*** dist-gdb.old/readline/readline.c	Sun Nov 26 21:31:36 1989
X--- readline/readline.c	Sat May  5 14:59:43 1990
X***************
X*** 1044,1048 ****
X  readline_default_bindings ()
X  {
X! #ifdef TIOCGETP
X    struct sgttyb ttybuff;
X    int tty = fileno (rl_instream);
X--- 1044,1048 ----
X  readline_default_bindings ()
X  {
X! #if 0 /* def TIOCGETP */
X    struct sgttyb ttybuff;
X    int tty = fileno (rl_instream);
X*** dist-gdb.old/symtab.h	Fri Sep  8 00:59:14 1989
X--- symtab.h	Sat May  5 14:59:43 1990
X***************
X*** 150,153 ****
X--- 150,156 ----
X       how long errors take). */
X    int statics_offset, n_static_syms;
X+ #ifdef M_XENIX
X+   int stringtab_off;
X+ #endif /* M_XENIX */
X  };
X  
X*** dist-gdb.old/test/fred.h	Thu Jan  1 00:00:00 1970
X--- test/fred.h	Sat May  5 15:14:16 1990
X***************
X*** 0 ****
X--- 1,5 ----
X+ struct test_s {
X+ 	long l;
X+ 	int  i;
X+ 	char c;
X+ };
X*** dist-gdb.old/test/test.c	Thu Jan  1 00:00:00 1970
X--- test/test.c	Sat May  5 15:48:37 1990
X***************
X*** 0 ****
X--- 1,32 ----
X+ #include <stdio.h>
X+ #include "fred.h"
X+ 
X+ extern char **environ;
X+ int j = 100;
X+ 
X+ struct test_s test_v;
X+ 
X+ boo(char *p)
X+ {
X+ 	return 0x3742;
X+ }
X+ 
X+ 
X+ #define alloca __builtin_alloca
X+ main(int argc, char **argv)
X+ {
X+ 	int i;
X+ 	char *p;
X+ 	i = 1234;
X+ 	test_v.l = 34;
X+ 	test_v.i = 35;
X+ 	test_v.c = 36;
X+ 	foo(&test_v);
X+ 	printf("%s: hello world (%d, %d)\n", *argv, i, j);
X+ 	p = alloca(200000);
X+ 	foo(p);
X+ 	p = alloca(10);
X+ 	strcpy(p, "FooBar");
X+ 	*p = 'Z';
X+ 	while (1) ;
X+ }
X*** dist-gdb.old/test/test1.c	Thu Jan  1 00:00:00 1970
X--- test/test1.c	Sat May  5 17:41:05 1990
X***************
X*** 0 ****
X--- 1,9 ----
X+ #include <stdio.h>
X+ #include "fred.h"
X+ 
X+ foo(st)
X+ struct test_s *st;
X+ {
X+ 	printf("%d %d %d\n", st->l, st->i, st->c);
X+ 	while (1);
X+ }
X*** dist-gdb.old/values.c	Sun Sep 10 03:39:19 1989
X--- values.c	Sat May  5 17:28:02 1990
X***************
X*** 1025,1028 ****
X    add_info ("values", value_history_info,
X  	    "Elements of value history (around item number IDX, or last ten).");
X!   add_info_alias ("history", value_history_info, 0);
X  }
X--- 1025,1028 ----
X    add_info ("values", value_history_info,
X  	    "Elements of value history (around item number IDX, or last ten).");
X! /*  add_info_alias ("history", value_history_info, 0); */
X  }
SHAR_EOF
if test 39436 -ne "`wc -c < 'gdb-x386.01'`"
then
	echo shar: error transmitting "'gdb-x386.01'" '(should have been 39436 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

Steve.Bleazard@RoboBar.Co.UK (05/08/90)

This is part four of a coordinated set of 4 patches for Xenix GCC, GAS and GDB.
Please collect all parts before you start hacking :-)

This is part 4 which patches GDB, say |patch -p -d /usr/local/src/dist-gdb
or whatever AFTER APPLYING part 3.

#! /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:
#	gdb-x386.02
# This archive created: Tue May  8 09:56:53 1990
export PATH; PATH=/bin:$PATH
echo shar: extracting "'gdb-x386.02'" '(48390 characters)'
if test -f 'gdb-x386.02'
then
	echo shar: will not over-write existing file "'gdb-x386.02'"
else
sed 's/^X//' << \SHAR_EOF > 'gdb-x386.02'
X*** dist-gdb.old/x386dbx.c	Thu Jan  1 00:00:00 1970
X--- x386dbx.c	Sat May  5 14:59:45 1990
X***************
X*** 0 ****
X--- 1,478 ----
X+ #include <stdio.h>
X+ #include <a.out.h>
X+ #include <fcntl.h>
X+ #include <sys/types.h>
X+ #include <sys/relsym.h>
X+ #include <sys/param.h>
X+ #include <sys/file.h>
X+ #include "defs.h"
X+ #include "param.h"
X+ #include "symtab.h"
X+ #include "gas-nlist.h"
X+ 
X+ 
X+ /* XENIX symbol segment shape definitions */
X+ 
X+ struct section2 {			/* File info table shape */
X+ 	short		segment;	/* segment number */
X+ 	CORE_ADDR	address;	/* start address for this file */
X+ 	unsigned short	textsize;	/* size of the text for this file */
X+ 	long		type3off;	/* offset to type3 records, psym tab */
X+ 	long		type4off;	/* offset to type4 records, nlist tab */
X+ 	long		type5off;	/* offset to type5 records, str tab */
X+ 	long		type6off;	/* offset to type6 records */
X+ 	unsigned short	type3sz;	/* size of type3 records */
X+ 	unsigned short	type4sz;	/* size of type4 records */
X+ 	unsigned short	type5sz;	/* size of type5 records */
X+ 	unsigned short	type6sz;	/* size of type6 records */
X+ 	char		filelen;	/* length of filename */
X+ };
X+ 
X+ /* psymtable (attribute 3) symbol segment shape */
X+ 
X+ struct psymbol_seg {
X+ 	long		address;	/* core address */
X+ 	short		segid;		/* segment number */
X+ 	short		typeid;		/* variable's type */
X+ 	char		varlen;		/* variable's length */
X+ /*	char		name[0];	trailing name varlen long */
X+ } record3;
X+ 
X+ /*  Info maintenance structures */
X+ 
X+ struct fileinfo {		/* per file info */
X+ 	CORE_ADDR	address;	/* start address for this file */
X+ 	unsigned short	textsize;	/* size of text for this file */
X+ 	long		psymoff;	/* psyms table */
X+ 	long		strtaboff;	/* string table aka $$TYPES */
X+ 	long		ntaboff;	/* nlist table aka $$SYMBOLS */
X+ 	unsigned short	psymsz;		/* size of psyms table */
X+ 	unsigned short	strtabsz;	/* size of string table */
X+ 	unsigned short	ntabsz;		/* size of nlist table */
X+ 	int		mscdebuginfo;	/* compiled with cc -g not gcc -g */
X+ 	char		*filename;	/* name of this file */
X+ 	struct fileinfo *next;
X+ };
X+ 
X+ static struct fileinfo *fi_table = 0;
X+ struct xseg *seg_table;
X+ long num_seg_table_entries;
X+ 
X+ #ifdef __GNUC__
X+ #define alloca __builtin_alloca
X+ #endif
X+ 
X+ #define IGNORE_ATTR (-1)
X+ 
X+ static read_fileinfo_table(fp, segsize, name)
X+ FILE *fp;
X+ int segsize;
X+ char *name;
X+ {
X+   extern char *strrchr(), *xmalloc();
X+   char *fi_name;
X+   char *filename;
X+   struct section2 fi_entry;
X+   struct fileinfo *fi;
X+ 
X+   fi_table = fi = (struct fileinfo *)xmalloc(sizeof(struct fileinfo));
X+   while (segsize > 0)
X+   {
X+     if ((fread((char *)&fi_entry.segment, sizeof(short), 1, fp) != 1)
X+       || (fread((char *)&fi_entry.address, sizeof(CORE_ADDR), 1, fp) != 1)
X+       || (fread((char *)&fi_entry.textsize, sizeof(unsigned short),1,fp) != 1)
X+       || (fread((char *)&fi_entry.type3off, sizeof(long), 1, fp) != 1)
X+       || (fread((char *)&fi_entry.type4off, sizeof(long), 1, fp) != 1)
X+       || (fread((char *)&fi_entry.type5off, sizeof(long), 1, fp) != 1)
X+       || (fread((char *)&fi_entry.type6off, sizeof(long), 1, fp) != 1)
X+       || (fread((char *)&fi_entry.type3sz, sizeof(unsigned short),1,fp) != 1)
X+       || (fread((char *)&fi_entry.type4sz, sizeof(unsigned short),1,fp) != 1)
X+       || (fread((char *)&fi_entry.type5sz, sizeof(unsigned short),1,fp) != 1)
X+       || (fread((char *)&fi_entry.type6sz, sizeof(unsigned short),1,fp) != 1)
X+       || (fread((char *)&fi_entry.filelen, sizeof(char), 1, fp) != 1))
X+       perror_with_name(name);
X+ 
X+     segsize -= sizeof(short) + sizeof(CORE_ADDR) + 5 * sizeof(unsigned short)
X+ 	       + 4 * sizeof(long) + sizeof(char);
X+ 
X+     fi_name = alloca(fi_entry.filelen + 1);
X+     if (fread(fi_name, fi_entry.filelen, 1, fp) != 1)
X+       perror_with_name(name);
X+     fi_name[fi_entry.filelen] = '\0';
X+     segsize -= fi_entry.filelen;
X+ 
X+     if ((filename = strrchr(fi_name, '/')) != (char *)0)
X+       fi_name = filename + 1;
X+ 
X+     if ((filename = strrchr(fi_name, '(')) != (char *)0)
X+       fi_name = filename + 1;
X+ 
X+     if ((filename = strrchr(fi_name, ')')) != (char *)0)
X+         *filename = '\0';
X+    
X+     {
X+       int len = strlen(fi_name);
X+ 
X+       if (len > 2 && fi_name[len - 1] == 'o' && fi_name[len - 2] == '.')
X+       fi_name[len - 1] = 'c';
X+     }
X+ 
X+     fi_name = savestring(fi_name, strlen(fi_name) + 1);
X+ 
X+     fi->next = (struct fileinfo *)xmalloc(sizeof(struct fileinfo));
X+     fi = fi->next;
X+ 
X+     fi->address = fi_entry.address;
X+     fi->textsize = fi_entry.textsize;
X+     fi->psymoff = fi_entry.type3off;
X+     fi->psymsz = fi_entry.type3sz;
X+     fi->strtaboff = fi_entry.type4off;
X+     fi->strtabsz = fi_entry.type4sz;
X+     fi->ntaboff = fi_entry.type5off;
X+     fi->ntabsz = fi_entry.type5sz;
X+     fi->mscdebuginfo = (fi_entry.type6sz != 0);
X+     fi->filename = fi_name;
X+   }
X+   fi->next = 0;  fi = fi_table;  fi_table = fi_table->next;  free(fi);
X+ 
X+ #ifdef X_DEBUG
X+     printf("\naddress   textsz  symoff   symsz  stroff   strsz  taboff   tabsz  name\n\n");
X+   for (fi = fi_table; fi != 0; fi = fi->next)
X+   {
X+     printf("% 8x  % 6d  % 6d  % 6d  % 6d  % 6d  % 6d  %6d  %s\n", fi->address, fi->textsize, fi->psymoff, fi->psymsz, fi->strtaboff, fi->strtabsz, fi->ntaboff, fi->ntabsz, fi->filename);
X+   }
X+   printf("\n");
X+ #endif /* X_DEBUG */
X+ }
X+ 
X+ static read_seg_table(fp, pos, size, name)
X+ FILE *fp;
X+ long pos, size;
X+ {
X+   seg_table = (struct xseg *) xmalloc(size);
X+   fseek(fp, pos, 0);
X+   if (fread((char *)seg_table, size, 1, fp) != 1)
X+     perror_with_name(name);
X+   num_seg_table_entries = size / sizeof (struct xseg);
X+ }
X+ 
X+ 
X+ struct xseg *find_segment(type, attr)
X+ int type, attr;
X+ {
X+   struct xseg *cseg;
X+ 
X+   for (cseg = seg_table; cseg < seg_table + num_seg_table_entries; ++cseg)
X+   if (cseg->xs_type == type &&
X+     (attr == IGNORE_ATTR || attr == cseg->xs_attr))
X+     return cseg;
X+   return NULL;
X+ }
X+ 
X+ static int compare_misc_functions (fn1, fn2)
X+ struct misc_function *fn1, *fn2;
X+ {
X+   /* Return a signed result based on unsigned comparisons
X+      so that we sort into unsigned numeric order.  */
X+ 
X+   if (fn1->address < fn2->address)
X+     return -1;
X+   if (fn1->address > fn2->address)
X+     return 1;
X+   return 0;
X+ }
X+ 
X+ static int read_misc_functions(fp, segsize, name)
X+ FILE *fp;
X+ int segsize;
X+ char *name;
X+ {
X+   char *symdata, *p, *str_buff;
X+   long sym_count = 0, str_count = 0, i;
X+   struct misc_function *miscp;
X+   struct sym symb;
X+ 
X+   /* grab the symbol table */
X+ 
X+   symdata = alloca(segsize + 1);
X+   if (fread(symdata, segsize, 1, fp) != 1)
X+       perror_with_name(name);
X+ 
X+   /* first pass, work out how many symbols there are and the size of the
X+    * strings
X+    */
X+ 
X+   p = symdata;
X+   while (p < symdata + segsize)
X+   {
X+ 	int len;
X+ 
X+ 	p += sizeof(struct sym);
X+ 	len = strlen(p) + 1;
X+ 	str_count += len;  p += len;  sym_count++;
X+   }
X+ 
X+   /* Now build the misc function vector */
X+ 
X+   str_buff = xmalloc(str_count+1);
X+   misc_function_vector =
X+     (struct misc_function *) xmalloc (sym_count * sizeof(struct misc_function));
X+   misc_function_count = sym_count;
X+ 
X+   p = symdata;  miscp = misc_function_vector;
X+   while (p < symdata + segsize)
X+   {
X+ 	int len;
X+ 
X+ 	symb = *((struct sym *)p);
X+ 	p += sizeof(struct sym);
X+ 
X+ 	if (*p == '_')
X+ 	  strcpy(str_buff, p+1);
X+ 	else
X+ 	  strcpy(str_buff, p);
X+ 
X+ 	/* the following will result in a garbage byte every time a symbol
X+ 	 * starts with a _, I can'y be bothered to fix it.
X+ 	 */
X+ 
X+ 	miscp->name = str_buff;
X+ 	len = strlen(p) + 1;
X+ 	str_buff += len;  p += len;
X+ 	miscp->address = symb.s_value;
X+ 	switch(symb.s_type & S_TYPE)
X+ 	{
X+ 	case S_UNDEF:  miscp->type = mf_unknown;  break;
X+ 	case S_ABS:    miscp->type = mf_abs;  break;
X+ 	case S_TEXT:   miscp->type = mf_text;  break;
X+ 	case S_DATA:   miscp->type = mf_data;  break;
X+ 	case S_BSS:    miscp->type = mf_bss;  break;
X+ 	case S_COMM:   miscp->type = mf_data;  break;
X+ 	case S_REG:    miscp->type = mf_unknown;  break;
X+ 	case S_COMB:   miscp->type = mf_unknown;  break;
X+ 	case S_SEG:    miscp->type = mf_unknown;  break;
X+ 	case S_FN:     miscp->type = mf_unknown;  break;
X+ 	dewfault:      miscp->type = mf_unknown;  break;
X+ 	}
X+ 	miscp++;
X+   }
X+ 
X+   qsort (misc_function_vector, misc_function_count,
X+     sizeof (struct misc_function), compare_misc_functions);
X+ 
X+ #ifdef X_DEBUG
X+   {
X+     struct misc_function *miscp;
X+     int i;
X+ 
X+     printf("type      address  name\n\n");
X+     for (i = 0; i < misc_function_count; i++)
X+     {
X+       miscp = &misc_function_vector[i];
X+       switch (miscp->type)
X+       {
X+       case mf_unknown: printf("%-9s","unknown");  break;
X+       case mf_text:    printf("%-9s","text");  break;
X+       case mf_data:    printf("%-9s","data");  break;
X+       case mf_bss:     printf("%-9s","bss");  break;
X+       case mf_abs:     printf("%-9s","abs");  break;
X+       default:         printf("%-9s","UNKNOWN");  break;
X+       }
X+       printf("% 8x  ", miscp->address);
X+       printf("%s\n", miscp->name);
X+     }
X+   }
X+ #endif /* X_DEBUG */
X+   return misc_function_count;
X+ }
X+ 
X+ process_a_out(desc, name)
X+ int desc;
X+ char *name;
X+ {
X+   struct xexec exec_aouthdr;
X+   struct xext *xext;
X+   struct xseg *cseg;
X+   FILE *fp;
X+ 
X+   lseek(desc, 0L, 0);
X+   if ((fp = fdopen(dup(desc), "r")) == NULL)
X+ 		perror_with_name(name);
X+ 
X+   if (fread((char *)&exec_aouthdr, sizeof(struct xexec), 1, fp) != 1)
X+     perror_with_name(name);
X+   
X+   xext = (struct xext *) alloca(exec_aouthdr.x_ext);
X+   if (fread((char *)xext, exec_aouthdr.x_ext, 1, fp) != 1)
X+     perror_with_name(name);
X+   
X+   read_seg_table(fp, xext->xe_segpos, xext->xe_segsize, name);
X+ 
X+   if (cseg = find_segment(XS_TSYMS, 2))
X+   {
X+     fseek(fp, cseg->xs_filpos, 0);
X+     read_fileinfo_table(fp, cseg->xs_psize, name);
X+   }
X+ 
X+   fclose(fp);
X+ }
X+ 
X+ process_global_symbol_table(desc, name)
X+ int desc;
X+ char *name;
X+ {
X+   struct xseg *cseg;
X+   FILE *fp;
X+ 
X+   if ((fp = fdopen(dup(desc), "r")) == NULL)
X+ 		perror_with_name(name);
X+ 
X+   if (cseg = find_segment(XS_TSYMS, 1))
X+   {
X+     fseek(fp, cseg->xs_filpos, 0);
X+     read_misc_functions(fp, cseg->xs_psize, name);
X+   }
X+   fclose(fp);
X+ }
X+ 
X+ static struct fileinfo *current_fi;
X+ static int first_get_fileinfo_call = 1;
X+ 
X+ init_fileinfo_processing()  /* start processing the list of files */
X+ {
X+   first_get_fileinfo_call = 1;
X+ }
X+ 
X+ long get_next_fileinfo(stroff, nsyms, address, symtaboff)
X+ long *stroff, *nsyms, *address, *symtaboff;
X+ {
X+   struct xseg *cseg;
X+ 
X+   if (first_get_fileinfo_call)
X+   {
X+     current_fi = fi_table;
X+     first_get_fileinfo_call = 0;
X+   }
X+   else
X+     current_fi = current_fi->next;
X+   
X+   if (current_fi == 0)
X+     return 0;
X+ 
X+   if (current_fi->mscdebuginfo)
X+   {
X+     *stroff = 0;
X+     *nsyms = 0;
X+     *address = current_fi->address;
X+   }
X+   else if (cseg = find_segment(XS_TSYMS, 5))
X+   {
X+     *symtaboff = cseg->xs_filpos + current_fi->ntaboff;
X+     *stroff = current_fi->strtaboff;
X+     *nsyms = current_fi->ntabsz / sizeof(struct gas_nlist);
X+     *address = current_fi->address;
X+     return 1;
X+   }
X+   else
X+   {
X+     *symtaboff = 0;
X+     *stroff = 0;
X+     *nsyms = 0;
X+     *address = 0;
X+   }
X+ }
X+ 
X+ #ifdef TEST
X+ 
X+ main()
X+ {
X+ 	char *stab;
X+ 	long str_offset, nsyms, address, ntaboff;
X+  	int desc;
X+ 	struct xseg *cseg;
X+ 
X+ 	process_a_out((desc = open("a.out", O_RDONLY, 0)), "a.out");
X+ 
X+ 	printf("\n");
X+ 
X+      	  if (cseg = find_segment(XS_TSYMS, 4))
X+      	  {
X+ 	    lseek(desc, cseg->xs_filpos, 0);
X+ 	    stab = alloca(cseg->xs_psize);
X+ 	    read(desc, stab, cseg->xs_psize);
X+ 	  }
X+ 	  else
X+ 	    stab = 0;
X+ 
X+           init_fileinfo_processing();
X+ 	  while (get_next_fileinfo(&str_offset,&nsyms,&address,&ntaboff))
X+ 	  {
X+ 	    lseek(desc, ntaboff, 0);
X+ 	    printf("\n  type    desc     value  stroff  string (%#x)\n", address);
X+ 	    while (nsyms--)
X+ 	    {
X+ 	      struct gas_nlist nl;
X+ 
X+ 	      read(desc, &nl, sizeof(nl));
X+ 	      printf("% 6x  % 6x  % 8x  % 6x %s\n",
X+ 		     (unsigned char)nl.n_type,
X+ 		     (unsigned short)nl.n_desc,
X+ 		     (unsigned int)nl.n_value,
X+ 		     nl.n_un.n_strx ? stab + str_offset + nl.n_un.n_strx : "");
X+ 	    }
X+ 	    lseek(desc, 0L, 0);
X+ 	  }
X+ }
X+ 
X+ perror_with_name (string)
X+      char *string;
X+ {
X+   extern int sys_nerr;
X+   extern char *sys_errlist[];
X+   extern int errno;
X+   char *err;
X+   char *combined;
X+ 
X+   if (errno < sys_nerr)
X+     err = sys_errlist[errno];
X+   else
X+     err = "unknown error";
X+ 
X+   combined = (char *) alloca (strlen (err) + strlen (string) + 3);
X+   strcpy (combined, string);
X+   strcat (combined, ": ");
X+   strcat (combined, err);
X+ 
X+   error ("%s.", combined);
X+ }
X+ 
X+ error (string, arg1, arg2, arg3)
X+      char *string;
X+      int arg1, arg2, arg3;
X+ {
X+   fflush (stdout);
X+   fprintf (stderr, string, arg1, arg2, arg3);
X+   fprintf (stderr, "\n");
X+   exit(1);
X+ }
X+ 
X+ char * xmalloc (size)
X+      long size;
X+ {
X+   register char *val = (char *) malloc (size);
X+   if (!val)
X+     error ("virtual memory exhausted.");
X+   return val;
X+ }
X+ 
X+ char *savestring (ptr, size)
X+      char *ptr;
X+      int size;
X+ {
X+   register char *p = (char *) xmalloc (size + 1);
X+   memcpy(p, ptr, size);
X+   p[size] = 0;
X+   return p;
X+ }
X+ 
X+ #endif /* TEST */
X*** dist-gdb.old/xenix386-dep.c	Thu Jan  1 00:00:00 1970
X--- xenix386-dep.c	Mon May  7 15:02:10 1990
X***************
X*** 0 ****
X--- 1,1275 ----
X+ /* Low level interface to ptrace, for GDB when running on the Intel 386.
X+    Copyright (C) 1988, 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 <stdio.h>
X+ #include "defs.h"
X+ #include "param.h"
X+ #include "frame.h"
X+ #include "inferior.h"
X+ 
X+ #ifdef USG
X+ #include <sys/types.h>
X+ #endif
X+ 
X+ #include <stdio.h>
X+ #include <sys/param.h>
X+ #include <sys/dir.h>
X+ #include <signal.h>
X+ #ifdef M_XENIX
X+ #include <sys/page.h>
X+ #include <sys/seg.h>
X+ #endif
X+ #include <sys/user.h>
X+ #include <sys/ioctl.h>
X+ #include <fcntl.h>
X+ 
X+ #ifdef COFF_ENCAPSULATE
X+ #include "a.out.encap.h"
X+ #else
X+ #ifndef M_XENIX			/* brain-dead xenix strikes again */
X+ #include <a.out.h>
X+ #endif
X+ #endif
X+ 
X+ #ifndef N_SET_MAGIC
X+ #ifdef COFF_FORMAT
X+ #define N_SET_MAGIC(exec, val) ((exec).magic = (val))
X+ #else
X+ #define N_SET_MAGIC(aexec, val) ((aexec).xa_magic = (val))
X+ #endif
X+ #endif
X+ 
X+ #include <sys/file.h>
X+ #include <sys/stat.h>
X+ #include <sys/proc.h>
X+ 
X+ #include <sys/reg.h>
X+ 
X+ unsigned short text_segid;	/* segment number of text segment */
X+ unsigned short data_segid;	/* segment number of data segment */
X+ extern CORE_ADDR text_end; \
X+ 
X+ #ifdef X_DEBUG
X+ Ptrace(l, a, b, c, d)
X+ int l;
X+ int a, b, c, d;
X+ {
X+ 	printf("at line %d, req = %d, pid = %d, addr = %#x, data = %d\n",
X+ 	       l, a, b, c, d);
X+         return ptrace (a, b, c, d);
X+ }
X+ 
X+ #define ptrace(a,b,c,d) Ptrace(__LINE__, a, b, c, d)
X+ #endif /* X_DEBUG */
X+ 
X+ typedef struct saddr PTRACE;
X+ static PTRACE tmptrace;
X+ extern int errno;
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 (8, 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 (8, 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+   PTRACE addr;
X+   addr.sa_seg = 0;
X+   addr.sa_off = 1;
X+   errno = 0;
X+   if (remote_debugging)
X+     remote_resume (step, signal);
X+   else
X+     {
X+       /* ptrace (step ? 9 : 7, inferior_pid, &addr, signal); */
X+       ptrace (step ? 9 : 7, inferior_pid, 1, signal);
X+       if (errno)
X+ 	perror_with_name ("ptrace");
X+     }
X+ }
X+ 
X+ void
X+ fetch_inferior_registers ()
X+ {
X+   register int regno;
X+   register unsigned int regaddr;
X+   char buf[MAX_REGISTER_RAW_SIZE];
X+   register int i;
X+ 
X+   struct user u;
X+   unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
X+   offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
X+ 
X+   for (regno = 0; regno < NUM_REGS; regno++)
X+     {
X+       regaddr = register_addr (regno, offset);
X+       for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
X+  	{
X+  	  *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
X+  	  regaddr += sizeof (int);
X+  	}
X+       supply_register (regno, buf);
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+ 
X+   struct user u;
X+   unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
X+   offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
X+ 
X+   if (regno >= 0)
X+     {
X+       regaddr = register_addr (regno, offset);
X+       errno = 0;
X+       ptrace (6, inferior_pid, regaddr, read_register (regno));
X+       if (errno != 0)
X+ 	{
X+ 	  sprintf (buf, "writing register number %d", regno);
X+ 	  perror_with_name (buf);
X+ 	}
X+     }
X+   else for (regno = 0; regno < NUM_REGS; regno++)
X+     {
X+       regaddr = register_addr (regno, offset);
X+       errno = 0;
X+       ptrace (6, inferior_pid, regaddr, read_register (regno));
X+       if (errno != 0)
X+ 	{
X+ 	  sprintf (buf, "writing register number %d", regno);
X+ 	  perror_with_name (buf);
X+ 	}
X+     }
X+ }
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 (addr <= text_end ? 1 : 2, inferior_pid,
X+ 		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 (addr <= text_end ? 1 : 2, 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 (addr <= text_end ? 1 : 2, 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 <= text_end ? 4 : 5, 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.xa_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+ #define AOUTHDR struct xexec
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+ /* 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+ #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+ core_file_command (filename, from_tty)
X+      char *filename;
X+      int from_tty;
X+ {
X+   int val;
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 = 0;
X+   stack_end = 0;
X+ 
X+   /* Now, if a new core file was specified, open it and digest it.  */
X+ 
X+   if (filename)
X+     {
X+       filename = tilde_expand (filename);
X+       make_cleanup (free, 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+       /* xenix style core dump */
X+       {
X+ 	struct user u;
X+ 	long user_area_size;
X+ 	int reg_offset;
X+ 
X+ 
X+ 	val = myread (corechan, &u, sizeof u);
X+ 	if (val < 0)
X+ 	  perror_with_name (filename);
X+ 
X+ 	user_area_size = ((sizeof u + (u.u_ldtlimit-1)*sizeof(struct descriptor)
X+ 			 + NBPC - 1) / NBPC) * NBPC;
X+ 
X+ 	data_start = (CORE_ADDR)u.u_sdata;
X+ 	data_end = (CORE_ADDR)u.u_edatau;
X+ 	stack_start = (CORE_ADDR)u.u_stktop;
X+ 	stack_end = (CORE_ADDR)u.u_stkbotu;
X+ 
X+ 	data_offset = lseek(corechan, 0L, 2) - u.u_dsize;
X+ 	stack_offset = user_area_size;
X+ 	reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
X+ #ifdef X_DEBUG
X+ 	printf("data_offset = %#x\n", data_offset);
X+ 	printf("stack_offset  = %#x\n", stack_offset );
X+ 	printf("user_area_size = %#x\n", user_area_size);
X+ 	printf("test data_offset = %#x\n", user_area_size + u.u_ssize);
X+ #endif /* X_DEBUG */
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+ 	bzero ((char *) &core_aouthdr, sizeof core_aouthdr);
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+ 	      val = lseek (corechan, register_addr (regno, reg_offset), 0);
X+ 	      if (val < 0)
X+ 		perror_with_name (filename);
X+ 
X+  	      val = myread (corechan, buf, sizeof buf);
X+ 	      if (val < 0)
X+ 		perror_with_name (filename);
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+       filename = tilde_expand (filename);
X+       make_cleanup (free, 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+ 	char *extended_header;
X+ 	struct xext *xext;
X+ 	struct stat st_exec;
X+ 	struct xseg xseg;
X+ 	extern char *malloc();
X+ 	val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
X+ 
X+ 	if (val < 0)
X+ 	  perror_with_name (filename);
X+         if (exec_aouthdr.x_magic != X_MAGIC)
X+ 	  error ("\"%s\": not in executable format.", execfile);
X+ 	if ( (exec_aouthdr.x_cpu & XC_CPU) != XC_386 )
X+ 	  error ("\"%s\": not a 386 executable.", execfile);
X+ 	if ( (exec_aouthdr.x_renv & XE_SEG) == 0)
X+ 	  error ("\"%s\": not a segmented executable.", execfile);
X+ 	if ( (exec_aouthdr.x_renv & XE_EXEC) == 0)
X+ 	  error ("\"%s\": not executable.", execfile);
X+ 	extended_header = malloc(exec_aouthdr.x_ext);
X+ 	val = myread (execchan, extended_header, exec_aouthdr.x_ext);
X+ 	if (val < 0)
X+ 	  perror_with_name (filename);
X+ 	xext = (struct xext *)extended_header;
X+ 	lseek(execchan, xext->xe_segpos, 0);
X+ 	if (myread (execchan, (char *)&xseg, sizeof(xseg)) < 0)
X+ 	  perror_with_name (filename);
X+ 	if ( xseg.xs_type != XS_TTEXT )
X+ 	  error ("\"%s\": Text segment isn't first (huh?).", execfile);
X+ 	text_segid = xseg.xs_seg;
X+ 	text_start = xseg.xs_rbase;
X+ 	text_end = text_start + xseg.xs_vsize;
X+ 	text_offset = xseg.xs_filpos;
X+ 
X+ 	if (myread (execchan, (char *)&xseg, sizeof(xseg)) < 0)
X+ 	  perror_with_name (filename);
X+ 	if ( xseg.xs_type != XS_TDATA )
X+ 	  error ("\"%s\": Data segment isn't second (huh?).", execfile);
X+ 	data_segid = xseg.xs_seg;
X+ 	exec_data_start = xseg.xs_rbase;
X+ 	exec_data_end = exec_data_start + xseg.xs_psize;
X+ 	exec_data_offset = xseg.xs_filpos;
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+ 	free(extended_header);
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+ }
X+ 
X+ /* helper functions for m-i386.h */
X+ 
X+ /* stdio style buffering to minimize calls to ptrace */
X+ static CORE_ADDR codestream_next_addr;
X+ static CORE_ADDR codestream_addr;
X+ static unsigned char codestream_buf[sizeof (int)];
X+ static int codestream_off;
X+ static int codestream_cnt;
X+ 
X+ #define codestream_tell() (codestream_addr + codestream_off)
X+ #define codestream_peek() (codestream_cnt == 0 ? \
X+ 			   codestream_fill(1): codestream_buf[codestream_off])
X+ #define codestream_get() (codestream_cnt-- == 0 ? \
X+ 			 codestream_fill(0) : codestream_buf[codestream_off++])
X+ 
X+ static unsigned char 
X+ codestream_fill (peek_flag)
X+ {
X+   codestream_addr = codestream_next_addr;
X+   codestream_next_addr += sizeof (int);
X+   codestream_off = 0;
X+   codestream_cnt = sizeof (int);
X+   read_memory (codestream_addr,
X+ 	       (unsigned char *)codestream_buf,
X+ 	       sizeof (int));
X+   
X+   if (peek_flag)
X+     return (codestream_peek());
X+   else
X+     return (codestream_get());
X+ }
X+ 
X+ static void
X+ codestream_seek (place)
X+ {
X+   codestream_next_addr = place & -sizeof (int);
X+   codestream_cnt = 0;
X+   codestream_fill (1);
X+   while (codestream_tell() != place)
X+     codestream_get ();
X+ }
X+ 
X+ static void
X+ codestream_read (buf, count)
X+      unsigned char *buf;
X+ {
X+   unsigned char *p;
X+   int i;
X+   p = buf;
X+   for (i = 0; i < count; i++)
X+     *p++ = codestream_get ();
X+ }
X+ 
X+ /* next instruction is a jump, move to target */
X+ static
X+ i386_follow_jump ()
X+ {
X+   int long_delta;
X+   short short_delta;
X+   char byte_delta;
X+   int data16;
X+   int pos;
X+   
X+   pos = codestream_tell ();
X+   
X+   data16 = 0;
X+   if (codestream_peek () == 0x66)
X+     {
X+       codestream_get ();
X+       data16 = 1;
X+     }
X+   
X+   switch (codestream_get ())
X+     {
X+     case 0xe9:
X+       /* relative jump: if data16 == 0, disp32, else disp16 */
X+       if (data16)
X+ 	{
X+ 	  codestream_read ((unsigned char *)&short_delta, 2);
X+ 	  pos += short_delta + 3; /* include size of jmp inst */
X+ 	}
X+       else
X+ 	{
X+ 	  codestream_read ((unsigned char *)&long_delta, 4);
X+ 	  pos += long_delta + 5;
X+ 	}
X+       break;
X+     case 0xeb:
X+       /* relative jump, disp8 (ignore data16) */
X+       codestream_read ((unsigned char *)&byte_delta, 1);
X+       pos += byte_delta + 2;
X+       break;
X+     }
X+   codestream_seek (pos + data16);
X+ }
X+ 
X+ /*
X+  * find & return amound a local space allocated, and advance codestream to
X+  * first register push (if any)
X+  *
X+  * if entry sequence doesn't make sense, return -1, and leave 
X+  * codestream pointer random
X+  */
X+ static long
X+ i386_get_frame_setup (pc)
X+ {
X+   unsigned char op;
X+   
X+   codestream_seek (pc);
X+   
X+   i386_follow_jump ();
X+   
X+   op = codestream_get ();
X+   
X+   if (op == 0x58)		/* popl %eax */
X+     {
X+       /*
X+        * this function must start with
X+        * 
X+        *    popl %eax		  0x58
X+        *    xchgl %eax, (%esp)  0x87 0x04 0x24
X+        * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
X+        *
X+        * (the system 5 compiler puts out the second xchg
X+        * inst, and the assembler doesn't try to optimize it,
X+        * so the 'sib' form gets generated)
X+        * 
X+        * this sequence is used to get the address of the return
X+        * buffer for a function that returns a structure
X+        */
X+       int pos;
X+       unsigned char buf[4];
X+       static unsigned char proto1[3] = { 0x87,0x04,0x24 };
X+       static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
X+       pos = codestream_tell ();
X+       codestream_read (buf, 4);
X+       if (bcmp (buf, proto1, 3) == 0)
X+ 	pos += 3;
X+       else if (bcmp (buf, proto2, 4) == 0)
X+ 	pos += 4;
X+       
X+       codestream_seek (pos);
X+       op = codestream_get (); /* update next opcode */
X+     }
X+   
X+   if (op == 0x55)		/* pushl %esp */
X+     {			
X+       /* check for movl %esp, %ebp - can be written two ways */
X+       switch (codestream_get ())
X+ 	{
X+ 	case 0x8b:
X+ 	  if (codestream_get () != 0xec)
X+ 	    return (-1);
X+ 	  break;
X+ 	case 0x89:
X+ 	  if (codestream_get () != 0xe5)
X+ 	    return (-1);
X+ 	  break;
X+ 	default:
X+ 	  return (-1);
X+ 	}
X+       /* check for stack adjustment 
X+        *
X+        *  subl $XXX, %esp
X+        *
X+        * note: you can't subtract a 16 bit immediate
X+        * from a 32 bit reg, so we don't have to worry
X+        * about a data16 prefix 
X+        */
X+       op = codestream_peek ();
X+       if (op == 0x83)
X+ 	{
X+ 	  /* subl with 8 bit immed */
X+ 	  codestream_get ();
X+ 	  if (codestream_get () != 0xec)
X+ 	    return (-1);
X+ 	  /* subl with signed byte immediate 
X+ 	   * (though it wouldn't make sense to be negative)
X+ 	   */
X+ 	  return (codestream_get());
X+ 	}
X+       else if (op == 0x81)
X+ 	{
X+ 	  /* subl with 32 bit immed */
X+ 	  int locals;
X+ 	  codestream_get();
X+ 	  if (codestream_get () != 0xec)
X+ 	    return (-1);
X+ 	  /* subl with 32 bit immediate */
X+ 	  codestream_read ((unsigned char *)&locals, 4);
X+ 	  return (locals);
X+ 	}
X+       else
X+ 	{
X+ 	  return (0);
X+ 	}
X+     }
X+   else if (op == 0xc8)
X+     {
X+       /* enter instruction: arg is 16 bit unsigned immed */
X+       unsigned short slocals;
X+       codestream_read ((unsigned char *)&slocals, 2);
X+       codestream_get (); /* flush final byte of enter instruction */
X+       return (slocals);
X+     }
X+   return (-1);
X+ }
X+ 
X+ /* Return number of args passed to a frame.
X+    Can return -1, meaning no way to tell.  */
X+ 
X+ /* on the 386, the instruction following the call could be:
X+  *  popl %ecx        -  one arg
X+  *  addl $imm, %esp  -  imm/4 args; imm may be 8 or 32 bits
X+  *  anything else    -  zero args
X+  */
X+ 
X+ int
X+ i386_frame_num_args (fi)
X+      struct frame_info fi;
X+ {
X+   int retpc;						
X+   unsigned char op;					
X+   struct frame_info *pfi;
X+ 
X+   pfi = get_prev_frame_info ((fi));			
X+   if (pfi == 0)
X+     {
X+       /* Note:  this can happen if we are looking at the frame for
X+ 	 main, because FRAME_CHAIN_VALID won't let us go into
X+ 	 start.  If we have debugging symbols, that's not really
X+ 	 a big deal; it just means it will only show as many arguments
X+ 	 to main as are declared.  */
X+       return -1;
X+     }
X+   else
X+     {
X+       retpc = pfi->pc;					
X+       op = read_memory_integer (retpc, 1);			
X+       if (op == 0x59)					
X+ 	/* pop %ecx */			       
X+ 	return 1;				
X+       else if (op == 0x83)
X+ 	{
X+ 	  op = read_memory_integer (retpc+1, 1);	
X+ 	  if (op == 0xc4)				
X+ 	    /* addl $<signed imm 8 bits>, %esp */	
X+ 	    return (read_memory_integer (retpc+2,1)&0xff)/4;
X+ 	  else
X+ 	    return 0;
X+ 	}
X+       else if (op == 0x81)
X+ 	{ /* add with 32 bit immediate */
X+ 	  op = read_memory_integer (retpc+1, 1);	
X+ 	  if (op == 0xc4)				
X+ 	    /* addl $<imm 32>, %esp */		
X+ 	    return read_memory_integer (retpc+2, 4) / 4;
X+ 	  else
X+ 	    return 0;
X+ 	}
X+       else
X+ 	{
X+ 	  return 0;
X+ 	}
X+     }
X+ }
X+ 
X+ /*
X+  * parse the first few instructions of the function to see
X+  * what registers were stored.
X+  *
X+  * We handle these cases:
X+  *
X+  * The startup sequence can be at the start of the function,
X+  * or the function can start with a branch to startup code at the end.
X+  *
X+  * %ebp can be set up with either the 'enter' instruction, or 
X+  * 'pushl %ebp, movl %esp, %ebp' (enter is too slow to be useful,
X+  * but was once used in the sys5 compiler)
X+  *
X+  * Local space is allocated just below the saved %ebp by either the
X+  * 'enter' instruction, or by 'subl $<size>, %esp'.  'enter' has
X+  * a 16 bit unsigned argument for space to allocate, and the
X+  * 'addl' instruction could have either a signed byte, or
X+  * 32 bit immediate.
X+  *
X+  * Next, the registers used by this function are pushed.  In
X+  * the sys5 compiler they will always be in the order: %edi, %esi, %ebx
X+  * (and sometimes a harmless bug causes it to also save but not restore %eax);
X+  * however, the code below is willing to see the pushes in any order,
X+  * and will handle up to 8 of them.
X+  *
X+  * If the setup sequence is at the end of the function, then the
X+  * next instruction will be a branch back to the start.
X+  */
X+ 
X+ i386_frame_find_saved_regs (fip, fsrp)
X+      struct frame_info *fip;
X+      struct frame_saved_regs *fsrp;
X+ {
X+   unsigned long locals;
X+   unsigned char *p;
X+   unsigned char op;
X+   CORE_ADDR dummy_bottom;
X+   CORE_ADDR adr;
X+   int i;
X+   
X+   bzero (fsrp, sizeof *fsrp);
X+   
X+   /* if frame is the end of a dummy, compute where the
X+    * beginning would be
X+    */
X+   dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
X+   
X+   /* check if the PC is in the stack, in a dummy frame */
X+   if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) 
X+     {
X+       /* all regs were saved by push_call_dummy () */
X+       adr = fip->frame - 4;
X+       for (i = 0; i < NUM_REGS; i++) 
X+ 	{
X+ 	  fsrp->regs[i] = adr;
X+ 	  adr -= 4;
X+ 	}
X+       return;
X+     }
X+   
X+   locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
X+   
X+   if (locals >= 0) 
X+     {
X+       adr = fip->frame - 4 - locals;
X+       for (i = 0; i < 8; i++) 
X+ 	{
X+ 	  op = codestream_get ();
X+ 	  if (op < 0x50 || op > 0x57)
X+ 	    break;
X+ 	  fsrp->regs[op - 0x50] = adr;
X+ 	  adr -= 4;
X+ 	}
X+     }
X+   
X+   fsrp->regs[PC_REGNUM] = fip->frame + 4;
X+   fsrp->regs[FP_REGNUM] = fip->frame;
X+ }
X+ 
X+ /* return pc of first real instruction */
X+ i386_skip_prologue (pc)
X+ {
X+   unsigned char op;
X+   int i;
X+   
X+   if (i386_get_frame_setup (pc) < 0)
X+     return (pc);
X+   
X+   /* found valid frame setup - codestream now points to 
X+    * start of push instructions for saving registers
X+    */
X+   
X+   /* skip over register saves */
X+   for (i = 0; i < 8; i++)
X+     {
X+       op = codestream_peek ();
X+       /* break if not pushl inst */
X+       if (op < 0x50 || op > 0x57) 
X+ 	break;
X+       codestream_get ();
X+     }
X+   
X+   i386_follow_jump ();
X+   
X+   return (codestream_tell ());
X+ }
X+ 
X+ i386_push_dummy_frame ()
X+ {
X+   CORE_ADDR sp = read_register (SP_REGNUM);
X+   int regnum;
X+   
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 = 0; regnum < NUM_REGS; regnum++)
X+     sp = push_word (sp, read_register (regnum));
X+   write_register (SP_REGNUM, sp);
X+ }
X+ 
X+ i386_pop_frame ()
X+ {
X+   FRAME frame = get_current_frame ();
X+   CORE_ADDR fp;
X+   int regnum;
X+   struct frame_saved_regs fsr;
X+   struct frame_info *fi;
X+   
X+   fi = get_frame_info (frame);
X+   fp = fi->frame;
X+   get_frame_saved_regs (fi, &fsr);
X+   for (regnum = 0; regnum < NUM_REGS; regnum++) 
X+     {
X+       CORE_ADDR adr;
X+       adr = fsr.regs[regnum];
X+       if (adr)
X+ 	write_register (regnum, read_memory_integer (adr, 4));
X+     }
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+ 
X+ /* this table must line up with REGISTER_NAMES in m-i386.h */
X+ /* symbols like 'EAX' come from <sys/reg.h> */
X+ static int regmap[] = 
X+ {
X+   REAX, RECX, REDX, REBX,
X+   RESP, REBP, RESI, REDI,
X+   REIP, REFL, RCS, RSS,
X+   RDS, RES, RFS, RGS,
X+ };
X+ 
X+ /* blockend is the value of u.u_ar0, and points to the
X+  * place where GS is stored
X+  */
X+ i386_register_u_addr (blockend, regnum)
X+ {
X+ #if 0
X+   /* this will be needed if fp registers are reinstated */
X+   /* for now, you can look at them with 'info float'
X+    * sys5 wont let you change them with ptrace anyway
X+    */
X+   if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM) 
X+     {
X+       int ubase, fpstate;
X+       struct user u;
X+       ubase = blockend + 4 * (SS + 1) - KSTKSZ;
X+       fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
X+       return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
X+     } 
X+   else
X+ #endif
X+     return (blockend + 4 * regmap[regnum]);
X+   
X+ }
X+ 
X+ i387_to_double (from, to)
X+      char *from;
X+      char *to;
X+ {
X+   long *lp;
X+   /* push extended mode on 387 stack, then pop in double mode
X+    *
X+    * first, set exception masks so no error is generated -
X+    * number will be rounded to inf or 0, if necessary 
X+    */
X+   asm ("pushl %eax"); 		/* grab a stack slot */
X+   asm ("fstcw (%esp)");		/* get 387 control word */
X+   asm ("movl (%esp),%eax");	/* save old value */
X+   asm ("orl $0x3f,%eax");		/* mask all exceptions */
X+   asm ("pushl %eax");
X+   asm ("fldcw (%esp)");		/* load new value into 387 */
X+   
X+   asm ("movl 8(%ebp),%eax");
X+   asm ("fldt (%eax)");		/* push extended number on 387 stack */
X+   asm ("fwait");
X+   asm ("movl 12(%ebp),%eax");
X+   asm ("fstpl (%eax)");		/* pop double */
X+   asm ("fwait");
X+   
X+   asm ("popl %eax");		/* flush modified control word */
X+   asm ("fnclex");			/* clear exceptions */
X+   asm ("fldcw (%esp)");		/* restore original control word */
X+   asm ("popl %eax");		/* flush saved copy */
X+ }
X+ 
X+ double_to_i387 (from, to)
X+      char *from;
X+      char *to;
X+ {
X+   /* push double mode on 387 stack, then pop in extended mode
X+    * no errors are possible because every 64-bit pattern
X+    * can be converted to an extended
X+    */
X+   asm ("movl 8(%ebp),%eax");
X+   asm ("fldl (%eax)");
X+   asm ("fwait");
X+   asm ("movl 12(%ebp),%eax");
X+   asm ("fstpt (%eax)");
X+   asm ("fwait");
X+ }
X+ 
X+ struct env387 
X+ {
X+   unsigned int control;
X+   unsigned int status;
X+   unsigned int tag;
X+   unsigned long eip;
X+   unsigned short code_seg;
X+   unsigned short operand_seg;
X+   unsigned long opcode;
X+   unsigned long operand;
X+   unsigned char regs[8][10];
X+ };
X+ 
X+ static
X+ print_387_control_word (control)
X+ unsigned short control;
X+ {
X+   printf ("control 0x%04x: ", control);
X+   printf ("compute to ");
X+   switch ((control >> 8) & 3) 
X+     {
X+     case 0: printf ("24 bits; "); break;
X+     case 1: printf ("(bad); "); break;
X+     case 2: printf ("53 bits; "); break;
X+     case 3: printf ("64 bits; "); break;
X+     }
X+   printf ("round ");
X+   switch ((control >> 10) & 3) 
X+     {
X+     case 0: printf ("NEAREST; "); break;
X+     case 1: printf ("DOWN; "); break;
X+     case 2: printf ("UP; "); break;
X+     case 3: printf ("CHOP; "); break;
X+     }
X+   if (control & 0x3f) 
X+     {
X+       printf ("mask:");
X+       if (control & 0x0001) printf (" INVALID");
X+       if (control & 0x0002) printf (" DENORM");
X+       if (control & 0x0004) printf (" DIVZ");
X+       if (control & 0x0008) printf (" OVERF");
X+       if (control & 0x0010) printf (" UNDERF");
X+       if (control & 0x0020) printf (" LOS");
X+       printf (";");
X+     }
X+   printf ("\n");
X+   if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
X+ 				control & 0xe080);
X+ }
X+ 
X+ static
X+ print_387_status_word (status)
X+      unsigned short status;
X+ {
X+   printf ("status 0x%04x: ", status);
X+   if (status & 0xff) 
X+     {
X+       printf ("exceptions:");
X+       if (status & 0x0001) printf (" INVALID");
X+       if (status & 0x0002) printf (" DENORM");
X+       if (status & 0x0004) printf (" DIVZ");
X+       if (status & 0x0008) printf (" OVERF");
X+       if (status & 0x0010) printf (" UNDERF");
X+       if (status & 0x0020) printf (" LOS");
X+       if (status & 0x0040) printf (" FPSTACK");
X+       printf ("; ");
X+     }
X+   printf ("flags: %d%d%d%d; ",
X+ 	  (status & 0x4000) != 0,
X+ 	  (status & 0x0400) != 0,
X+ 	  (status & 0x0200) != 0,
X+ 	  (status & 0x0100) != 0);
X+   
X+   printf ("top %d\n", (status >> 11) & 7);
X+ }
X+ 
X+ static
X+ print_387_status (ep)
X+      struct env387 *ep;
X+ {
X+   int i;
X+   int top;
X+   int fpreg;
X+   unsigned char *p;
X+   
X+   if (ep->status != 0) 
X+       print_387_status_word (ep->status);
X+   
X+   print_387_control_word (ep->control);
X+   printf ("last exception: ");
X+   printf ("opcode 0x%x; ", ep->opcode);
X+   printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip);
X+   printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand);
X+   
X+   top = (ep->status >> 11) & 7;
X+   
X+   printf ("regno  tag  msb              lsb  value\n");
X+   for (fpreg = 7; fpreg >= 0; fpreg--) 
X+     {
X+       double val;
X+       
X+       printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
X+       
X+       switch ((ep->tag >> (fpreg * 2)) & 3) 
X+ 	{
X+ 	case 0: printf ("valid "); break;
X+ 	case 1: printf ("zero  "); break;
X+ 	case 2: printf ("trap  "); break;
X+ 	case 3: printf ("empty "); break;
X+ 	}
X+       for (i = 9; i >= 0; i--)
X+ 	printf ("%02x", ep->regs[fpreg][i]);
X+       
X+       i387_to_double (ep->regs[fpreg], (char *)&val);
X+       printf ("  %g\n", val);
X+     }
X+ }
X+ 
X+ #ifndef U_FPSTATE
X+ #define U_FPSTATE(u) u.u_fps
X+ #endif
X+ 
X+ i386_float_info ()
X+ {
X+   struct user u; /* just for address computations */
X+   int i;
X+   /* fpstate defined in <sys/user.h> */
X+   struct u_fps *fpstatep;
X+   char buf[sizeof (struct u_fps) + 2 * sizeof (int)];
X+   unsigned int uaddr;
X+   char fpvalid;
X+   unsigned int rounded_addr;
X+   unsigned int rounded_size;
X+   extern int corechan;
X+   int skip;
X+   
X+   uaddr = (char *)&u.u_fpsaved - (char *)&u;
X+   if (have_inferior_p()) 
X+     {
X+       unsigned int data;
X+       unsigned int mask;
X+       
X+       rounded_addr = uaddr & -sizeof (int);
X+       data = ptrace (3, inferior_pid, rounded_addr, 0);
X+       mask = 0xff << ((uaddr - rounded_addr) * 8);
X+       
X+       fpvalid = ((data & mask) != 0);
X+     } 
X+   else 
X+     {
X+       if (lseek (corechan, uaddr, 0) < 0)
X+ 	perror ("seek on core file");
X+       if (myread (corechan, &fpvalid, 1) < 0) 
X+ 	perror ("read on core file");
X+       
X+     }
X+   
X+   if (fpvalid == 0) 
X+     {
X+       printf ("no floating point status saved\n");
X+       return;
X+     }
X+   
X+   uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
X+   if (have_inferior_p ()) 
X+     {
X+       int *ip;
X+       
X+       rounded_addr = uaddr & -sizeof (int);
X+       rounded_size = (((uaddr + sizeof (struct u_fps)) - uaddr) +
X+ 		      sizeof (int) - 1) / sizeof (int);
X+       skip = uaddr - rounded_addr;
X+       
X+       ip = (int *)buf;
X+       for (i = 0; i < rounded_size; i++) 
X+ 	{
X+ 	  *ip++ = ptrace (3, inferior_pid, rounded_addr, 0);
X+ 	  rounded_addr += sizeof (int);
X+ 	}
X+     } 
X+   else 
X+     {
X+       if (lseek (corechan, uaddr, 0) < 0)
X+ 	perror_with_name ("seek on core file");
X+       if (myread (corechan, buf, sizeof (struct u_fps)) < 0) 
X+ 	perror_with_name ("read from core file");
X+       skip = 0;
X+     }
X+   
X+   fpstatep = (struct u_fps *)(buf + skip);
X+   print_387_status ((struct env387 *)fpstatep);
X+ }
SHAR_EOF
if test 48390 -ne "`wc -c < 'gdb-x386.02'`"
then
	echo shar: error transmitting "'gdb-x386.02'" '(should have been 48390 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0