daily update
[binutils-gdb.git] / bfd / linker.c
index 182786e361740d5d4d43c1bf4630277fa62cea0f..b4b9f292b871dcda8e62b5d4f1190cc2b286f139 100644 (file)
@@ -1,5 +1,5 @@
 /* linker.c -- BFD linker routines
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
    Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
 
@@ -426,7 +426,7 @@ static void set_symbol_from_hash
   PARAMS ((asymbol *, struct bfd_link_hash_entry *));
 static boolean generic_add_output_symbol
   PARAMS ((bfd *, size_t *psymalloc, asymbol *));
-static boolean default_fill_link_order
+static boolean default_data_link_order
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           struct bfd_link_order *));
 static boolean default_indirect_link_order
@@ -445,28 +445,27 @@ _bfd_link_hash_newfunc (entry, table, string)
      struct bfd_hash_table *table;
      const char *string;
 {
-  struct bfd_link_hash_entry *ret = (struct bfd_link_hash_entry *) entry;
-
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct bfd_link_hash_entry *) NULL)
-    ret = ((struct bfd_link_hash_entry *)
-          bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry)));
-  if (ret == (struct bfd_link_hash_entry *) NULL)
-    return NULL;
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry));
+      if (entry == NULL)
+       return entry;
+    }
 
   /* Call the allocation method of the superclass.  */
-  ret = ((struct bfd_link_hash_entry *)
-        bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
-
-  if (ret)
+  entry = bfd_hash_newfunc (entry, table, string);
+  if (entry)
     {
+      struct bfd_link_hash_entry *h = (struct bfd_link_hash_entry *) entry;
+
       /* Initialize the local fields.  */
-      ret->type = bfd_link_hash_new;
-      ret->next = NULL;
+      h->type = bfd_link_hash_new;
+      h->next = NULL;
     }
 
-  return (struct bfd_hash_entry *) ret;
+  return entry;
 }
 
 /* Initialize a link hash table.  The BFD argument is the one
@@ -642,30 +641,29 @@ _bfd_generic_link_hash_newfunc (entry, table, string)
      struct bfd_hash_table *table;
      const char *string;
 {
-  struct generic_link_hash_entry *ret =
-    (struct generic_link_hash_entry *) entry;
-
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct generic_link_hash_entry *) NULL)
-    ret = ((struct generic_link_hash_entry *)
-          bfd_hash_allocate (table, sizeof (struct generic_link_hash_entry)));
-  if (ret == (struct generic_link_hash_entry *) NULL)
-    return NULL;
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table,
+                                sizeof (struct generic_link_hash_entry));
+      if (entry == NULL)
+       return entry;
+    }
 
   /* Call the allocation method of the superclass.  */
-  ret = ((struct generic_link_hash_entry *)
-        _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
-                                table, string));
-
-  if (ret)
+  entry = _bfd_link_hash_newfunc (entry, table, string);
+  if (entry)
     {
+      struct generic_link_hash_entry *ret;
+
       /* Set local fields.  */
+      ret = (struct generic_link_hash_entry *) entry;
       ret->written = false;
       ret->sym = NULL;
     }
 
-  return (struct bfd_hash_entry *) ret;
+  return entry;
 }
 
 /* Create an generic link hash table.  */
@@ -677,7 +675,7 @@ _bfd_generic_link_hash_table_create (abfd)
   struct generic_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct generic_link_hash_table);
 
-  ret = (struct generic_link_hash_table *) bfd_alloc (abfd, amt);
+  ret = (struct generic_link_hash_table *) bfd_malloc (amt);
   if (ret == NULL)
     return (struct bfd_link_hash_table *) NULL;
   if (! _bfd_link_hash_table_init (&ret->root, abfd,
@@ -689,6 +687,17 @@ _bfd_generic_link_hash_table_create (abfd)
   return &ret->root;
 }
 
+void
+_bfd_generic_link_hash_table_free (hash)
+     struct bfd_link_hash_table *hash;
+{
+  struct generic_link_hash_table *ret
+    = (struct generic_link_hash_table *) hash;
+
+  bfd_hash_table_free (&ret->root.table);
+  free (ret);
+}
+
 /* Grab the symbols for an object file when doing a generic link.  We
    store the symbols in the outsymbols field.  We need to keep them
    around for the entire link to ensure that we only read them once.
@@ -1421,7 +1430,7 @@ static const enum link_action link_action[8][8] =
   /* DEFW_ROW  */  {DEFW,  DEFW,  DEFW,  NOACT, NOACT, NOACT, NOACT, CYCLE },
   /* COMMON_ROW        */  {COM,   COM,   COM,   CREF,  COM,   BIG,   REFC,  WARNC },
   /* INDR_ROW  */  {IND,   IND,   IND,   MDEF,  IND,   CIND,  MIND,  CYCLE },
-  /* WARN_ROW   */  {MWARN, WARN,  WARN,  CWARN, CWARN, WARN,  CWARN, MWARN },
+  /* WARN_ROW   */  {MWARN, WARN,  WARN,  CWARN, CWARN, WARN,  CWARN, NOACT },
   /* SET_ROW   */  {SET,   SET,   SET,   SET,   SET,   SET,   CYCLE, CYCLE }
 };
 
@@ -2458,6 +2467,9 @@ _bfd_generic_link_write_global_symbol (h, data)
     (struct generic_write_global_symbol_info *) data;
   asymbol *sym;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct generic_link_hash_entry *) h->root.u.i.link;
+
   if (h->written)
     return true;
 
@@ -2610,14 +2622,13 @@ bfd_new_link_order (abfd, section)
      asection *section;
 {
   bfd_size_type amt = sizeof (struct bfd_link_order);
-  struct bfd_link_order *new = (struct bfd_link_order *) bfd_alloc (abfd, amt);
+  struct bfd_link_order *new;
+
+  new = (struct bfd_link_order *) bfd_zalloc (abfd, amt);
   if (!new)
     return NULL;
 
   new->type = bfd_undefined_link_order;
-  new->offset = 0;
-  new->size = 0;
-  new->next = (struct bfd_link_order *) NULL;
 
   if (section->link_order_tail != (struct bfd_link_order *) NULL)
     section->link_order_tail->next = new;
@@ -2639,8 +2650,6 @@ _bfd_default_link_order (abfd, info, sec, link_order)
      asection *sec;
      struct bfd_link_order *link_order;
 {
-  file_ptr loc;
-
   switch (link_order->type)
     {
     case bfd_undefined_link_order:
@@ -2651,29 +2660,23 @@ _bfd_default_link_order (abfd, info, sec, link_order)
     case bfd_indirect_link_order:
       return default_indirect_link_order (abfd, info, sec, link_order,
                                          false);
-    case bfd_fill_link_order:
-      return default_fill_link_order (abfd, info, sec, link_order);
     case bfd_data_link_order:
-      loc = link_order->offset * bfd_octets_per_byte (abfd);
-      return bfd_set_section_contents (abfd, sec,
-                                      (PTR) link_order->u.data.contents,
-                                      loc, link_order->size);
+      return default_data_link_order (abfd, info, sec, link_order);
     }
 }
 
-/* Default routine to handle a bfd_fill_link_order.  */
+/* Default routine to handle a bfd_data_link_order.  */
 
 static boolean
-default_fill_link_order (abfd, info, sec, link_order)
+default_data_link_order (abfd, info, sec, link_order)
      bfd *abfd;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      asection *sec;
      struct bfd_link_order *link_order;
 {
   bfd_size_type size;
-  unsigned char *space;
-  size_t i;
-  unsigned int fill;
+  size_t fill_size;
+  bfd_byte *fill;
   file_ptr loc;
   boolean result;
 
@@ -2683,24 +2686,37 @@ default_fill_link_order (abfd, info, sec, link_order)
   if (size == 0)
     return true;
 
-  space = (unsigned char *) bfd_malloc (size);
-  if (space == NULL)
-    return false;
-
-  fill = link_order->u.fill.value;
-  for (i = 0; i < size; i += 4)
-    space[i] = fill >> 24;
-  for (i = 1; i < size; i += 4)
-    space[i] = fill >> 16;
-  for (i = 2; i < size; i += 4)
-    space[i] = fill >> 8;
-  for (i = 3; i < size; i += 4)
-    space[i] = fill;
+  fill = link_order->u.data.contents;
+  fill_size = link_order->u.data.size;
+  if (fill_size != 0 && fill_size < size)
+    {
+      bfd_byte *p;
+      fill = (bfd_byte *) bfd_malloc (size);
+      if (fill == NULL)
+       return false;
+      p = fill;
+      if (fill_size == 1)
+       memset (p, (int) link_order->u.data.contents[0], (size_t) size);
+      else
+       {
+         do
+           {
+             memcpy (p, link_order->u.data.contents, fill_size);
+             p += fill_size;
+             size -= fill_size;
+           }
+         while (size >= fill_size);
+         if (size != 0)
+           memcpy (p, link_order->u.data.contents, (size_t) size);
+         size = link_order->size;
+       }
+    }
 
   loc = link_order->offset * bfd_octets_per_byte (abfd);
-  result = bfd_set_section_contents (abfd, sec, space, loc, size);
+  result = bfd_set_section_contents (abfd, sec, fill, loc, size);
 
-  free (space);
+  if (fill != link_order->u.data.contents)
+    free (fill);
   return result;
 }