diff options
-rw-r--r-- | ld/ChangeLog | 13 | ||||
-rw-r--r-- | ld/ldemul.h | 147 | ||||
-rw-r--r-- | ld/ldlang.c | 61 |
3 files changed, 218 insertions, 3 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 9fb6850..fa41a1d 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,16 @@ +1998-11-25 DJ Delorie <dj@cygnus.com> + + * ldemul.h (ld_emulation_xfer_struct): new hook "recognized_file" + * ldemul.c (ldemul_recognized_file): new function, new hook + * ldint.texinfo: document new hook. + * ldlang.c (load_symbols): call recognized_hook for all objects we + do recognize, in case the emulation needs to handle them + specially. PE DLLs use this. + * pe-dll.c (pe_dll_generate_def_file): take out hack and debug + printfs + * emultempl/pe.em (gld_i386_recognized_file): new function + (gld_i486_unrecognized_file): take out hack + start-sanitize-vr4xxx 1998-11-24 Gavin Romig-Koch <gavin@cygnus.com> diff --git a/ld/ldemul.h b/ld/ldemul.h new file mode 100644 index 0000000..eb34da9 --- /dev/null +++ b/ld/ldemul.h @@ -0,0 +1,147 @@ +/* ld-emul.h - Linker emulation header file + Copyright 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. + + This file is part of GLD, the Gnu Linker. + + GLD 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 1, or (at your option) + any later version. + + GLD 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. */ + +#ifndef LDEMUL_H +#define LDEMUL_H + +#if ANSI_PROTOTYPES +struct lang_input_statement_struct; +struct search_dirs; +#endif + +extern void ldemul_hll PARAMS ((char *)); +extern void ldemul_syslib PARAMS ((char *)); +extern void ldemul_after_parse PARAMS ((void)); +extern void ldemul_before_parse PARAMS ((void)); +extern void ldemul_after_open PARAMS ((void)); +extern void ldemul_after_allocation PARAMS ((void)); +extern void ldemul_before_allocation PARAMS ((void)); +extern void ldemul_set_output_arch PARAMS ((void)); +extern char *ldemul_choose_target PARAMS ((void)); +extern void ldemul_choose_mode PARAMS ((char *)); +extern void ldemul_list_emulations PARAMS ((FILE *)); +extern void ldemul_list_emulation_options PARAMS ((FILE *)); +extern char *ldemul_get_script PARAMS ((int *isfile)); +extern void ldemul_finish PARAMS ((void)); +extern void ldemul_set_symbols PARAMS ((void)); +extern void ldemul_create_output_section_statements PARAMS ((void)); +extern boolean ldemul_place_orphan + PARAMS ((struct lang_input_statement_struct *, asection *)); +extern int ldemul_parse_args PARAMS ((int, char **)); +extern boolean ldemul_unrecognized_file + PARAMS ((struct lang_input_statement_struct *)); +extern boolean ldemul_open_dynamic_archive + PARAMS ((const char *, struct search_dirs *, + struct lang_input_statement_struct *)); +extern char *ldemul_default_target PARAMS ((void)); +extern void after_parse_default PARAMS ((void)); +extern void after_open_default PARAMS ((void)); +extern void after_allocation_default PARAMS ((void)); +extern void before_allocation_default PARAMS ((void)); +extern void set_output_arch_default PARAMS ((void)); +extern void syslib_default PARAMS ((char*)); +extern void hll_default PARAMS ((char*)); + +typedef struct ld_emulation_xfer_struct +{ + /* Run before parsing the command line and script file. + Set the architecture, maybe other things. */ + void (*before_parse) PARAMS ((void)); + + /* Handle the SYSLIB (low level library) script command. */ + void (*syslib) PARAMS ((char *)); + + /* Handle the HLL (high level library) script command. */ + void (*hll) PARAMS ((char *)); + + /* Run after parsing the command line and script file. */ + void (*after_parse) PARAMS ((void)); + + /* Run after opening all input files, and loading the symbols. */ + void (*after_open) PARAMS ((void)); + + /* Run after allocating output sections. */ + void (*after_allocation) PARAMS ( (void)); + + /* Set the output architecture and machine if possible. */ + void (*set_output_arch) PARAMS ((void)); + + /* Decide which target name to use. */ + char * (*choose_target) PARAMS ((void)); + + /* Run before allocating output sections. */ + void (*before_allocation) PARAMS ((void)); + + /* Return the appropriate linker script. */ + char * (*get_script) PARAMS ((int *isfile)); + + /* The name of this emulation. */ + char *emulation_name; + + /* The output format. */ + char *target_name; + + /* Run after assigning values from the script. */ + void (*finish) PARAMS ((void)); + + /* Create any output sections needed by the target. */ + void (*create_output_section_statements) PARAMS ((void)); + + /* Try to open a dynamic library. ARCH is an architecture name, and + is normally the empty string. ENTRY is the lang_input_statement + that should be opened. */ + boolean (*open_dynamic_archive) + PARAMS ((const char *arch, struct search_dirs *, + struct lang_input_statement_struct *entry)); + + /* Place an orphan section. Return true if it was placed, false if + the default action should be taken. This field may be NULL, in + which case the default action will always be taken. */ + boolean (*place_orphan) + PARAMS ((struct lang_input_statement_struct *, asection *)); + + /* Run after assigning parsing with the args, but before + reading the script. Used to initialize symbols used in the script. */ + void (*set_symbols) PARAMS ((void)); + + /* Run to parse args which the base linker doesn't + understand. Return non zero on sucess. */ + int (*parse_args) PARAMS ((int, char **)); + + /* Run to handle files which are not recognized as object files or + archives. Return true if the file was handled. */ + boolean (*unrecognized_file) + PARAMS ((struct lang_input_statement_struct *)); + + /* Run to list the command line options which parse_args handles. */ + void (* list_options) PARAMS ((FILE *)); + + /* Run to specially handle files which *are* recognized as object + files or archives. Return true if the file was handled. */ + boolean (*recognized_file) + PARAMS ((struct lang_input_statement_struct *)); + +} ld_emulation_xfer_type; + +typedef enum +{ + intel_ic960_ld_mode_enum, + default_mode_enum , + intel_gld960_ld_mode_enum +} lang_emulation_mode_enum_type; + +extern ld_emulation_xfer_type *ld_emulations[]; + +#endif diff --git a/ld/ldlang.c b/ld/ldlang.c index 2106b3e..f9dbd88 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -151,6 +151,7 @@ static void lang_gc_wild PARAMS ((lang_wild_statement_type *, const char *, const char *)); static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *)); static void lang_gc_sections PARAMS ((void)); +static void lang_do_version_exports_section PARAMS ((void)); /* EXPORTS */ @@ -1253,6 +1254,9 @@ load_symbols (entry, place) return; } + if (ldemul_recognized_file (entry)) + return; + /* We don't call ldlang_add_file for an archive. Instead, the add_symbols entry point will call ldlang_add_file, via the add_archive_element callback, for each element of the archive @@ -2089,7 +2093,10 @@ print_statement (s, os) case lang_constructors_statement_enum: if (constructor_list.head != NULL) { - minfo (" CONSTRUCTORS\n"); + if (constructors_sorted) + minfo (" SORT (CONSTRUCTORS)\n"); + else + minfo (" CONSTRUCTORS\n"); print_statement_list (constructor_list.head, os); } break; @@ -3549,6 +3556,8 @@ lang_gc_sections_1 (s) case lang_group_statement_enum: lang_gc_sections_1 (s->group_statement.children.head); break; + default: + break; } } } @@ -3567,7 +3576,7 @@ lang_gc_sections () Handle the entry symbol at the same time. */ fake_list_start.next = ldlang_undef_chain_list_head; - fake_list_start.name = entry_symbol; + fake_list_start.name = (char *) entry_symbol; for (ulist = &fake_list_start; ulist; ulist = ulist->next) { @@ -3612,6 +3621,10 @@ lang_process () link. */ lang_check (); + /* Handle .exports instead of a version script if we're told to do so. */ + if (command_line.version_exports_section) + lang_do_version_exports_section (); + /* Build all sets based on the information gathered from the input files. */ ldctor_build_sets (); @@ -3655,6 +3668,10 @@ lang_process () relax_again = false; + /* Note: pe-dll.c does something like this also. If you find + you need to change this code, you probably need to change + pe-dll.c also. DJ */ + /* Do all the assignments with our current guesses as to section sizes. */ lang_do_assignments (statement_list.head, @@ -3836,7 +3853,7 @@ lang_add_reloc (reloc, howto, section, name, addend) p->output_vma = 0; } -void +lang_assignment_statement_type * lang_add_assignment (exp) etree_type * exp; { @@ -3844,6 +3861,7 @@ lang_add_assignment (exp) stat_ptr); new->exp = exp; + return new; } void @@ -4476,3 +4494,40 @@ lang_add_vers_depend (list, name) return ret; } + +static void +lang_do_version_exports_section () +{ + struct bfd_elf_version_expr *greg = NULL, *lreg; + + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + asection *sec = bfd_get_section_by_name (is->the_bfd, ".exports"); + char *contents, *p; + bfd_size_type len; + + if (sec == NULL) + continue; + + len = bfd_section_size (is->the_bfd, sec); + contents = xmalloc (len); + if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len)) + einfo (_("%X%P: unable to read .exports section contents"), sec); + + while (p < contents+len) + { + greg = lang_new_vers_regex (greg, p); + p = strchr (p, '\0') + 1; + } + + free (contents); + + /* Do not include this section in the link. */ + bfd_set_section_flags (is->the_bfd, sec, + bfd_get_section_flags (is->the_bfd, sec) | SEC_EXCLUDE); + } + + lreg = lang_new_vers_regex (NULL, "*"); + lang_register_vers_node (command_line.version_exports_section, + lang_new_vers_node (greg, lreg), NULL); +} |