This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: The new assembler with unwind table bug fix


On Thu, 2004-02-12 at 23:05, David Mosberger wrote:
> Then I thought I'd do some more sanity checking by compiling the Linux
> kernel with -falign-loops=32.  Unfortunately, it looks like that's
> triggering a bug:

As Alan's message points out, md_estimate_size_before_frag is wrong.

This is a problem with HJ's patch to make .align work.  If we are going
to change the size of a frag when finalizing, then we need to tell the
relaxation code about this before hand, but we don't.  This isn't too
hard to do by copying the first part of ia64_convert_frag into a new
ia64_estimate_size_before_relax function.  Then there is a related
problem that slot_index needs to compute proper sizes before we
finalize, instead of during.  I fixed this by adding a new argument to a
bunch of functions so we could pass this info down from
estimate_size_before_relax.

The result works for your testcase.  I haven't tried it on anything else
yet.  I am not happy with the code duplication between convert_frag and
estimate_size_before_frag.  This needs to be looked at.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com
Index: tc-ia64.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ia64.c,v
retrieving revision 1.100
diff -p -r1.100 tc-ia64.c
*** tc-ia64.c	7 Feb 2004 02:41:20 -0000	1.100
--- tc-ia64.c	17 Feb 2004 08:51:11 -0000
*************** static void process_unw_records PARAMS (
*** 898,906 ****
  static int calc_record_size PARAMS ((unw_rec_list *));
  static void set_imask PARAMS ((unw_rec_list *, unsigned long, unsigned long, unsigned int));
  static unsigned long slot_index PARAMS ((unsigned long, fragS *,
! 					 unsigned long, fragS *));
  static unw_rec_list *optimize_unw_records PARAMS ((unw_rec_list *));
! static void fixup_unw_records PARAMS ((unw_rec_list *));
  static int convert_expr_to_ab_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
  static int convert_expr_to_xy_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
  static void generate_unwind_image PARAMS ((const char *));
--- 898,907 ----
  static int calc_record_size PARAMS ((unw_rec_list *));
  static void set_imask PARAMS ((unw_rec_list *, unsigned long, unsigned long, unsigned int));
  static unsigned long slot_index PARAMS ((unsigned long, fragS *,
! 					 unsigned long, fragS *,
! 					 int));
  static unw_rec_list *optimize_unw_records PARAMS ((unw_rec_list *));
! static void fixup_unw_records PARAMS ((unw_rec_list *, int));
  static int convert_expr_to_ab_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
  static int convert_expr_to_xy_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
  static void generate_unwind_image PARAMS ((const char *));
*************** set_imask (region, regmask, t, type)
*** 2593,2603 ****
     containing FIRST_ADDR.  */
  
  unsigned long
! slot_index (slot_addr, slot_frag, first_addr, first_frag)
       unsigned long slot_addr;
       fragS *slot_frag;
       unsigned long first_addr;
       fragS *first_frag;
  {
    unsigned long index = 0;
  
--- 2594,2605 ----
     containing FIRST_ADDR.  */
  
  unsigned long
! slot_index (slot_addr, slot_frag, first_addr, first_frag, before_relax)
       unsigned long slot_addr;
       fragS *slot_frag;
       unsigned long first_addr;
       fragS *first_frag;
+      int before_relax;
  {
    unsigned long index = 0;
  
*************** slot_index (slot_addr, slot_frag, first_
*** 2612,2621 ****
      {
        unsigned long start_addr = (unsigned long) &first_frag->fr_literal;
  
!       if (finalize_syms)
  	{
! 	  /* We can get the final addresses only after relaxation is
! 	     done. */
  	  if (first_frag->fr_next && first_frag->fr_next->fr_address)
  	    index += 3 * ((first_frag->fr_next->fr_address
  			   - first_frag->fr_address
--- 2614,2623 ----
      {
        unsigned long start_addr = (unsigned long) &first_frag->fr_literal;
  
!       if (! before_relax)
  	{
! 	  /* We can get the final addresses only during and after
! 	     relaxation.  */
  	  if (first_frag->fr_next && first_frag->fr_next->fr_address)
  	    index += 3 * ((first_frag->fr_next->fr_address
  			   - first_frag->fr_address
*************** optimize_unw_records (list)
*** 2694,2701 ****
     within each record to generate an image.  */
  
  static void
! fixup_unw_records (list)
       unw_rec_list *list;
  {
    unw_rec_list *ptr, *region = 0;
    unsigned long first_addr = 0, rlen = 0, t;
--- 2696,2704 ----
     within each record to generate an image.  */
  
  static void
! fixup_unw_records (list, before_relax)
       unw_rec_list *list;
+      int before_relax;
  {
    unw_rec_list *ptr, *region = 0;
    unsigned long first_addr = 0, rlen = 0, t;
*************** fixup_unw_records (list)
*** 2706,2712 ****
        if (ptr->slot_number == SLOT_NUM_NOT_SET)
  	as_bad (" Insn slot not set in unwind record.");
        t = slot_index (ptr->slot_number, ptr->slot_frag,
! 		      first_addr, first_frag);
        switch (ptr->r.type)
  	{
  	case prologue:
--- 2709,2715 ----
        if (ptr->slot_number == SLOT_NUM_NOT_SET)
  	as_bad (" Insn slot not set in unwind record.");
        t = slot_index (ptr->slot_number, ptr->slot_frag,
! 		      first_addr, first_frag, before_relax);
        switch (ptr->r.type)
  	{
  	case prologue:
*************** fixup_unw_records (list)
*** 2730,2736 ****
  		  last_frag = last->slot_frag;
  		  break;
  		}
! 	    size = slot_index (last_addr, last_frag, first_addr, first_frag);
  	    rlen = ptr->r.record.r.rlen = size;
  	    if (ptr->r.type == body)
  	      /* End of region.  */
--- 2733,2740 ----
  		  last_frag = last->slot_frag;
  		  break;
  		}
! 	    size = slot_index (last_addr, last_frag, first_addr, first_frag,
! 			       before_relax);
  	    rlen = ptr->r.record.r.rlen = size;
  	    if (ptr->r.type == body)
  	      /* End of region.  */
*************** fixup_unw_records (list)
*** 2830,2835 ****
--- 2834,2867 ----
      }
  }
  
+ /* Estimate the size of a frag before relaxing.  We only have one type of frag
+    to handle here, which is the unwind info frag.  */
+ 
+ int
+ ia64_estimate_size_before_relax (fragS *frag,
+ 				 asection *segtype ATTRIBUTE_UNUSED)
+ {
+   unw_rec_list *list;
+   int len, size, pad;
+ 
+   list = (unw_rec_list *) frag->fr_opcode;
+   fixup_unw_records (list, 0);
+ 
+   len = calc_record_size (list);
+   /* pad to pointer-size boundary.  */
+   pad = len % md.pointer_size;
+   if (pad != 0)
+     len += md.pointer_size - pad;
+   /* Add 8 for the header + a pointer for the personality offset.  */
+   size = len + 8 + md.pointer_size;
+ 
+   /* fr_var carries the max_chars that we created the fragment with.
+      We must, of course, have allocated enough memory earlier.  */
+   assert (frag->fr_var >= size);
+ 
+   return frag->fr_fix + size;
+ }
+ 
  /* This function converts a rs_machine_dependent variant frag into a
    normal fill frag with the unwind image from the the record list.  */
  void
*************** ia64_convert_frag (fragS *frag)
*** 2839,2846 ****
    int len, size, pad;
    valueT flag_value;
  
    list = (unw_rec_list *) frag->fr_opcode;
!   fixup_unw_records (list);
  
    len = calc_record_size (list);
    /* pad to pointer-size boundary.  */
--- 2871,2879 ----
    int len, size, pad;
    valueT flag_value;
  
+   /* ??? This code is redundant.  */
    list = (unw_rec_list *) frag->fr_opcode;
!   fixup_unw_records (list, 0);
  
    len = calc_record_size (list);
    /* pad to pointer-size boundary.  */
*************** ia64_convert_frag (fragS *frag)
*** 2853,2858 ****
--- 2886,2892 ----
    /* fr_var carries the max_chars that we created the fragment with.
       We must, of course, have allocated enough memory earlier.  */
    assert (frag->fr_var >= size);
+   /* ??? This code is redundant.  */
  
    /* Initialize the header area. fr_offset is initialized with
       unwind.personality_routine.  */
*************** generate_unwind_image (text_name)
*** 3264,3270 ****
  
    /* Generate the unwind record.  */
    list = optimize_unw_records (unwind.list);
!   fixup_unw_records (list);
    size = calc_record_size (list);
  
    if (size > 0 || unwind.force_unwind_entry)
--- 3298,3304 ----
  
    /* Generate the unwind record.  */
    list = optimize_unw_records (unwind.list);
!   fixup_unw_records (list, 1);
    size = calc_record_size (list);
  
    if (size > 0 || unwind.force_unwind_entry)
Index: tc-ia64.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ia64.h,v
retrieving revision 1.30
diff -p -r1.30 tc-ia64.h
*** tc-ia64.h	5 Feb 2004 23:50:21 -0000	1.30
--- tc-ia64.h	17 Feb 2004 08:51:11 -0000
*************** extern void ia64_handle_align PARAMS ((f
*** 112,117 ****
--- 112,118 ----
  extern void ia64_after_parse_args PARAMS ((void));
  extern void ia64_dwarf2_emit_offset PARAMS ((symbolS *, unsigned int));
  extern void ia64_check_label PARAMS ((symbolS *));
+ extern int ia64_estimate_size_before_relax (fragS *, asection *);
  extern void ia64_convert_frag (fragS *);
  
  #define md_end()       			ia64_end_of_source ()
*************** extern void ia64_convert_frag (fragS *);
*** 132,138 ****
  #define md_create_short_jump(p,f,t,fr,s) \
  					as_fatal ("ia64_create_short_jump")
  #define md_estimate_size_before_relax(f,s) \
! 					(f)->fr_var
  #define md_elf_section_letter		ia64_elf_section_letter
  #define md_elf_section_flags		ia64_elf_section_flags
  #define TC_FIX_TYPE			struct ia64_fix
--- 133,139 ----
  #define md_create_short_jump(p,f,t,fr,s) \
  					as_fatal ("ia64_create_short_jump")
  #define md_estimate_size_before_relax(f,s) \
! 					ia64_estimate_size_before_relax(f,s)
  #define md_elf_section_letter		ia64_elf_section_letter
  #define md_elf_section_flags		ia64_elf_section_flags
  #define TC_FIX_TYPE			struct ia64_fix

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]