aboutsummaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-12-01 21:49:51 +0000
committerIan Lance Taylor <ian@airs.com>1995-12-01 21:49:51 +0000
commit061e65f8551b1ed3af488dddb92d947c868d4948 (patch)
tree7f12c87b4a03e064acdf42d888de4ac865ed709c /ld/ldlang.c
parentae0a6bea51963cb58d2df3e5b453efdcfdd41628 (diff)
downloadgdb-061e65f8551b1ed3af488dddb92d947c868d4948.zip
gdb-061e65f8551b1ed3af488dddb92d947c868d4948.tar.gz
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/ldlang.c')
-rw-r--r--ld/ldlang.c149
1 files changed, 147 insertions, 2 deletions
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);
+ }
+}