diff --git a/gas/ChangeLog b/gas/ChangeLog index 3adaae7499..2cc96695d5 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,19 @@ +2002-05-23 Alan Modra + + * write.c (size_seg): Check adjustment to last frag. + (SUB_SEGMENT_ALIGN): If HANDLE_ALIGN defined, pad out last frag to + section alignment. + * config/obj-coff.c (SUB_SEGMENT_ALIGN): Likewise. + * config/obj-ieee.c (SUB_SEGMENT_ALIGN): Likewise. + (write_object_file): Invoke md_do_align if available, and use + frag_align_code on text sections. + * config/obj-vms.h (SUB_SEGMENT_ALIGN): Now two args. + * config/tc-m88k.h (SUB_SEGMENT_ALIGN): Likewise. + * config/tc-ppc.h (SUB_SEGMENT_ALIGN): Likewise. + * config/tc-sh.h (SUB_SEGMENT_ALIGN): Likewise. + * config/tc-i386.h (SUB_SEGMENT_ALIGN): Likewise. Define for + BFD_ASSEMBLER too. + 2002-05-22 H.J. Lu * dwarf2dbg.c (dwarf2_directive_loc): Call listing_source_file diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c index 72233b81d1..c48ba63f1b 100644 --- a/gas/config/obj-coff.c +++ b/gas/config/obj-coff.c @@ -3420,6 +3420,19 @@ remove_subsegs () unsigned long machine; int coff_flags; +#ifndef SUB_SEGMENT_ALIGN +#ifdef HANDLE_ALIGN +/* The last subsegment gets an aligment corresponding to the alignment + of the section. This allows proper nop-filling at the end of + code-bearing sections. */ +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \ + (!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG) \ + ? get_recorded_alignment (SEG) : 0) +#else +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 1 +#endif +#endif + extern void write_object_file () { @@ -3443,28 +3456,27 @@ write_object_file () string_byte_count = 4; + /* Run through all the sub-segments and align them up. Also + close any open frags. We tack a .fill onto the end of the + frag chain so that any .align's size can be worked by looking + at the next frag. */ for (frchain_ptr = frchain_root; frchain_ptr != (struct frchain *) NULL; frchain_ptr = frchain_ptr->frch_next) { - /* Run through all the sub-segments and align them up. Also - close any open frags. We tack a .fill onto the end of the - frag chain so that any .align's size can be worked by looking - at the next frag. */ + int alignment; subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); -#ifndef SUB_SEGMENT_ALIGN -#define SUB_SEGMENT_ALIGN(SEG) 1 -#endif + alignment = SUB_SEGMENT_ALIGN (now_seg, frchain_ptr) + #ifdef md_do_align - md_do_align (SUB_SEGMENT_ALIGN (now_seg), (char *) NULL, 0, 0, - alignment_done); + md_do_align (alignment, (char *) NULL, 0, 0, alignment_done); #endif if (subseg_text_p (now_seg)) - frag_align_code (SUB_SEGMENT_ALIGN (now_seg), 0); + frag_align_code (alignment, 0); else - frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0); + frag_align (alignment, 0, 0); #ifdef md_do_align alignment_done: diff --git a/gas/config/obj-ieee.c b/gas/config/obj-ieee.c index 505bb3533f..1846a9240c 100644 --- a/gas/config/obj-ieee.c +++ b/gas/config/obj-ieee.c @@ -493,6 +493,20 @@ obj_symbol_new_hook (symbolP) } #if 1 + +#ifndef SUB_SEGMENT_ALIGN +#ifdef HANDLE_ALIGN +/* The last subsegment gets an aligment corresponding to the alignment + of the section. This allows proper nop-filling at the end of + code-bearing sections. */ +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \ + (!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG) \ + ? get_recorded_alignment (SEG) : 0) +#else +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 2 +#endif +#endif + extern void write_object_file () { @@ -512,20 +526,33 @@ write_object_file () subseg_set (1, 0); subseg_set (2, 0); subseg_set (3, 0); + + /* Run through all the sub-segments and align them up. Also + close any open frags. We tack a .fill onto the end of the + frag chain so that any .align's size can be worked by looking + at the next frag. */ for (frchain_ptr = frchain_root; frchain_ptr != (struct frchain *) NULL; frchain_ptr = frchain_ptr->frch_next) { - /* Run through all the sub-segments and align them up. Also - close any open frags. We tack a .fill onto the end of the - frag chain so that any .align's size can be worked by looking - at the next frag. */ + int alignment; subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); -#ifndef SUB_SEGMENT_ALIGN -#define SUB_SEGMENT_ALIGN(SEG) 2 + + alignment = SUB_SEGMENT_ALIGN (now_seg, frchain_ptr) + +#ifdef md_do_align + md_do_align (alignment, (char *) NULL, 0, 0, alignment_done); #endif - frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0); + if (subseg_text_p (now_seg)) + frag_align_code (alignment, 0); + else + frag_align (alignment, 0, 0); + +#ifdef md_do_align + alignment_done: +#endif + frag_wane (frag_now); frag_now->fr_fix = 0; know (frag_now->fr_next == NULL); diff --git a/gas/config/obj-vms.h b/gas/config/obj-vms.h index fa4f3bd8f9..ac0794f917 100644 --- a/gas/config/obj-vms.h +++ b/gas/config/obj-vms.h @@ -1,6 +1,6 @@ /* VMS object file format - Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 - Free Software Foundation, Inc. + Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000, + 2002 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -33,8 +33,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA * Doing the alignment here (on initialized data) can * mess up the calculation of global data PSECT sizes. */ -#define SUB_SEGMENT_ALIGN(SEG) \ - (((SEG) == data_section) ? 0 : LONGWORD_ALIGNMENT) +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \ + (((SEG) == data_section) ? 0 : LONGWORD_ALIGNMENT) /* This flag is used to remember whether we are in the const or the data section. By and large they are identical, but we set a no-write diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index 61b5bb909e..8af855505d 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -116,6 +116,8 @@ extern const char *i386_target_format PARAMS ((void)); extern void i386_elf_emit_arch_note PARAMS ((void)); #endif +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0 + #else /* ! BFD_ASSEMBLER */ /* COFF STUFF */ @@ -131,7 +133,7 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag)); #ifdef TE_GO32 /* DJGPP now expects some sections to be 2**4 aligned. */ -#define SUB_SEGMENT_ALIGN(SEG) \ +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \ ((strcmp (obj_segment_name (SEG), ".text") == 0 \ || strcmp (obj_segment_name (SEG), ".data") == 0 \ || strcmp (obj_segment_name (SEG), ".bss") == 0 \ @@ -141,7 +143,7 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag)); ? 4 \ : 2) #else -#define SUB_SEGMENT_ALIGN(SEG) 2 +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 2 #endif #define TC_RVA_RELOC 7 diff --git a/gas/config/tc-m88k.h b/gas/config/tc-m88k.h index ee8560584a..5b0a835152 100644 --- a/gas/config/tc-m88k.h +++ b/gas/config/tc-m88k.h @@ -1,8 +1,8 @@ /* m88k.h -- Assembler for the Motorola 88000 Contributed by Devon Bowen of Buffalo University and Torbjorn Granlund of the Swedish Institute of Computer Science. - Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 - Free Software Foundation, Inc. + Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000, + 2002 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -98,7 +98,7 @@ struct reloc_info_m88k #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif -#define SUB_SEGMENT_ALIGN(SEG) max (section_alignment[(int) (SEG)], 4) +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) max (section_alignment[(int) (SEG)], 4) /* Fill in rs_align_code fragments. */ extern void m88k_handle_align PARAMS ((fragS *)); diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index 7e513e78cd..74e77945d3 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -198,7 +198,7 @@ extern void ppc_adjust_symtab PARAMS ((void)); /* Niclas Andersson says this is needed. */ extern int ppc_subseg_align PARAMS ((void)); -#define SUB_SEGMENT_ALIGN(SEG) ppc_subseg_align() +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) ppc_subseg_align () /* We also need to copy, in particular, the class of the symbol, over what obj-coff would otherwise have copied. */ diff --git a/gas/config/tc-sh.h b/gas/config/tc-sh.h index 313ac88c1b..ffe948a7dd 100644 --- a/gas/config/tc-sh.h +++ b/gas/config/tc-sh.h @@ -152,7 +152,7 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *)); #endif /* We align most sections to a 16 byte boundary. */ -#define SUB_SEGMENT_ALIGN(SEG) \ +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \ (strncmp (SEG_NAME (SEG), ".stabstr", 8) == 0 \ ? 0 \ : ((strncmp (SEG_NAME (SEG), ".stab", 5) == 0 \ diff --git a/gas/write.c b/gas/write.c index 8d08674caa..ce3ca8d6cf 100644 --- a/gas/write.c +++ b/gas/write.c @@ -678,7 +678,14 @@ size_seg (abfd, sec, xxx) while (fragp->fr_next != last) fragp = fragp->fr_next; last->fr_address = size; - fragp->fr_offset += newsize - size; + if ((newsize - size) % fragp->fr_var == 0) + fragp->fr_offset += (newsize - size) / fragp->fr_var; + else + /* If we hit this abort, it's likely due to subsegs_finish not + providing sufficient alignment on the last frag, and the + machine dependent code using alignment frags with fr_var + greater than 1. */ + abort (); } #ifdef tc_frob_section @@ -1418,10 +1425,19 @@ set_segment_vma (abfd, sec, xxx) makes calculating their intended length trivial. */ #ifndef SUB_SEGMENT_ALIGN -#ifdef BFD_ASSEMBLER -#define SUB_SEGMENT_ALIGN(SEG) (0) +#ifdef HANDLE_ALIGN +/* The last subsegment gets an aligment corresponding to the alignment + of the section. This allows proper nop-filling at the end of + code-bearing sections. */ +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \ + (!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG) \ + ? get_recorded_alignment (SEG) : 0) #else -#define SUB_SEGMENT_ALIGN(SEG) (2) +#ifdef BFD_ASSEMBLER +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0 +#else +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 2 +#endif #endif #endif @@ -1432,14 +1448,15 @@ subsegs_finish () for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next) { - int alignment; + int alignment = 0; subseg_set (frchainP->frch_seg, frchainP->frch_subseg); /* This now gets called even if we had errors. In that case, any alignment is meaningless, and, moreover, will look weird if we are generating a listing. */ - alignment = had_errors () ? 0 : SUB_SEGMENT_ALIGN (now_seg); + if (!had_errors ()) + alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP); if (subseg_text_p (now_seg)) frag_align_code (alignment, 0);