/* Routines to help build PEI-format DLLs (Win32 etc)
- Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
Written by DJ Delorie <dj@cygnus.com>
This file is part of GLD, the Gnu Linker.
int pe_dll_do_default_excludes = 1;
int pe_dll_kill_ats = 0;
int pe_dll_stdcall_aliases = 0;
+int pe_dll_warn_dup_exports = 0;
+int pe_dll_compat_implib = 0;
/************************************************************************
} pe_details_type;
#define PE_ARCH_i386 1
+#define PE_ARCH_sh 2
+#define PE_ARCH_mips 3
+#define PE_ARCH_arm 4
static pe_details_type pe_detail_list[] = {
{
bfd_arch_i386,
1
},
+ {
+ "pei-shl",
+ "pe-shl",
+ 16 /* R_SH_IMAGEBASE */,
+ PE_ARCH_sh,
+ bfd_arch_sh,
+ 1
+ },
+ {
+ "pei-mips",
+ "pe-mips",
+ 34 /* MIPS_R_RVA */,
+ PE_ARCH_mips,
+ bfd_arch_mips,
+ 0
+ },
+ {
+ "pei-arm-little",
+ "pe-arm-little",
+ 11 /* ARM_RVA32 */,
+ PE_ARCH_arm,
+ bfd_arch_arm,
+ 0
+ },
{ NULL, NULL, 0, 0, 0, 0 }
};
{
if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)
{
- /* This is a duplicate */
+ /* This is a duplicate. */
if (e[j - 1].ordinal != -1
&& e[i].ordinal != -1
&& e[j - 1].ordinal != e[i].ordinal)
{
- /* xgettext:c-format */
- einfo (_("%XError, duplicate EXPORT with oridinals: %s (%d vs %d)\n"),
- e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);
+ if (pe_dll_warn_dup_exports)
+ /* xgettext:c-format */
+ einfo (_("%XError, duplicate EXPORT with oridinals: %s (%d vs %d)\n"),
+ e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);
}
else
{
- /* xgettext:c-format */
- einfo (_("Warning, duplicate EXPORT: %s\n"),
- e[j - 1].name);
+ if (pe_dll_warn_dup_exports)
+ /* xgettext:c-format */
+ einfo (_("Warning, duplicate EXPORT: %s\n"),
+ e[j - 1].name);
}
if (e[i].ordinal)
e[j - 1].ordinal = e[i].ordinal;
name,
false, false, true);
- if (blhe && (blhe->type == bfd_link_hash_defined))
+ if (blhe
+ && (blhe->type == bfd_link_hash_defined
+ || (blhe->type == bfd_link_hash_common)))
{
count_exported++;
if (!pe_def_file->exports[i].flag_noname)
count_exported_byname++;
- exported_symbol_offsets[i] = blhe->u.def.value;
- exported_symbol_sections[i] = blhe->u.def.section;
+
+ /* Only fill in the sections. The actual offsets are computed
+ in fill_exported_offsets() after common symbols are laid
+ out. */
+ if (blhe->type == bfd_link_hash_defined)
+ exported_symbol_sections[i] = blhe->u.def.section;
+ else
+ exported_symbol_sections[i] = blhe->u.c.p->section;
+
if (pe_def_file->exports[i].ordinal != -1)
{
if (max_ordinal < pe_def_file->exports[i].ordinal)
+ name_table_size + strlen (dll_name) + 1);
}
+/* Fill the exported symbol offsets. The preliminary work has already
+ been done in process_def_file(). */
+
+static void
+fill_exported_offsets (abfd, info)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ struct bfd_link_info *info;
+{
+ int i;
+ struct bfd_link_hash_entry *blhe;
+
+ for (i = 0; i < pe_def_file->num_exports; i++)
+ {
+ char *name = (char *) xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
+ if (pe_details->underscored)
+ {
+ *name = '_';
+ strcpy (name + 1, pe_def_file->exports[i].internal_name);
+ }
+ else
+ strcpy (name, pe_def_file->exports[i].internal_name);
+
+ blhe = bfd_link_hash_lookup (info->hash,
+ name,
+ false, false, true);
+
+ if (blhe && (blhe->type == bfd_link_hash_defined))
+ {
+ exported_symbol_offsets[i] = blhe->u.def.value;
+ }
+ free (name);
+ }
+}
+
static void
fill_edata (abfd, info)
bfd *abfd;
bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32);
bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36);
+ fill_exported_offsets (abfd, info);
+
/* Ok, now for the filling in part */
hint = 0;
for (i = 0; i < export_table_size; i++)
+ sym->section->output_offset
+ sym->section->output_section->vma);
reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
- switch (relocs[i]->howto->bitsize*1000
- + relocs[i]->howto->rightshift)
+
+#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
+
+ switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
+ relocs[i]->howto->rightshift)
{
- case 32000:
+ case BITS_AND_SHIFT (32, 0):
reloc_data[total_relocs].type = 3;
total_relocs++;
break;
+ case BITS_AND_SHIFT (16, 0):
+ reloc_data[total_relocs].type = 2;
+ total_relocs++;
+ break;
+ case BITS_AND_SHIFT (16, 16):
+ reloc_data[total_relocs].type = 4;
+ /* 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 it zero is safe. */
+ reloc_data[total_relocs].extra = 0;
+ total_relocs++;
+ break;
+ case BITS_AND_SHIFT (26, 2):
+ reloc_data[total_relocs].type = 5;
+ total_relocs++;
+ break;
default:
/* xgettext:c-format */
einfo (_("%XError: %d-bit reloc in dll\n"),
for (i = 0; i < total_relocs; i++)
{
unsigned long this_page = (reloc_data[i].vma >> 12);
+
if (this_page != sec_page)
{
reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align */
reloc_sz += 8;
sec_page = this_page;
}
+
reloc_sz += 2;
+
+ if (reloc_data[i].type == 4)
+ reloc_sz += 2;
}
reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align */
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
};
+/*
+ *_function:
+ * mov.l ip+8,r0
+ * mov.l @r0,r0
+ * jmp @r0
+ * nop
+ * .dw __imp_function
+ */
+
+static unsigned char jmp_sh_bytes[] = {
+ 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/*
+ *_function:
+ * lui $t0,<high:__imp_function>
+ * lw $t0,<low:__imp_function>
+ * jr $t0
+ * nop
+ */
+
+static unsigned char jmp_mips_bytes[] = {
+ 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d,
+ 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+};
static bfd *
make_one (exp, parent)
bfd *parent;
{
asection *tx, *id7, *id5, *id4, *id6;
- unsigned char *td, *d7, *d5, *d4, *d6;
+ unsigned char *td, *d7, *d5, *d4, *d6 = NULL;
int len;
char *oname;
bfd *abfd;
- unsigned char *jmp_bytes;
- int jmp_byte_count;
+ unsigned char *jmp_bytes = NULL;
+ int jmp_byte_count = 0;
switch (pe_details->pe_arch)
{
jmp_bytes = jmp_ix86_bytes;
jmp_byte_count = sizeof (jmp_ix86_bytes);
break;
+ case PE_ARCH_sh:
+ jmp_bytes = jmp_sh_bytes;
+ jmp_byte_count = sizeof (jmp_sh_bytes);
+ break;
+ case PE_ARCH_mips:
+ jmp_bytes = jmp_mips_bytes;
+ jmp_byte_count = sizeof (jmp_mips_bytes);
+ break;
}
oname = (char *) xmalloc (20);
id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
- quick_symbol (abfd, U(""), exp->internal_name, "", tx, BSF_GLOBAL, 0);
+ if (! exp->flag_data)
+ quick_symbol (abfd, U(""), exp->internal_name, "", tx, BSF_GLOBAL, 0);
quick_symbol (abfd, U("_head_"), dll_symname, "", UNDSEC, BSF_GLOBAL, 0);
quick_symbol (abfd, U("__imp_"), exp->internal_name, "", id5, BSF_GLOBAL, 0);
- quick_symbol (abfd, U("_imp__"), exp->internal_name, "", id5, BSF_GLOBAL, 0);
+ if (pe_dll_compat_implib)
+ quick_symbol (abfd, U("__imp_"), exp->internal_name, "",
+ id5, BSF_GLOBAL, 0);
bfd_set_section_size (abfd, tx, jmp_byte_count);
td = (unsigned char *) xmalloc (jmp_byte_count);
case PE_ARCH_i386:
quick_reloc (abfd, 2, BFD_RELOC_32, 2);
break;
+ case PE_ARCH_sh:
+ quick_reloc (abfd, 8, BFD_RELOC_32, 2);
+ break;
+ case PE_ARCH_mips:
+ quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2);
+ quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */
+ quick_reloc (abfd, 4, BFD_RELOC_LO16, 2);
+ break;
}
save_relocs (tx);
bfd *outarch;
bfd *head = 0;
- dll_filename = def->name;
- if (dll_filename == 0)
- {
- dll_filename = dll_name;
- for (i=0; impfilename[i]; i++)
- if (impfilename[i] == '/' || impfilename[i] == '\\')
- dll_filename = impfilename+1;
- }
+ dll_filename = (def->name) ? def->name : dll_name;
dll_symname = xstrdup (dll_filename);
for (i=0; dll_symname[i]; i++)
if (!isalnum ((unsigned char) dll_symname[i]))