Esempio n. 1
0
int main(int argc, char **argv) {
     progname = argv[0];

     buf_init(module, INIT_MODS, 1, struct _module, "modules");
     buf_init(dep, INIT_MODS, 1, int, "dependencies");

     stack_size = STACK_SIZE;

     get_options(argc, argv);
     if (nfiles == 0 && !dump) panic("no input files");
     if (stdlib && libdir == NULL) panic("no libdir specified");
     if (rtlibdir == NULL) rtlibdir = libdir;

     make_prim("INTERP");
     make_prim("DLTRAP");
     
#define bind(x) def_global(find_symbol(#x), ABS, x, X_SYM)

     bind(GC_BASE); bind(GC_REPEAT); bind(GC_BLOCK);
     bind(GC_MAP); bind(GC_FLEX); bind(GC_END);
     bind(E_CAST); bind(E_ASSIGN); bind(E_CASE);
     bind(E_WITH); bind(E_ASSERT); bind(E_RETURN);
     bind(E_BOUND); bind(E_NULL); bind(E_DIV);
     bind(E_FDIV); bind(E_STACK); bind(E_GLOB);

     /* First pass -- check for dependencies */
     scan_files();

     /* Compute needed modules */
     buf_grow(module);
     module[nmodules].m_dep = ndeps;
     trace_imports();

     if (status != 0) return status;

     /* Second pass -- link the modules that are needed */
     if (!dump) {
	  init_linker(outname, interp);
	  load_needed();
	  gen_main();
	  if (rtlibdir != NULL)
	       save_string("LIBDIR", rtlibdir);
	  end_linking();
     }

     if (dump || custom) {
	  printf("/* Primitive table -- generated by oblink */\n\n");
	  printf("#include \"obx.h\"\n\n");
	  dump_prims(stdout);
     }

     return status;
}
Esempio n. 2
0
int
main (int argc, char *argv[])
{
  int remaining;
  int err;

#ifndef NDEBUG
  /* Enable memory debugging.  */
  mtrace ();
#endif

  /* Sanity check.  We always want to use the LFS functionality.  */
  if (sizeof (off_t) != sizeof (off64_t))
    abort ();

  /* We use no threads here which can interfere with handling a stream.  */
  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
  __fsetlocking (stderr, FSETLOCKING_BYCALLER);

  /* Set locale.  */
  setlocale (LC_ALL, "");

  /* Make sure the message catalog can be found.  */
  bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);

  /* Initialize the message catalog.  */
  textdomain (PACKAGE_TARNAME);

  /* Before we start tell the ELF library which version we are using.  */
  elf_version (EV_CURRENT);

  /* The user can use the LD_LIBRARY_PATH environment variable to add
     additional lookup directories.  */
  ld_library_path1 = getenv ("LD_LIBRARY_PATH");

  /* Initialize the memory handling.  */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
  obstack_init (&ld_state.smem);

  /* Recognize old-style parameters for compatibility.  */
  replace_args (argc, argv);

  /* One quick pass over the parameters which allows us to scan for options
     with global effect which influence the rest of the processing.  */
  argp_parse (&argp_1st, argc, argv, ARGP_IN_ORDER, &remaining, NULL);

  /* We need at least one input file.  */
  if (input_file_list == NULL)
    {
      error (0, 0, gettext ("At least one input file needed"));
      argp_help (&argp_1st, stderr, ARGP_HELP_SEE, "ld");
      exit (EXIT_FAILURE);
    }

  /* Determine which ELF backend to use.  */
  determine_output_format ();

  /* If no hash style was specific default to the oldand slow SysV
     method.  */
  if (unlikely (ld_state.hash_style == hash_style_none))
    ld_state.hash_style = hash_style_sysv;

  /* Prepare state.  */
  err = ld_prepare_state (emulation);
  if (err != 0)
    error (EXIT_FAILURE, 0, gettext ("error while preparing linking"));

  /* XXX Read the linker script now.  Since we later will have the linker
     script built in we don't go into trouble to make sure we handle GROUP
     statements in the script.  This simply must not happen.  */
  ldin = fopen (linker_script, "r");
  if (ldin == NULL)
    error (EXIT_FAILURE, errno, gettext ("cannot open linker script '%s'"),
	   linker_script);
  /* No need for locking.  */
  __fsetlocking (ldin, FSETLOCKING_BYCALLER);

  ld_state.srcfiles = NULL;
  ldlineno = 1;
  ld_scan_version_script = 0;
  ldin_fname = linker_script;
  if (ldparse () != 0)
    /* Something went wrong during parsing.  */
    exit (EXIT_FAILURE);
  fclose (ldin);

  /* We now might have a list of directories to look for libraries in
     named by the linker script.  Put them in a different list so that
     they are searched after all paths given by the user on the
     command line.  */
  ld_state.default_paths = ld_state.paths;
  ld_state.paths = ld_state.tailpaths = NULL;

  /* Get runpath/rpath information in usable form.  */
  gen_rxxpath_data ();

  /* Parse and process arguments for real.  */
  argp_parse (&argp_2nd, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
  /* All options should have been processed by the argp parser.  */
  assert (remaining == argc);

  /* Process the last file.  */
  while (last_file != NULL)
    /* Try to open the file.  */
    error_loading |= FILE_PROCESS (-1, last_file, &ld_state, &last_file);

  /* Stop if there has been a problem while reading the input files.  */
  if (error_loading)
    exit (error_loading);

  /* See whether all opened -( were closed.  */
  if (group_level > 0)
    {
      error (0, 0, gettext ("-( without matching -)"));
      argp_help (&argp_1st, stderr, ARGP_HELP_SEE, "ld");
      exit (EXIT_FAILURE);
    }

  /* When we create a relocatable file we don't have to look for the
     DT_NEEDED DSOs and we also don't test for undefined symbols.  */
  if (ld_state.file_type != relocatable_file_type)
    {
      /* At this point we have loaded all the direct dependencies.  What
	 remains to be done is find the indirect dependencies.  These are
	 DSOs which are referenced by the DT_NEEDED entries in the DSOs
	 which are direct dependencies.  We have to transitively find and
	 load all these dependencies.  */
      load_needed ();

      /* At this point all object files and DSOs are read.  If there
	 are still undefined symbols left they might have to be
	 synthesized from the linker script.  */
      create_lscript_symbols ();

      /* Now that we have loaded all the object files we can determine
	 whether we have any non-weak unresolved references left.  If
	 there are any we stop.  If the user used the '-z nodefs' option
	 and we are creating a DSO don't perform the tests.  */
      if (FLAG_UNRESOLVED (&ld_state) != 0)
	exit (1);
    }

  /* Collect information about the relocations which will be carried
     forward into the output.  We have to do this here and now since
     we need to know which sections have to be created.  */
  if (ld_state.file_type != relocatable_file_type)
    {
      void *p ;
      struct scnhead *h;

      p = NULL;
      while ((h = ld_section_tab_iterate (&ld_state.section_tab, &p)) != NULL)
	if (h->type == SHT_REL || h->type == SHT_RELA)
	  {
	    struct scninfo *runp = h->last;
	    do
	      {
		/* If we are processing the relocations determine how
		   many will be in the output file.  Also determine
		   how many GOT entries are needed.  */
		COUNT_RELOCATIONS (&ld_state, runp);

		ld_state.relsize_total += runp->relsize;
	      }
	    while ((runp = runp->next) != h->last);
	  }
    }

  /* Not part of the gABI, but part of every psABI: the symbols for the
     GOT section.  Add the symbol if necessary.  */
  if (ld_state.need_got)
    create_special_section_symbol (&ld_state.got_symbol,
				   "_GLOBAL_OFFSET_TABLE_");
  /* Similarly for the _DYNAMIC symbol which points to the dynamic
     section.  */
  if (dynamically_linked_p ())
    create_special_section_symbol (&ld_state.dyn_symbol, "_DYNAMIC");

  /* We are ready to start working on the output file.  Not all
     information has been gather or created yet.  This will be done as
     we go.  Open the file now.  */
  if (OPEN_OUTFILE (&ld_state, EM_NONE, ELFCLASSNONE, ELFDATANONE) != 0)
    exit (1);

  /* Create the sections which are generated by the linker and are not
     present in the input file.  The output file must already have
     been opened since we need the ELF descriptor to deduce type
     sizes.  */
  GENERATE_SECTIONS (&ld_state);

  /* At this point we have read all the files and know all the
     sections which have to be linked into the application.  We do now
     create an array listing all the sections.  We will than pass this
     array to a system specific function which can reorder it at will.
     The functions can also merge sections if this is what is
     wanted.  */
  collect_sections ();

  /* Create the output sections now.  This may requires sorting them
     first.  */
  CREATE_SECTIONS (&ld_state);

  /* Create the output file data.  Appropriate code for the selected
     output file type is called.  */
  if (CREATE_OUTFILE (&ld_state) != 0)
    exit (1);

  /* Finalize the output file, write the data out.  */
  err |= FINALIZE (&ld_state);

  /* Return with an non-zero exit status also if any error message has
     been printed.  */
  return err | (error_message_count != 0);
}