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; }
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); }