/* nlmconv.c -- NLM conversion program
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-This file is part of GNU Binutils.
+ This file is part of GNU Binutils.
-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
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ 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
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by Ian Lance Taylor <ian@cygnus.com>.
This program can be used to convert any appropriate object file
into a NetWare Loadable Module (an NLM). It will accept a linker
specification file which is identical to that accepted by the
- NetWare linker, NLMLINK, except that the INPUT command, normally
- used to give a list of object files to link together, is not used.
- This program will convert only a single object file. */
+ NetWare linker, NLMLINK. */
+
+/* AIX requires this to be the first thing in the file. */
+#ifndef __GNUC__
+# ifdef _AIX
+ #pragma alloca
+#endif
+#endif
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
-#include <ansidecl.h>
-#include <stdio.h>
+#include "ansidecl.h"
#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <assert.h>
-#include <getopt.h>
-#include <bfd.h>
-#include <libiberty.h>
-#include "sysdep.h"
-#include "bucomm.h"
+#include "getopt.h"
+
/* Internal BFD NLM header. */
#include "libnlm.h"
#include "nlmconv.h"
-/* Needed for Alpha support. */
+#ifdef NLMCONV_ALPHA
#include "coff/sym.h"
#include "coff/ecoff.h"
+#endif
+
+#include "bucomm.h"
/* If strerror is just a macro, we want to use the one from libiberty
since it will handle undefined values. */
#undef strerror
-extern char *strerror ();
-
-#ifndef localtime
-extern struct tm *localtime ();
-#endif
-
-#ifndef getenv
-extern char *getenv ();
-#endif
+extern char *strerror (int);
#ifndef SEEK_SET
#define SEEK_SET 0
/* The name used to invoke the program. */
char *program_name;
-/* The version number. */
-extern char *program_version;
-
/* Local variables. */
/* Whether to print out debugging information (currently just controls
/* The symbol table. */
static asymbol **symbols;
+/* A section we create in the output file to hold pointers to where
+ the sections of the input file end up. We will put a pointer to
+ this section in the NLM header. These is an entry for each input
+ section. The format is
+ null terminated section name
+ zeroes to adjust to 4 byte boundary
+ 4 byte section data file pointer
+ 4 byte section size
+ We don't need a version number. The way we find this information
+ is by finding a stamp in the NLM header information. If we need to
+ change the format of this information, we can simply change the
+ stamp. */
+static asection *secsec;
+
/* A temporary file name to be unlinked on exit. Actually, for most
errors, we leave it around. It's not clear whether that is helpful
or not. */
/* Local routines. */
-static void show_help PARAMS ((void));
-static void show_usage PARAMS ((FILE *, int));
-static const char *select_output_format PARAMS ((enum bfd_architecture,
- unsigned long, boolean));
-static void setup_sections PARAMS ((bfd *, asection *, PTR));
-static void copy_sections PARAMS ((bfd *, asection *, PTR));
-static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
- long *, char *,
- bfd_size_type));
-static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
- long *, char *,
- bfd_size_type));
-static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
- long *, char *,
- bfd_size_type));
-/* start-sanitize-powerpc-netware */
-static void powerpc_build_stubs PARAMS ((bfd *, asymbol ***, long *));
-static void powerpc_resolve_stubs PARAMS ((bfd *, bfd *));
-static void powerpc_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
- long *, char *,
- bfd_size_type));
-/* end-sanitize-powerpc-netware */
-static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
- long *, char *,
- bfd_size_type));
-static char *link_inputs PARAMS ((struct string_list *, char *));
-static const char *choose_temp_base_try PARAMS ((const char *,
- const char *));
-static void choose_temp_base PARAMS ((void));
-static int pexecute PARAMS ((char *, char *[]));
+int main (int, char **);
+
+static void show_usage (FILE *, int);
+static const char *select_output_format
+ (enum bfd_architecture, unsigned long, bfd_boolean);
+static void setup_sections (bfd *, asection *, void *);
+static void copy_sections (bfd *, asection *, void *);
+static void mangle_relocs
+ (bfd *, asection *, arelent ***, long *, char *, bfd_size_type);
+static void default_mangle_relocs
+ (bfd *, asection *, arelent ***, long *, char *, bfd_size_type);
+static char *link_inputs (struct string_list *, char *, char *);
+
+#ifdef NLMCONV_I386
+static void i386_mangle_relocs (bfd *, asection *, arelent ***, long *, char *, bfd_size_type);
+#endif
+
+#ifdef NLMCONV_ALPHA
+static void alpha_mangle_relocs (bfd *, asection *, arelent ***, long *, char *, bfd_size_type);
+#endif
+
+#ifdef NLMCONV_POWERPC
+static void powerpc_build_stubs (bfd *, bfd *, asymbol ***, long *);
+static void powerpc_resolve_stubs (bfd *, bfd *);
+static void powerpc_mangle_relocs (bfd *, asection *, arelent ***, long *, char *, bfd_size_type);
+#endif
\f
/* The main routine. */
int
-main (argc, argv)
- int argc;
- char **argv;
+main (int argc, char **argv)
{
int opt;
char *input_file = NULL;
asymbol *endsym;
long i;
char inlead, outlead;
- boolean gotstart, gotexit, gotcheck;
+ bfd_boolean gotstart, gotexit, gotcheck;
struct stat st;
- FILE *custom_data, *help_data, *message_data, *rpc_data, *shared_data;
- size_t custom_size, help_size, message_size, module_size, rpc_size;
- asection *custom_section, *help_section, *message_section, *module_section;
- asection *rpc_section, *shared_section;
+ FILE *custom_data = NULL;
+ FILE *help_data = NULL;
+ FILE *message_data = NULL;
+ FILE *rpc_data = NULL;
+ FILE *shared_data = NULL;
+ size_t custom_size = 0;
+ size_t help_size = 0;
+ size_t message_size = 0;
+ size_t module_size = 0;
+ size_t rpc_size = 0;
+ asection *custom_section = NULL;
+ asection *help_section = NULL;
+ asection *message_section = NULL;
+ asection *module_section = NULL;
+ asection *rpc_section = NULL;
+ asection *shared_section = NULL;
bfd *sharedbfd;
- size_t shared_offset, shared_size;
- Nlm_Internal_Fixed_Header sharedhdr;
+ size_t shared_offset = 0;
+ size_t shared_size = 0;
+ static Nlm_Internal_Fixed_Header sharedhdr;
int len;
char *modname;
char **matching;
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+ setlocale (LC_MESSAGES, "");
+#endif
+#if defined (HAVE_SETLOCALE)
+ setlocale (LC_CTYPE, "");
+#endif
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
program_name = argv[0];
xmalloc_set_program_name (program_name);
+ expandargv (&argc, &argv);
+
bfd_init ();
+ set_default_bfd_target ();
- while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options,
+ while ((opt = getopt_long (argc, argv, "dHhI:l:O:T:Vv", long_options,
(int *) NULL))
!= EOF)
{
case 'd':
debug = 1;
break;
+ case 'H':
case 'h':
- show_help ();
- /*NOTREACHED*/
+ show_usage (stdout, 0);
+ break;
case 'I':
input_format = optarg;
break;
case 'T':
header_file = optarg;
break;
+ case 'v':
case 'V':
- printf ("GNU %s version %s\n", program_name, program_version);
- exit (0);
- /*NOTREACHED*/
+ print_version ("nlmconv");
+ break;
case 0:
break;
default:
show_usage (stderr, 1);
- /*NOTREACHED*/
+ break;
}
}
show_usage (stderr, 1);
if (strcmp (input_file, output_file) == 0)
{
- fprintf (stderr,
- "%s: input and output files must be different\n",
- program_name);
- exit (1);
+ fatal (_("input and output files must be different"));
}
}
}
/* Initialize the header information to default values. */
fixed_hdr = &fixed_hdr_struct;
- memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct);
+ memset ((void *) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct);
var_hdr = &var_hdr_struct;
- memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct);
+ memset ((void *) &var_hdr_struct, 0, sizeof var_hdr_struct);
version_hdr = &version_hdr_struct;
- memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct);
+ memset ((void *) &version_hdr_struct, 0, sizeof version_hdr_struct);
copyright_hdr = ©right_hdr_struct;
- memset ((PTR) ©right_hdr_struct, 0, sizeof copyright_hdr_struct);
+ memset ((void *) ©right_hdr_struct, 0, sizeof copyright_hdr_struct);
extended_hdr = &extended_hdr_struct;
- memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct);
+ memset ((void *) &extended_hdr_struct, 0, sizeof extended_hdr_struct);
check_procedure = NULL;
custom_file = NULL;
- debug_info = false;
+ debug_info = FALSE;
exit_procedure = "_Stop";
export_symbols = NULL;
map_file = NULL;
- full_map = false;
+ full_map = FALSE;
help_file = NULL;
import_symbols = NULL;
message_file = NULL;
modules = NULL;
sharelib_file = NULL;
start_procedure = "_Prelude";
- verbose = false;
+ verbose = FALSE;
rpc_file = NULL;
parse_errors = 0;
{
if (input_file != NULL)
{
- fprintf (stderr,
- "%s: input file named both on command line and with INPUT\n",
- program_name);
- exit (1);
+ fatal (_("input file named both on command line and with INPUT"));
}
if (input_files->next == NULL)
input_file = input_files->string;
else
- input_file = link_inputs (input_files, ld_arg);
+ input_file = link_inputs (input_files, ld_arg, map_file);
}
else if (input_file == NULL)
{
- fprintf (stderr, "%s: no input file\n", program_name);
+ non_fatal (_("no input file"));
show_usage (stderr, 1);
}
if (output_format == NULL)
output_format = select_output_format (bfd_get_arch (inbfd),
bfd_get_mach (inbfd),
- inbfd->xvec->byteorder_big_p);
+ bfd_big_endian (inbfd));
assert (output_format != NULL);
Otherwise use the file named in the OUTPUT statement. */
if (output_file == NULL)
{
- fprintf (stderr, "%s: no name for output file\n",
- program_name);
+ non_fatal (_("no name for output file"));
show_usage (stderr, 1);
}
assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour);
- if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
- fprintf (stderr,
- "%s: warning:input and output formats are not compatible\n",
- program_name);
+ /* XXX: Should we accept the unknown bfd format here ? */
+ if (bfd_arch_get_compatible (inbfd, outbfd, TRUE) == NULL)
+ non_fatal (_("warning: input and output formats are not compatible"));
/* Move the values read from the command file into outbfd. */
*nlm_fixed_header (outbfd) = fixed_hdr_struct;
bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
if (bss_sec == NULL)
{
- bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
+ bss_sec = bfd_make_section_with_flags (outbfd,
+ NLM_UNINITIALIZED_DATA_NAME,
+ SEC_ALLOC);
if (bss_sec == NULL
- || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
|| ! bfd_set_section_alignment (outbfd, bss_sec, 1))
- bfd_fatal ("make .bss section");
+ bfd_fatal (_("make .bss section"));
}
-/* start-sanitize-powerpc-netware */
+ /* We store the original section names in the .nlmsections section,
+ so that programs which understand it can resurrect the original
+ sections from the NLM. We will put a pointer to .nlmsections in
+ the NLM header area. */
+ secsec = bfd_make_section_with_flags (outbfd, ".nlmsections",
+ SEC_HAS_CONTENTS);
+ if (secsec == NULL)
+ bfd_fatal (_("make .nlmsections section"));
+
+#ifdef NLMCONV_POWERPC
/* For PowerPC NetWare we need to build stubs for calls to undefined
symbols. Because each stub requires an entry in the TOC section
which must be at the same location as other entries in the TOC
section, we must do this before determining where the TOC section
goes in setup_sections. */
if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
- powerpc_build_stubs (inbfd, &symbols, &symcount);
-/* end-sanitize-powerpc-netware */
+ powerpc_build_stubs (inbfd, outbfd, &symbols, &symcount);
+#endif
/* Set up the sections. */
- bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
+ bfd_map_over_sections (inbfd, setup_sections, (void *) outbfd);
text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME);
{
bfd_size_type add;
- vma = bfd_get_section_size_before_reloc (data_sec);
+ vma = bfd_get_section_size (data_sec);
align = 1 << bss_sec->alignment_power;
add = ((vma + align - 1) &~ (align - 1)) - vma;
vma += add;
if (! bfd_set_section_vma (outbfd, bss_sec, vma))
- bfd_fatal ("set .bss vma");
+ bfd_fatal (_("set .bss vma"));
if (add != 0)
{
bfd_size_type data_size;
- data_size = bfd_get_section_size_before_reloc (data_sec);
+ data_size = bfd_get_section_size (data_sec);
if (! bfd_set_section_size (outbfd, data_sec, data_size + add))
- bfd_fatal ("set .data size");
+ bfd_fatal (_("set .data size"));
}
}
/* Adjust symbol information. */
inlead = bfd_get_symbol_leading_char (inbfd);
outlead = bfd_get_symbol_leading_char (outbfd);
- gotstart = false;
- gotexit = false;
- gotcheck = false;
+ gotstart = FALSE;
+ gotexit = FALSE;
+ gotcheck = FALSE;
newsymalloc = 10;
newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
newsymcount = 0;
endsym = NULL;
for (i = 0; i < symcount; i++)
{
- register asymbol *sym;
+ asymbol *sym;
sym = symbols[i];
symbols into the .bss section, and mark them as exported. */
if (bfd_is_com_section (bfd_get_section (sym)))
{
- bfd_vma size;
+ bfd_vma size = sym->value;
sym->section = bss_sec;
- size = sym->value;
- sym->value = bss_sec->_raw_size;
- bss_sec->_raw_size += size;
+ sym->value = bfd_get_section_size (bss_sec);
+ size += sym->value;
align = 1 << bss_sec->alignment_power;
- bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1);
+ size = (size + align - 1) & ~(align - 1);
+ bfd_set_section_size (outbfd, bss_sec, size);
sym->flags |= BSF_EXPORT | BSF_GLOBAL;
}
else if (bfd_get_section (sym)->output_section != NULL)
symbols will confuse it. */
if ((sym->flags & BSF_DEBUGGING) == 0
&& bfd_asymbol_name (sym)[0] == '_'
- && bfd_get_section (sym) == &bfd_und_section)
+ && bfd_is_und_section (bfd_get_section (sym)))
{
if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
{
sym->section = bss_sec;
endsym = sym;
}
-/* start-sanitize-powerpc-netware */
+
+#ifdef NLMCONV_POWERPC
/* For PowerPC NetWare, we define __GOT0. This is the start
of the .got section. */
if (bfd_get_arch (inbfd) == bfd_arch_powerpc
sym->value = got_sec->output_offset;
sym->section = got_sec->output_section;
}
-/* end-sanitize-powerpc-netware */
- }
+#endif
+ }
/* If this is a global symbol, check the export list. */
if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
{
- register struct string_list *l;
+ struct string_list *l;
int found_simple;
/* Unfortunately, a symbol can appear multiple times on the
{
newsymalloc += 10;
newsyms = ((asymbol **)
- xrealloc ((PTR) newsyms,
+ xrealloc ((void *) newsyms,
(newsymalloc
* sizeof (asymbol *))));
}
/* If it's an undefined symbol, see if it's on the import list.
Change the prefix if necessary. */
- if (bfd_get_section (sym) == &bfd_und_section)
+ if (bfd_is_und_section (bfd_get_section (sym)))
{
- register struct string_list *l;
+ struct string_list *l;
for (l = import_symbols; l != NULL; l = l->next)
{
}
}
if (l == NULL)
- fprintf (stderr,
- "%s: warning: symbol %s imported but not in import list\n",
- program_name, bfd_asymbol_name (sym));
+ non_fatal (_("warning: symbol %s imported but not in import list"),
+ bfd_asymbol_name (sym));
}
-
+
/* See if it's one of the special named symbols. */
if ((sym->flags & BSF_DEBUGGING) == 0)
{
&& text_sec != (asection *) NULL)
val += bfd_section_size (outbfd, text_sec);
if (! bfd_set_start_address (outbfd, val))
- bfd_fatal ("set start address");
- gotstart = true;
+ bfd_fatal (_("set start address"));
+ gotstart = TRUE;
}
if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
{
&& text_sec != (asection *) NULL)
val += bfd_section_size (outbfd, text_sec);
nlm_fixed_header (outbfd)->exitProcedureOffset = val;
- gotexit = true;
+ gotexit = TRUE;
}
if (check_procedure != NULL
&& strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
&& text_sec != (asection *) NULL)
val += bfd_section_size (outbfd, text_sec);
nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val;
- gotcheck = true;
+ gotcheck = TRUE;
}
}
}
if (endsym != NULL)
{
- endsym->value = bfd_get_section_size_before_reloc (bss_sec);
+ endsym->value = bfd_get_section_size (bss_sec);
/* FIXME: If any relocs referring to _end use inplace addends,
then I think they need to be updated. This is handled by
}
bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
-
+
if (! gotstart)
- fprintf (stderr, "%s: warning: START procedure %s not defined\n",
- program_name, start_procedure);
+ non_fatal (_("warning: START procedure %s not defined"), start_procedure);
if (! gotexit)
- fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
- program_name, exit_procedure);
- if (check_procedure != NULL
- && ! gotcheck)
- fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
- program_name, check_procedure);
+ non_fatal (_("warning: EXIT procedure %s not defined"), exit_procedure);
+ if (check_procedure != NULL && ! gotcheck)
+ non_fatal (_("warning: CHECK procedure %s not defined"), check_procedure);
/* Add additional sections required for the header information. */
if (custom_file != NULL)
else
{
custom_size = st.st_size;
- custom_section = bfd_make_section (outbfd, ".nlmcustom");
+ custom_section = bfd_make_section_with_flags (outbfd, ".nlmcustom",
+ SEC_HAS_CONTENTS);
if (custom_section == NULL
- || ! bfd_set_section_size (outbfd, custom_section, custom_size)
- || ! bfd_set_section_flags (outbfd, custom_section,
- SEC_HAS_CONTENTS))
- bfd_fatal ("custom section");
+ || ! bfd_set_section_size (outbfd, custom_section, custom_size))
+ bfd_fatal (_("custom section"));
}
}
if (help_file != NULL)
else
{
help_size = st.st_size;
- help_section = bfd_make_section (outbfd, ".nlmhelp");
+ help_section = bfd_make_section_with_flags (outbfd, ".nlmhelp",
+ SEC_HAS_CONTENTS);
if (help_section == NULL
- || ! bfd_set_section_size (outbfd, help_section, help_size)
- || ! bfd_set_section_flags (outbfd, help_section,
- SEC_HAS_CONTENTS))
- bfd_fatal ("help section");
- strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+ || ! bfd_set_section_size (outbfd, help_section, help_size))
+ bfd_fatal (_("help section"));
+ LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
}
}
if (message_file != NULL)
else
{
message_size = st.st_size;
- message_section = bfd_make_section (outbfd, ".nlmmessages");
+ message_section = bfd_make_section_with_flags (outbfd,
+ ".nlmmessages",
+ SEC_HAS_CONTENTS);
if (message_section == NULL
- || ! bfd_set_section_size (outbfd, message_section, message_size)
- || ! bfd_set_section_flags (outbfd, message_section,
- SEC_HAS_CONTENTS))
- bfd_fatal ("message section");
- strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+ || ! bfd_set_section_size (outbfd, message_section, message_size))
+ bfd_fatal (_("message section"));
+ LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
}
}
if (modules != NULL)
module_size = 0;
for (l = modules; l != NULL; l = l->next)
module_size += strlen (l->string) + 1;
- module_section = bfd_make_section (outbfd, ".nlmmodules");
+ module_section = bfd_make_section_with_flags (outbfd, ".nlmmodules",
+ SEC_HAS_CONTENTS);
if (module_section == NULL
- || ! bfd_set_section_size (outbfd, module_section, module_size)
- || ! bfd_set_section_flags (outbfd, module_section,
- SEC_HAS_CONTENTS))
- bfd_fatal ("module section");
+ || ! bfd_set_section_size (outbfd, module_section, module_size))
+ bfd_fatal (_("module section"));
}
if (rpc_file != NULL)
{
else
{
rpc_size = st.st_size;
- rpc_section = bfd_make_section (outbfd, ".nlmrpc");
+ rpc_section = bfd_make_section_with_flags (outbfd, ".nlmrpc",
+ SEC_HAS_CONTENTS);
if (rpc_section == NULL
- || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
- || ! bfd_set_section_flags (outbfd, rpc_section,
- SEC_HAS_CONTENTS))
- bfd_fatal ("rpc section");
- strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+ || ! bfd_set_section_size (outbfd, rpc_section, rpc_size))
+ bfd_fatal (_("rpc section"));
+ LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
}
}
if (sharelib_file != NULL)
if (sharedhdr.uninitializedDataSize > 0)
{
/* There is no place to record this information. */
- fprintf (stderr,
- "%s:%s: warning: shared libraries can not have uninitialized data\n",
- program_name, sharelib_file);
+ non_fatal (_("%s: warning: shared libraries can not have uninitialized data"),
+ sharelib_file);
}
shared_offset = st.st_size;
- if (shared_offset > sharedhdr.codeImageOffset)
+ if (shared_offset > (size_t) sharedhdr.codeImageOffset)
shared_offset = sharedhdr.codeImageOffset;
- if (shared_offset > sharedhdr.dataImageOffset)
+ if (shared_offset > (size_t) sharedhdr.dataImageOffset)
shared_offset = sharedhdr.dataImageOffset;
- if (shared_offset > sharedhdr.relocationFixupOffset)
+ if (shared_offset > (size_t) sharedhdr.relocationFixupOffset)
shared_offset = sharedhdr.relocationFixupOffset;
- if (shared_offset > sharedhdr.externalReferencesOffset)
+ if (shared_offset > (size_t) sharedhdr.externalReferencesOffset)
shared_offset = sharedhdr.externalReferencesOffset;
- if (shared_offset > sharedhdr.publicsOffset)
+ if (shared_offset > (size_t) sharedhdr.publicsOffset)
shared_offset = sharedhdr.publicsOffset;
shared_size = st.st_size - shared_offset;
- shared_section = bfd_make_section (outbfd, ".nlmshared");
+ shared_section = bfd_make_section_with_flags (outbfd,
+ ".nlmshared",
+ SEC_HAS_CONTENTS);
if (shared_section == NULL
|| ! bfd_set_section_size (outbfd, shared_section,
- shared_size)
- || ! bfd_set_section_flags (outbfd, shared_section,
- SEC_HAS_CONTENTS))
- bfd_fatal ("shared section");
- strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+ shared_size))
+ bfd_fatal (_("shared section"));
+ LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
}
}
}
/* Check whether a version was given. */
- if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0)
- fprintf (stderr, "%s: warning: No version number given\n",
- program_name);
+ if (!CONST_STRNEQ (version_hdr->stamp, "VeRsIoN#"))
+ non_fatal (_("warning: No version number given"));
/* At least for now, always create an extended header, because that
is what NLMLINK does. */
- strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+ LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
+
+ LITMEMCPY (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx");
/* If the date was not given, force it in. */
if (nlm_version_header (outbfd)->month == 0
nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
nlm_version_header (outbfd)->day = ptm->tm_mday;
nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
- strncpy (version_hdr->stamp, "VeRsIoN#", 8);
+ LITMEMCPY (version_hdr->stamp, "VeRsIoN#");
}
-/* start-sanitize-powerpc-netware */
+#ifdef NLMCONV_POWERPC
/* Resolve the stubs we build for PowerPC NetWare. */
if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
powerpc_resolve_stubs (inbfd, outbfd);
-/* end-sanitize-powerpc-netware */
+#endif
/* Copy over the sections. */
- bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
+ bfd_map_over_sections (inbfd, copy_sections, (void *) outbfd);
/* Finish up the header information. */
if (custom_file != NULL)
{
- PTR data;
+ void *data;
data = xmalloc (custom_size);
if (fread (data, 1, custom_size, custom_data) != custom_size)
- fprintf (stderr, "%s:%s: read: %s\n", program_name, custom_file,
- strerror (errno));
+ non_fatal (_("%s: read: %s"), custom_file, strerror (errno));
else
{
if (! bfd_set_section_contents (outbfd, custom_section, data,
(file_ptr) 0, custom_size))
- bfd_fatal ("custom section");
+ bfd_fatal (_("custom section"));
nlm_fixed_header (outbfd)->customDataOffset =
custom_section->filepos;
nlm_fixed_header (outbfd)->customDataSize = custom_size;
export information and the debugging information. */
nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
}
- if (map_file != NULL)
- fprintf (stderr,
- "%s: warning: MAP and FULLMAP are not supported; try ld -M\n",
- program_name);
+ if (full_map)
+ non_fatal (_("warning: FULLMAP is not supported; try ld -M"));
if (help_file != NULL)
{
- PTR data;
+ void *data;
data = xmalloc (help_size);
if (fread (data, 1, help_size, help_data) != help_size)
- fprintf (stderr, "%s:%s: read: %s\n", program_name, help_file,
- strerror (errno));
+ non_fatal (_("%s: read: %s"), help_file, strerror (errno));
else
{
if (! bfd_set_section_contents (outbfd, help_section, data,
(file_ptr) 0, help_size))
- bfd_fatal ("help section");
+ bfd_fatal (_("help section"));
nlm_extended_header (outbfd)->helpFileOffset =
help_section->filepos;
nlm_extended_header (outbfd)->helpFileLength = help_size;
}
if (message_file != NULL)
{
- PTR data;
+ void *data;
data = xmalloc (message_size);
if (fread (data, 1, message_size, message_data) != message_size)
- fprintf (stderr, "%s:%s: read: %s\n", program_name, message_file,
- strerror (errno));
+ non_fatal (_("%s: read: %s"), message_file, strerror (errno));
else
{
if (! bfd_set_section_contents (outbfd, message_section, data,
(file_ptr) 0, message_size))
- bfd_fatal ("message section");
+ bfd_fatal (_("message section"));
nlm_extended_header (outbfd)->messageFileOffset =
message_section->filepos;
nlm_extended_header (outbfd)->messageFileLength = message_size;
}
if (modules != NULL)
{
- PTR data;
+ void *data;
unsigned char *set;
struct string_list *l;
bfd_size_type c;
for (l = modules; l != NULL; l = l->next)
{
*set = strlen (l->string);
- strncpy (set + 1, l->string, *set);
+ strncpy ((char *) set + 1, l->string, *set);
set += *set + 1;
++c;
}
if (! bfd_set_section_contents (outbfd, module_section, data,
(file_ptr) 0, module_size))
- bfd_fatal ("module section");
+ bfd_fatal (_("module section"));
nlm_fixed_header (outbfd)->moduleDependencyOffset =
module_section->filepos;
nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
}
if (rpc_file != NULL)
{
- PTR data;
+ void *data;
data = xmalloc (rpc_size);
if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
- fprintf (stderr, "%s:%s: read: %s\n", program_name, rpc_file,
- strerror (errno));
+ non_fatal (_("%s: read: %s"), rpc_file, strerror (errno));
else
{
if (! bfd_set_section_contents (outbfd, rpc_section, data,
(file_ptr) 0, rpc_size))
- bfd_fatal ("rpc section");
+ bfd_fatal (_("rpc section"));
nlm_extended_header (outbfd)->RPCDataOffset =
rpc_section->filepos;
nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
}
if (sharelib_file != NULL)
{
- PTR data;
+ void *data;
data = xmalloc (shared_size);
if (fseek (shared_data, shared_offset, SEEK_SET) != 0
|| fread (data, 1, shared_size, shared_data) != shared_size)
- fprintf (stderr, "%s:%s: read: %s\n", program_name, sharelib_file,
- strerror (errno));
+ non_fatal (_("%s: read: %s"), sharelib_file, strerror (errno));
else
{
if (! bfd_set_section_contents (outbfd, shared_section, data,
(file_ptr) 0, shared_size))
- bfd_fatal ("shared section");
+ bfd_fatal (_("shared section"));
}
nlm_extended_header (outbfd)->sharedCodeOffset =
sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
sharedhdr.exitProcedureOffset;
free (data);
}
- len = strlen (output_file);
- if (len > NLM_MODULE_NAME_SIZE - 2)
- len = NLM_MODULE_NAME_SIZE - 2;
- nlm_fixed_header (outbfd)->moduleName[0] = len;
-
- strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file,
- NLM_MODULE_NAME_SIZE - 2);
- nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
- for (modname = nlm_fixed_header (outbfd)->moduleName;
- *modname != '\0';
- modname++)
- if (islower (*modname))
- *modname = toupper (*modname);
+
+ {
+ const int max_len = NLM_MODULE_NAME_SIZE - 2;
+ const char * filename = lbasename (output_file);
+
+ len = strlen (filename);
+ if (len > max_len)
+ len = max_len;
+ nlm_fixed_header (outbfd)->moduleName[0] = len;
+
+ strncpy (nlm_fixed_header (outbfd)->moduleName + 1, filename, max_len);
+ nlm_fixed_header (outbfd)->moduleName[max_len + 1] = '\0';
+
+ for (modname = nlm_fixed_header (outbfd)->moduleName;
+ *modname != '\0';
+ modname++)
+ *modname = TOUPPER (*modname);
+ }
strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
NLM_OLD_THREAD_NAME_LENGTH);
+ nlm_cygnus_ext_header (outbfd)->offset = secsec->filepos;
+ nlm_cygnus_ext_header (outbfd)->length = bfd_section_size (outbfd, secsec);
+
if (! bfd_close (outbfd))
bfd_fatal (output_file);
if (! bfd_close (inbfd))
return 0;
}
\f
-/* Display a help message and exit. */
-
-static void
-show_help ()
-{
- printf ("%s: Convert an object file into a NetWare Loadable Module\n",
- program_name);
- show_usage (stdout, 0);
-}
/* Show a usage message and exit. */
static void
-show_usage (file, status)
- FILE *file;
- int status;
+show_usage (FILE *file, int status)
{
- fprintf (file, "\
-Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n\
- [--input-target=bfdname] [--output-target=bfdname]\n\
- [--header-file=file] [--linker=linker] [--debug]\n\
- [--help] [--version]\n\
- [in-file [out-file]]\n",
- program_name);
+ fprintf (file, _("Usage: %s [option(s)] [in-file [out-file]]\n"), program_name);
+ fprintf (file, _(" Convert an object file into a NetWare Loadable Module\n"));
+ fprintf (file, _(" The options are:\n\
+ -I --input-target=<bfdname> Set the input binary file format\n\
+ -O --output-target=<bfdname> Set the output binary file format\n\
+ -T --header-file=<file> Read <file> for NLM header information\n\
+ -l --linker=<linker> Use <linker> for any linking\n\
+ -d --debug Display on stderr the linker command line\n\
+ @<file> Read options from <file>.\n\
+ -h --help Display this information\n\
+ -v --version Display the program's version\n\
+"));
+ if (REPORT_BUGS_TO[0] && status == 0)
+ fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
exit (status);
}
\f
and endianness. This chooses the appropriate NLM target. */
static const char *
-select_output_format (arch, mach, bigendian)
- enum bfd_architecture arch;
- unsigned long mach;
- boolean bigendian;
+select_output_format (enum bfd_architecture arch, unsigned long mach,
+ bfd_boolean bigendian ATTRIBUTE_UNUSED)
{
switch (arch)
{
+#ifdef NLMCONV_I386
case bfd_arch_i386:
return "nlm32-i386";
+#endif
+#ifdef NLMCONV_SPARC
case bfd_arch_sparc:
return "nlm32-sparc";
+#endif
+#ifdef NLMCONV_ALPHA
case bfd_arch_alpha:
return "nlm32-alpha";
-/* start-sanitize-powerpc-netware */
+#endif
+#ifdef NLMCONV_POWERPC
case bfd_arch_powerpc:
return "nlm32-powerpc";
-/* end-sanitize-powerpc-netware */
+#endif
default:
- fprintf (stderr, "%s: no default NLM format for %s\n",
- program_name, bfd_printable_arch_mach (arch, mach));
- exit (1);
- /* Avoid warning. */
- return NULL;
+ fatal (_("support not compiled in for %s"),
+ bfd_printable_arch_mach (arch, mach));
}
/*NOTREACHED*/
}
name, size, etc. */
static void
-setup_sections (inbfd, insec, data_ptr)
- bfd *inbfd;
- asection *insec;
- PTR data_ptr;
+setup_sections (bfd *inbfd ATTRIBUTE_UNUSED, asection *insec, void *data_ptr)
{
bfd *outbfd = (bfd *) data_ptr;
flagword f;
bfd_vma offset;
bfd_size_type align;
bfd_size_type add;
-
- /* FIXME: We don't want to copy the .reginfo section of an ECOFF
- file. However, I don't have a good way to describe this section.
- We do want to copy the section when using objcopy. */
- if (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour
- && strcmp (bfd_section_name (inbfd, insec), ".reginfo") == 0)
- return;
+ bfd_size_type secsecsize;
f = bfd_get_section_flags (inbfd, insec);
if (f & SEC_CODE)
{
outsec = bfd_make_section (outbfd, outname);
if (outsec == NULL)
- bfd_fatal ("make section");
+ bfd_fatal (_("make section"));
}
insec->output_section = outsec;
(bfd_section_size (outbfd, outsec)
+ bfd_section_size (inbfd, insec)
+ add)))
- bfd_fatal ("set section size");
+ bfd_fatal (_("set section size"));
if ((bfd_section_alignment (inbfd, insec)
> bfd_section_alignment (outbfd, outsec))
&& ! bfd_set_section_alignment (outbfd, outsec,
bfd_section_alignment (inbfd, insec)))
- bfd_fatal ("set section alignment");
+ bfd_fatal (_("set section alignment"));
- if (! bfd_set_section_flags (outbfd, outsec, f))
- bfd_fatal ("set section flags");
+ if (! bfd_set_section_flags (outbfd, outsec,
+ f | bfd_get_section_flags (outbfd, outsec)))
+ bfd_fatal (_("set section flags"));
bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
+
+ /* For each input section we allocate space for an entry in
+ .nlmsections. */
+ secsecsize = bfd_section_size (outbfd, secsec);
+ secsecsize += strlen (bfd_section_name (inbfd, insec)) + 1;
+ secsecsize = (secsecsize + 3) &~ 3;
+ secsecsize += 8;
+ if (! bfd_set_section_size (outbfd, secsec, secsecsize))
+ bfd_fatal (_("set .nlmsections size"));
}
/* Copy the section contents. */
static void
-copy_sections (inbfd, insec, data_ptr)
- bfd *inbfd;
- asection *insec;
- PTR data_ptr;
+copy_sections (bfd *inbfd, asection *insec, void *data_ptr)
{
+ static bfd_size_type secsecoff = 0;
bfd *outbfd = (bfd *) data_ptr;
+ const char *inname;
asection *outsec;
bfd_size_type size;
- PTR contents;
+ void *contents;
long reloc_size;
+ bfd_byte buf[4];
+ bfd_size_type add;
- /* FIXME: We don't want to copy the .reginfo section of an ECOFF
- file. However, I don't have a good way to describe this section.
- We do want to copy the section when using objcopy. */
- if (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour
- && strcmp (bfd_section_name (inbfd, insec), ".reginfo") == 0)
- return;
+ inname = bfd_section_name (inbfd, insec);
outsec = insec->output_section;
assert (outsec != NULL);
- size = bfd_get_section_size_before_reloc (insec);
- if (size == 0)
- return;
-
- /* FIXME: Why are these necessary? */
- insec->_cooked_size = insec->_raw_size;
- insec->reloc_done = true;
+ size = bfd_get_section_size (insec);
if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
contents = NULL;
arelent **combined;
total_count = reloc_count + outsec->reloc_count;
- combined = (arelent **) xmalloc (total_count * sizeof (arelent));
+ combined = (arelent **) xmalloc (total_count * sizeof (arelent *));
memcpy (combined, outsec->orelocation,
- outsec->reloc_count * sizeof (arelent));
+ outsec->reloc_count * sizeof (arelent *));
memcpy (combined + outsec->reloc_count, relocs,
- (size_t) (reloc_count * sizeof (arelent)));
+ (size_t) (reloc_count * sizeof (arelent *)));
free (outsec->orelocation);
reloc_count = total_count;
relocs = combined;
bfd_fatal (bfd_get_filename (outbfd));
free (contents);
}
+
+ /* Add this section to .nlmsections. */
+ if (! bfd_set_section_contents (outbfd, secsec, (void *) inname, secsecoff,
+ strlen (inname) + 1))
+ bfd_fatal (_("set .nlmsection contents"));
+ secsecoff += strlen (inname) + 1;
+
+ add = ((secsecoff + 3) &~ 3) - secsecoff;
+ if (add != 0)
+ {
+ bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
+ if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, add))
+ bfd_fatal (_("set .nlmsection contents"));
+ secsecoff += add;
+ }
+
+ if (contents != NULL)
+ bfd_h_put_32 (outbfd, (bfd_vma) outsec->filepos, buf);
+ else
+ bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
+ if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
+ bfd_fatal (_("set .nlmsection contents"));
+ secsecoff += 4;
+
+ bfd_h_put_32 (outbfd, (bfd_vma) size, buf);
+ if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
+ bfd_fatal (_("set .nlmsection contents"));
+ secsecoff += 4;
}
/* Some, perhaps all, NetWare targets require changing the relocs used
by the input formats. */
static void
-mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
- contents_size)
- bfd *outbfd;
- asection *insec;
- arelent ***relocs_ptr;
- long *reloc_count_ptr;
- char *contents;
- bfd_size_type contents_size;
+mangle_relocs (bfd *outbfd, asection *insec, arelent ***relocs_ptr,
+ long *reloc_count_ptr, char *contents,
+ bfd_size_type contents_size)
{
switch (bfd_get_arch (outbfd))
{
+#ifdef NLMCONV_I386
case bfd_arch_i386:
i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
contents, contents_size);
break;
+#endif
+#ifdef NLMCONV_ALPHA
case bfd_arch_alpha:
alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
contents, contents_size);
break;
-/* start-sanitize-powerpc-netware */
+#endif
+#ifdef NLMCONV_POWERPC
case bfd_arch_powerpc:
powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
contents, contents_size);
break;
-/* end-sanitize-powerpc-netware */
+#endif
default:
default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
contents, contents_size);
/* By default all we need to do for relocs is change the address by
the output_offset. */
-/*ARGSUSED*/
static void
-default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
- contents_size)
- bfd *outbfd;
- asection *insec;
- arelent ***relocs_ptr;
- long *reloc_count_ptr;
- char *contents;
- bfd_size_type contents_size;
+default_mangle_relocs (bfd *outbfd ATTRIBUTE_UNUSED, asection *insec,
+ arelent ***relocs_ptr, long *reloc_count_ptr,
+ char *contents ATTRIBUTE_UNUSED,
+ bfd_size_type contents_size ATTRIBUTE_UNUSED)
{
if (insec->output_offset != 0)
{
long reloc_count;
- register arelent **relocs;
- register long i;
+ arelent **relocs;
+ long i;
reloc_count = *reloc_count_ptr;
relocs = *relocs_ptr;
(*relocs)->address += insec->output_offset;
}
}
+\f
+#ifdef NLMCONV_I386
/* NetWare on the i386 supports a restricted set of relocs, which are
different from those used on other i386 targets. This routine
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- true, /* pc_relative */
+ TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
0, /* special_function */
"DISP32", /* name */
- true, /* partial_inplace */
+ TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
- true); /* pcrel_offset */
+ TRUE); /* pcrel_offset */
static void
-i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
- contents_size)
- bfd *outbfd;
- asection *insec;
- arelent ***relocs_ptr;
- long *reloc_count_ptr;
- char *contents;
- bfd_size_type contents_size;
+i386_mangle_relocs (bfd *outbfd, asection *insec, arelent ***relocs_ptr,
+ long *reloc_count_ptr, char *contents,
+ bfd_size_type contents_size)
{
long reloc_count, i;
arelent **relocs;
/* Adjust the reloc for the changes we just made. */
rel->addend = 0;
- if (bfd_get_section (sym) != &bfd_und_section)
+ if (! bfd_is_und_section (bfd_get_section (sym)))
rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
}
}
}
+#endif /* NLMCONV_I386 */
+\f
+#ifdef NLMCONV_ALPHA
+
/* On the Alpha the first reloc for every section must be a special
relocs which hold the GP address. Also, the first reloc in the
file must be a special reloc which holds the address of the .lita
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
- false, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
0, /* special_function */
"NW_RELOC", /* name */
- false, /* partial_inplace */
+ FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false); /* pcrel_offset */
+ FALSE); /* pcrel_offset */
-/*ARGSUSED*/
static void
-alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
- contents_size)
- bfd *outbfd;
- asection *insec;
- register arelent ***relocs_ptr;
- long *reloc_count_ptr;
- char *contents;
- bfd_size_type contents_size;
+alpha_mangle_relocs (bfd *outbfd, asection *insec,
+ arelent ***relocs_ptr, long *reloc_count_ptr,
+ char *contents ATTRIBUTE_UNUSED,
+ bfd_size_type contents_size ATTRIBUTE_UNUSED)
{
long old_reloc_count;
arelent **old_relocs;
- register arelent **relocs;
+ arelent **relocs;
old_reloc_count = *reloc_count_ptr;
old_relocs = *relocs_ptr;
}
*relocs = (arelent *) xmalloc (sizeof (arelent));
- (*relocs)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
(*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address;
(*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1;
(*relocs)->howto = &nlm32_alpha_nw_howto;
++(*reloc_count_ptr);
}
- /* Get the GP value from bfd. It is in the .reginfo section. */
+ /* Get the GP value from bfd. */
if (nlm_alpha_backend_data (outbfd)->gp == 0)
- {
- bfd *inbfd;
- asection *reginfo_sec;
- struct ecoff_reginfo sreginfo;
-
- inbfd = insec->owner;
- assert (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour);
- reginfo_sec = bfd_get_section_by_name (inbfd, REGINFO);
- if (reginfo_sec != (asection *) NULL
- && bfd_get_section_contents (inbfd, reginfo_sec,
- (PTR) &sreginfo, (file_ptr) 0,
- sizeof sreginfo) != false)
- nlm_alpha_backend_data (outbfd)->gp = sreginfo.gp_value;
- }
+ nlm_alpha_backend_data (outbfd)->gp =
+ bfd_ecoff_get_gp_value (insec->owner);
*relocs = (arelent *) xmalloc (sizeof (arelent));
- (*relocs)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
(*relocs)->address = nlm_alpha_backend_data (outbfd)->gp;
(*relocs)->addend = 0;
(*relocs)->howto = &nlm32_alpha_nw_howto;
++relocs;
++(*reloc_count_ptr);
- memcpy ((PTR) relocs, (PTR) old_relocs,
- (size_t) old_reloc_count * sizeof (arelent *));
+ memcpy (relocs, old_relocs, (size_t) old_reloc_count * sizeof (arelent *));
relocs[old_reloc_count] = (arelent *) NULL;
free (old_relocs);
if (insec->output_offset != 0)
{
- register bfd_size_type i;
+ bfd_size_type i;
- for (i = 0; i < old_reloc_count; i++, relocs++)
+ for (i = 0; i < (bfd_size_type) old_reloc_count; i++, relocs++)
(*relocs)->address += insec->output_offset;
}
}
-/* start-sanitize-powerpc-netware */
+
+#endif /* NLMCONV_ALPHA */
+\f
+#ifdef NLMCONV_POWERPC
/* We keep a linked list of stubs which we must build. Because BFD
requires us to know the sizes of all sections before we can set the
build a stub for each one. */
static void
-powerpc_build_stubs (inbfd, symbols_ptr, symcount_ptr)
- bfd *inbfd;
- asymbol ***symbols_ptr;
- long *symcount_ptr;
+powerpc_build_stubs (bfd *inbfd, bfd *outbfd ATTRIBUTE_UNUSED,
+ asymbol ***symbols_ptr, long *symcount_ptr)
{
asection *stub_sec;
asection *got_sec;
/* Make a section to hold stubs. We don't set SEC_HAS_CONTENTS for
the section to prevent copy_sections from reading from it. */
- stub_sec = bfd_make_section (inbfd, ".stubs");
+ stub_sec = bfd_make_section_with_flags (inbfd, ".stubs",
+ (SEC_CODE
+ | SEC_RELOC
+ | SEC_ALLOC
+ | SEC_LOAD));
if (stub_sec == (asection *) NULL
- || ! bfd_set_section_flags (inbfd, stub_sec,
- (SEC_CODE
- | SEC_RELOC
- | SEC_ALLOC
- | SEC_LOAD))
|| ! bfd_set_section_alignment (inbfd, stub_sec, 2))
bfd_fatal (".stubs");
got_sec = bfd_get_section_by_name (inbfd, ".got");
if (got_sec == (asection *) NULL)
{
- got_sec = bfd_make_section (inbfd, ".got");
+ got_sec = bfd_make_section_with_flags (inbfd, ".got",
+ (SEC_DATA
+ | SEC_RELOC
+ | SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS));
if (got_sec == (asection *) NULL
- || ! bfd_set_section_flags (inbfd, got_sec,
- (SEC_DATA
- | SEC_RELOC
- | SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS))
|| ! bfd_set_section_alignment (inbfd, got_sec, 2))
bfd_fatal (".got");
}
/* We must make a stub for every undefined symbol whose name
starts with '.'. */
if (bfd_asymbol_name (sym)[0] != '.'
- || bfd_get_section (sym) != &bfd_und_section)
+ || ! bfd_is_und_section (bfd_get_section (sym)))
continue;
/* Make a new undefined symbol with the same name but without
the leading `.'. */
- newsym = (asymbol *) xmalloc (sizeof (asymbol));
+ newsym = xmalloc (sizeof (asymbol));
*newsym = *sym;
- newname = (char *) xmalloc (strlen (bfd_asymbol_name (sym)));
+ newname = xmalloc (strlen (bfd_asymbol_name (sym)));
strcpy (newname, bfd_asymbol_name (sym) + 1);
newsym->name = newname;
item->next = powerpc_stubs;
powerpc_stubs = item;
-
+
++stubcount;
}
(got_base
+ (stubcount
* POWERPC_STUB_TOC_ENTRY_SIZE))))
- bfd_fatal ("stub section sizes");
+ bfd_fatal (_("stub section sizes"));
}
}
of the output section, and create new relocs in the TOC. */
static void
-powerpc_resolve_stubs (inbfd, outbfd)
- bfd *inbfd;
- bfd *outbfd;
+powerpc_resolve_stubs (bfd *inbfd, bfd *outbfd)
{
bfd_byte buf[POWERPC_STUB_SIZE];
unsigned int i;
buf,
l->start->value,
POWERPC_STUB_SIZE))
- bfd_fatal ("writing stub");
+ bfd_fatal (_("writing stub"));
/* Create a new reloc for the TOC entry. */
reloc = (arelent *) xmalloc (sizeof (arelent));
reloc->address = l->toc_index + got_sec->output_offset;
reloc->addend = 0;
reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32);
-
+
*r++ = reloc;
}
r2, will be set to the correct TOC value, so there is no need for
any further reloc. */
-/*ARGSUSED*/
static void
-powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
- contents_size)
- bfd *outbfd;
- asection *insec;
- register arelent ***relocs_ptr;
- long *reloc_count_ptr;
- char *contents;
- bfd_size_type contents_size;
+powerpc_mangle_relocs (bfd *outbfd, asection *insec,
+ arelent ***relocs_ptr,
+ long *reloc_count_ptr, char *contents,
+ bfd_size_type contents_size ATTRIBUTE_UNUSED)
{
- const reloc_howto_type *toc_howto;
+ reloc_howto_type *toc_howto;
long reloc_count;
- register arelent **relocs;
- register long i;
+ arelent **relocs;
+ long i;
toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16);
if (toc_howto == (reloc_howto_type *) NULL)
going to write out whatever we return in the contents field. */
if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0)
memset (contents + powerpc_initial_got_size, 0,
- (bfd_get_section_size_after_reloc (insec)
- - powerpc_initial_got_size));
+ (size_t) (bfd_get_section_size (insec) - powerpc_initial_got_size));
reloc_count = *reloc_count_ptr;
relocs = *relocs_ptr;
{
arelent *rel;
asymbol *sym;
- bfd_vma symvalue;
+ bfd_vma sym_value;
rel = *relocs++;
sym = *rel->sym_ptr_ptr;
+ /* Convert any relocs against the .bss section into relocs
+ against the .data section. */
+ if (strcmp (bfd_get_section_name (outbfd, bfd_get_section (sym)),
+ NLM_UNINITIALIZED_DATA_NAME) == 0)
+ {
+ asection *datasec;
+
+ datasec = bfd_get_section_by_name (outbfd,
+ NLM_INITIALIZED_DATA_NAME);
+ if (datasec != NULL)
+ {
+ rel->addend += (bfd_get_section_vma (outbfd,
+ bfd_get_section (sym))
+ + sym->value);
+ rel->sym_ptr_ptr = datasec->symbol_ptr_ptr;
+ sym = *rel->sym_ptr_ptr;
+ }
+ }
+
/* We must be able to resolve all PC relative relocs at this
point. If we get a branch to an undefined symbol we build a
stub, since NetWare will resolve undefined symbols into a
between two sections both of which were placed in the
same output section. This should not happen. */
if (bfd_get_section (sym) != insec->output_section)
- fprintf (stderr, "%s: unresolved PC relative reloc against %s\n",
- program_name, bfd_asymbol_name (sym));
+ non_fatal (_("unresolved PC relative reloc against %s"),
+ bfd_asymbol_name (sym));
else
{
bfd_vma val;
symbol value. The symbol will be start of the TOC section
(which is named .got). We do want to include the addend. */
if (rel->howto == toc_howto)
- symvalue = 0;
+ sym_value = 0;
else
- symvalue = sym->value;
+ sym_value = sym->value;
/* If this is a relocation against a symbol with a value, or
there is a reloc addend, we need to update the addend in the
object file. */
- if (symvalue + rel->addend != 0)
+ if (sym_value + rel->addend != 0)
{
bfd_vma val;
(bfd_byte *) contents + rel->address);
val = ((val &~ rel->howto->dst_mask)
| (((val & rel->howto->src_mask)
- + symvalue
+ + sym_value
+ rel->addend)
& rel->howto->dst_mask));
if ((bfd_signed_vma) val < - 0x8000
|| (bfd_signed_vma) val >= 0x8000)
- fprintf (stderr,
- "%s: overflow when adjusting relocation against %s\n",
- program_name, bfd_asymbol_name (sym));
+ non_fatal (_("overflow when adjusting relocation against %s"),
+ bfd_asymbol_name (sym));
bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address);
break;
(bfd_byte *) contents + rel->address);
val = ((val &~ rel->howto->dst_mask)
| (((val & rel->howto->src_mask)
- + symvalue
+ + sym_value
+ rel->addend)
& rel->howto->dst_mask));
bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
abort ();
}
- rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
+ if (! bfd_is_und_section (bfd_get_section (sym)))
+ rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
rel->addend = 0;
}
rel->address += insec->output_offset;
}
}
-/* end-sanitize-powerpc-netware */
+
+#endif /* NLMCONV_POWERPC */
\f
/* Name of linker. */
#ifndef LD_NAME
#define LD_NAME "ld"
#endif
-/* Temporary file name base. */
-static char *temp_filename;
-
/* The user has specified several input files. Invoke the linker to
link them all together, and convert and delete the resulting output
file. */
static char *
-link_inputs (inputs, ld)
- struct string_list *inputs;
- char *ld;
+link_inputs (struct string_list *inputs, char *ld, char * map_file)
{
size_t c;
struct string_list *q;
size_t i;
int pid;
int status;
+ char *errfmt;
+ char *errarg;
c = 0;
for (q = inputs; q != NULL; q = q->next)
++c;
- argv = (char **) alloca (c + 5);
+ argv = (char **) alloca ((c + 7) * sizeof (char *));
#ifndef __MSDOS__
if (ld == NULL)
if (ld == NULL)
ld = (char *) LD_NAME;
- choose_temp_base ();
-
- unlink_on_exit = xmalloc (strlen (temp_filename) + 3);
- sprintf (unlink_on_exit, "%s.O", temp_filename);
+ unlink_on_exit = make_temp_file (".O");
argv[0] = ld;
- argv[1] = (char *) "-r";
+ argv[1] = (char *) "-Ur";
argv[2] = (char *) "-o";
argv[3] = unlink_on_exit;
- i = 4;
+ /* If we have been given the name of a mapfile and that
+ name is not 'stderr' then pass it on to the linker. */
+ if (map_file
+ && * map_file
+ && strcmp (map_file, "stderr") == 0)
+ {
+ argv[4] = (char *) "-Map";
+ argv[5] = map_file;
+ i = 6;
+ }
+ else
+ i = 4;
+
for (q = inputs; q != NULL; q = q->next, i++)
argv[i] = q->string;
argv[i] = NULL;
fprintf (stderr, "\n");
}
- pid = pexecute (ld, argv);
-
- if (waitpid (pid, &status, 0) < 0)
+ pid = pexecute (ld, argv, program_name, (char *) NULL, &errfmt, &errarg,
+ PEXECUTE_SEARCH | PEXECUTE_ONE);
+ if (pid == -1)
{
- perror ("waitpid");
+ fprintf (stderr, _("%s: execution of %s failed: "), program_name, ld);
+ fprintf (stderr, errfmt, errarg);
unlink (unlink_on_exit);
exit (1);
}
- if (status != 0)
+ if (pwait (pid, &status, 0) < 0)
{
- fprintf (stderr, "%s: Execution of %s failed\n", program_name, ld);
+ perror ("pwait");
unlink (unlink_on_exit);
exit (1);
}
- return unlink_on_exit;
-}
-
-/* Choose a temporary file name. Stolen from gcc.c. */
-
-static const char *
-choose_temp_base_try (try, base)
- const char *try;
- const char *base;
-{
- const char *rv;
-
- if (base)
- rv = base;
- else if (try == NULL)
- rv = NULL;
- else if (access (try, R_OK | W_OK) != 0)
- rv = NULL;
- else
- rv = try;
- return rv;
-}
-
-static void
-choose_temp_base ()
-{
- const char *base = NULL;
- int len;
-
- base = choose_temp_base_try (getenv ("TMPDIR"), base);
- base = choose_temp_base_try (getenv ("TMP"), base);
- base = choose_temp_base_try (getenv ("TEMP"), base);
-
-#ifdef P_tmpdir
- base = choose_temp_base_try (P_tmpdir, base);
-#endif
-
- base = choose_temp_base_try ("/usr/tmp", base);
- base = choose_temp_base_try ("/tmp", base);
-
- /* If all else fails, use the current directory! */
- if (base == NULL)
- base = "./";
-
- len = strlen (base);
- temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
- strcpy (temp_filename, base);
- if (len > 0 && temp_filename[len-1] != '/')
- temp_filename[len++] = '/';
- strcpy (temp_filename + len, "ccXXXXXX");
-
- mktemp (temp_filename);
- if (*temp_filename == '\0')
- abort ();
-}
-
-/* Execute a job. Stolen from gcc.c. */
-
-#ifndef OS2
-#ifdef __MSDOS__
-
-static int
-pexecute (program, argv)
- char *program;
- char *argv[];
-{
- char *scmd, *rf;
- FILE *argfile;
- int i;
-
- scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 10);
- rf = scmd + strlen(program) + 2 + el;
- sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
- argfile = fopen (rf, "w");
- if (argfile == 0)
- pfatal_with_name (rf);
-
- for (i=1; argv[i]; i++)
- {
- char *cp;
- for (cp = argv[i]; *cp; cp++)
- {
- if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
- fputc ('\\', argfile);
- fputc (*cp, argfile);
- }
- fputc ('\n', argfile);
- }
- fclose (argfile);
-
- i = system (scmd);
-
- remove (rf);
-
- if (i == -1)
- {
- perror (program);
- return MIN_FATAL_STATUS << 8;
- }
-
- return i << 8;
-}
-
-#else /* not __MSDOS__ */
-
-static int
-pexecute (program, argv)
- char *program;
- char *argv[];
-{
- int pid;
- int retries, sleep_interval;
-
- /* Fork a subprocess; wait and retry if it fails. */
- sleep_interval = 1;
- for (retries = 0; retries < 4; retries++)
- {
- pid = vfork ();
- if (pid >= 0)
- break;
- sleep (sleep_interval);
- sleep_interval *= 2;
- }
-
- switch (pid)
+ if (status != 0)
{
- case -1:
-#ifdef vfork
- perror ("fork");
-#else
- perror ("vfork");
-#endif
- exit (1);
- /* NOTREACHED */
- return 0;
-
- case 0: /* child */
- /* Exec the program. */
- execvp (program, argv);
- perror (program);
+ non_fatal (_("Execution of %s failed"), ld);
+ unlink (unlink_on_exit);
exit (1);
- /* NOTREACHED */
- return 0;
-
- default:
- /* Return child's process number. */
- return pid;
}
-}
-
-#endif /* not __MSDOS__ */
-#else /* not OS2 */
-static int
-pexecute (program, argv)
- char *program;
- char *argv[];
-{
- return spawnvp (1, program, argv);
+ return unlink_on_exit;
}
-#endif /* not OS2 */