From 061e65f8551b1ed3af488dddb92d947c868d4948 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 1 Dec 1995 21:49:51 +0000 Subject: [PATCH] * 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. --- ld/ChangeLog | 21 ++++++++ ld/ldlang.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 2 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index ebaddc5b982..cbd3d4339cc 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,24 @@ +Fri Dec 1 16:48:36 1995 Ian Lance Taylor + + * 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 * scripttempl/ppcpe.sc: Moved .edata into its own section to diff --git a/ld/ldlang.c b/ld/ldlang.c index 07562b84fca..e1406f632f5 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); + } +} -- 2.30.2