# This shell script emits a C file. -*- C -*-
# It does some substitutions.
-(echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
+rm -f e${EMULATION_NAME}.c
+(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
cat >>e${EMULATION_NAME}.c <<EOF
/* This file is part of GLD, the Gnu Linker.
- Copyright 1995, 96, 97, 98, 1999 Free Software Foundation, Inc.
+ Copyright 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "ldctor.h"
#include "ldfile.h"
#include "coff/internal.h"
+
+/* FIXME: This is a BFD internal header file, and we should not be
+ using it here. */
#include "../bfd/libcoff.h"
-#include "../bfd/libbfd.h"
+
#include "deffile.h"
+#include "pe-dll.h"
#define TARGET_IS_${EMULATION_NAME}
+/* Permit the emulation parameters to override the default section
+ alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes
+ it seem that include/coff/internal.h should not define
+ PE_DEF_SECTION_ALIGNMENT. */
+#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
+#undef PE_DEF_SECTION_ALIGNMENT
+#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
+#endif
+
#if defined(TARGET_IS_i386pe)
#define DLL_SUPPORT
#endif
+#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) || defined(TARGET_IS_armpe)
+#define DLL_SUPPORT
+#endif
+#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT)
#define PE_DEF_SUBSYSTEM 3
+#else
+#undef NT_EXE_IMAGE_BASE
+#undef PE_DEF_SECTION_ALIGNMENT
+#undef PE_DEF_FILE_ALIGNMENT
+#define NT_EXE_IMAGE_BASE 0x00010000
+#ifdef TARGET_IS_armpe
+#define PE_DEF_SECTION_ALIGNMENT 0x00001000
+#define PE_DEF_SUBSYSTEM 9
+#else
+#define PE_DEF_SECTION_ALIGNMENT 0x00000400
+#define PE_DEF_SUBSYSTEM 2
+#endif
+#define PE_DEF_FILE_ALIGNMENT 0x00000200
+#endif
#ifdef TARGET_IS_arm_epoc_pe
#define bfd_arm_pe_allocate_interworking_sections \
static int dll;
static int support_old_code = 0;
static char * thumb_entry_symbol = NULL;
-extern def_file *pe_def_file;
static lang_assignment_statement_type *image_base_statement = 0;
-static char *pe_out_def_filename = 0;
-extern int pe_dll_export_everything;
-extern int pe_dll_kill_ats;
-extern int pe_dll_stdcall_aliases;
static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable */
+#ifdef DLL_SUPPORT
+static char *pe_out_def_filename = 0;
static char *pe_implib_filename = 0;
+#endif
extern const char *output_filename;
static void
gld_${EMULATION_NAME}_before_parse()
{
- output_filename = "a.exe";
+ output_filename = "${EXECUTABLE_NAME:-a.exe}";
ldfile_output_architecture = bfd_arch_${ARCH};
#ifdef DLL_SUPPORT
config.has_shared = 1;
+
+#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
+ lang_add_entry ("WinMainCRTStartup", 1);
+#else
+ lang_add_entry ("_WinMainCRTStartup", 1);
+#endif
+#endif
#endif
}
\f
#define OPTION_DISABLE_STDCALL_FIXUP (OPTION_ENABLE_STDCALL_FIXUP + 1)
#define OPTION_IMPLIB_FILENAME (OPTION_DISABLE_STDCALL_FIXUP + 1)
#define OPTION_THUMB_ENTRY (OPTION_IMPLIB_FILENAME + 1)
+#define OPTION_WARN_DUPLICATE_EXPORTS (OPTION_THUMB_ENTRY + 1)
+#define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1)
static struct option longopts[] =
{
{"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
{"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
{"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
+ {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
+ {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
#endif
{NULL, no_argument, NULL, 0}
};
#define IMAGEBASEOFF 0
D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
#define DLLOFF 1
- {&dll, sizeof(dll), 0, "__dll__"},
+ {&dll, sizeof(dll), 0, "__dll__", 0},
D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
D(MajorOperatingSystemVersion,"__major_os_version__", 4),
D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
D(MajorImageVersion,"__major_image_version__", 1),
D(MinorImageVersion,"__minor_image_version__", 0),
+#ifdef TARGET_IS_armpe
+ D(MajorSubsystemVersion,"__major_subsystem_version__", 2),
+#else
D(MajorSubsystemVersion,"__major_subsystem_version__", 4),
+#endif
D(MinorSubsystemVersion,"__minor_subsystem_version__", 0),
- D(Subsystem,"__subsystem__", PE_DEF_SUBSYSTEM),
+ D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x2000000),
D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
fprintf (file, _(" --kill-at Remove @nn from exported symbols\n"));
fprintf (file, _(" --out-implib <file> Generate import library\n"));
fprintf (file, _(" --output-def <file> Generate a .DEF file for the built DLL\n"));
+ fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n"));
+ fprintf (file, _(" --compat-implib Create backward compatible import libs;\n"));
+ fprintf (file, _(" create __imp_<SYMBOL> as well.\n"));
#endif
}
}
v[] =
{
- { "native", 1, "_NtProcessStartup" },
- { "windows", 2, "_WinMainCRTStartup" },
- { "console", 3, "_mainCRTStartup" },
+ { "native", 1, "NtProcessStartup" },
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
+ { "windows", 2, "WinMainCRTStartup" },
+#else
+ { "windows", 2, "WinMainCRTStartup" },
+#endif
+ { "console", 3, "mainCRTStartup" },
#if 0
/* The Microsoft linker does not recognize this. */
{ "os2", 5, "" },
#endif
- { "posix", 7, "___PosixProcessStartup"},
+ { "posix", 7, "__PosixProcessStartup"},
+ { "wince", 9, "_WinMainCRTStartup" },
{ 0, 0, 0 }
};
if (strncmp (optarg, v[i].name, len) == 0
&& v[i].name[len] == '\0')
{
+ const char *initial_symbol_char;
+ const char *entry;
+
set_pe_name ("__subsystem__", v[i].value);
- lang_add_entry (v[i].entry, 1);
+ initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+ if (*initial_symbol_char == '\0')
+ entry = v[i].entry;
+ else
+ {
+ char *alc_entry;
+
+ /* lang_add_entry expects its argument to be permanently
+ allocated, so we don't free this string. */
+ alc_entry = xmalloc (strlen (initial_symbol_char)
+ + strlen (v[i].entry)
+ + 1);
+ strcpy (alc_entry, initial_symbol_char);
+ strcat (alc_entry, v[i].entry);
+ entry = alc_entry;
+ }
+
+ lang_add_entry (entry, 1);
return;
}
case OPTION_IMPLIB_FILENAME:
pe_implib_filename = xstrdup (optarg);
break;
+ case OPTION_WARN_DUPLICATE_EXPORTS:
+ pe_dll_warn_dup_exports = 1;
+ break;
+ case OPTION_IMP_COMPAT:
+ pe_dll_compat_implib = 1;
+ break;
#endif
}
return 1;
return true;
}
+#ifdef DLL_SUPPORT
static void
pe_fixup_stdcalls ()
{
}
}
}
+#endif /* DLL_SUPPORT */
static void
gld_${EMULATION_NAME}_after_open ()
pe_process_import_defs(output_bfd, &link_info);
if (link_info.shared)
pe_dll_build_sections (output_bfd, &link_info);
+
+#ifndef TARGET_IS_i386pe
+#ifndef TARGET_IS_armpe
+ else
+ pe_exe_build_sections (output_bfd, &link_info);
+#endif
+#endif
#endif
#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
#endif
{
- static int sequence = 0;
- int is_ms_arch;
- bfd *cur_arch = 0, *elt;
+ int is_ms_arch = 0;
+ bfd *cur_arch = 0;
lang_input_statement_type *is2;
+
/* Careful - this is a shell script. Watch those dollar signs! */
/* Microsoft import libraries have every member named the same,
and not in the right order for us to link them correctly. We
thunks, and the sentinel(s). The head is easy; it's the one
with idata2. We assume that the sentinels won't have relocs,
and the thunks will. It's easier than checking the symbol
- table for external references. */
+ table for external references. */
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
if (is->the_bfd->my_archive)
if (is_ms_arch)
{
- int idata2 = 0, i, reloc_count=0;
+ int idata2 = 0, reloc_count=0;
asection *sec;
char *new_name, seq;
+
for (sec = is->the_bfd->sections; sec; sec = sec->next)
{
if (strcmp (sec->name, ".idata\$2") == 0)
else /* sentinel */
seq = 'c';
- new_name = bfd_alloc (is->the_bfd,
- strlen (is->the_bfd->filename)+2);
+ new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
is->the_bfd->filename = new_name;
- new_name = bfd_alloc(is->the_bfd, strlen(is->filename)+2);
+ new_name = xmalloc (strlen(is->filename) + 3);
sprintf (new_name, "%s.%c", is->filename, seq);
is->filename = new_name;
}
/* This is called when an input file isn't recognized as a BFD. We
check here for .DEF files and pull them in automatically. */
-
+#ifdef DLL_SUPPORT
static int
saw_option(char *option)
{
return init[i].inited;
return 0;
}
+#endif
static boolean
gld_${EMULATION_NAME}_unrecognized_file(entry)
- lang_input_statement_type *entry;
+ lang_input_statement_type *entry ATTRIBUTE_UNUSED;
{
#ifdef DLL_SUPPORT
const char *ext = entry->filename + strlen (entry->filename) - 4;
static boolean
gld_${EMULATION_NAME}_recognized_file(entry)
- lang_input_statement_type *entry;
+ lang_input_statement_type *entry ATTRIBUTE_UNUSED;
{
#ifdef DLL_SUPPORT
#ifdef TARGET_IS_i386pe
pe_dll_id_target ("pei-i386");
+#endif
+#ifdef TARGET_IS_shpe
+ pe_dll_id_target ("pei-shl");
+#endif
+#ifdef TARGET_IS_mipspe
+ pe_dll_id_target ("pei-mips");
+#endif
+#ifdef TARGET_IS_armpe
+ pe_dll_id_target ("pei-arm-little");
#endif
if (bfd_get_format (entry->the_bfd) == bfd_object)
{
if (pe_implib_filename)
pe_dll_generate_implib (pe_def_file, pe_implib_filename);
}
+#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe)
+ else
+ {
+ pe_exe_fill_sections (output_bfd, &link_info);
+ }
+#endif
+
if (pe_out_def_filename)
pe_dll_generate_def_file (pe_out_def_filename);
#endif
asection *s;
{
const char *secname;
- char *dollar;
+ char *dollar = NULL;
if ((s->flags & SEC_ALLOC) == 0)
return false;
hold_section = s;
hold_section_name = xstrdup (secname);
- dollar = strchr (hold_section_name, '$');
- if (dollar != NULL)
- *dollar = '\0';
+ if (!link_info.relocateable)
+ {
+ dollar = strchr (hold_section_name, '$');
+ if (dollar != NULL)
+ *dollar = '\0';
+ }
hold_use = NULL;
lang_for_each_statement (gld${EMULATION_NAME}_place_section);
lang_leave_output_section_statement
((bfd_vma) 0, "*default*",
- (struct lang_output_section_phdr_list *) NULL);
+ (struct lang_output_section_phdr_list *) NULL,
+ "*default*");
/* Now stick the new statement list right after PLACE. */
if (place != NULL)
else if (strcmp (os->name, ".bss") == 0)
hold_bss = os;
}
+
+static int
+gld_${EMULATION_NAME}_find_potential_libraries (name, entry)
+ char * name;
+ lang_input_statement_type * entry;
+{
+ return ldfile_open_file_search (name, entry, "", ".lib");
+}
\f
static char *
gld_${EMULATION_NAME}_get_script(isfile)
gld_${EMULATION_NAME}_parse_args,
gld_${EMULATION_NAME}_unrecognized_file,
gld_${EMULATION_NAME}_list_options,
- gld_${EMULATION_NAME}_recognized_file
+ gld_${EMULATION_NAME}_recognized_file,
+ gld_${EMULATION_NAME}_find_potential_libraries
};
EOF