+ *psb = elf_gp (output_bfd);
+ return bfd_reloc_ok;
+}
+\f
+/* Return size of a PLT entry. */
+#define elf_m32r_sizeof_plt(info) PLT_ENTRY_SIZE
+
+/* The m32r linker needs to keep track of the number of relocs that it
+ decides to copy in check_relocs for each symbol. This is so that
+ it can discard PC relative relocs if it doesn't need them when
+ linking with -Bsymbolic. We store the information in a field
+ extending the regular ELF linker hash table. */
+
+/* This structure keeps track of the number of PC relative relocs we
+ have copied for a given symbol. */
+
+struct elf_m32r_pcrel_relocs_copied
+{
+ /* Next section. */
+ struct elf_m32r_pcrel_relocs_copied *next;
+ /* A section in dynobj. */
+ asection *section;
+ /* Number of relocs copied in this section. */
+ bfd_size_type count;
+};
+
+/* The sh linker needs to keep track of the number of relocs that it
+ decides to copy as dynamic relocs in check_relocs for each symbol.
+ This is so that it can later discard them if they are found to be
+ unnecessary. We store the information in a field extending the
+ regular ELF linker hash table. */
+
+struct elf_m32r_dyn_relocs
+{
+ struct elf_m32r_dyn_relocs *next;
+
+ /* The input section of the reloc. */
+ asection *sec;
+
+ /* Total number of relocs copied for the input section. */
+ bfd_size_type count;
+
+ /* Number of pc-relative relocs copied for the input section. */
+ bfd_size_type pc_count;
+};
+
+
+/* m32r ELF linker hash entry. */
+
+struct elf_m32r_link_hash_entry
+{
+ struct elf_link_hash_entry root;
+
+ /* Track dynamic relocs copied for this symbol. */
+ struct elf_m32r_dyn_relocs *dyn_relocs;
+
+// bfd_signed_vma gotplt_refcount;
+
+ /* Number of PC relative relocs copied for this symbol. */
+ /* struct elf_m32r_pcrel_relocs_copied *pcrel_relocs_copied; FIXME */
+};
+
+/* m32r ELF linker hash table. */
+
+struct elf_m32r_link_hash_table
+{
+ struct elf_link_hash_table root;
+
+ /* Short-cuts to get to dynamic linker sections. */
+ asection *sgot;
+ asection *sgotplt;
+ asection *srelgot;
+ asection *splt;
+ asection *srelplt;
+ asection *sdynbss;
+ asection *srelbss;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
+};
+
+/* Traverse an m32r ELF linker hash table. */
+
+#define m32r_elf_link_hash_traverse(table, func, info) \
+ (elf_link_hash_traverse \
+ (&(table)->root, \
+ (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the m32r ELF linker hash table from a link_info structure. */
+
+
+#define m32r_elf_hash_table(p) \
+ ((struct elf_m32r_link_hash_table *) ((p)->hash))
+
+/* Create an entry in an m32r ELF linker hash table. */
+static struct bfd_hash_entry *
+m32r_elf_link_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char * );
+
+static struct bfd_hash_entry *
+m32r_elf_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct elf_m32r_link_hash_entry *ret =
+ (struct elf_m32r_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct elf_m32r_link_hash_entry *) NULL)
+ ret = ((struct elf_m32r_link_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct elf_m32r_link_hash_entry)));
+ if (ret == (struct elf_m32r_link_hash_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct elf_m32r_link_hash_entry *)
+ _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != (struct elf_m32r_link_hash_entry *) NULL)
+ {
+ struct elf_m32r_link_hash_entry *eh;
+
+ eh = (struct elf_m32r_link_hash_entry *) ret;
+ eh->dyn_relocs = NULL;
+// eh->gotplt_refcount = 0;
+ /* eh->pcrel_relocs_copied = NULL; FIXME */
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create an m32r ELF linker hash table. */
+static struct bfd_link_hash_table *m32r_elf_link_hash_table_create (bfd *);
+
+static struct bfd_link_hash_table *
+m32r_elf_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct elf_m32r_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct elf_m32r_link_hash_table);
+
+ ret = (struct elf_m32r_link_hash_table *) bfd_malloc (amt);
+ if (ret == (struct elf_m32r_link_hash_table *) NULL)
+ return NULL;
+
+ if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+ m32r_elf_link_hash_newfunc))
+ {
+ free (ret);
+ return NULL;
+ }
+
+ ret->sgot = NULL;
+ ret->sgotplt = NULL;
+ ret->srelgot = NULL;
+ ret->splt = NULL;
+ ret->srelplt = NULL;
+ ret->sdynbss = NULL;
+ ret->srelbss = NULL;
+ ret->sym_sec.abfd = NULL;
+
+ return &ret->root.root;
+}
+
+/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
+ shortcuts to them in our hash table. */
+static bfd_boolean create_got_section (bfd *, struct bfd_link_info *);
+
+static bfd_boolean
+create_got_section (dynobj, info)
+ bfd *dynobj;
+ struct bfd_link_info *info;
+{
+ struct elf_m32r_link_hash_table *htab;
+
+ if (! _bfd_elf_create_got_section (dynobj, info))
+ return FALSE;
+
+ htab = m32r_elf_hash_table (info);
+ htab->sgot = bfd_get_section_by_name (dynobj, ".got");
+ htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+ if (! htab->sgot || ! htab->sgotplt)
+ abort ();
+
+ htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY));
+ if (htab->srelgot == NULL
+ || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Create dynamic sections when linking against a dynamic object. */
+
+static bfd_boolean
+m32r_elf_create_dynamic_sections (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ struct elf_m32r_link_hash_table *htab;
+ flagword flags, pltflags;
+ register asection *s;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int ptralign = 2; /* 32bit */
+
+ htab = m32r_elf_hash_table (info);
+
+ /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+ .rel[a].bss sections. */
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+
+ pltflags = flags;
+ pltflags |= SEC_CODE;
+ if (bed->plt_not_loaded)
+ pltflags &= ~ (SEC_LOAD | SEC_HAS_CONTENTS);
+ if (bed->plt_readonly)
+ pltflags |= SEC_READONLY;
+
+ s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
+ htab->splt = s;
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+ return FALSE;
+
+ if (bed->want_plt_sym)
+ {
+ /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
+ .plt section. */
+ struct bfd_link_hash_entry *bh = NULL;
+ struct elf_link_hash_entry *h;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
+ (bfd_vma) 0, (const char *) NULL, FALSE,
+ get_elf_backend_data (abfd)->collect, &bh)))
+ return FALSE;
+ h = (struct elf_link_hash_entry *) bh;
+ h->def_regular = 1;
+ h->type = STT_OBJECT;
+
+ if (info->shared
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ s = bfd_make_section_with_flags (abfd,
+ bed->default_use_rela_p ? ".rela.plt" : ".rel.plt",
+ flags | SEC_READONLY);
+ htab->srelplt = s;
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, ptralign))
+ return FALSE;
+
+ if (htab->sgot == NULL
+ && ! create_got_section (abfd, info))
+ return FALSE;
+
+ {
+ const char *secname;
+ char *relname;
+ flagword secflags;
+ asection *sec;
+
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ secflags = bfd_get_section_flags (abfd, sec);
+ if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
+ || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
+ continue;
+ secname = bfd_get_section_name (abfd, sec);
+ relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6);
+ strcpy (relname, ".rela");
+ strcat (relname, secname);
+ if (bfd_get_section_by_name (abfd, secname))
+ continue;
+ s = bfd_make_section_with_flags (abfd, relname,
+ flags | SEC_READONLY);
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, ptralign))
+ return FALSE;
+ }
+ }
+
+ if (bed->want_dynbss)
+ {
+ /* The .dynbss section is a place to put symbols which are defined
+ by dynamic objects, are referenced by regular objects, and are
+ not functions. We must allocate space for them in the process
+ image and use a R_*_COPY reloc to tell the dynamic linker to
+ initialize them at run time. The linker script puts the .dynbss
+ section into the .bss section of the final image. */
+ s = bfd_make_section_with_flags (abfd, ".dynbss",
+ SEC_ALLOC | SEC_LINKER_CREATED);
+ htab->sdynbss = s;
+ if (s == NULL)
+ return FALSE;
+ /* The .rel[a].bss section holds copy relocs. This section is not
+ normally needed. We need to create it here, though, so that the
+ linker will map it to an output section. We can't just create it
+ only if we need it, because we will not know whether we need it
+ until we have seen all the input files, and the first time the
+ main linker code calls BFD after examining all the input files
+ (size_dynamic_sections) the input sections have already been
+ mapped to the output sections. If the section turns out not to
+ be needed, we can discard it later. We will never need this
+ section when generating a shared object, since they do not use
+ copy relocs. */
+ if (! info->shared)
+ {
+ s = bfd_make_section_with_flags (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.bss" : ".rel.bss"),
+ flags | SEC_READONLY);
+ htab->srelbss = s;
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, ptralign))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Copy the extra info we tack onto an elf_link_hash_entry. */
+static void m32r_elf_copy_indirect_symbol (const struct elf_backend_data *,
+ struct elf_link_hash_entry *,
+ struct elf_link_hash_entry *);
+
+static void
+m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
+ struct elf_link_hash_entry *dir,
+ struct elf_link_hash_entry *ind)
+{
+ struct elf_m32r_link_hash_entry *edir, *eind;
+
+ edir = (struct elf_m32r_link_hash_entry *) dir;
+ eind = (struct elf_m32r_link_hash_entry *) ind;
+
+ if (eind->dyn_relocs != NULL)
+ {
+ if (edir->dyn_relocs != NULL)
+ {
+ struct elf_m32r_dyn_relocs **pp;
+ struct elf_m32r_dyn_relocs *p;
+
+ if (ind->root.type == bfd_link_hash_indirect)
+ abort ();
+
+ /* Add reloc counts against the weak sym to the strong sym
+ list. Merge any entries against the same section. */
+ for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
+ {
+ struct elf_m32r_dyn_relocs *q;
+
+ for (q = edir->dyn_relocs; q != NULL; q = q->next)
+ if (q->sec == p->sec)
+ {
+ q->pc_count += p->pc_count;
+ q->count += p->count;
+ *pp = p->next;
+ break;
+ }
+ if (q == NULL)
+ pp = &p->next;
+ }
+ *pp = edir->dyn_relocs;
+ }
+
+ edir->dyn_relocs = eind->dyn_relocs;
+ eind->dyn_relocs = NULL;
+ }
+
+// if (ind->root.type == bfd_link_hash_indirect
+// && dir->got.refcount <= 0)
+// {
+// edir->tls_type = eind->tls_type;
+// eind->tls_type = GOT_UNKNOWN;
+// }
+ _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+}
+
+\f
+/* Adjust a symbol defined by a dynamic object and referenced by a
+ regular object. The current definition is in some section of the
+ dynamic object, but we're not including those sections. We have to
+ change the definition to something the rest of the link can
+ understand. */
+
+static bfd_boolean
+m32r_elf_adjust_dynamic_symbol (info, h)
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+{
+ struct elf_m32r_link_hash_table *htab;
+ struct elf_m32r_link_hash_entry *eh;
+ struct elf_m32r_dyn_relocs *p;
+ bfd *dynobj;
+ asection *s;
+ unsigned int power_of_two;
+
+#ifdef DEBUG_PIC
+printf("m32r_elf_adjust_dynamic_symbol()\n");
+#endif
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ /* Make sure we know what is going on here. */
+ BFD_ASSERT (dynobj != NULL
+ && (h->needs_plt
+ || h->u.weakdef != NULL
+ || (h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular)));
+
+
+ /* If this is a function, put it in the procedure linkage table. We
+ will fill in the contents of the procedure linkage table later,
+ when we know the address of the .got section. */
+ if (h->type == STT_FUNC
+ || h->needs_plt)
+ {
+ if (! info->shared
+ && !h->def_dynamic
+ && !h->ref_dynamic
+ && h->root.type != bfd_link_hash_undefweak
+ && h->root.type != bfd_link_hash_undefined)
+ {
+ /* This case can occur if we saw a PLT reloc in an input
+ file, but the symbol was never referred to by a dynamic
+ object. In such a case, we don't actually need to build
+ a procedure linkage table, and we can just do a PCREL
+ reloc instead. */
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+
+ return TRUE;
+ }
+ else
+ h->plt.offset = (bfd_vma) -1;
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->u.weakdef != NULL)
+ {
+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ return TRUE;
+ }
+
+ /* This is a reference to a symbol defined by a dynamic object which
+ is not a function. */
+
+ /* If we are creating a shared library, we must presume that the
+ only references to the symbol are via the global offset table.
+ For such cases we need not do anything here; the relocations will
+ be handled correctly by relocate_section. */
+ if (info->shared)
+ return TRUE;
+
+ /* If there are no references to this symbol that do not use the
+ GOT, we don't need to generate a copy reloc. */
+ if (!h->non_got_ref)
+ return TRUE;
+
+ /* If -z nocopyreloc was given, we won't generate them either. */
+ if (info->nocopyreloc)
+ {
+ h->non_got_ref = 0;
+ return TRUE;
+ }
+
+ eh = (struct elf_m32r_link_hash_entry *) h;
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ {
+ s = p->sec->output_section;
+ if (s != NULL && (s->flags & (SEC_READONLY | SEC_HAS_CONTENTS)) != 0)
+ break;
+ }
+
+ /* If we didn't find any dynamic relocs in sections which needs the
+ copy reloc, then we'll be keeping the dynamic relocs and avoiding
+ the copy reloc. */
+ if (p == NULL)
+ {
+ h->non_got_ref = 0;
+ return TRUE;
+ }
+
+ /* We must allocate the symbol in our .dynbss section, which will
+ become part of the .bss section of the executable. There will be
+ an entry for this symbol in the .dynsym section. The dynamic
+ object will contain position independent code, so all references
+ from the dynamic object to this symbol will go through the global
+ offset table. The dynamic linker will use the .dynsym entry to
+ determine the address it must put in the global offset table, so
+ both the dynamic object and the regular object will refer to the
+ same memory location for the variable. */
+
+ htab = m32r_elf_hash_table (info);
+ s = htab->sdynbss;
+ BFD_ASSERT (s != NULL);
+
+ /* We must generate a R_M32R_COPY reloc to tell the dynamic linker
+ to copy the initial value out of the dynamic object and into the
+ runtime process image. We need to remember the offset into the
+ .rela.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ {
+ asection *srel;
+
+ srel = htab->srelbss;
+ BFD_ASSERT (srel != NULL);
+ srel->size += sizeof (Elf32_External_Rela);
+ h->needs_copy = 1;
+ }
+
+ /* We need to figure out the alignment required for this symbol. I
+ have no idea how ELF linkers handle this. */
+ power_of_two = bfd_log2 (h->size);
+ if (power_of_two > 3)
+ power_of_two = 3;
+
+ /* Apply the required alignment. */
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > bfd_get_section_alignment (dynobj, s))
+ {
+ if (! bfd_set_section_alignment (dynobj, s, power_of_two))
+ return FALSE;
+ }
+
+ /* Define the symbol as being at this point in the section. */
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->size;
+
+ /* Increment the section size to make room for the symbol. */
+ s->size += h->size;
+
+ return TRUE;
+}
+
+/* Allocate space in .plt, .got and associated reloc sections for
+ dynamic relocs. */
+
+static bfd_boolean
+allocate_dynrelocs (h, inf)
+ struct elf_link_hash_entry *h;
+ PTR inf;
+{
+ struct bfd_link_info *info;
+ struct elf_m32r_link_hash_table *htab;
+ struct elf_m32r_link_hash_entry *eh;
+ struct elf_m32r_dyn_relocs *p;
+
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
+
+ if (h->root.type == bfd_link_hash_warning)
+ /* When warning symbols are created, they **replace** the "real"
+ entry in the hash table, thus we never get to see the real
+ symbol in a hash traversal. So look at it now. */
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ info = (struct bfd_link_info *) inf;
+ htab = m32r_elf_hash_table (info);
+
+ eh = (struct elf_m32r_link_hash_entry *) h;
+// if ((h->got.refcount > 0
+// || h->forced_local)
+// && eh->gotplt_refcount > 0)
+// {
+// /* The symbol has been forced local, or we have some direct got refs,
+// so treat all the gotplt refs as got refs. */
+// h->got.refcount += eh->gotplt_refcount;
+// if (h->plt.refcount >= eh->gotplt_refcount)
+// h->plt.refcount -= eh->gotplt_refcount;
+// }
+
+ if (htab->root.dynamic_sections_created
+ && h->plt.refcount > 0)
+ {
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
+ {
+ asection *s = htab->splt;
+
+ /* If this is the first .plt entry, make room for the special
+ first entry. */
+ if (s->size == 0)
+ s->size += PLT_ENTRY_SIZE;
+
+ h->plt.offset = s->size;
+
+ /* If this symbol is not defined in a regular file, and we are
+ not generating a shared library, then set the symbol to this
+ location in the .plt. This is required to make function
+ pointers compare as equal between the normal executable and
+ the shared library. */
+ if (! info->shared
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = h->plt.offset;
+ }
+
+ /* Make room for this entry. */
+ s->size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .got.plt section, which
+ will be placed in the .got section by the linker script. */
+ htab->sgotplt->size += 4;
+
+ /* We also need to make an entry in the .rel.plt section. */
+ htab->srelplt->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+
+ if (h->got.refcount > 0)
+ {
+ asection *s;
+ bfd_boolean dyn;
+
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ s = htab->sgot;
+
+ h->got.offset = s->size;
+ s->size += 4;
+ dyn = htab->root.dynamic_sections_created;
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h))
+ htab->srelgot->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ h->got.offset = (bfd_vma) -1;
+
+ if (eh->dyn_relocs == NULL)
+ return TRUE;
+
+ /* In the shared -Bsymbolic case, discard space allocated for
+ dynamic pc-relative relocs against symbols which turn out to be
+ defined in regular objects. For the normal shared case, discard
+ space for pc-relative relocs that have become local due to symbol
+ visibility changes. */
+
+ if (info->shared)
+ {
+ if (h->def_regular
+ && (h->forced_local
+ || info->symbolic))
+ {
+ struct elf_m32r_dyn_relocs **pp;
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+ {
+ p->count -= p->pc_count;
+ p->pc_count = 0;
+ if (p->count == 0)
+ *pp = p->next;
+ else
+ pp = &p->next;
+ }
+ }
+ }
+ else
+ {
+ /* For the non-shared case, discard space for relocs against
+ symbols which turn out to need copy relocs or are not
+ dynamic. */
+
+ if (!h->non_got_ref
+ && ((h->def_dynamic
+ && !h->def_regular)
+ || (htab->root.dynamic_sections_created
+ && (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined))))
+ {
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ /* If that succeeded, we know we'll be keeping all the
+ relocs. */
+ if (h->dynindx != -1)
+ goto keep;
+ }
+
+ eh->dyn_relocs = NULL;
+
+ keep: ;
+ }
+
+ /* Finally, allocate space. */
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *sreloc = elf_section_data (p->sec)->sreloc;
+ sreloc->size += p->count * sizeof (Elf32_External_Rela);
+ }
+
+ return TRUE;
+}
+/* Find any dynamic relocs that apply to read-only sections. */
+
+static bfd_boolean
+readonly_dynrelocs (h, inf)
+ struct elf_link_hash_entry *h;
+ PTR inf;
+{
+ struct elf_m32r_link_hash_entry *eh;
+ struct elf_m32r_dyn_relocs *p;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ eh = (struct elf_m32r_link_hash_entry *) h;
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *s = p->sec->output_section;
+
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ {
+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+ info->flags |= DF_TEXTREL;
+
+ /* Not an error, just cut short the traversal. */
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static bfd_boolean
+m32r_elf_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd ATTRIBUTE_UNUSED;
+ struct bfd_link_info *info;
+{
+ struct elf_m32r_link_hash_table *htab;
+ bfd *dynobj;
+ asection *s;
+ bfd_boolean relocs;
+ bfd *ibfd;
+
+#ifdef DEBUG_PIC
+printf("m32r_elf_size_dynamic_sections()\n");
+#endif
+
+ htab = m32r_elf_hash_table (info);
+ dynobj = htab->root.dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (htab->root.dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (! info->shared)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ }
+ }
+
+ /* Set up .got offsets for local syms, and space for local dynamic
+ relocs. */
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ {
+ bfd_signed_vma *local_got;
+ bfd_signed_vma *end_local_got;
+ bfd_size_type locsymcount;
+ Elf_Internal_Shdr *symtab_hdr;
+ asection *srel;
+
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+ continue;
+
+ for (s = ibfd->sections; s != NULL; s = s->next)
+ {
+ struct elf_m32r_dyn_relocs *p;
+
+ for (p = ((struct elf_m32r_dyn_relocs *)
+ elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
+ {
+ if (! bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else if (p->count != 0)
+ {
+ srel = elf_section_data (p->sec)->sreloc;
+ srel->size += p->count * sizeof (Elf32_External_Rela);
+ if ((p->sec->output_section->flags & SEC_READONLY) != 0)
+ info->flags |= DF_TEXTREL;
+ }
+ }
+ }
+
+ local_got = elf_local_got_refcounts (ibfd);
+ if (!local_got)
+ continue;
+
+ symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+ locsymcount = symtab_hdr->sh_info;
+ end_local_got = local_got + locsymcount;
+ s = htab->sgot;
+ srel = htab->srelgot;
+ for (; local_got < end_local_got; ++local_got)
+ {
+ if (*local_got > 0)
+ {
+ *local_got = s->size;
+ s->size += 4;
+ if (info->shared)
+ srel->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ *local_got = (bfd_vma) -1;
+ }
+ }
+
+ /* Allocate global sym .plt and .got entries, and space for global
+ sym dynamic relocs. */
+ elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
+
+ /* We now have determined the sizes of the various dynamic sections.
+ Allocate memory for them. */
+ relocs = FALSE;
+ for (s = dynobj->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_LINKER_CREATED) == 0)
+ continue;
+
+ if (s == htab->splt
+ || s == htab->sgot
+ || s == htab->sgotplt)
+ {
+ /* Strip this section if we don't need it; see the
+ comment below. */
+ }
+ else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
+ {
+ if (s->size != 0 && s != htab->srelplt)
+ relocs = TRUE;
+
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ s->reloc_count = 0;
+ }
+ else
+ {
+ /* It's not one of our sections, so don't allocate space. */
+ continue;
+ }
+
+ if (s->size == 0)
+ {
+ /* If we don't need this section, strip it from the
+ output file. This is mostly to handle .rela.bss and
+ .rela.plt. We must create both sections in
+ create_dynamic_sections, because they must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ s->flags |= SEC_EXCLUDE;
+ continue;
+ }
+
+ /* Allocate memory for the section contents. We use bfd_zalloc
+ here in case unused entries are not reclaimed before the
+ section's contents are written out. This should not happen,
+ but this way if it does, we get a R_M32R_NONE reloc instead
+ of garbage. */
+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+ if (s->contents == NULL)
+ return FALSE;
+ }
+
+ if (htab->root.dynamic_sections_created)
+ {
+ /* Add some entries to the .dynamic section. We fill in the
+ values later, in m32r_elf_finish_dynamic_sections, but we
+ must add the entries now so that we get the correct size for
+ the .dynamic section. The DT_DEBUG entry is filled in by the
+ dynamic linker and used by the debugger. */
+#define add_dynamic_entry(TAG, VAL) \
+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
+
+ if (! info->shared)
+ {
+ if (! add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+ }
+
+ if (htab->splt->size != 0)
+ {
+ if (! add_dynamic_entry (DT_PLTGOT, 0)
+ || ! add_dynamic_entry (DT_PLTRELSZ, 0)
+ || ! add_dynamic_entry (DT_PLTREL, DT_RELA)
+ || ! add_dynamic_entry (DT_JMPREL, 0))
+ return FALSE;
+ }
+
+ if (relocs)
+ {
+ if (! add_dynamic_entry (DT_RELA, 0)
+ || ! add_dynamic_entry (DT_RELASZ, 0)
+ || ! add_dynamic_entry (DT_RELAENT,
+ sizeof (Elf32_External_Rela)))
+ return FALSE;
+
+ /* If any dynamic relocs apply to a read-only section,
+ then we need a DT_TEXTREL entry. */
+ if ((info->flags & DF_TEXTREL) == 0)
+ elf_link_hash_traverse (&htab->root, readonly_dynrelocs,
+ (PTR) info);
+
+ if ((info->flags & DF_TEXTREL) != 0)
+ {
+ if (! add_dynamic_entry (DT_TEXTREL, 0))
+ return FALSE;
+ }
+ }
+ }
+#undef add_dynamic_entry
+
+ return TRUE;