static bfd *filler_bfd;
static struct bfd_section *edata_s, *reloc_s;
static unsigned char *edata_d, *reloc_d;
-static size_t edata_sz, reloc_sz;
+static unsigned char *reloc_d = NULL;
+static size_t edata_sz, reloc_sz = 0;
static int runtime_pseudo_relocs_created = 0;
static bool runtime_pseudp_reloc_v2_init = false;
/* Build the bfd that will contain .edata and .reloc sections. */
static void
-build_filler_bfd (int include_edata)
+build_filler_bfd (bool include_edata)
{
lang_input_statement_type *filler_file;
+
filler_file = lang_add_input_file ("dll stuff",
lang_input_file_is_fake_enum,
NULL);
bfd_set_section_size (reloc_s, 0);
+ /* FIXME: I am not sure if this is the right way to solve PR 29998.
+ It might be better to change ldlang.c:lang_statement_append() so that it
+ checks to see if *(list->tail) is non-NULL and if so, set element->next
+ to its contents.
+
+ The issue is that this function is called after lang_process().
+ lang_process () will have gone through any input archives, and if the
+ last input file is an archive then it will have left file_chain.tail
+ pointing to the last used element of that archive. Calling
+ ldlang_add_file() here then blows aaway the link to that archive element,
+ effectively deleting it from the input. In order to prevent this, the
+ assignment below fills in the next field of the statement that is about
+ to appended to the file chain. */
+ if (file_chain.tail != NULL)
+ filler_file->next = & (* file_chain.tail)->input_statement;
+
ldlang_add_file (filler_file);
}
char *impname;
if (pe_dll_extra_pe_debug)
- printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+ printf ("%s:%s\n", __func__, undef->root.string);
strcpy (name, undef->root.string);
impname = name - (sizeof "__imp_" - 1);
if (reloc_s == NULL || reloc_s->output_section == bfd_abs_section_ptr)
return;
+
+ /* Set an upper bound for the total number of relocations we will have to generate. */
total_relocs = 0;
for (b = info->input_bfds; b; b = b->link.next)
for (s = b->sections; s; s = s->next)
{
arelent **relocs;
int relsize, nrelocs;
+ asymbol **symbols;
+
+ if (!bfd_generic_link_read_symbols (b))
+ {
+ einfo (_("%F%P: %pB: could not read symbols: %E\n"), b);
+ return;
+ }
+
+ symbols = bfd_get_outsymbols (b);
for (s = b->sections; s; s = s->next)
{
- bfd_vma sec_vma = s->output_section->vma + s->output_offset;
- asymbol **symbols;
+ bfd_vma sec_vma;
- /* If it's not loaded, we don't need to relocate it this way. */
- if (!(s->output_section->flags & SEC_LOAD))
- continue;
+ /* If the section is not going to be output, then ignore it. */
+ if (s->output_section == NULL)
+ {
+ /* FIXME: This should not happen. Convert to the correct
+ form here, but really, this should be investigated. */
+ s->output_section = bfd_abs_section_ptr;
+ continue;
+ }
/* I don't know why there would be a reloc for these, but I've
seen it happen - DJ */
if (s->output_section == bfd_abs_section_ptr)
continue;
+ /* If it's not loaded, we don't need to relocate it this way. */
+ if (!(s->output_section->flags & SEC_LOAD))
+ continue;
+
+ /* This happens when linking with --just-symbols=<file>
+ so do not generate an error. */
if (s->output_section->vma == 0)
- {
- /* Huh? Shouldn't happen, but punt if it does. */
-#if 0 /* This happens when linking with --just-symbols=<file>, so do not generate an error. */
- einfo (_("%P: zero vma section reloc detected: `%s' #%d f=%d\n"),
- s->output_section->name, s->output_section->index,
- s->output_section->flags);
-#endif
- continue;
- }
+ continue;
- if (!bfd_generic_link_read_symbols (b))
- {
- einfo (_("%F%P: %pB: could not read symbols: %E\n"), b);
- return;
- }
+ sec_vma = s->output_section->vma + s->output_offset;
- symbols = bfd_get_outsymbols (b);
relsize = bfd_get_reloc_upper_bound (b, s);
relocs = xmalloc (relsize);
nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
}
}
}
+
free (relocs);
/* Warning: the allocated symbols are remembered in BFD and
reused later, so don't free them! */
}
}
+ /* This can happen for example when LTO has eliminated all code. */
+ if (total_relocs == 0)
+ return;
+
/* At this point, we have total_relocs relocation addresses in
reloc_addresses, which are all suitable for the .reloc section.
We must now create the new sections. */
reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */
reloc_d = xmalloc (reloc_sz);
- sec_page = (bfd_vma) -1;
+
+ page_ptr = sec_page = (bfd_vma) -1;
reloc_sz = 0;
- page_ptr = (bfd_vma) -1;
for (i = 0; i < total_relocs; i++)
{
bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
reloc_sz += 2;
}
-
}
while (reloc_sz & 3)
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
};
-/* _function:
- b <__imp_function>
- nop */
static const unsigned char jmp_aarch64_bytes[] =
{
- 0x00, 0x00, 0x00, 0x14,
- 0x1f, 0x20, 0x03, 0xD5
+ 0x10, 0x00, 0x00, 0x90, /* adrp x16, 0 */
+ 0x10, 0x02, 0x00, 0x91, /* add x16, x16, #0x0 */
+ 0x10, 0x02, 0x40, 0xf9, /* ldr x16, [x16] */
+ 0x00, 0x02, 0x1f, 0xd6 /* br x16 */
};
/* _function:
quick_reloc (abfd, 8, BFD_RELOC_32, 2);
break;
case PE_ARCH_aarch64:
- quick_reloc (abfd, 0, BFD_RELOC_AARCH64_JUMP26, 2);
+ quick_reloc (abfd, 0, BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL, 2);
+ quick_reloc (abfd, 4, BFD_RELOC_AARCH64_ADD_LO12, 2);
break;
default:
abort ();
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
- __FUNCTION__, sec_name, (unsigned long) vaddr,
+ __func__, sec_name, (unsigned long) vaddr,
(unsigned long) (vaddr + vsize), (unsigned long) flags);
}
else if (strcmp(sec_name,".rdata") == 0)
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
- __FUNCTION__, sec_name, (unsigned long) vaddr,
+ __func__, sec_name, (unsigned long) vaddr,
(unsigned long) (vaddr + vsize), (unsigned long) flags);
}
else if (strcmp (sec_name,".bss") == 0)
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
- __FUNCTION__, sec_name, (unsigned long) vaddr,
+ __func__, sec_name, (unsigned long) vaddr,
(unsigned long) (vaddr + vsize), (unsigned long) flags);
}
}
if (pe_dll_extra_pe_debug)
printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
- __FUNCTION__, dllname, erva + name_rva,
+ __func__, dllname, erva + name_rva,
(unsigned long) func_rva, is_data ? "(data)" : "");
}
if (pe_dll_extra_pe_debug)
printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
- __FUNCTION__, dllname, erva + name_rva,
+ __func__, dllname, erva + name_rva,
(unsigned long) func_rva, is_data ? "(data)" : "");
}
}
{
if (pe_dll_enable_reloc_section)
{
- build_filler_bfd (0);
+ build_filler_bfd (false /* edata not needed. */);
pe_output_file_set_long_section_names (filler_bfd);
}
return;
}
generate_edata ();
- build_filler_bfd (1);
+ build_filler_bfd (true /* edata is needed. */);
pe_output_file_set_long_section_names (filler_bfd);
}
image_base = pe_data (abfd)->pe_opthdr.ImageBase;
generate_reloc (abfd, info);
+
if (reloc_sz > 0)
{
bfd_set_section_size (reloc_s, reloc_sz);
/* Do the assignments again. */
lang_do_assignments (lang_final_phase_enum);
+
+ reloc_s->contents = reloc_d;
+ }
+ else if (reloc_s)
+ {
+ /* Do not emit an empty reloc section. */
+ bfd_set_section_flags (reloc_s, SEC_IN_MEMORY | SEC_EXCLUDE);
+ reloc_s->output_section = bfd_abs_section_ptr;
}
- if (reloc_s)
- reloc_s->contents = reloc_d;
}
bool