nlmconv.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,181 行 · 第 1/5 页

C
2,181
字号
/* nlmconv.c -- NLM conversion program   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000   Free Software Foundation, Inc.This file is part of GNU Binutils.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.  *//* AIX requires this to be the first thing in the file.  */#ifndef __GNUC__# ifdef _AIX #pragma alloca#endif#endif#include "bfd.h"#include "libiberty.h"#include "bucomm.h"#include <ansidecl.h>#include <time.h>#include <ctype.h>#include <sys/stat.h>#include <sys/file.h>#include <assert.h>#include <getopt.h>/* Internal BFD NLM header.  */#include "libnlm.h"#include "nlmconv.h"#ifdef NLMCONV_ALPHA#include "coff/sym.h"#include "coff/ecoff.h"#endif/* If strerror is just a macro, we want to use the one from libiberty   since it will handle undefined values.  */#undef strerrorextern char *strerror ();#ifndef localtimeextern struct tm *localtime ();#endif#ifndef SEEK_SET#define SEEK_SET 0#endif#ifndef R_OK#define R_OK 4#define W_OK 2#define X_OK 1#endif/* Global variables.  *//* The name used to invoke the program.  */char *program_name;/* Local variables.  *//* Whether to print out debugging information (currently just controls   whether it prints the linker command if there is one).  */static int debug;/* 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.  */static char *unlink_on_exit;/* The list of long options.  */static struct option long_options[] ={  { "debug", no_argument, 0, 'd' },  { "header-file", required_argument, 0, 'T' },  { "help", no_argument, 0, 'h' },  { "input-target", required_argument, 0, 'I' },  { "input-format", required_argument, 0, 'I' }, /* Obsolete */  { "linker", required_argument, 0, 'l' },  { "output-target", required_argument, 0, 'O' },  { "output-format", required_argument, 0, 'O' }, /* Obsolete */  { "version", no_argument, 0, 'V' },  { NULL, no_argument, 0, 0 }};/* 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 default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,					   long *, char *,					   bfd_size_type));static char *link_inputs PARAMS ((struct string_list *, char *));#ifdef NLMCONV_I386static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,					long *, char *,					bfd_size_type));#endif#ifdef NLMCONV_ALPHAstatic void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,					 long *, char *,					 bfd_size_type));#endif#ifdef NLMCONV_POWERPCstatic void powerpc_build_stubs PARAMS ((bfd *, 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));#endif/* The main routine.  */intmain (argc, argv)     int argc;     char **argv;{  int opt;  char *input_file = NULL;  const char *input_format = NULL;  const char *output_format = NULL;  const char *header_file = NULL;  char *ld_arg = NULL;  Nlm_Internal_Fixed_Header fixed_hdr_struct;  Nlm_Internal_Variable_Header var_hdr_struct;  Nlm_Internal_Version_Header version_hdr_struct;  Nlm_Internal_Copyright_Header copyright_hdr_struct;  Nlm_Internal_Extended_Header extended_hdr_struct;  bfd *inbfd;  bfd *outbfd;  asymbol **newsyms, **outsyms;  long symcount, newsymalloc, newsymcount;  long symsize;  asection *text_sec, *bss_sec, *data_sec;  bfd_vma vma;  bfd_size_type align;  asymbol *endsym;  long i;  char inlead, outlead;  boolean gotstart, gotexit, gotcheck;  struct stat st;  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 = 0;  size_t shared_size = 0;  Nlm_Internal_Fixed_Header sharedhdr;  int len;  char *modname;  char **matching;#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)  setlocale (LC_MESSAGES, "");#endif  bindtextdomain (PACKAGE, LOCALEDIR);  textdomain (PACKAGE);  program_name = argv[0];  xmalloc_set_program_name (program_name);  bfd_init ();  set_default_bfd_target ();  while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options,			     (int *) NULL))	 != EOF)    {      switch (opt)	{	case 'd':	  debug = 1;	  break;	case 'h':	  show_help ();	  /*NOTREACHED*/	case 'I':	  input_format = optarg;	  break;	case 'l':	  ld_arg = optarg;	  break;	case 'O':	  output_format = optarg;	  break;	case 'T':	  header_file = optarg;	  break;	case 'V':	  print_version ("nlmconv");	  /*NOTREACHED*/	case 0:	  break;	default:	  show_usage (stderr, 1);	  /*NOTREACHED*/	}    }  /* The input and output files may be named on the command line.  */  output_file = NULL;  if (optind < argc)    {      input_file = argv[optind];      ++optind;      if (optind < argc)	{	  output_file = argv[optind];	  ++optind;	  if (optind < argc)	    show_usage (stderr, 1);	  if (strcmp (input_file, output_file) == 0)	    {	      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);  var_hdr = &var_hdr_struct;  memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct);  version_hdr = &version_hdr_struct;  memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct);  copyright_hdr = &copyright_hdr_struct;  memset ((PTR) &copyright_hdr_struct, 0, sizeof copyright_hdr_struct);  extended_hdr = &extended_hdr_struct;  memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct);  check_procedure = NULL;  custom_file = NULL;  debug_info = false;  exit_procedure = "_Stop";  export_symbols = NULL;  map_file = NULL;  full_map = false;  help_file = NULL;  import_symbols = NULL;  message_file = NULL;  modules = NULL;  sharelib_file = NULL;  start_procedure = "_Prelude";  verbose = false;  rpc_file = NULL;  parse_errors = 0;  /* Parse the header file (if there is one).  */  if (header_file != NULL)    {      if (! nlmlex_file (header_file)	  || yyparse () != 0	  || parse_errors != 0)	exit (1);    }  if (input_files != NULL)    {      if (input_file != NULL)	{	  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);    }  else if (input_file == NULL)    {      non_fatal (_("no input file"));      show_usage (stderr, 1);    }  inbfd = bfd_openr (input_file, input_format);  if (inbfd == NULL)    bfd_fatal (input_file);  if (! bfd_check_format_matches (inbfd, bfd_object, &matching))    {      bfd_nonfatal (input_file);      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)	{	  list_matching_formats (matching);	  free (matching);	}      exit (1);    }  if (output_format == NULL)    output_format = select_output_format (bfd_get_arch (inbfd),					  bfd_get_mach (inbfd),					  bfd_big_endian (inbfd));  assert (output_format != NULL);  /* Use the output file named on the command line if it exists.     Otherwise use the file named in the OUTPUT statement.  */  if (output_file == NULL)    {      non_fatal (_("no name for output file"));      show_usage (stderr, 1);    }  outbfd = bfd_openw (output_file, output_format);  if (outbfd == NULL)    bfd_fatal (output_file);  if (! bfd_set_format (outbfd, bfd_object))    bfd_fatal (output_file);  assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour);  if (bfd_arch_get_compatible (inbfd, outbfd) == 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;  *nlm_variable_header (outbfd) = var_hdr_struct;  *nlm_version_header (outbfd) = version_hdr_struct;  *nlm_copyright_header (outbfd) = copyright_hdr_struct;  *nlm_extended_header (outbfd) = extended_hdr_struct;  /* Start copying the input BFD to the output BFD.  */  if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd)))    bfd_fatal (bfd_get_filename (outbfd));  symsize = bfd_get_symtab_upper_bound (inbfd);  if (symsize < 0)    bfd_fatal (input_file);  symbols = (asymbol **) xmalloc (symsize);  symcount = bfd_canonicalize_symtab (inbfd, symbols);  if (symcount < 0)    bfd_fatal (input_file);  /* Make sure we have a .bss section.  */  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);      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"));    }  /* 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 (outbfd, ".nlmsections");  if (secsec == NULL)    bfd_fatal (_("make .nlmsections section"));  if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS))    bfd_fatal (_("set .nlmsections flags"));#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, outbfd, &symbols, &symcount);#endif  /* Set up the sections.  */  bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);  text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME);  /* The .bss section immediately follows the .data section.  */  data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME);  if (data_sec != NULL)    {      bfd_size_type add;      vma = bfd_get_section_size_before_reloc (data_sec);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?