diff options
Diffstat (limited to 'contrib/binutils/ld/ldwrite.c')
-rw-r--r-- | contrib/binutils/ld/ldwrite.c | 133 |
1 files changed, 79 insertions, 54 deletions
diff --git a/contrib/binutils/ld/ldwrite.c b/contrib/binutils/ld/ldwrite.c index eb31171..e4bec32 100644 --- a/contrib/binutils/ld/ldwrite.c +++ b/contrib/binutils/ld/ldwrite.c @@ -1,5 +1,5 @@ /* ldwrite.c -- write out the linked file - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002 + Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. Written by Steve Chamberlain sac@cygnus.com @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sysdep.h" #include "bfdlink.h" #include "libiberty.h" +#include "safe-ctype.h" #include "ld.h" #include "ldexp.h" @@ -32,15 +33,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <ldgram.h> #include "ldmain.h" -static void build_link_order PARAMS ((lang_statement_union_type *)); -static asection *clone_section PARAMS ((bfd *, asection *, const char *, int *)); -static void split_sections PARAMS ((bfd *, struct bfd_link_info *)); - /* Build link_order structures for the BFD linker. */ static void -build_link_order (statement) - lang_statement_union_type *statement; +build_link_order (lang_statement_union_type *statement) { switch (statement->header.type) { @@ -49,7 +45,7 @@ build_link_order (statement) asection *output_section; struct bfd_link_order *link_order; bfd_vma value; - boolean big_endian = false; + bfd_boolean big_endian = FALSE; output_section = statement->data_statement.output_section; ASSERT (output_section->owner == output_bfd); @@ -60,7 +56,7 @@ build_link_order (statement) link_order->type = bfd_data_link_order; link_order->offset = statement->data_statement.output_vma; - link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE); + link_order->u.data.contents = xmalloc (QUAD_SIZE); value = statement->data_statement.value; @@ -70,24 +66,24 @@ build_link_order (statement) endianness are big endian, so we must swap here if the input file is little endian. */ if (bfd_big_endian (output_bfd)) - big_endian = true; + big_endian = TRUE; else if (bfd_little_endian (output_bfd)) - big_endian = false; + big_endian = FALSE; else { - boolean swap; + bfd_boolean swap; - swap = false; + swap = FALSE; if (command_line.endian == ENDIAN_BIG) - big_endian = true; + big_endian = TRUE; else if (command_line.endian == ENDIAN_LITTLE) { - big_endian = false; - swap = true; + big_endian = FALSE; + swap = TRUE; } else if (command_line.endian == ENDIAN_UNSET) { - big_endian = true; + big_endian = TRUE; { LANG_FOR_EACH_INPUT_STATEMENT (s) { @@ -95,8 +91,8 @@ build_link_order (statement) { if (bfd_little_endian (s->the_bfd)) { - big_endian = false; - swap = true; + big_endian = FALSE; + swap = TRUE; } break; } @@ -197,9 +193,7 @@ build_link_order (statement) link_order->offset = rs->output_vma; link_order->size = bfd_get_reloc_size (rs->howto); - link_order->u.reloc.p = - ((struct bfd_link_order_reloc *) - xmalloc (sizeof (struct bfd_link_order_reloc))); + link_order->u.reloc.p = xmalloc (sizeof (struct bfd_link_order_reloc)); link_order->u.reloc.p->reloc = rs->reloc; link_order->u.reloc.p->addend = rs->addend_value; @@ -226,7 +220,7 @@ build_link_order (statement) case lang_input_section_enum: /* Create a new link_order in the output section with this attached */ - if (statement->input_section.ifile->just_syms_flag == false) + if (!statement->input_section.ifile->just_syms_flag) { asection *i = statement->input_section.section; asection *output_section = i->output_section; @@ -292,9 +286,24 @@ build_link_order (statement) } } -/* Call BFD to write out the linked file. */ +/* Return true if NAME is the name of an unsplittable section. These + are the stabs strings, dwarf strings. */ -/**********************************************************************/ +static bfd_boolean +unsplittable_name (const char *name) +{ + if (strncmp (name, ".stab", 5) == 0) + { + /* There are several stab like string sections. We pattern match on + ".stab...str" */ + unsigned len = strlen (name); + if (strcmp (&name[len-3], "str") == 0) + return TRUE; + } + else if (strcmp (name, "$GDB_STRINGS$") == 0) + return TRUE; + return FALSE; +} /* Wander around the input sections, make sure that we'll never try and create an output section with more relocs @@ -302,31 +311,53 @@ build_link_order (statement) creating new output sections with all the right bits. */ #define TESTIT 1 static asection * -clone_section (abfd, s, name, count) - bfd *abfd; - asection *s; - const char *name; - int *count; +clone_section (bfd *abfd, asection *s, const char *name, int *count) { - char templ[6]; + char *tname; char *sname; + unsigned int len; asection *n; struct bfd_link_hash_entry *h; - /* Invent a section name from the first five chars of the base - section name and a digit suffix. */ - strncpy (templ, name, sizeof (templ) - 1); - templ[sizeof (templ) - 1] = '\0'; - if ((sname = bfd_get_unique_section_name (abfd, templ, count)) == NULL + /* Invent a section name from the section name and a dotted numeric + suffix. */ + len = strlen (name); + tname = xmalloc (len + 1); + memcpy (tname, name, len + 1); + /* Remove a dotted number suffix, from a previous split link. */ + while (len && ISDIGIT (tname[len-1])) + len--; + if (len > 1 && tname[len-1] == '.') + /* It was a dotted number. */ + tname[len-1] = 0; + + /* We want to use the whole of the original section name for the + split name, but coff can be restricted to 8 character names. */ + if (bfd_family_coff (abfd) && strlen (tname) > 5) + { + /* Some section names cannot be truncated, as the name is + used to locate some other section. */ + if (strncmp (name, ".stab", 5) == 0 + || strcmp (name, "$GDB_SYMBOLS$") == 0) + { + einfo (_ ("%F%P: cannot create split section name for %s\n"), name); + /* Silence gcc warnings. einfo exits, so we never reach here. */ + return NULL; + } + tname[5] = 0; + } + + if ((sname = bfd_get_unique_section_name (abfd, tname, count)) == NULL || (n = bfd_make_section_anyway (abfd, sname)) == NULL || (h = bfd_link_hash_lookup (link_info.hash, - sname, true, true, false)) == NULL) + sname, TRUE, TRUE, FALSE)) == NULL) { einfo (_("%F%P: clone section failed: %E\n")); /* Silence gcc warnings. einfo exits, so we never reach here. */ return NULL; } - + free (tname); + /* Set up section symbol. */ h->type = bfd_link_hash_defined; h->u.def.value = 0; @@ -348,8 +379,7 @@ clone_section (abfd, s, name, count) #if TESTING static void -ds (s) - asection *s; +ds (asection *s) { struct bfd_link_order *l = s->link_order_head; printf ("vma %x size %x\n", s->vma, s->_raw_size); @@ -368,10 +398,7 @@ ds (s) printf ("\n"); } -dump (s, a1, a2) - char *s; - asection *a1; - asection *a2; +dump (char *s, asection *a1, asection *a2) { printf ("%s\n", s); ds (a1); @@ -379,8 +406,7 @@ dump (s, a1, a2) } static void -sanity_check (abfd) - bfd *abfd; +sanity_check (bfd *abfd) { asection *s; for (s = abfd->sections; s; s = s->next) @@ -403,9 +429,7 @@ sanity_check (abfd) #endif static void -split_sections (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +split_sections (bfd *abfd, struct bfd_link_info *info) { asection *original_sec; int nsecs = abfd->section_count; @@ -441,7 +465,7 @@ split_sections (abfd, info) || info->strip == strip_some) thislines = sec->lineno_count; - if (info->relocateable) + if (info->relocatable) thisrelocs = sec->reloc_count; if (sec->_cooked_size != 0) @@ -450,7 +474,7 @@ split_sections (abfd, info) thissize = sec->_raw_size; } - else if (info->relocateable + else if (info->relocatable && (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order)) thisrelocs++; @@ -458,7 +482,8 @@ split_sections (abfd, info) if (l != NULL && (thisrelocs + relocs >= config.split_by_reloc || thislines + lines >= config.split_by_reloc - || thissize + sec_size >= config.split_by_file)) + || (thissize + sec_size >= config.split_by_file)) + && !unsplittable_name (cursor->name)) { /* Create a new section and put this link order and the following link orders into it. */ @@ -524,10 +549,10 @@ split_sections (abfd, info) sanity_check (abfd); } -/**********************************************************************/ +/* Call BFD to write out the linked file. */ void -ldwrite () +ldwrite (void) { /* Reset error indicator, which can typically something like invalid format from opening up the .o files. */ |