* ldgram.y (PHDRS): New token.
authorIan Lance Taylor <ian@airs.com>
Fri, 1 Dec 1995 21:49:51 +0000 (21:49 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 1 Dec 1995 21:49:51 +0000 (21:49 +0000)
(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
ld/ldlang.c

index ebaddc5b982502843eed4fc7dcd808648b88ebb8..cbd3d4339cc3b6628e79f9640fbe00798e216e52 100644 (file)
@@ -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
index 07562b84fca35e49ad2aecec529a036bf5660fab..e1406f632f51585c7f264d2e4c04c0c837bc9d4a 100644 (file)
@@ -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);
+    }
+}