/* Routines to help build PEI-format DLLs (Win32 etc)
- Copyright (C) 1998-2020 Free Software Foundation, Inc.
+ Copyright (C) 1998-2024 Free Software Foundation, Inc.
Written by DJ Delorie <dj@cygnus.com>
This file is part of the GNU Binutils.
#include "../bfd/libcoff.h"
#include "deffile.h"
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
#define PE_IDATA4_SIZE 8
#define PE_IDATA5_SIZE 8
int pe_use_nul_prefixed_import_tables = 0;
int pe_use_coff_long_section_names = -1;
int pe_leading_underscore = -1;
+int pe_dll_enable_reloc_section = 1;
/* Static variables and types. */
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 bfd_boolean runtime_pseudp_reloc_v2_init = FALSE;
+static bool runtime_pseudp_reloc_v2_init = false;
typedef struct
{
unsigned int imagebase_reloc;
int pe_arch;
int bfd_arch;
- bfd_boolean underscored;
+ bool underscored;
const autofilter_entry_type* autofilter_symbollist;
}
pe_details_type;
{ STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") },
/* Entry point symbols, and entry hooks. */
{ STRING_COMMA_LEN ("cygwin_crt0") },
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
{ STRING_COMMA_LEN ("DllMain") },
{ STRING_COMMA_LEN ("DllEntryPoint") },
{ STRING_COMMA_LEN ("DllMainCRTStartup") },
#define PE_ARCH_mips 3
#define PE_ARCH_arm 4
#define PE_ARCH_arm_wince 5
+#define PE_ARCH_aarch64 6
/* Don't make it constant as underscore mode gets possibly overriden
by target or -(no-)leading-underscore option. */
static pe_details_type pe_detail_list[] =
{
{
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
"pei-x86-64",
"pe-x86-64",
3 /* R_IMAGEBASE */,
#endif
PE_ARCH_i386,
bfd_arch_i386,
-#ifdef pe_use_x86_64
- FALSE,
+#ifdef pe_use_plus
+ false,
#else
- TRUE,
+ true,
#endif
autofilter_symbollist_i386
},
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
{
"pei-x86-64",
"pe-bigobj-x86-64",
3 /* R_IMAGEBASE */,
PE_ARCH_i386,
bfd_arch_i386,
- FALSE,
+ false,
+ autofilter_symbollist_i386
+ },
+#else
+ {
+ "pei-i386",
+ "pe-bigobj-i386",
+ 7 /* R_IMAGEBASE */,
+ PE_ARCH_i386,
+ bfd_arch_i386,
+ true,
autofilter_symbollist_i386
},
#endif
16 /* R_SH_IMAGEBASE */,
PE_ARCH_sh,
bfd_arch_sh,
- TRUE,
+ true,
autofilter_symbollist_generic
},
{
34 /* MIPS_R_RVA */,
PE_ARCH_mips,
bfd_arch_mips,
- FALSE,
+ false,
autofilter_symbollist_generic
},
{
11 /* ARM_RVA32 */,
PE_ARCH_arm,
bfd_arch_arm,
- TRUE,
+ true,
autofilter_symbollist_generic
},
{
2, /* ARM_RVA32 on Windows CE, see bfd/coff-arm.c. */
PE_ARCH_arm_wince,
bfd_arch_arm,
- FALSE,
+ false,
+ autofilter_symbollist_generic
+ },
+ {
+ "pei-aarch64-little",
+ "pe-aarch64-little",
+ 2, /* ARM64_RVA32 */
+ PE_ARCH_aarch64,
+ bfd_arch_aarch64,
+ false,
autofilter_symbollist_generic
},
- { NULL, NULL, 0, 0, 0, FALSE, NULL }
+ { NULL, NULL, 0, 0, 0, false, NULL }
};
static const pe_details_type *pe_details;
{ STRING_COMMA_LEN ("libgcj") },
{ STRING_COMMA_LEN ("libmsvcrt") },
{ STRING_COMMA_LEN ("libmsvcrt-os") },
+ { STRING_COMMA_LEN ("libucrt") },
{ STRING_COMMA_LEN ("libucrtbase") },
{ NULL, 0 }
};
bfd_get_target_info (target, NULL, NULL, &u, NULL);
if (u == -1)
abort ();
- pe_detail_list[i].underscored = (u != 0 ? TRUE : FALSE);
+ pe_detail_list[i].underscored = u != 0;
pe_details = pe_detail_list + i;
pe_leading_underscore = (u != 0 ? 1 : 0);
return;
static int count_exported;
static int count_exported_byname;
static int count_with_ordinals;
-static const char *dll_name;
+static const char *dll_filename;
static int min_ordinal, max_ordinal;
static int *exported_symbols;
free (local_copy);
}
-static bfd_boolean
+static bool
is_import (const char* n)
{
- return (CONST_STRNEQ (n, "__imp_"));
+ return (startswith (n, "__imp_"));
}
/* abfd is a bfd containing n (or NULL)
const char * libname = NULL;
if (abfd && abfd->my_archive)
- libname = lbasename (abfd->my_archive->filename);
+ libname = lbasename (bfd_get_filename (abfd->my_archive));
key.name = key.its_name = (char *) n;
/* Return false if n is in the d->exports table. */
- if (bsearch (&key, d->exports, d->num_exports,
- sizeof (pe_def_file->exports[0]), pe_export_sort))
+ if (d->num_exports != 0
+ && bsearch (&key, d->exports, d->num_exports,
+ sizeof (pe_def_file->exports[0]), pe_export_sort))
return 0;
if (pe_dll_do_default_excludes)
/* Next, exclude symbols from certain startup objects. */
- if (abfd && (p = lbasename (abfd->filename)))
+ if (abfd && (p = lbasename (bfd_get_filename (abfd))))
{
afptr = autofilter_objlist;
while (afptr->name)
}
else if (ex->type == EXCLUDEFORIMPLIB)
{
- if (filename_cmp (abfd->filename, ex->string) == 0)
+ if (filename_cmp (bfd_get_filename (abfd), ex->string) == 0)
return 0;
}
else if (strcmp (n, ex->string) == 0)
process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
{
int i, j;
+ unsigned int ui;
struct bfd_link_hash_entry *blhe;
bfd *b;
struct bfd_section *s;
def_file_export *e = 0;
- bfd_boolean resort_needed;
+ bool resort_needed;
if (!pe_def_file)
pe_def_file = def_file_empty ();
{
struct coff_link_hash_entry *sym_hash;
sym_hash = coff_link_hash_lookup (coff_hash_table (info),
- ac->symbol_name, FALSE, FALSE, FALSE);
+ ac->symbol_name, false, false, false);
if (sym_hash && sym_hash->root.type == bfd_link_hash_common
&& sym_hash->root.u.c.p->alignment_power < (unsigned) ac->alignment)
{
}
}
+ if (pe_def_file->exclude_symbols)
+ {
+ for (ui = 0; ui < pe_def_file->num_exclude_symbols; ui++)
+ {
+ pe_dll_add_excludes (pe_def_file->exclude_symbols[ui].symbol_name,
+ EXCLUDESYMS);
+ }
+ }
+
/* If we are building an executable and there is nothing
to export, we do not build an export table at all. */
if (bfd_link_executable (info) && pe_def_file->num_exports == 0
/* We should export symbols which are either global or not
anything at all. (.bss data is the latter)
We should not export undefined symbols. */
- bfd_boolean would_export
+ bool would_export
= (symbols[j]->section != bfd_und_section_ptr
&& ((symbols[j]->flags & BSF_GLOBAL)
|| (symbols[j]->flags == 0)));
sprintf (name, "%s%s", "__imp_", sn);
blhe = bfd_link_hash_lookup (info->hash, name,
- FALSE, FALSE, FALSE);
+ false, false, false);
free (name);
if (blhe && blhe->type == bfd_link_hash_defined)
if (auto_export (b, pe_def_file, sn))
{
- int is_dup = 0;
+ bool is_dup = false;
def_file_export *p;
p = def_file_add_export (pe_def_file, sn, 0, -1,
if (NE == 0)
return;
- resort_needed = FALSE;
+ resort_needed = false;
/* Canonicalize the export list. */
if (pe_dll_kill_ats)
einfo (_("%X%P: cannot export %s: invalid export name\n"),
pe_def_file->exports[i].name);
pe_def_file->exports[i].name = tmp;
- resort_needed = TRUE;
+ resort_needed = true;
}
}
}
if (strchr (pe_def_file->exports[i].name, '@'))
{
- int is_dup = 1;
+ bool is_dup = true;
int lead_at = (*pe_def_file->exports[i].name == '@');
char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
e[j - 1].flag_constant |= e[i].flag_constant;
e[j - 1].flag_noname |= e[i].flag_noname;
e[j - 1].flag_data |= e[i].flag_data;
- if (e[i].name)
- free (e[i].name);
- if (e[i].internal_name)
- free (e[i].internal_name);
- if (e[i].its_name)
- free (e[i].its_name);
+ free (e[i].name);
+ free (e[i].internal_name);
+ free (e[i].its_name);
}
else
{
blhe = bfd_link_hash_lookup (info->hash,
name,
- FALSE, FALSE, TRUE);
+ false, false, true);
if (blhe
&& (blhe->type == bfd_link_hash_defined
/* 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);
/* Gather all the exported symbols and build the .edata section. */
static void
-generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+generate_edata (void)
{
int i, next_ordinal;
int name_table_size = 0;
- const char *dlnp;
/* First, we need to know how many exported symbols there are,
and what the range of ordinals is. */
- if (pe_def_file->name)
- dll_name = pe_def_file->name;
- else
- {
- dll_name = abfd->filename;
-
- for (dlnp = dll_name; *dlnp; dlnp++)
- if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':')
- dll_name = dlnp + 1;
- }
-
if (count_with_ordinals && max_ordinal > count_exported)
{
if (min_ordinal > max_ordinal - count_exported + 1)
+ 4 * export_table_size /* addresses */
+ 4 * count_exported_byname /* name ptrs */
+ 2 * count_exported_byname /* ordinals */
- + name_table_size + strlen (dll_name) + 1);
+ + name_table_size + strlen (dll_filename) + 1);
}
/* Fill the exported symbol offsets. The preliminary work has already
blhe = bfd_link_hash_lookup (info->hash,
name,
- FALSE, FALSE, TRUE);
+ false, false, true);
if (blhe && blhe->type == bfd_link_hash_defined)
exported_symbol_offsets[i] = blhe->u.def.value;
memset (edata_d, 0, edata_sz);
- if (pe_data (abfd)->insert_timestamp)
- H_PUT_32 (abfd, time (0), edata_d + 4);
+ if (pe_data (abfd)->timestamp == -1)
+ {
+ time_t now = bfd_get_current_time (0);
+ H_PUT_32 (abfd, now, edata_d + 4);
+ }
+ else
+ H_PUT_32 (abfd, pe_data (abfd)->timestamp, edata_d + 4);
if (pe_def_file->version_major != -1)
{
}
bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12);
- strcpy (enamestr, dll_name);
+ strcpy (enamestr, dll_filename);
enamestr += strlen (enamestr) + 1;
bfd_put_32 (abfd, min_ordinal, edata_d + 16);
bfd_put_32 (abfd, export_table_size, edata_d + 20);
/* Warning: the callback needs to be passed NAME directly. */
if (import_hash)
{
- if (bfd_hash_lookup (import_hash, sym->name, FALSE, FALSE))
+ if (bfd_hash_lookup (import_hash, sym->name, false, false))
{
strcpy (name, sym->name);
cb (relocs[i], s, name, symname);
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 (sym && sym->type == bfd_link_hash_defined)
{
if (import_hash)
- bfd_hash_lookup (import_hash, undef->root.string, TRUE, FALSE);
+ bfd_hash_lookup (import_hash, undef->root.string, true, false);
else
{
bfd *b = sym->u.def.section->owner;
if (link_info.pei386_auto_import == -1)
{
- static bfd_boolean warned = FALSE;
+ static bool warned = false;
info_msg (_("Info: resolving %s by linking to %s "
"(auto-import)\n"), name, impname);
"command line; this should work unless it "
"involves constant data structures referencing "
"symbols from auto-imported DLLs\n"));
- warned = TRUE;
+ warned = true;
}
}
}
static void
generate_reloc (bfd *abfd, struct bfd_link_info *info)
{
-
/* For .reloc stuff. */
reloc_data_type *reloc_data;
int total_relocs = 0;
int i;
bfd_vma sec_page = (bfd_vma) -1;
- bfd_vma page_ptr, page_count;
- int bi;
+ bfd_vma page_ptr;
bfd *b;
struct bfd_section *s;
+ 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)
reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type));
total_relocs = 0;
- bi = 0;
- for (bi = 0, b = info->input_bfds; b; bi++, b = b->link.next)
+ for (b = info->input_bfds; b; b = b->link.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. */
- einfo (_("%P: zero vma section reloc detected: `%s' #%d f=%d\n"),
- s->output_section->name, s->output_section->index,
- s->output_section->flags);
- 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);
&& relocs[i]->howto->type != pe_details->imagebase_reloc)
{
struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
+ const struct bfd_link_hash_entry *blhe
+ = bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
+ false, false, false);
/* Don't create relocs for undefined weak symbols. */
if (sym->flags == BSF_WEAK)
{
- struct bfd_link_hash_entry *blhe
- = bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
- FALSE, FALSE, FALSE);
if (blhe && blhe->type == bfd_link_hash_undefweak)
{
/* Check aux sym and see if it is defined or not. */
if (h->symbol_class != C_NT_WEAK || h->numaux != 1)
continue;
h2 = h->auxbfd->tdata.coff_obj_data->sym_hashes
- [h->aux->x_sym.x_tagndx.l];
+ [h->aux->x_sym.x_tagndx.u32];
/* We don't want a base reloc if the aux sym is not
found, undefined, or if it is the constant ABS
zero default value. (We broaden that slightly by
if (!strcmp (s->name, ".eh_frame"))
continue;
}
+ /* Nor for absolute symbols. */
+ else if (blhe && ldexp_is_final_sym_absolute (blhe)
+ && (!blhe->linker_def
+ || (strcmp (sym->name, "__image_base__")
+ && strcmp (sym->name, U ("__ImageBase")))))
+ continue;
reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
reloc_data[total_relocs].idx = total_relocs;
+ /* Since we're only about to determine .reloc's size,
+ subsequent output section VMA calculations will shift up
+ sections at this or higher addresses. Relocations for
+ such sections would hence end up not being correct. */
+ if (reloc_data[total_relocs].vma
+ >= reloc_s->output_section->vma)
+ einfo (_("%P: base relocation for section `%s' above "
+ ".reloc section\n"), s->output_section->name);
+
#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
relocs[i]->howto->rightshift)
{
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
case BITS_AND_SHIFT (64, 0):
- reloc_data[total_relocs].type = 10;
+ reloc_data[total_relocs].type = IMAGE_REL_BASED_DIR64;
total_relocs++;
break;
#endif
case BITS_AND_SHIFT (32, 0):
- reloc_data[total_relocs].type = 3;
+ reloc_data[total_relocs].type = IMAGE_REL_BASED_HIGHLOW;
total_relocs++;
break;
case BITS_AND_SHIFT (16, 0):
- reloc_data[total_relocs].type = 2;
+ reloc_data[total_relocs].type = IMAGE_REL_BASED_LOW;
total_relocs++;
break;
case BITS_AND_SHIFT (16, 16):
- reloc_data[total_relocs].type = 4;
+ reloc_data[total_relocs].type = IMAGE_REL_BASED_HIGHADJ;
/* FIXME: we can't know the symbol's right value
yet, but we probably can safely assume that
CE will relocate us in 64k blocks, so leaving
total_relocs++;
break;
case BITS_AND_SHIFT (26, 2):
- reloc_data[total_relocs].type = 5;
+ reloc_data[total_relocs].type =
+ IMAGE_REL_BASED_ARM_MOV32;
total_relocs++;
break;
case BITS_AND_SHIFT (24, 2):
}
}
}
+
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 += 2;
- if (reloc_data[i].type == 4)
+ if (reloc_data[i].type == IMAGE_REL_BASED_HIGHADJ)
reloc_sz += 2;
}
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;
- page_count = 0;
for (i = 0; i < total_relocs; i++)
{
page_ptr = reloc_sz;
reloc_sz += 8;
sec_page = this_page;
- page_count = 0;
}
bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
reloc_d + reloc_sz);
reloc_sz += 2;
- if (reloc_data[i].type == 4)
+ if (reloc_data[i].type == IMAGE_REL_BASED_HIGHADJ)
{
bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
reloc_sz += 2;
}
-
- page_count++;
}
while (reloc_sz & 3)
if (page_ptr != (bfd_vma) -1)
bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
-
- while (reloc_sz < reloc_s->size)
- reloc_d[reloc_sz++] = 0;
}
/* Given the exiting def_file structure, print out a .DEF file that
quoteput (pe_def_file->name, out, 1);
if (pe_data (link_info.output_bfd)->pe_opthdr.ImageBase)
- {
- fprintf (out, " BASE=0x");
- fprintf_vma (out, ((bfd_vma) pe_data (link_info.output_bfd)->pe_opthdr.ImageBase));
- }
+ fprintf (out, " BASE=0x%" PRIx64,
+ (uint64_t) pe_data (link_info.output_bfd)->pe_opthdr.ImageBase);
fprintf (out, "\n");
}
static asymbol **symtab;
static int symptr;
static int tmp_seq;
-static const char *dll_filename;
static char *dll_symname;
#define UNDSEC bfd_und_section_ptr
char *oname;
bfd *abfd;
- oname = xmalloc (20);
- sprintf (oname, "d%06d.o", tmp_seq);
+ if (asprintf (&oname, "%s_d%06d.o", dll_symname, tmp_seq) < 4)
+ /* In theory we should return NULL here at let our caller decide what to
+ do. But currently the return value is not checked, just used, and
+ besides, this condition only happens when the system has run out of
+ memory. So just give up. */
+ exit (EXIT_FAILURE);
tmp_seq++;
abfd = bfd_create (oname, parent);
+ free (oname);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
char *oname;
bfd *abfd;
- oname = xmalloc (20);
- sprintf (oname, "d%06d.o", tmp_seq);
+ if (asprintf (&oname, "%s_d%06d.o", dll_symname, tmp_seq) < 4)
+ /* In theory we should return NULL here at let our caller decide what to
+ do. But currently the return value is not checked, just used, and
+ besides, this condition only happens when the system has run out of
+ memory. So just give up. */
+ exit (EXIT_FAILURE);
tmp_seq++;
abfd = bfd_create (oname, parent);
+ free (oname);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
};
+static const unsigned char jmp_aarch64_bytes[] =
+{
+ 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:
mov.l ip+8,r0
mov.l @r0,r0
static bfd *
-make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
+make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub)
{
asection *tx, *id7, *id5, *id4, *id6;
unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL;
bfd *abfd;
const unsigned char *jmp_bytes = NULL;
int jmp_byte_count = 0;
+ const char *internal_name = exp->internal_name;
+
+ if (!exp->flag_noname)
+ {
+ /* Check for a decorated symbol name */
+ struct decoration_hash_entry *entry;
+
+ entry = (struct decoration_hash_entry *)
+ bfd_hash_lookup (&(coff_hash_table (&link_info)->decoration_hash),
+ internal_name, false, false);
+ if (entry)
+ {
+ if (entry->decorated_link)
+ {
+ internal_name = entry->decorated_link->root.string;
+
+ if (pe_details->underscored && internal_name[0] == '_')
+ internal_name++;
+ }
+ else
+ {
+ einfo (_("%P: error: NULL decorated name for %s\n"), internal_name);
+ }
+ }
+ }
/* Include the jump stub section only if it is needed. A jump
stub is needed if the symbol being imported <sym> is a function
jmp_bytes = jmp_arm_bytes;
jmp_byte_count = sizeof (jmp_arm_bytes);
break;
+ case PE_ARCH_aarch64:
+ jmp_bytes = jmp_aarch64_bytes;
+ jmp_byte_count = sizeof (jmp_aarch64_bytes);
+ break;
default:
abort ();
}
}
- oname = xmalloc (20);
- sprintf (oname, "d%06d.o", tmp_seq);
+ if (asprintf (&oname, "%s_d%06d.o", dll_symname, tmp_seq) < 4)
+ /* In theory we should return NULL here at let our caller decide what to
+ do. But currently the return value is not checked, just used, and
+ besides, this condition only happens when the system has run out of
+ memory. So just give up. */
+ exit (EXIT_FAILURE);
tmp_seq++;
abfd = bfd_create (oname, parent);
+ free (oname);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
- if (*exp->internal_name == '@')
+ if (*internal_name == '@')
{
quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
BSF_GLOBAL, 0);
if (include_jmp_stub)
- quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
- quick_symbol (abfd, "__imp_", exp->internal_name, "", id5,
+ quick_symbol (abfd, "", internal_name, "", tx, BSF_GLOBAL, 0);
+ quick_symbol (abfd, "__imp_", internal_name, "", id5,
BSF_GLOBAL, 0);
/* Fastcall applies only to functions,
so no need for auto-import symbol. */
quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
BSF_GLOBAL, 0);
if (include_jmp_stub)
- quick_symbol (abfd, U (""), exp->internal_name, "", tx,
+ quick_symbol (abfd, U (""), internal_name, "", tx,
BSF_GLOBAL, 0);
- quick_symbol (abfd, "__imp_", U (""), exp->internal_name, id5,
+ quick_symbol (abfd, "__imp_", U (""), internal_name, id5,
BSF_GLOBAL, 0);
/* Symbol to reference ord/name of imported
data symbol, used to implement auto-import. */
if (exp->flag_data)
- quick_symbol (abfd, "__nm_", U (""), exp->internal_name, id6,
+ quick_symbol (abfd, "__nm_", U (""), internal_name, id6,
BSF_GLOBAL,0);
}
if (pe_dll_compat_implib)
- quick_symbol (abfd, "___imp_", exp->internal_name, "", id5,
+ quick_symbol (abfd, "___imp_", internal_name, "", id5,
BSF_GLOBAL, 0);
if (include_jmp_stub)
switch (pe_details->pe_arch)
{
case PE_ARCH_i386:
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2);
#else
/* Mark this object as SAFESEH compatible. */
case PE_ARCH_arm_wince:
quick_reloc (abfd, 8, BFD_RELOC_32, 2);
break;
+ case PE_ARCH_aarch64:
+ 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 ();
}
}
else
{
- int ord;
-
- /* { short, asciz } */
+ /* { short, asciz } = { hint, name } */
if (exp->its_name)
len = 2 + strlen (exp->its_name) + 1;
else
d6 = xmalloc (len);
id6->contents = d6;
memset (d6, 0, len);
-
- /* PR 20880: Use exp->hint as a backup, just in case exp->ordinal
- contains an invalid value (-1). */
- ord = (exp->ordinal >= 0) ? exp->ordinal : exp->hint;
- d6[0] = ord;
- d6[1] = ord >> 8;
-
+ d6[0] = exp->hint & 0xff;
+ d6[1] = exp->hint >> 8;
if (exp->its_name)
strcpy ((char*) d6 + 2, exp->its_name);
else
char *oname;
bfd *abfd;
- oname = xmalloc (20);
- sprintf (oname, "nmth%06d.o", tmp_seq);
+ if (asprintf (&oname, "%s_nmth%06d.o", dll_symname, tmp_seq) < 4)
+ /* In theory we should return NULL here at let our caller decide what to
+ do. But currently the return value is not checked, just used, and
+ besides, this condition only happens when the system has run out of
+ memory. So just give up. */
+ exit (EXIT_FAILURE);
tmp_seq++;
abfd = bfd_create (oname, parent);
+ free (oname);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
struct bfd_symbol *sym = *rel->sym_ptr_ptr;
bfd *abfd = bfd_asymbol_bfd (sym);
struct bfd_link_hash_entry *bh;
- char *fixup_name, buf[26];
+ char *fixup_name, buf[256];
size_t prefix_len;
/* "name" buffer has space before the symbol name for prefixes. */
bh = NULL;
bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL,
current_sec, /* sym->section, */
- rel->address, NULL, TRUE, FALSE, &bh);
+ rel->address, NULL, true, false, &bh);
return bh->root.string;
}
char *oname;
bfd *abfd;
- oname = xmalloc (20);
- sprintf (oname, "fu%06d.o", tmp_seq);
+ if (asprintf (&oname, "%s_fu%06d.o", dll_symname, tmp_seq) < 4)
+ /* In theory we should return NULL here at let our caller decide what to
+ do. But currently the return value is not checked, just used, and
+ besides, this condition only happens when the system has run out of
+ memory. So just give up. */
+ exit (EXIT_FAILURE);
tmp_seq++;
abfd = bfd_create (oname, parent);
+ free (oname);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
bfd *abfd;
bfd_size_type size;
- oname = xmalloc (20);
- sprintf (oname, "rtr%06d.o", tmp_seq);
+ if (asprintf (&oname, "%s_rtr%06d.o", dll_symname, tmp_seq) < 4)
+ /* In theory we should return NULL here at let our caller decide what to
+ do. But currently the return value is not checked, just used, and
+ besides, this condition only happens when the system has run out of
+ memory. So just give up. */
+ exit (EXIT_FAILURE);
tmp_seq++;
abfd = bfd_create (oname, parent);
+ free (oname);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
rt_rel
= quick_section (abfd, ".rdata_runtime_pseudo_reloc", SEC_HAS_CONTENTS, 2);
+ bfd_coff_set_long_section_names (abfd, true);
quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
if (!runtime_pseudp_reloc_v2_init)
{
size += 12;
- runtime_pseudp_reloc_v2_init = TRUE;
+ runtime_pseudp_reloc_v2_init = true;
}
quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0);
char *oname;
bfd *abfd;
- oname = xmalloc (20);
- sprintf (oname, "ertr%06d.o", tmp_seq);
+ if (asprintf (&oname, "%s_ertr%06d.o", dll_symname, tmp_seq) < 4)
+ /* In theory we should return NULL here at let our caller decide what to
+ do. But currently the return value is not checked, just used, and
+ besides, this condition only happens when the system has run out of
+ memory. So just give up. */
+ exit (EXIT_FAILURE);
tmp_seq++;
abfd = bfd_create (oname, parent);
+ free (oname);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
if (!(name_thunk_sym && name_thunk_sym->type == bfd_link_hash_defined))
{
b = make_singleton_name_thunk (name, link_info.output_bfd);
- add_bfd_to_link (b, b->filename, &link_info);
+ add_bfd_to_link (b, bfd_get_filename (b), &link_info);
/* If we ever use autoimport, we have to cast text section writable. */
- config.text_read_only = FALSE;
+ config.text_read_only = false;
link_info.output_bfd->flags &= ~WP_TEXT;
}
{
b = make_import_fixup_entry (name, fixup_name, symname,
link_info.output_bfd);
- add_bfd_to_link (b, b->filename, &link_info);
+ add_bfd_to_link (b, bfd_get_filename (b), &link_info);
}
}
printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n",
fixup_name, (int) addend);
- b = make_runtime_pseudo_reloc (name, fixup_name, addend, rel->howto->bitsize,
+ b = make_runtime_pseudo_reloc (name, fixup_name, addend,
+ rel->howto->bitsize,
link_info.output_bfd);
- add_bfd_to_link (b, b->filename, &link_info);
+ add_bfd_to_link (b, bfd_get_filename (b), &link_info);
if (runtime_pseudo_relocs_created++ == 0)
{
b = pe_create_runtime_relocator_reference (link_info.output_bfd);
- add_bfd_to_link (b, b->filename, &link_info);
+ add_bfd_to_link (b, bfd_get_filename (b), &link_info);
}
}
else if (addend != 0)
- einfo (_("%X%P: %C: variable '%pT' can't be auto-imported; please read the documentation for ld's --enable-auto-import for details\n"),
+ einfo (_("%X%P: %H: variable '%pT' can't be auto-imported; please read the documentation for ld's --enable-auto-import for details\n"),
s->owner, s, rel->address, (*rel->sym_ptr_ptr)->name);
}
bfd *ibfd;
bfd *head = 0;
- dll_filename = (def->name) ? def->name : dll_name;
- dll_symname = xstrdup (dll_filename);
- for (i = 0; dll_symname[i]; i++)
- if (!ISALNUM (dll_symname[i]))
- dll_symname[i] = '_';
-
unlink_if_ordinary (impfilename);
outarch = bfd_openw (impfilename, 0);
{
if (ex->type != EXCLUDEFORIMPLIB)
continue;
- found = (filename_cmp (ex->string, ibfd->filename) == 0);
+ found = (filename_cmp (ex->string, bfd_get_filename (ibfd)) == 0);
}
/* If it matched, we must open a fresh BFD for it (the original
input BFD is still needed for the DLL's final link) and add
if (found)
{
bfd *newbfd = bfd_openr (ibfd->my_archive
- ? ibfd->my_archive->filename : ibfd->filename, NULL);
+ ? bfd_get_filename (ibfd->my_archive)
+ : bfd_get_filename (ibfd), NULL);
if (!newbfd)
{
- einfo (_("%X%P: bfd_openr %s: %E\n"), ibfd->filename);
+ einfo (_("%X%P: bfd_openr %s: %E\n"), bfd_get_filename (ibfd));
return;
}
if (ibfd->my_archive)
if (!bfd_check_format_matches (arbfd, bfd_archive, NULL))
{
einfo (_("%X%P: %s(%s): can't find member in non-archive file"),
- ibfd->my_archive->filename, ibfd->filename);
+ bfd_get_filename (ibfd->my_archive),
+ bfd_get_filename (ibfd));
return;
}
newbfd = NULL;
while ((newbfd = bfd_openr_next_archived_file (arbfd, newbfd)) != 0)
{
- if (filename_cmp (newbfd->filename, ibfd->filename) == 0)
+ if (filename_cmp (bfd_get_filename (newbfd),
+ bfd_get_filename (ibfd)) == 0)
break;
}
if (!newbfd)
{
einfo (_("%X%P: %s(%s): can't find member in archive"),
- ibfd->my_archive->filename, ibfd->filename);
+ bfd_get_filename (ibfd->my_archive),
+ bfd_get_filename (ibfd));
return;
}
}
struct coff_link_hash_entry *h;
h = coff_link_hash_lookup (coff_hash_table (info), internal,
- FALSE, FALSE, FALSE);
+ false, false, false);
if (h != NULL
/* If the symbol is hidden and undefined then it
has been swept up by garbage collection. */
sprintf (name, "_%s", internal);
h = coff_link_hash_lookup (coff_hash_table (info), name,
- FALSE, FALSE, FALSE);
+ false, false, false);
free (name);
if (h != NULL
}
}
- n = make_one (def->exports + i, outarch,
- ! (def->exports + i)->flag_data);
+ n = make_one (def->exports + i, outarch, !(def->exports + i)->flag_data);
n->archive_next = head;
head = n;
def->exports[i].internal_name = internal;
if (kv)
{
- h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
if (h->type == bfd_link_hash_undefined)
goto return_h;
}
if (pe_details->underscored)
lname[0] = '_';
else
- strcpy (lname, lname + 1);
+ /* Use memmove rather than strcpy as that
+ can handle overlapping buffers. */
+ memmove (lname, lname + 1, strlen (lname));
key.key = lname;
kv = bsearch (&key, udef_table, undef_count,
sizeof (struct key_value), undef_sort_cmp);
if (kv)
{
- h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
if (h->type == bfd_link_hash_undefined)
goto return_h;
}
sizeof (struct key_value), undef_sort_cmp);
if (kv)
{
- h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
if (h->type == bfd_link_hash_undefined)
goto return_h;
}
if (kv)
{
- h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
if (h->type == bfd_link_hash_undefined)
goto return_h;
}
if (kv)
{
- h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
if (h->type == bfd_link_hash_undefined)
goto return_h;
}
return h;
}
-static bfd_boolean
+static bool
pe_undef_count (struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
void *inf ATTRIBUTE_UNUSED)
{
if (h->type == bfd_link_hash_undefined)
undef_count++;
- return TRUE;
+ return true;
}
-static bfd_boolean
+static bool
pe_undef_fill (struct bfd_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
{
if (h->type == bfd_link_hash_undefined)
udef_table[undef_count].oname = h->root.string;
undef_count++;
}
- return TRUE;
+ return true;
}
static void
void
pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
{
- int i, j;
- def_file_module *module;
- def_file_import *imp;
-
pe_dll_id_target (bfd_get_target (output_bfd));
- if (!pe_def_file)
- return;
-
- imp = pe_def_file->imports;
-
- pe_create_undef_table ();
-
- for (module = pe_def_file->modules; module; module = module->next)
+ if (pe_def_file)
{
- int do_this_dll = 0;
+ int i, j;
+ def_file_module *module;
+ def_file_import *imp;
- for (i = 0; i < pe_def_file->num_imports && imp[i].module != module; i++)
- ;
- if (i >= pe_def_file->num_imports)
- continue;
+ imp = pe_def_file->imports;
- dll_filename = module->name;
- dll_symname = xstrdup (module->name);
- for (j = 0; dll_symname[j]; j++)
- if (!ISALNUM (dll_symname[j]))
- dll_symname[j] = '_';
+ pe_create_undef_table ();
- for (; i < pe_def_file->num_imports && imp[i].module == module; i++)
+ for (module = pe_def_file->modules; module; module = module->next)
{
- def_file_export exp;
- struct bfd_link_hash_entry *blhe;
- int lead_at = (*imp[i].internal_name == '@');
- /* See if we need this import. */
- size_t len = strlen (imp[i].internal_name);
- char *name = xmalloc (len + 2 + 6);
- bfd_boolean include_jmp_stub = FALSE;
- bfd_boolean is_cdecl = FALSE;
- bfd_boolean is_undef = FALSE;
-
- if (!lead_at && strchr (imp[i].internal_name, '@') == NULL)
- is_cdecl = TRUE;
-
- if (lead_at)
- sprintf (name, "%s", imp[i].internal_name);
- else
- sprintf (name, "%s%s",U (""), imp[i].internal_name);
+ int do_this_dll = 0;
+
+ for (i = 0; i < pe_def_file->num_imports; i++)
+ if (imp[i].module == module)
+ break;
+ if (i >= pe_def_file->num_imports)
+ continue;
- blhe = bfd_link_hash_lookup (linfo->hash, name,
- FALSE, FALSE, FALSE);
+ dll_filename = module->name;
+ dll_symname = xstrdup (module->name);
+ for (j = 0; dll_symname[j]; j++)
+ if (!ISALNUM (dll_symname[j]))
+ dll_symname[j] = '_';
- /* Include the jump stub for <sym> only if the <sym>
- is undefined. */
- if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
+ for (; i < pe_def_file->num_imports && imp[i].module == module; i++)
{
+ def_file_export exp;
+ struct bfd_link_hash_entry *blhe;
+ int lead_at = (*imp[i].internal_name == '@');
+ /* See if we need this import. */
+ size_t len = strlen (imp[i].internal_name);
+ char *name = xmalloc (len + 2 + 6);
+ bool include_jmp_stub = false;
+ bool is_cdecl = false;
+ bool is_undef = false;
+
+ if (!lead_at && strchr (imp[i].internal_name, '@') == NULL)
+ is_cdecl = true;
+
if (lead_at)
- sprintf (name, "%s%s", "__imp_", imp[i].internal_name);
+ sprintf (name, "%s", imp[i].internal_name);
else
- sprintf (name, "%s%s%s", "__imp_", U (""),
- imp[i].internal_name);
+ sprintf (name, "%s%s",U (""), imp[i].internal_name);
blhe = bfd_link_hash_lookup (linfo->hash, name,
- FALSE, FALSE, FALSE);
- if (blhe)
- is_undef = (blhe->type == bfd_link_hash_undefined);
- }
- else
- {
- include_jmp_stub = TRUE;
- is_undef = (blhe->type == bfd_link_hash_undefined);
- }
+ false, false, false);
- if (is_cdecl && (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)))
- {
- sprintf (name, "%s%s",U (""), imp[i].internal_name);
- blhe = pe_find_cdecl_alias_match (linfo, name);
- include_jmp_stub = TRUE;
- if (blhe)
- is_undef = (blhe->type == bfd_link_hash_undefined);
- }
+ /* Include the jump stub for <sym> only if the <sym>
+ is undefined. */
+ if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
+ {
+ if (lead_at)
+ sprintf (name, "%s%s", "__imp_", imp[i].internal_name);
+ else
+ sprintf (name, "%s%s%s", "__imp_", U (""),
+ imp[i].internal_name);
+
+ blhe = bfd_link_hash_lookup (linfo->hash, name,
+ false, false, false);
+ if (blhe)
+ is_undef = (blhe->type == bfd_link_hash_undefined);
+
+ if (is_cdecl && (!blhe || !is_undef))
+ {
+ blhe = pe_find_cdecl_alias_match (linfo, name + 6);
+ include_jmp_stub = true;
+ if (blhe)
+ is_undef = (blhe->type == bfd_link_hash_undefined);
+ }
+ }
+ else
+ {
+ include_jmp_stub = true;
+ is_undef = (blhe->type == bfd_link_hash_undefined);
+ }
- free (name);
+ free (name);
- if (is_undef)
- {
- bfd *one;
- /* We do. */
- if (!do_this_dll)
+ if (is_undef)
{
- bfd *ar_head = make_head (output_bfd);
- add_bfd_to_link (ar_head, ar_head->filename, linfo);
- do_this_dll = 1;
+ bfd *one;
+ /* We do. */
+ if (!do_this_dll)
+ {
+ bfd *ar_head = make_head (output_bfd);
+ add_bfd_to_link (ar_head, bfd_get_filename (ar_head),
+ linfo);
+ do_this_dll = 1;
+ }
+ exp.internal_name = imp[i].internal_name;
+ exp.name = imp[i].name;
+ exp.its_name = imp[i].its_name;
+ exp.ordinal = imp[i].ordinal;
+ exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
+ exp.flag_private = 0;
+ exp.flag_constant = 0;
+ exp.flag_data = imp[i].data;
+ exp.flag_noname = exp.name ? 0 : 1;
+ one = make_one (&exp, output_bfd,
+ !exp.flag_data && include_jmp_stub);
+ add_bfd_to_link (one, bfd_get_filename (one), linfo);
}
- exp.internal_name = imp[i].internal_name;
- exp.name = imp[i].name;
- exp.its_name = imp[i].its_name;
- exp.ordinal = imp[i].ordinal;
- exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
- exp.flag_private = 0;
- exp.flag_constant = 0;
- exp.flag_data = imp[i].data;
- exp.flag_noname = exp.name ? 0 : 1;
- one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub);
- add_bfd_to_link (one, one->filename, linfo);
}
+ if (do_this_dll)
+ {
+ bfd *ar_tail = make_tail (output_bfd);
+ add_bfd_to_link (ar_tail, bfd_get_filename (ar_tail), linfo);
+ }
+
+ free (dll_symname);
}
- if (do_this_dll)
+
+ while (undef_count)
{
- bfd *ar_tail = make_tail (output_bfd);
- add_bfd_to_link (ar_tail, ar_tail->filename, linfo);
+ --undef_count;
+ free (udef_table[undef_count].key);
}
-
- free (dll_symname);
+ free (udef_table);
}
- while (undef_count)
+ if (pe_def_file && pe_def_file->name)
+ dll_filename = pe_def_file->name;
+ else
{
- --undef_count;
- free (udef_table[undef_count].key);
+ dll_filename = bfd_get_filename (output_bfd);
+ for (const char *p = dll_filename; *p; p++)
+ if (*p == '\\' || *p == '/' || *p == ':')
+ dll_filename = p + 1;
}
- free (udef_table);
+ dll_symname = xstrdup (dll_filename);
+ for (int i = 0; dll_symname[i]; i++)
+ if (!ISALNUM (dll_symname[i]))
+ dll_symname[i] = '_';
}
/* We were handed a *.DLL file. Parse it and turn it into a set of
handled, FALSE if not. */
static unsigned int
-pe_get16 (bfd *abfd, int where)
+pe_get16 (bfd *abfd, int where, bool *fail)
{
unsigned char b[2];
- bfd_seek (abfd, (file_ptr) where, SEEK_SET);
- bfd_bread (b, (bfd_size_type) 2, abfd);
+ if (bfd_seek (abfd, where, SEEK_SET) != 0
+ || bfd_read (b, 2, abfd) != 2)
+ {
+ *fail = true;
+ return 0;
+ }
return b[0] + (b[1] << 8);
}
static unsigned int
-pe_get32 (bfd *abfd, int where)
+pe_get32 (bfd *abfd, int where, bool *fail)
{
unsigned char b[4];
- bfd_seek (abfd, (file_ptr) where, SEEK_SET);
- bfd_bread (b, (bfd_size_type) 4, abfd);
+ if (bfd_seek (abfd, where, SEEK_SET) != 0
+ || bfd_read (b, 4, abfd) != 4)
+ {
+ *fail = true;
+ return 0;
+ }
return b[0] + (b[1] << 8) + (b[2] << 16) + ((unsigned) b[3] << 24);
}
return b[0] + (b[1] << 8) + (b[2] << 16) + ((unsigned) b[3] << 24);
}
-bfd_boolean
+bool
pe_implied_import_dll (const char *filename)
{
bfd *dll;
if (!dll)
{
einfo (_("%X%P: open %s: %E\n"), filename);
- return FALSE;
+ return false;
}
+ track_dependency_files (filename);
+
/* PEI dlls seem to be bfd_objects. */
if (!bfd_check_format (dll, bfd_object))
{
+ notdll:
einfo (_("%X%P: %s: this doesn't appear to be a DLL\n"), filename);
- return FALSE;
+ return false;
}
/* Get pe_header, optional header and numbers of directory entries. */
- pe_header_offset = pe_get32 (dll, 0x3c);
+ bool fail = false;
+ pe_header_offset = pe_get32 (dll, 0x3c, &fail);
+ if (fail)
+ goto notdll;
opthdr_ofs = pe_header_offset + 4 + 20;
-#ifdef pe_use_x86_64
- num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4); /* & NumberOfRvaAndSizes. */
+#ifdef pe_use_plus
+ /* NumberOfRvaAndSizes. */
+ num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4, &fail);
#else
- num_entries = pe_get32 (dll, opthdr_ofs + 92);
+ num_entries = pe_get32 (dll, opthdr_ofs + 92, &fail);
#endif
+ if (fail)
+ goto notdll;
/* No import or export directory entry. */
if (num_entries < 1)
- return FALSE;
+ return false;
-#ifdef pe_use_x86_64
- export_rva = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4);
- export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4);
+#ifdef pe_use_plus
+ export_rva = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4, &fail);
+ export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4, &fail);
#else
- export_rva = pe_get32 (dll, opthdr_ofs + 96);
- export_size = pe_get32 (dll, opthdr_ofs + 100);
+ export_rva = pe_get32 (dll, opthdr_ofs + 96, &fail);
+ export_size = pe_get32 (dll, opthdr_ofs + 100, &fail);
#endif
+ if (fail)
+ goto notdll;
/* No export table - nothing to export. */
if (export_size == 0)
- return FALSE;
+ return false;
- nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
+ nsections = pe_get16 (dll, pe_header_offset + 4 + 2, &fail);
secptr = (pe_header_offset + 4 + 20 +
- pe_get16 (dll, pe_header_offset + 4 + 16));
+ pe_get16 (dll, pe_header_offset + 4 + 16, &fail));
+ if (fail)
+ goto notdll;
expptr = 0;
/* Get the rva and size of the export section. */
{
char sname[8];
bfd_vma secptr1 = secptr + 40 * i;
- bfd_vma vaddr = pe_get32 (dll, secptr1 + 12);
- bfd_vma vsize = pe_get32 (dll, secptr1 + 16);
- bfd_vma fptr = pe_get32 (dll, secptr1 + 20);
+ bfd_vma vaddr = pe_get32 (dll, secptr1 + 12, &fail);
+ bfd_vma vsize = pe_get32 (dll, secptr1 + 16, &fail);
+ bfd_vma fptr = pe_get32 (dll, secptr1 + 20, &fail);
- bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
- bfd_bread (sname, (bfd_size_type) 8, dll);
+ if (fail
+ || bfd_seek (dll, secptr1, SEEK_SET) != 0
+ || bfd_read (sname, 8, dll) != 8)
+ goto notdll;
if (vaddr <= export_rva && vaddr + vsize > export_rva)
{
for (i = 0; i < nsections; i++)
{
bfd_vma secptr1 = secptr + 40 * i;
- bfd_vma vsize = pe_get32 (dll, secptr1 + 8);
- bfd_vma vaddr = pe_get32 (dll, secptr1 + 12);
- bfd_vma flags = pe_get32 (dll, secptr1 + 36);
+ bfd_vma vsize = pe_get32 (dll, secptr1 + 8, &fail);
+ bfd_vma vaddr = pe_get32 (dll, secptr1 + 12, &fail);
+ bfd_vma flags = pe_get32 (dll, secptr1 + 36, &fail);
char sec_name[9];
sec_name[8] = '\0';
- bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
- bfd_bread (sec_name, (bfd_size_type) 8, dll);
+ if (fail
+ || bfd_seek (dll, secptr1 + 0, SEEK_SET) != 0
+ || bfd_read (sec_name, 8, dll) != 8)
+ goto notdll;
if (strcmp(sec_name,".data") == 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,".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);
}
}
expdata = xmalloc (export_size);
- bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
- bfd_bread (expdata, (bfd_size_type) export_size, dll);
+ if (bfd_seek (dll, expptr, SEEK_SET) != 0
+ || bfd_read (expdata, export_size, dll) != export_size)
+ goto notdll;
erva = (char *) expdata - export_rva;
if (pe_def_file == 0)
{
if (pe_dll_extra_pe_debug)
printf ("%s is already loaded\n", dllname);
- return TRUE;
+ return true;
}
/* This is an optimized version of the insertion loop, which avoids lots of
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)" : "");
}
- return TRUE;
+ return true;
}
/* Iterate through the list of symbols. */
/* Skip unwanted symbols, which are
exported in buggy auto-import releases. */
- if (! CONST_STRNEQ (erva + name_rva, "__nm_"))
+ if (! startswith (erva + name_rva, "__nm_"))
{
- int is_dup = 0;
+ bool is_dup = false;
/* is_data is true if the address is in the data, rdata or bss
segment. */
is_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)" : "");
}
}
- return TRUE;
+ return true;
}
void
pe_output_file_set_long_section_names (abfd);
process_def_file_and_drectve (abfd, info);
- if (pe_def_file->num_exports == 0 && !bfd_link_pic (info))
- return;
+ if (pe_def_file->num_exports == 0
+ && (!bfd_link_pic (info) || pe_dll_exclude_all_symbols))
+ {
+ if (pe_dll_enable_reloc_section)
+ {
+ build_filler_bfd (false /* edata not needed. */);
+ pe_output_file_set_long_section_names (filler_bfd);
+ }
+ return;
+ }
- generate_edata (abfd, info);
- build_filler_bfd (1);
+ generate_edata ();
+ build_filler_bfd (true /* edata is needed. */);
pe_output_file_set_long_section_names (filler_bfd);
}
void
pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
{
- pe_dll_id_target (bfd_get_target (abfd));
- pe_output_file_set_long_section_names (abfd);
- image_base = pe_data (abfd)->pe_opthdr.ImageBase;
+ pe_exe_fill_sections (abfd, info);
- generate_reloc (abfd, info);
- if (reloc_sz > 0)
+ if (edata_s)
{
- bfd_set_section_size (reloc_s, reloc_sz);
-
- /* Resize the sections. */
- lang_reset_memory_regions ();
- lang_size_sections (NULL, TRUE);
-
- /* Redo special stuff. */
- ldemul_after_allocation ();
-
- /* Do the assignments again. */
- lang_do_assignments (lang_final_phase_enum);
+ fill_edata (abfd, info);
+ edata_s->contents = edata_d;
}
- fill_edata (abfd, info);
-
if (bfd_link_dll (info))
pe_data (abfd)->dll = 1;
-
- edata_s->contents = edata_d;
- reloc_s->contents = reloc_d;
}
void
image_base = pe_data (abfd)->pe_opthdr.ImageBase;
generate_reloc (abfd, info);
+
if (reloc_sz > 0)
{
bfd_set_section_size (reloc_s, reloc_sz);
/* Resize the sections. */
lang_reset_memory_regions ();
- lang_size_sections (NULL, TRUE);
+ lang_size_sections (NULL, true);
/* Redo special stuff. */
ldemul_after_allocation ();
/* 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;
}
- reloc_s->contents = reloc_d;
}
-bfd_boolean
+bool
pe_bfd_is_dll (bfd *abfd)
{
return (bfd_get_format (abfd) == bfd_object