diff options
author | Ian Lance Taylor <ian@airs.com> | 1995-12-01 21:49:51 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1995-12-01 21:49:51 +0000 |
commit | 061e65f8551b1ed3af488dddb92d947c868d4948 (patch) | |
tree | 7f12c87b4a03e064acdf42d888de4ac865ed709c /ld | |
parent | ae0a6bea51963cb58d2df3e5b453efdcfdd41628 (diff) | |
download | fsf-binutils-gdb-061e65f8551b1ed3af488dddb92d947c868d4948.zip fsf-binutils-gdb-061e65f8551b1ed3af488dddb92d947c868d4948.tar.gz fsf-binutils-gdb-061e65f8551b1ed3af488dddb92d947c868d4948.tar.bz2 |
* ldgram.y (PHDRS): New token.
(ifile_p1): Accept phdrs.
(section): Accept phdr_opt at the end of the section definition.
(phdr_op): New nonterminal.
(phdrs, phdr_list, phdr, phdr_type, opt_hdrs, hdr): Likewise.
* ldlex.l: Accept PHDRS.
* ldlang.h (struct lang_output_section_phdr_list): Define.
(lang_output_section_statement_type): Add phdrs field.
(struct lang_phdr): Define.
(LANG_PHDR_FILEHDR, LANG_PHDR_PHDRS): Define.
(lang_new_phdr): Declare.
* ldlang.c (lang_phdr_list): New static variable.
(lang_output_section_statement_lookup): Initialize phdrs field.
(lang_process): Call lang_record_phdrs.
(lang_new_phdr): New function.
(lang_section_in_phdr): New function.
(lang_record_phdrs): New static function.
* ld.texinfo: Document PHDRS.
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 21 | ||||
-rw-r--r-- | ld/ldlang.c | 149 |
2 files changed, 168 insertions, 2 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index ebaddc5..cbd3d43 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,24 @@ +Fri Dec 1 16:48:36 1995 Ian Lance Taylor <ian@cygnus.com> + + * ldgram.y (PHDRS): New token. + (ifile_p1): Accept phdrs. + (section): Accept phdr_opt at the end of the section definition. + (phdr_op): New nonterminal. + (phdrs, phdr_list, phdr, phdr_type, opt_hdrs, hdr): Likewise. + * ldlex.l: Accept PHDRS. + * ldlang.h (struct lang_output_section_phdr_list): Define. + (lang_output_section_statement_type): Add phdrs field. + (struct lang_phdr): Define. + (LANG_PHDR_FILEHDR, LANG_PHDR_PHDRS): Define. + (lang_new_phdr): Declare. + * ldlang.c (lang_phdr_list): New static variable. + (lang_output_section_statement_lookup): Initialize phdrs field. + (lang_process): Call lang_record_phdrs. + (lang_new_phdr): New function. + (lang_section_in_phdr): New function. + (lang_record_phdrs): New static function. + * ld.texinfo: Document PHDRS. + Thu Nov 30 13:14:30 1995 Kim Knuttila <krk@cygnus.com> * scripttempl/ppcpe.sc: Moved .edata into its own section to diff --git a/ld/ldlang.c b/ld/ldlang.c index 07562b8..e1406f6 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -59,6 +59,7 @@ static CONST char *current_target; static CONST char *output_target; static int longest_section_name = 8; static lang_statement_list_type statement_list; +static struct lang_phdr *lang_phdr_list; static void print_size PARAMS ((size_t value)); static void print_alignment PARAMS ((unsigned int value)); @@ -128,12 +129,13 @@ static void lang_place_orphans PARAMS ((void)); static int topower PARAMS ((int)); static void lang_set_startof PARAMS ((void)); static void reset_memory_regions PARAMS ((void)); +static void lang_record_phdrs PARAMS ((void)); /* EXPORTS */ lang_output_section_statement_type *abs_output_section; lang_statement_list_type *stat_ptr = &statement_list; lang_statement_list_type file_chain = { 0 }; -static const char *entry_symbol = 0; +const char *entry_symbol = NULL; boolean entry_from_cmdline; boolean lang_has_input_file = false; boolean had_output_filename = false; @@ -526,6 +528,7 @@ lang_output_section_statement_lookup (name) lookup->subsection_alignment = -1; lookup->section_alignment = -1; lookup->load_base = (union etree_union *) NULL; + lookup->phdrs = NULL; lang_statement_append (&lang_output_section_statement, (lang_statement_union_type *) lookup, @@ -2245,7 +2248,8 @@ lang_finish () h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true); if (h != (struct bfd_link_hash_entry *) NULL && (h->type == bfd_link_hash_defined - || h->type == bfd_link_hash_defweak)) + || h->type == bfd_link_hash_defweak) + && h->u.def.section->output_section != NULL) { bfd_vma val; @@ -2724,6 +2728,10 @@ lang_process () ldemul_before_allocation (); + /* We must record the program headers before we try to fix the + section positions, since they will affect SIZEOF_HEADERS. */ + lang_record_phdrs (); + /* Now run around and relax if we can */ if (command_line.relax) { @@ -3114,3 +3122,140 @@ lang_leave_group () { stat_ptr = &statement_list; } + +/* Add a new program header. This is called for each entry in a PHDRS + command in a linker script. */ + +void +lang_new_phdr (name, type, hdrs, at) + const char *name; + etree_type *type; + unsigned int hdrs; + etree_type *at; +{ + struct lang_phdr *n, **pp; + + n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr)); + n->next = NULL; + n->name = name; + n->type = exp_get_value_int (type, 0, "program header type", + lang_final_phase_enum); + n->hdrs = hdrs; + n->at = at; + + for (pp = &lang_phdr_list; *pp != NULL; pp = &(*pp)->next) + ; + *pp = n; +} + +/* Record that a section should be placed in a phdr. */ + +void +lang_section_in_phdr (name) + const char *name; +{ + struct lang_output_section_phdr_list *n; + + n = ((struct lang_output_section_phdr_list *) + stat_alloc (sizeof (struct lang_output_section_phdr_list))); + n->name = name; + n->used = false; + n->next = current_section->phdrs; + current_section->phdrs = n; +} + +/* Record the program header information in the output BFD. FIXME: We + should not be calling an ELF specific function here. */ + +static void +lang_record_phdrs () +{ + unsigned int alc; + asection **secs; + struct lang_output_section_phdr_list *last; + struct lang_phdr *l; + lang_statement_union_type *u; + + alc = 10; + secs = xmalloc (alc * sizeof (asection *)); + last = NULL; + for (l = lang_phdr_list; l != NULL; l = l->next) + { + unsigned int c; + bfd_vma at; + + c = 0; + for (u = lang_output_section_statement.head; + u != NULL; + u = u->output_section_statement.next) + { + lang_output_section_statement_type *os; + struct lang_output_section_phdr_list *pl; + + os = &u->output_section_statement; + + pl = os->phdrs; + if (pl != NULL) + last = pl; + else + { + if (! os->loadable + || os->bfd_section == NULL + || (os->bfd_section->flags & SEC_ALLOC) == 0) + continue; + pl = last; + } + + if (os->bfd_section == NULL) + continue; + + for (; pl != NULL; pl = pl->next) + { + if (strcmp (pl->name, l->name) == 0) + { + if (c >= alc) + { + alc *= 2; + secs = xrealloc (secs, alc * sizeof (asection *)); + } + secs[c] = os->bfd_section; + ++c; + pl->used = true; + } + } + } + + if (l->at == NULL) + at = 0; + else + at = exp_get_vma (l->at, 0, "phdr load address", + lang_final_phase_enum); + if (! bfd_record_phdr (output_bfd, l->type, false, 0, + l->at == NULL ? false : true, + at, + (l->hdrs & LANG_PHDR_FILEHDR) ? true : false, + (l->hdrs & LANG_PHDR_PHDRS) ? true : false, + c, secs)) + einfo ("%F%P: bfd_record_phdr failed: %E\n"); + } + + free (secs); + + /* Make sure all the phdr assignments succeeded. */ + for (u = lang_output_section_statement.head; + u != NULL; + u = u->output_section_statement.next) + { + struct lang_output_section_phdr_list *pl; + + if (u->output_section_statement.bfd_section == NULL) + continue; + + for (pl = u->output_section_statement.phdrs; + pl != NULL; + pl = pl->next) + if (! pl->used && strcmp (pl->name, "NONE") != 0) + einfo ("%X%P: section `%s' assigned to non-existent phdr `%s'\n", + u->output_section_statement.name, pl->name); + } +} |