[PATCH] S/390 bi-arch debugging support

Ulrich Weigand weigand@i1.informatik.uni-erlangen.de
Thu Dec 4 20:10:00 GMT 2003


Hello,

this patch adds support for debugging 32-bit applications running
under a 64-bit kernel from within a 64-bit gdb.

This involves only a minor change in s390-nat.c to convert register
values between 64-bit and 32-bit formats, and installing a
solib_svr4_fetch_link_map_offsets handler.

Tested on s390-ibm-linux and s390x-ibm-linux with no new regressions.

When running the test suite in 32-bit mode (i.e.
  make check RUNTESTFLAGS="CC_FOR_TARGET='gcc -m31' ..."), 
several test cases are still failing:

- asm-source.exp because it uses the wrong assembler file
  (I didn't bother to fix that)

- dump.exp because it gets confused by a 32/64-bit size mismatch:
  it computes a difference between two target addresses (which
  happens to be negative), prints this using "/x" so that it gets
  converted to a *32-bit* unsigned hex value on 32-bit targets.  
  This is then used as argument to the 'restore' command, which 
  interprets its argument as *64-bit* unsigned long value on 
  64-bit hosts, and performs a 64-bit addition to arrive at the
  (now incorrect) destination address.

  I've simply changed the test case to use decimal representation
  for the offset, which includes the sign -- then everything gets
  computed correctly.  If you think the test case should work
  fine as is and gdb needs to be fixed, just ignore that part
  of the patch.

- gcore.exp because generate-core writes 64-bit style NOTEs into 
  a 32-bit format core dump file.  This is because gdb calls into 
  bfd's elfcore_write_prpsinfo, which always writes a NOTE in the
  current host's format without checking the target at all.

  I guess this needs to be fixed in bfd.

- All multi-threaded test cases fail.  This is because they use
  the proc-service API implemented in linuxthreads_db, and this
  appears to be fundamentally unsuited to handle 32-bit processes
  on a 64-bit host ...   I have no idea what to do here.


Bye,
Ulrich


ChangeLog:

	* s390-nat.c (supply_gregset, fill_gregset): Handle debugging
	of 32-bit exectuables running under a 64-bit kernel.
	* s390-tdep.c: Include "solib-svr4.h".
	(s390_svr4_fetch_link_map_offset): New function.
	(s390x_svr_fetch_link_map_offset): Likewise.
	(s390_gdbarch_init): Call set_solib_svr4_fetch_link_map_offsets.
	* Makefile.in (s390-tdep.o): Update dependencies.

testsuite/ChangeLog:

	* gdb.base/dump.exp: Handle negative offsets in decimal, not hex.


diff -c -p -r gdb-head/gdb/Makefile.in gdb-head-new/gdb/Makefile.in
*** gdb-head/gdb/Makefile.in	Wed Dec  3 23:50:44 2003
--- gdb-head-new/gdb/Makefile.in	Thu Dec  4 03:14:20 2003
*************** s390-tdep.o: s390-tdep.c $(defs_h) $(arc
*** 2254,2260 ****
  	$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \
  	$(objfiles_h) $(tm_h) $(__bfd_bfd_h) $(floatformat_h) $(regcache_h) \
  	$(trad_frame_h) $(frame_base_h) $(frame_unwind_h) $(dwarf2_frame_h) \
! 	$(reggroups_h) $(regset_h) $(value_h) $(gdb_assert_h) $(dis_asm_h)
  scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
  	$(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \
  	$(scm_tags_h)
--- 2254,2261 ----
  	$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \
  	$(objfiles_h) $(tm_h) $(__bfd_bfd_h) $(floatformat_h) $(regcache_h) \
  	$(trad_frame_h) $(frame_base_h) $(frame_unwind_h) $(dwarf2_frame_h) \
! 	$(reggroups_h) $(regset_h) $(value_h) $(gdb_assert_h) $(dis_asm_h) \
! 	$(solib_svr4_h)
  scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
  	$(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \
  	$(scm_tags_h)
diff -c -p -r gdb-head/gdb/s390-nat.c gdb-head-new/gdb/s390-nat.c
*** gdb-head/gdb/s390-nat.c	Thu Dec  4 03:09:05 2003
--- gdb-head-new/gdb/s390-nat.c	Thu Dec  4 03:08:58 2003
*************** supply_gregset (gregset_t *regp)
*** 112,118 ****
    int i;
    for (i = 0; i < s390_gregset_regmap_len; i++)
      if (s390_gregset_regmap[i] != -1)
!       supply_register (i, (char *)regp + s390_gregset_regmap[i]);
  }
  
  /* Fill register REGNO (if it is a general-purpose register) in
--- 112,128 ----
    int i;
    for (i = 0; i < s390_gregset_regmap_len; i++)
      if (s390_gregset_regmap[i] != -1)
!       {
! 	char *ptr = (char *)regp + s390_gregset_regmap[i];
! #ifdef __s390x__
! 	  /* When debugging a 32-bit executable running under a 64-bit kernel,
! 	     we have to fix up the 64-bit registers we get from the kernel
! 	     to make them look like 32-bit registers.  */
! 	  if (TARGET_PTR_BIT == 32 && i < 18)
! 	    ptr += (i == 0) ? 0 : 4;
! #endif
! 	supply_register (i, ptr);
!       }
  }
  
  /* Fill register REGNO (if it is a general-purpose register) in
*************** fill_gregset (gregset_t *regp, int regno
*** 125,131 ****
    for (i = 0; i < s390_gregset_regmap_len; i++)
      if (s390_gregset_regmap[i] != -1)
        if (regno == -1 || regno == i)
! 	regcache_collect (i, (char *)regp + s390_gregset_regmap[i]);
  }
  
  /* Fill GDB's register array with the floating-point register values
--- 135,151 ----
    for (i = 0; i < s390_gregset_regmap_len; i++)
      if (s390_gregset_regmap[i] != -1)
        if (regno == -1 || regno == i)
! 	{
! 	  char *ptr = (char *)regp + s390_gregset_regmap[i];
! #ifdef __s390x__
! 	  /* When debugging a 32-bit executable running under a 64-bit kernel,
! 	     we have to fix up the 32-bit registers we get from the debugger
! 	     to make them look like 64-bit registers.  */
! 	  if (TARGET_PTR_BIT == 32 && i < 18)
! 	    ptr += (i == 0) ? 0 : 4;
! #endif
!           regcache_collect (i, ptr);
! 	}
  }
  
  /* Fill GDB's register array with the floating-point register values
diff -c -p -r gdb-head/gdb/s390-tdep.c gdb-head-new/gdb/s390-tdep.c
*** gdb-head/gdb/s390-tdep.c	Thu Dec  4 03:09:05 2003
--- gdb-head-new/gdb/s390-tdep.c	Thu Dec  4 00:08:03 2003
***************
*** 45,50 ****
--- 45,51 ----
  #include "value.h"
  #include "gdb_assert.h"
  #include "dis-asm.h"
+ #include "solib-svr4.h"         /* For struct link_map_offsets.  */
  
  
  
*************** s390_address_class_name_to_type_flags (s
*** 2957,2962 ****
--- 2958,3032 ----
  }
  
  
+ /* Link map offsets.  */
+ 
+ static struct link_map_offsets *
+ s390_svr4_fetch_link_map_offsets (void)
+ {
+   static struct link_map_offsets lmo;
+   static struct link_map_offsets *lmp = NULL;
+ 
+   if (lmp == NULL)
+     {
+       lmp = &lmo;
+ 
+       lmo.r_debug_size = 8;
+ 
+       lmo.r_map_offset = 4;
+       lmo.r_map_size   = 4;
+ 
+       lmo.link_map_size = 20;
+ 
+       lmo.l_addr_offset = 0;
+       lmo.l_addr_size   = 4;
+ 
+       lmo.l_name_offset = 4;
+       lmo.l_name_size   = 4;
+ 
+       lmo.l_next_offset = 12;
+       lmo.l_next_size   = 4;
+ 
+       lmo.l_prev_offset = 16;
+       lmo.l_prev_size   = 4;
+     }
+ 
+   return lmp;
+ }
+ 
+ static struct link_map_offsets *
+ s390x_svr4_fetch_link_map_offsets (void)
+ {
+   static struct link_map_offsets lmo;
+   static struct link_map_offsets *lmp = NULL;
+ 
+   if (lmp == NULL)
+     {
+       lmp = &lmo;
+ 
+       lmo.r_debug_size = 16;   /* All we need.  */
+ 
+       lmo.r_map_offset = 8;
+       lmo.r_map_size   = 8;
+ 
+       lmo.link_map_size = 40;   /* All we need.  */
+ 
+       lmo.l_addr_offset = 0;
+       lmo.l_addr_size   = 8;
+ 
+       lmo.l_name_offset = 8;
+       lmo.l_name_size   = 8;
+ 
+       lmo.l_next_offset = 24;
+       lmo.l_next_size   = 8;
+ 
+       lmo.l_prev_offset = 32;
+       lmo.l_prev_size   = 8;
+     }
+ 
+   return lmp;
+ }
+ 
+ 
  /* Set up gdbarch struct.  */
  
  static struct gdbarch *
*************** s390_gdbarch_init (struct gdbarch_info i
*** 3043,3048 ****
--- 3113,3121 ----
        set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove);
        set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
        set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write);
+       set_solib_svr4_fetch_link_map_offsets (gdbarch,
+ 					     s390_svr4_fetch_link_map_offsets);
+ 
        break;
      case bfd_mach_s390_64:
        tdep->abi = ABI_LINUX_ZSERIES;
*************** s390_gdbarch_init (struct gdbarch_info i
*** 3057,3062 ****
--- 3130,3137 ----
        set_gdbarch_ptr_bit (gdbarch, 64);
        set_gdbarch_pseudo_register_read (gdbarch, s390x_pseudo_register_read);
        set_gdbarch_pseudo_register_write (gdbarch, s390x_pseudo_register_write);
+       set_solib_svr4_fetch_link_map_offsets (gdbarch,
+ 					     s390x_svr4_fetch_link_map_offsets);
        set_gdbarch_address_class_type_flags (gdbarch,
                                              s390_address_class_type_flags);
        set_gdbarch_address_class_type_flags_to_name (gdbarch,
diff -c -p -r gdb-head/gdb/testsuite/gdb.base/dump.exp gdb-head-new/gdb/testsuite/gdb.base/dump.exp
*** gdb-head/gdb/testsuite/gdb.base/dump.exp	Thu Dec  4 03:09:05 2003
--- gdb-head-new/gdb/testsuite/gdb.base/dump.exp	Thu Dec  4 00:08:03 2003
*************** test_restore_saved_value "intstr2.bin bi
*** 353,361 ****
  set array2_start   [capture_value "/x &intarray2\[0\]"]
  set struct2_start  [capture_value "/x &intstruct2"]
  set array2_offset  \
! 	[capture_value "/x (char *) &intarray2 - (char *) &intarray"]
  set struct2_offset \
! 	[capture_value "/x (char *) &intstruct2 - (char *) &intstruct"]
  
  gdb_test "print zero_all ()" ""
  
--- 353,361 ----
  set array2_start   [capture_value "/x &intarray2\[0\]"]
  set struct2_start  [capture_value "/x &intstruct2"]
  set array2_offset  \
! 	[capture_value "(char *) &intarray2 - (char *) &intarray"]
  set struct2_offset \
! 	[capture_value "(char *) &intstruct2 - (char *) &intstruct"]
  
  gdb_test "print zero_all ()" ""
  
-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de



More information about the Gdb-patches mailing list