/* 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.
#include "coff/internal.h"
#include "../bfd/libcoff.h"
#include "deffile.h"
+#include "pe-dll.h"
/************************************************************************
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;
/************************************************************************
static bfd *filler_bfd;
static struct sec *edata_s, *reloc_s;
static unsigned char *edata_d, *reloc_d;
-static int edata_sz, reloc_sz;
+static size_t edata_sz, reloc_sz;
typedef struct {
char *target_name;
char *object_target;
- int imagebase_reloc;
+ unsigned int imagebase_reloc;
int pe_arch;
int bfd_arch;
int underscored;
bfd_arch_i386,
1
},
- { 0 }
+ { NULL, NULL, 0, 0, 0, 0 }
};
static pe_details_type *pe_details;
void
pe_dll_id_target (target)
- char *target;
+ const char *target;
{
int i;
for (i=0; pe_detail_list[i].target_name; i++)
static void
process_def_file (abfd, info)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
int i, j;
{
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)
static void
generate_edata (abfd, info)
bfd *abfd;
- struct bfd_link_info *info;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
{
int i, next_ordinal;
int name_table_size = 0;
+ 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_edata (abfd, info)
+fill_exported_offsets (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
+{
+ int i, j;
+ struct bfd_link_hash_entry *blhe;
+ bfd *b;
+ struct sec *s;
+ def_file_export *e=0;
+
+ 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;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
{
int i, hint;
unsigned char *edirectory;
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++)
void
pe_dll_generate_def_file (pe_out_def_filename)
- char *pe_out_def_filename;
+ const char *pe_out_def_filename;
{
int i;
FILE *out = fopen (pe_out_def_filename, "w");
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);
void
pe_dll_generate_implib (def, impfilename)
def_file *def;
- char *impfilename;
+ const char *impfilename;
{
int i;
bfd *ar_head;
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]))
boolean
pe_implied_import_dll (filename)
- char *filename;
+ const char *filename;
{
bfd *dll;
unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
unsigned long export_rva, export_size, nsections, secptr, expptr;
unsigned char *expdata, *erva;
unsigned long name_rvas, ordinals, nexp, ordbase;
- char *dll_name;
+ const char *dll_name;
/* No, I can't use bfd here. kernel32.dll puts its export table in
the middle of the .rdata section. */
void
pe_exe_build_sections (abfd, info)
bfd *abfd;
- struct bfd_link_info *info;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
{
pe_dll_id_target (bfd_get_target (abfd));
build_filler_bfd (0);