* pe-dll.c (process_def_file): properly note undefined exported

symbols, clean up old code.
	(pe_dll_generate_def_file): don't crash if pe_def_file is NULL
	* emultempl/pe.em (gld_i386_parse_args): add
 	(en/dis)able-stdcall-fixups
	(pe_fixup_stdcalls): warn about stdcall fixups
	(gld_i386_unrecognized_file): make exported symbols undefs so that
 	archive members get pulled in
This commit is contained in:
DJ Delorie
1998-11-10 22:57:13 +00:00
parent bb7c5d2a02
commit e2586bc8de
3 changed files with 196 additions and 123 deletions

View File

@ -1,3 +1,14 @@
Tue Nov 10 17:53:17 1998 DJ Delorie <dj@cygnus.com>
* pe-dll.c (process_def_file): properly note undefined exported
symbols, clean up old code.
(pe_dll_generate_def_file): don't crash if pe_def_file is NULL
* emultempl/pe.em (gld_i386_parse_args): add
(en/dis)able-stdcall-fixups
(pe_fixup_stdcalls): warn about stdcall fixups
(gld_i386_unrecognized_file): make exported symbols undefs so that
archive members get pulled in
Tue Nov 10 14:50:51 1998 Catherine Moore <clm@cygnus.com> Tue Nov 10 14:50:51 1998 Catherine Moore <clm@cygnus.com>
* scripttempl/elfd10v.sc: Add KEEP attribute to .init, * scripttempl/elfd10v.sc: Add KEEP attribute to .init,

View File

@ -69,6 +69,7 @@ int pe_dll_export_everything = 0;
int pe_dll_do_default_excludes = 1; int pe_dll_do_default_excludes = 1;
int pe_dll_kill_ats = 0; int pe_dll_kill_ats = 0;
int pe_dll_stdcall_aliases = 0; int pe_dll_stdcall_aliases = 0;
int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable */
extern const char *output_filename; extern const char *output_filename;
@ -105,6 +106,8 @@ gld_${EMULATION_NAME}_before_parse()
#define OPTION_EXCLUDE_SYMBOLS (OPTION_EXPORT_ALL + 1) #define OPTION_EXCLUDE_SYMBOLS (OPTION_EXPORT_ALL + 1)
#define OPTION_KILL_ATS (OPTION_EXCLUDE_SYMBOLS + 1) #define OPTION_KILL_ATS (OPTION_EXCLUDE_SYMBOLS + 1)
#define OPTION_STDCALL_ALIASES (OPTION_KILL_ATS + 1) #define OPTION_STDCALL_ALIASES (OPTION_KILL_ATS + 1)
#define OPTION_ENABLE_STDCALL_FIXUP (OPTION_STDCALL_ALIASES + 1)
#define OPTION_DISABLE_STDCALL_FIXUP (OPTION_ENABLE_STDCALL_FIXUP + 1)
static struct option longopts[] = static struct option longopts[] =
{ {
@ -132,6 +135,8 @@ static struct option longopts[] =
{"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS}, {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
{"kill-at", no_argument, NULL, OPTION_KILL_ATS}, {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
{"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES}, {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
{"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
{"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
{NULL, no_argument, NULL, 0} {NULL, no_argument, NULL, 0}
}; };
@ -198,6 +203,8 @@ gld_${EMULATION_NAME}_list_options (file)
fprintf (file, _(" --exclude-symbols sym,sym,... Exclude symbols from automatic export\n")); fprintf (file, _(" --exclude-symbols sym,sym,... Exclude symbols from automatic export\n"));
fprintf (file, _(" --kill-at Remove @nn from exported symbols\n")); fprintf (file, _(" --kill-at Remove @nn from exported symbols\n"));
fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n")); fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n"));
fprintf (file, _(" --enable-stdcall-fixup Link _sym to _sym@nn without warnings\n"));
fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n"));
} }
static void static void
@ -411,6 +418,12 @@ gld_${EMULATION_NAME}_parse_args(argc, argv)
case OPTION_STDCALL_ALIASES: case OPTION_STDCALL_ALIASES:
pe_dll_stdcall_aliases = 1; pe_dll_stdcall_aliases = 1;
break; break;
case OPTION_ENABLE_STDCALL_FIXUP:
pe_enable_stdcall_fixup = 1;
break;
case OPTION_DISABLE_STDCALL_FIXUP:
pe_enable_stdcall_fixup = 0;
break;
} }
return 1; return 1;
} }
@ -516,6 +529,7 @@ pe_undef_cdecl_match (h, string)
static void static void
pe_fixup_stdcalls () pe_fixup_stdcalls ()
{ {
static int gave_warning_message = 0;
struct bfd_link_hash_entry *undef, *sym; struct bfd_link_hash_entry *undef, *sym;
char *at; char *at;
for (undef = link_info.hash->undefs; undef; undef=undef->next) for (undef = link_info.hash->undefs; undef; undef=undef->next)
@ -535,6 +549,17 @@ pe_fixup_stdcalls ()
undef->type = bfd_link_hash_defined; undef->type = bfd_link_hash_defined;
undef->u.def.value = sym->u.def.value; undef->u.def.value = sym->u.def.value;
undef->u.def.section = sym->u.def.section; undef->u.def.section = sym->u.def.section;
if (pe_enable_stdcall_fixup == -1)
{
einfo (_("Warning: resolving %s by linking to %s\n"),
undef->root.string, cname);
if (! gave_warning_message)
{
gave_warning_message = 1;
einfo(_("Use --enable-stdcall-fixup to disable these warnings\n"));
einfo(_("Use --disable-stdcall-fixup to disable these fixups\n"));
}
}
} }
} }
else else
@ -550,6 +575,17 @@ pe_fixup_stdcalls ()
undef->type = bfd_link_hash_defined; undef->type = bfd_link_hash_defined;
undef->u.def.value = sym->u.def.value; undef->u.def.value = sym->u.def.value;
undef->u.def.section = sym->u.def.section; undef->u.def.section = sym->u.def.section;
if (pe_enable_stdcall_fixup == -1)
{
einfo (_("Warning: resolving %s by linking to %s\n"),
undef->root.string, sym->root.string);
if (! gave_warning_message)
{
gave_warning_message = 1;
einfo(_("Use --enable-stdcall-fixup to disable these warnings\n"));
einfo(_("Use --disable-stdcall-fixup to disable these fixups\n"));
}
}
} }
} }
} }
@ -568,7 +604,8 @@ gld_${EMULATION_NAME}_after_open ()
pe_data (output_bfd)->pe_opthdr = pe; pe_data (output_bfd)->pe_opthdr = pe;
pe_data (output_bfd)->dll = init[DLLOFF].value; pe_data (output_bfd)->dll = init[DLLOFF].value;
pe_fixup_stdcalls (); if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
pe_fixup_stdcalls ();
#ifdef TARGET_IS_i386pe #ifdef TARGET_IS_i386pe
if (link_info.shared) if (link_info.shared)
@ -660,6 +697,32 @@ gld_${EMULATION_NAME}_unrecognized_file(entry)
def_file_parse (entry->filename, pe_def_file); def_file_parse (entry->filename, pe_def_file);
if (pe_def_file) if (pe_def_file)
{ {
int i, buflen=0, len;
char *buf;
for (i=0; i<pe_def_file->num_exports; i++)
{
len = strlen(pe_def_file->exports[i].internal_name);
if (buflen < len+2)
buflen = len+2;
}
buf = (char *) xmalloc (buflen);
for (i=0; i<pe_def_file->num_exports; i++)
{
struct bfd_link_hash_entry *h;
sprintf(buf, "_%s", pe_def_file->exports[i].internal_name);
h = bfd_link_hash_lookup (link_info.hash, buf, true, true, true);
if (h == (struct bfd_link_hash_entry *) NULL)
einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
if (h->type == bfd_link_hash_new)
{
h->type = bfd_link_hash_undefined;
h->u.undef.abfd = NULL;
bfd_link_add_undef (link_info.hash, h);
}
}
free (buf);
/* def_file_print (stdout, pe_def_file); */ /* def_file_print (stdout, pe_def_file); */
if (pe_def_file->is_dll == 1) if (pe_def_file->is_dll == 1)
link_info.shared = 1; link_info.shared = 1;

View File

@ -342,11 +342,18 @@ process_def_file (abfd, info)
count_with_ordinals++; count_with_ordinals++;
} }
} }
else if (blhe && blhe->type == bfd_link_hash_undefined)
{
/* xgettext:c-format */
einfo (_("%XCannot export %s: symbol not defined\n"),
pe_def_file->exports[i].internal_name);
}
else if (blhe) else if (blhe)
{ {
/* xgettext:c-format */ /* xgettext:c-format */
einfo (_("%XCannot export %s: symbol wrong type\n"), einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"),
pe_def_file->exports[i].internal_name); pe_def_file->exports[i].internal_name,
blhe->type, bfd_link_hash_defined);
} }
else else
{ {
@ -356,19 +363,6 @@ process_def_file (abfd, info)
} }
free(name); free(name);
} }
#if 0
/* For now, just export all global functions. Read DEF files later */
for (i = 0; i < num_input_bfds; i++)
{
for (j = 0; j < symtab[i].nsyms; j++)
{
if ((symtab[i].symbols[j]->flags & (BSF_FUNCTION | BSF_GLOBAL))
== (BSF_FUNCTION | BSF_GLOBAL))
symtab[i].exported[j] = 1;
}
}
#endif
} }
/************************************************************************ /************************************************************************
@ -755,119 +749,124 @@ pe_dll_generate_def_file (pe_out_def_filename)
program_name, pe_out_def_filename); program_name, pe_out_def_filename);
} }
if (pe_def_file->name) if (pe_def_file)
{ {
if (pe_def_file->is_dll) if (pe_def_file->name)
fprintf (out, "LIBRARY ");
else
fprintf (out, "NAME ");
quoteput (pe_def_file->name, out, 1);
if (pe_def_file->base_address != (bfd_vma) (-1))
fprintf (out, " BASE=0x%x", pe_def_file->base_address);
fprintf (out, "\n");
}
if (pe_def_file->description)
{
fprintf (out, "DESCRIPTION ");
quoteput (pe_def_file->description, out, 1);
fprintf (out, "\n");
}
if (pe_def_file->version_minor)
fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major,
pe_def_file->version_minor);
else
fprintf (out, "VERSION %d\n", pe_def_file->version_major);
if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1)
fprintf (out, "\n");
if (pe_def_file->stack_commit != -1)
fprintf (out, "STACKSIZE 0x%x,0x%x\n",
pe_def_file->stack_reserve, pe_def_file->stack_commit);
else if (pe_def_file->stack_reserve != -1)
fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve);
if (pe_def_file->heap_commit != -1)
fprintf (out, "HEAPSIZE 0x%x,0x%x\n",
pe_def_file->heap_reserve, pe_def_file->heap_commit);
else if (pe_def_file->heap_reserve != -1)
fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve);
if (pe_def_file->num_section_defs > 0)
{
fprintf (out, "\nSECTIONS\n\n");
for (i = 0; i < pe_def_file->num_section_defs; i++)
{ {
fprintf (out, " "); if (pe_def_file->is_dll)
quoteput (pe_def_file->section_defs[i].name, out, 0); fprintf (out, "LIBRARY ");
if (pe_def_file->section_defs[i].class)
{
fprintf (out, " CLASS ");
quoteput (pe_def_file->section_defs[i].class, out, 0);
}
if (pe_def_file->section_defs[i].flag_read)
fprintf (out, " READ");
if (pe_def_file->section_defs[i].flag_write)
fprintf (out, " WRITE");
if (pe_def_file->section_defs[i].flag_execute)
fprintf (out, " EXECUTE");
if (pe_def_file->section_defs[i].flag_shared)
fprintf (out, " SHARED");
fprintf (out, "\n");
}
}
if (pe_def_file->num_exports > 0)
{
fprintf (out, "\nEXPORTS\n\n");
for (i = 0; i < pe_def_file->num_exports; i++)
{
def_file_export *e = pe_def_file->exports + i;
fprintf (out, " ");
quoteput (e->name, out, 0);
if (e->internal_name && strcmp (e->internal_name, e->name))
{
fprintf (out, " = ");
quoteput (e->internal_name, out, 0);
}
if (e->ordinal != -1)
fprintf (out, " @%d", e->ordinal);
if (e->flag_private)
fprintf (out, " PRIVATE");
if (e->flag_constant)
fprintf (out, " CONSTANT");
if (e->flag_noname)
fprintf (out, " NONAME");
if (e->flag_data)
fprintf (out, " DATA");
fprintf (out, "\n");
}
}
if (pe_def_file->num_imports > 0)
{
fprintf (out, "\nIMPORTS\n\n");
for (i = 0; i < pe_def_file->num_imports; i++)
{
def_file_import *im = pe_def_file->imports + i;
fprintf (out, " ");
if (im->internal_name
&& (!im->name || strcmp (im->internal_name, im->name)))
{
quoteput (im->internal_name, out, 0);
fprintf (out, " = ");
}
quoteput (im->module->name, out, 0);
fprintf (out, ".");
if (im->name)
quoteput (im->name, out, 0);
else else
fprintf (out, "%d", im->ordinal); fprintf (out, "NAME ");
quoteput (pe_def_file->name, out, 1);
if (pe_def_file->base_address != (bfd_vma) (-1))
fprintf (out, " BASE=0x%x", pe_def_file->base_address);
fprintf (out, "\n"); fprintf (out, "\n");
} }
if (pe_def_file->description)
{
fprintf (out, "DESCRIPTION ");
quoteput (pe_def_file->description, out, 1);
fprintf (out, "\n");
}
if (pe_def_file->version_minor)
fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major,
pe_def_file->version_minor);
else
fprintf (out, "VERSION %d\n", pe_def_file->version_major);
if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1)
fprintf (out, "\n");
if (pe_def_file->stack_commit != -1)
fprintf (out, "STACKSIZE 0x%x,0x%x\n",
pe_def_file->stack_reserve, pe_def_file->stack_commit);
else if (pe_def_file->stack_reserve != -1)
fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve);
if (pe_def_file->heap_commit != -1)
fprintf (out, "HEAPSIZE 0x%x,0x%x\n",
pe_def_file->heap_reserve, pe_def_file->heap_commit);
else if (pe_def_file->heap_reserve != -1)
fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve);
if (pe_def_file->num_section_defs > 0)
{
fprintf (out, "\nSECTIONS\n\n");
for (i = 0; i < pe_def_file->num_section_defs; i++)
{
fprintf (out, " ");
quoteput (pe_def_file->section_defs[i].name, out, 0);
if (pe_def_file->section_defs[i].class)
{
fprintf (out, " CLASS ");
quoteput (pe_def_file->section_defs[i].class, out, 0);
}
if (pe_def_file->section_defs[i].flag_read)
fprintf (out, " READ");
if (pe_def_file->section_defs[i].flag_write)
fprintf (out, " WRITE");
if (pe_def_file->section_defs[i].flag_execute)
fprintf (out, " EXECUTE");
if (pe_def_file->section_defs[i].flag_shared)
fprintf (out, " SHARED");
fprintf (out, "\n");
}
}
if (pe_def_file->num_exports > 0)
{
fprintf (out, "\nEXPORTS\n\n");
for (i = 0; i < pe_def_file->num_exports; i++)
{
def_file_export *e = pe_def_file->exports + i;
fprintf (out, " ");
quoteput (e->name, out, 0);
if (e->internal_name && strcmp (e->internal_name, e->name))
{
fprintf (out, " = ");
quoteput (e->internal_name, out, 0);
}
if (e->ordinal != -1)
fprintf (out, " @%d", e->ordinal);
if (e->flag_private)
fprintf (out, " PRIVATE");
if (e->flag_constant)
fprintf (out, " CONSTANT");
if (e->flag_noname)
fprintf (out, " NONAME");
if (e->flag_data)
fprintf (out, " DATA");
fprintf (out, "\n");
}
}
if (pe_def_file->num_imports > 0)
{
fprintf (out, "\nIMPORTS\n\n");
for (i = 0; i < pe_def_file->num_imports; i++)
{
def_file_import *im = pe_def_file->imports + i;
fprintf (out, " ");
if (im->internal_name
&& (!im->name || strcmp (im->internal_name, im->name)))
{
quoteput (im->internal_name, out, 0);
fprintf (out, " = ");
}
quoteput (im->module->name, out, 0);
fprintf (out, ".");
if (im->name)
quoteput (im->name, out, 0);
else
fprintf (out, "%d", im->ordinal);
fprintf (out, "\n");
}
}
} }
else
fprintf (out, _("; no contents available\n"));
if (fclose (out) == EOF) if (fclose (out) == EOF)
{ {