static void lang_set_startof PARAMS ((void));
static void reset_memory_regions PARAMS ((void));
static void lang_record_phdrs PARAMS ((void));
+static void lang_gc_wild_section
+ PARAMS ((lang_wild_statement_type *, const char *,
+ lang_input_statement_type *));
+static void lang_gc_wild_file
+ PARAMS ((lang_wild_statement_type *, const char *,
+ lang_input_statement_type *));
+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));
+
/* EXPORTS */
lang_output_section_statement_type *abs_output_section;
if (wild->filenames_sorted)
{
+ const char *fn, *ln;
+ boolean fa, la;
int i;
- i = strcmp (file->filename, ls->ifile->filename);
- if (i < 0)
+ /* The PE support for the .idata section as generated by
+ dlltool assumes that files will be sorted by the name of
+ the archive and then the name of the file within the
+ archive. */
+
+ if (file->the_bfd != NULL
+ && bfd_my_archive (file->the_bfd) != NULL)
+ {
+ fn = bfd_get_filename (bfd_my_archive (file->the_bfd));
+ fa = true;
+ }
+ else
+ {
+ fn = file->filename;
+ fa = false;
+ }
+
+ if (ls->ifile->the_bfd != NULL
+ && bfd_my_archive (ls->ifile->the_bfd) != NULL)
+ {
+ ln = bfd_get_filename (bfd_my_archive (ls->ifile->the_bfd));
+ la = true;
+ }
+ else
+ {
+ ln = ls->ifile->filename;
+ la = false;
+ }
+
+ i = strcmp (fn, ln);
+ if (i > 0)
continue;
- else if (i > 0)
+ else if (i < 0)
break;
+
+ if (fa || la)
+ {
+ if (fa)
+ fn = file->filename;
+ if (la)
+ ln = ls->ifile->filename;
+
+ i = strcmp (fn, ln);
+ if (i > 0)
+ continue;
+ else if (i < 0)
+ break;
+ }
}
/* Here either the files are not sorted by name, or we are
if (strcmp (section_name,
bfd_get_section_name (ls->ifile->the_bfd,
ls->section))
- > 0)
+ < 0)
break;
}
}
{
lang_statement_union_type *before;
+ /* If the wild pattern was marked KEEP, the member sections
+ should be as well. */
+ if (ptr->keep_sections)
+ s->flags |= SEC_KEEP;
+
before = wild_sort (ptr, file, s);
/* Here BEFORE points to the lang_input_section which
lang_list_init (&list);
wild_doit (&list, s, output, file);
- ASSERT (list.head != NULL && list.head->next == NULL);
- for (pp = &ptr->children.head;
- *pp != before;
- pp = &(*pp)->next)
- ASSERT (*pp != NULL);
+ /* If we are discarding the section, LIST.HEAD will
+ be NULL. */
+ if (list.head != NULL)
+ {
+ ASSERT (list.head->next == NULL);
- list.head->next = *pp;
- *pp = list.head;
+ for (pp = &ptr->children.head;
+ *pp != before;
+ pp = &(*pp)->next)
+ ASSERT (*pp != NULL);
+
+ list.head->next = *pp;
+ *pp = list.head;
+ }
}
}
}
}
else
{
- asection *ts;
+ bfd_vma val;
+ CONST char *send;
- /* Can't find the entry symbol. Use the first address in the
- text section. */
- ts = bfd_get_section_by_name (output_bfd, ".text");
- if (ts != (asection *) NULL)
+ /* We couldn't find the entry symbol. Try parsing it as a
+ number. */
+ val = bfd_scan_vma (entry_symbol, &send, 0);
+ if (*send == '\0')
{
- if (warn)
- einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
- entry_symbol, bfd_get_section_vma (output_bfd, ts));
- if (! bfd_set_start_address (output_bfd,
- bfd_get_section_vma (output_bfd, ts)))
+ if (! bfd_set_start_address (output_bfd, val))
einfo (_("%P%F: can't set start address\n"));
}
else
{
- if (warn)
- einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
- entry_symbol);
+ asection *ts;
+
+ /* Can't find the entry symbol, and it's not a number. Use
+ the first address in the text section. */
+ ts = bfd_get_section_by_name (output_bfd, ".text");
+ if (ts != (asection *) NULL)
+ {
+ if (warn)
+ einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
+ entry_symbol, bfd_get_section_vma (output_bfd, ts));
+ if (! bfd_set_start_address (output_bfd,
+ bfd_get_section_vma (output_bfd,
+ ts)))
+ einfo (_("%P%F: can't set start address\n"));
+ }
+ else
+ {
+ if (warn)
+ einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
+ entry_symbol);
+ }
}
}
}
}
}
+/* ??? At some point this traversal for GC should share code with the
+ traversal for manipulating the output file. */
+
+/* Expand a wild statement for a particular FILE, marking its sections KEEP
+ as needed. SECTION may be NULL, in which case it is a wild card. */
+
+static void
+lang_gc_wild_section (ptr, section, file)
+ lang_wild_statement_type *ptr;
+ const char *section;
+ lang_input_statement_type *file;
+{
+ if (file->just_syms_flag == false)
+ {
+ register asection *s;
+ boolean wildcard;
+
+ if (section == NULL)
+ wildcard = false;
+ else
+ wildcard = wildcardp (section);
+
+ for (s = file->the_bfd->sections; s != NULL; s = s->next)
+ {
+ boolean match;
+
+ if (section == NULL)
+ match = true;
+ else
+ {
+ const char *name;
+
+ name = bfd_get_section_name (file->the_bfd, s);
+ if (wildcard)
+ match = fnmatch (section, name, 0) == 0 ? true : false;
+ else
+ match = strcmp (section, name) == 0 ? true : false;
+ }
+
+ if (match)
+ {
+ /* If the wild pattern was marked KEEP, the member sections
+ should be as well. */
+ if (ptr->keep_sections)
+ s->flags |= SEC_KEEP;
+ }
+ }
+ }
+}
+
+/* Handle a wild statement for a single file F. */
+
+static void
+lang_gc_wild_file (s, section, f)
+ lang_wild_statement_type *s;
+ const char *section;
+ lang_input_statement_type *f;
+{
+ if (f->the_bfd == NULL
+ || ! bfd_check_format (f->the_bfd, bfd_archive))
+ lang_gc_wild_section (s, section, f);
+ else
+ {
+ bfd *member;
+
+ /* This is an archive file. We must map each member of the
+ archive separately. */
+ member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);
+ while (member != NULL)
+ {
+ /* When lookup_name is called, it will call the add_symbols
+ entry point for the archive. For each element of the
+ archive which is included, BFD will call ldlang_add_file,
+ which will set the usrdata field of the member to the
+ lang_input_statement. */
+ if (member->usrdata != NULL)
+ {
+ lang_gc_wild_section (s, section,
+ (lang_input_statement_type *) member->usrdata);
+ }
+
+ member = bfd_openr_next_archived_file (f->the_bfd, member);
+ }
+ }
+}
+
+/* Handle a wild statement, marking it against GC. SECTION or FILE or both
+ may be NULL, indicating that it is a wildcard. */
+
+static void
+lang_gc_wild (s, section, file)
+ lang_wild_statement_type *s;
+ const char *section;
+ const char *file;
+{
+ lang_input_statement_type *f;
+
+ if (file == (char *) NULL)
+ {
+ /* Perform the iteration over all files in the list */
+ for (f = (lang_input_statement_type *) file_chain.head;
+ f != (lang_input_statement_type *) NULL;
+ f = (lang_input_statement_type *) f->next)
+ {
+ lang_gc_wild_file (s, section, f);
+ }
+ }
+ else if (wildcardp (file))
+ {
+ for (f = (lang_input_statement_type *) file_chain.head;
+ f != (lang_input_statement_type *) NULL;
+ f = (lang_input_statement_type *) f->next)
+ {
+ if (fnmatch (file, f->filename, FNM_FILE_NAME) == 0)
+ lang_gc_wild_file (s, section, f);
+ }
+ }
+ else
+ {
+ /* Perform the iteration over a single file */
+ f = lookup_name (file);
+ lang_gc_wild_file (s, section, f);
+ }
+}
+
+/* Iterate over sections marking them against GC. */
+
+static void
+lang_gc_sections_1 (s)
+ lang_statement_union_type * s;
+{
+ for (; s != (lang_statement_union_type *) NULL; s = s->next)
+ {
+ switch (s->header.type)
+ {
+ case lang_wild_statement_enum:
+ lang_gc_wild (&s->wild_statement,
+ s->wild_statement.section_name,
+ s->wild_statement.filename);
+ break;
+ case lang_constructors_statement_enum:
+ lang_gc_sections_1 (constructor_list.head);
+ break;
+ case lang_output_section_statement_enum:
+ lang_gc_sections_1 (s->output_section_statement.children.head);
+ break;
+ case lang_group_statement_enum:
+ lang_gc_sections_1 (s->group_statement.children.head);
+ break;
+ }
+ }
+}
+
+static void
+lang_gc_sections ()
+{
+ struct bfd_link_hash_entry *h;
+ ldlang_undef_chain_list_type *ulist, fake_list_start;
+
+ /* Keep all sections so marked in the link script. */
+
+ lang_gc_sections_1 (statement_list.head);
+
+ /* Keep all sections containing symbols undefined on the command-line.
+ Handle the entry symbol at the same time. */
+
+ fake_list_start.next = ldlang_undef_chain_list_head;
+ fake_list_start.name = entry_symbol;
+
+ for (ulist = &fake_list_start; ulist; ulist = ulist->next)
+ {
+ h = bfd_link_hash_lookup (link_info.hash, ulist->name,
+ false, false, false);
+
+ if (h != (struct bfd_link_hash_entry *) NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ && ! bfd_is_abs_section (h->u.def.section))
+ {
+ h->u.def.section->flags |= SEC_KEEP;
+ }
+ }
+
+ bfd_gc_sections (output_bfd, &link_info);
+}
+
void
lang_process ()
{
files. */
ldctor_build_sets ();
+ /* Remove unreferenced sections if asked to. */
+ if (command_line.gc_sections)
+ lang_gc_sections ();
+
/* Size up the common data */
lang_common ();
/* EXPORTED TO YACC */
void
-lang_add_wild (section_name, sections_sorted, filename, filenames_sorted)
+lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
+ keep_sections)
const char *const section_name;
boolean sections_sorted;
const char *const filename;
boolean filenames_sorted;
+ boolean keep_sections;
{
lang_wild_statement_type *new = new_stat (lang_wild_statement,
stat_ptr);
new->sections_sorted = sections_sorted;
new->filename = filename;
new->filenames_sorted = filenames_sorted;
+ new->keep_sections = keep_sections;
lang_list_init (&new->children);
}
called by ENTRY in a linker script. Command line arguments take
precedence. */
-/* WINDOWS_NT. When an entry point has been specified, we will also force
- this symbol to be defined by calling ldlang_add_undef (equivalent to
- having switch -u entry_name on the command line). The reason we do
- this is so that the user doesn't have to because they would have to use
- the -u switch if they were specifying an entry point other than
- _mainCRTStartup. Specifically, if creating a windows application, entry
- point _WinMainCRTStartup must be specified.
- What I have found for non console applications (entry not _mainCRTStartup)
- is that the .obj that contains mainCRTStartup is brought in since it is
- the first encountered in libc.lib and it has other symbols in it which will
- be pulled in by the link process. To avoid this, adding -u with the entry
- point name specified forces the correct .obj to be used. We can avoid
- making the user do this by always adding the entry point name as an
- undefined symbol. */
-
void
lang_add_entry (name, cmdline)
CONST char *name;
entry_symbol = name;
entry_from_cmdline = cmdline;
}
-#if 0
- /* don't do this yet. It seems to work (the executables run), but the
- image created is very different from what I was getting before indicating
- that something else is being pulled in. When everything else is working,
- then try to put this back in to see if it will do the right thing for
- other more complicated applications */
- ldlang_add_undef (name);
-#endif
}
void
if (overlay_max == NULL)
overlay_max = size;
else
- overlay_max = exp_binop (MAX, overlay_max, size);
+ overlay_max = exp_binop (MAX_K, overlay_max, size);
}
/* Finish a section in an overlay. There isn't any special to do