diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 95532c4f98..6a8758ca28 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +1999-08-08 Mark Elbrecht + + * libcoff-in.h (struct coff_section_alignment_entry): Define. + * coffcode.h (coff_set_custom_section_alignment): New static + function. + (coff_section_alignment_table): New static array. + (coff_new_section_hook): Use coff_set_customer_section_alignment. + * coff-go32.c (COFF_SECTION_ALIGNMENT_ENTRIES): Define. + * coff-stgo32.c (COFF_SECTION_ALIGNMENT_ENTRIES): Define. + * libcoff.h: Rebuild. + 1999-08-08 Ian Lance Taylor * Makefile.am: Rename .dep* files to DEP*. Change DEP variable to diff --git a/bfd/coff-go32.c b/bfd/coff-go32.c index 0b783a07a7..15b4e36a09 100644 --- a/bfd/coff-go32.c +++ b/bfd/coff-go32.c @@ -24,4 +24,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define COFF_LONG_SECTION_NAMES #define COFF_SUPPORT_GNU_LINKONCE +#define COFF_SECTION_ALIGNMENT_ENTRIES \ +{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ +{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.d"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ +{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.t"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ +{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.r"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 } + #include "coff-i386.c" diff --git a/bfd/coff-stgo32.c b/bfd/coff-stgo32.c index 9115e3c818..26dba40b5e 100644 --- a/bfd/coff-stgo32.c +++ b/bfd/coff-stgo32.c @@ -42,6 +42,12 @@ #define COFF_LONG_SECTION_NAMES #define COFF_SUPPORT_GNU_LINKONCE +#define COFF_SECTION_ALIGNMENT_ENTRIES \ +{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 } + #include "bfd.h" /* At first the prototypes */ diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 301e5f79c0..1f393946dc 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -315,6 +315,9 @@ CODE_FRAGMENT static long sec_to_styp_flags PARAMS ((const char *, flagword)); static flagword styp_to_sec_flags PARAMS ((bfd *, PTR, const char *)); static boolean coff_bad_format_hook PARAMS ((bfd *, PTR)); +static void coff_set_custom_section_alignment + PARAMS ((bfd *, asection *, const struct coff_section_alignment_entry *, + unsigned int)); static boolean coff_new_section_hook PARAMS ((bfd *, asection *)); static boolean coff_set_arch_mach_hook PARAMS ((bfd *, PTR)); static boolean coff_write_relocs PARAMS ((bfd *, int)); @@ -1076,15 +1079,73 @@ coff_bad_format_hook (abfd, filehdr) return true; } -/* - initialize a section structure with information peculiar to this - particular implementation of coff -*/ +/* Check whether this section uses an alignment other than the + default. */ + +static void +coff_set_custom_section_alignment (abfd, section, alignment_table, table_size) + bfd *abfd ATTRIBUTE_UNUSED; + asection *section; + const struct coff_section_alignment_entry *alignment_table; + const unsigned int table_size; +{ + const unsigned int default_alignment = COFF_DEFAULT_SECTION_ALIGNMENT_POWER; + unsigned int i; + + for (i = 0; i < table_size; ++i) + { + const char *secname = bfd_get_section_name (abfd, section); + if (alignment_table[i].comparison_length == (unsigned int) -1 + ? strcmp (alignment_table[i].name, secname) == 0 + : strncmp (alignment_table[i].name, secname, + alignment_table[i].comparison_length) == 0) + break; + } + if (i >= table_size) + return; + + if (alignment_table[i].default_alignment_min != COFF_ALIGNMENT_FIELD_EMPTY + && default_alignment < alignment_table[i].default_alignment_min) + return; + + if (alignment_table[i].default_alignment_max != COFF_ALIGNMENT_FIELD_EMPTY + && default_alignment > alignment_table[i].default_alignment_max) + return; + + section->alignment_power = alignment_table[i].alignment_power; +} + +/* Custom section alignment records. */ + +static const struct coff_section_alignment_entry +coff_section_alignment_table[] = +{ +#ifdef COFF_SECTION_ALIGNMENT_ENTRIES + COFF_SECTION_ALIGNMENT_ENTRIES, +#endif + /* There must not be any gaps between .stabstr sections. */ + { COFF_SECTION_NAME_PARTIAL_MATCH (".stabstr"), + 1, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, + /* The .stab section must be aligned to 2**2 at most, to avoid gaps. */ + { COFF_SECTION_NAME_PARTIAL_MATCH (".stab"), + 3, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, + /* Similarly for the .ctors and .dtors sections. */ + { COFF_SECTION_NAME_EXACT_MATCH (".ctors"), + 3, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, + { COFF_SECTION_NAME_EXACT_MATCH (".dtors"), + 3, COFF_ALIGNMENT_FIELD_EMPTY, 2 } +}; + +static const unsigned int coff_section_alignment_table_size = + sizeof coff_section_alignment_table / sizeof coff_section_alignment_table[0]; + +/* Initialize a section structure with information peculiar to this + particular implementation of COFF. */ static boolean coff_new_section_hook (abfd, section) - bfd * abfd; - asection * section; + bfd *abfd; + asection *section; { combined_entry_type *native; @@ -1120,22 +1181,9 @@ coff_new_section_hook (abfd, section) coffsymbol (section->symbol)->native = native; - /* The .stab section must be aligned to 2**2 at most, because - otherwise there may be gaps in the section which gdb will not - know how to interpret. Examining the section name is a hack, but - that is also how gdb locates the section. - We need to handle the .ctors and .dtors sections similarly, to - avoid introducing null words in the tables. */ - if (COFF_DEFAULT_SECTION_ALIGNMENT_POWER > 2 - && (strncmp (section->name, ".stab", 5) == 0 - || strcmp (section->name, ".ctors") == 0 - || strcmp (section->name, ".dtors") == 0)) - section->alignment_power = 2; - - /* Similarly, the .stabstr section must be aligned to 2**0 at most. */ - if (COFF_DEFAULT_SECTION_ALIGNMENT_POWER > 0 - && strncmp (section->name, ".stabstr", 8) == 0) - section->alignment_power = 0; + coff_set_custom_section_alignment (abfd, section, + coff_section_alignment_table, + coff_section_alignment_table_size); return true; } diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h index dae881f288..a0362ca9f1 100644 --- a/bfd/libcoff-in.h +++ b/bfd/libcoff-in.h @@ -1,5 +1,5 @@ /* BFD COFF object file private structure. - Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 1998 + Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. Written by Cygnus Support. @@ -467,6 +467,41 @@ struct coff_final_link_info struct internal_reloc *internal_relocs; }; +/* Most COFF variants have no way to record the alignment of a + section. This struct is used to set a specific alignment based on + the name of the section. */ + +struct coff_section_alignment_entry +{ + /* The section name. */ + const char *name; + + /* This is either (unsigned int) -1, indicating that the section + name must match exactly, or it is the number of letters which + must match at the start of the name. */ + unsigned int comparison_length; + + /* These macros may be used to fill in the first two fields in a + structure initialization. */ +#define COFF_SECTION_NAME_EXACT_MATCH(name) (name), ((unsigned int) -1) +#define COFF_SECTION_NAME_PARTIAL_MATCH(name) (name), (sizeof (name) - 1) + + /* Only use this entry if the default section alignment for this + target is at least that much (as a power of two). If this field + is COFF_ALIGNMENT_FIELD_EMPTY, it should be ignored. */ + unsigned int default_alignment_min; + + /* Only use this entry if the default section alignment for this + target is no greater than this (as a power of two). If this + field is COFF_ALIGNMENT_FIELD_EMPTY, it should be ignored. */ + unsigned int default_alignment_max; + +#define COFF_ALIGNMENT_FIELD_EMPTY ((unsigned int) -1) + + /* The desired alignment for this section (as a power of two). */ + unsigned int alignment_power; +}; + extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); extern boolean _bfd_coff_link_hash_table_init diff --git a/bfd/libcoff.h b/bfd/libcoff.h index 229668ed58..fb3d5be73d 100644 --- a/bfd/libcoff.h +++ b/bfd/libcoff.h @@ -1,5 +1,5 @@ /* BFD COFF object file private structure. - Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 1998 + Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. Written by Cygnus Support. @@ -467,6 +467,41 @@ struct coff_final_link_info struct internal_reloc *internal_relocs; }; +/* Most COFF variants have no way to record the alignment of a + section. This struct is used to set a specific alignment based on + the name of the section. */ + +struct coff_section_alignment_entry +{ + /* The section name. */ + const char *name; + + /* This is either (unsigned int) -1, indicating that the section + name must match exactly, or it is the number of letters which + must match at the start of the name. */ + unsigned int comparison_length; + + /* These macros may be used to fill in the first two fields in a + structure initialization. */ +#define COFF_SECTION_NAME_EXACT_MATCH(name) (name), ((unsigned int) -1) +#define COFF_SECTION_NAME_PARTIAL_MATCH(name) (name), (sizeof (name) - 1) + + /* Only use this entry if the default section alignment for this + target is at least that much (as a power of two). If this field + is COFF_ALIGNMENT_FIELD_EMPTY, it should be ignored. */ + unsigned int default_alignment_min; + + /* Only use this entry if the default section alignment for this + target is no greater than this (as a power of two). If this + field is COFF_ALIGNMENT_FIELD_EMPTY, it should be ignored. */ + unsigned int default_alignment_max; + +#define COFF_ALIGNMENT_FIELD_EMPTY ((unsigned int) -1) + + /* The desired alignment for this section (as a power of two). */ + unsigned int alignment_power; +}; + extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); extern boolean _bfd_coff_link_hash_table_init