summaryrefslogtreecommitdiff
path: root/patches/binutils/2.16.1a
diff options
context:
space:
mode:
Diffstat (limited to 'patches/binutils/2.16.1a')
-rw-r--r--patches/binutils/2.16.1a/100-bfd-hash-tweak.patch23
-rw-r--r--patches/binutils/2.16.1a/110-psignal.patch40
-rw-r--r--patches/binutils/2.16.1a/120-skip-comments.patch95
-rw-r--r--patches/binutils/2.16.1a/130-callahan.patch693
-rw-r--r--patches/binutils/2.16.1a/140-cross-gprof.patch22
-rw-r--r--patches/binutils/2.16.1a/150-stabs-tweak.patch28
-rw-r--r--patches/binutils/2.16.1a/160-i386-no-divide-comment.patch40
7 files changed, 941 insertions, 0 deletions
diff --git a/patches/binutils/2.16.1a/100-bfd-hash-tweak.patch b/patches/binutils/2.16.1a/100-bfd-hash-tweak.patch
new file mode 100644
index 0000000..c6de93a
--- /dev/null
+++ b/patches/binutils/2.16.1a/100-bfd-hash-tweak.patch
@@ -0,0 +1,23 @@
+Signed-off-by: dank@kegel.com
+
+Raising the size of the hash table is a noticable win when linking
+at least one large app.
+
+There was a patch,
+http://sources.redhat.com/ml/binutils/2004-06/msg00165.html
+to do this dynamically. No idea why that didn't make it in.
+So this tiny change to raise the default size is just
+a stopgap for now.
+
+
+--- binutils-2.16.1/bfd/hash.c.old 2006-03-02 23:01:39.000000000 -0800
++++ binutils-2.16.1/bfd/hash.c 2006-03-02 23:01:58.000000000 -0800
+@@ -300,7 +300,7 @@
+ */
+
+ /* The default number of entries to use when creating a hash table. */
+-#define DEFAULT_SIZE 4051
++#define DEFAULT_SIZE 32749
+ static size_t bfd_default_hash_table_size = DEFAULT_SIZE;
+
+ /* Create a new hash table, given a number of entries. */
diff --git a/patches/binutils/2.16.1a/110-psignal.patch b/patches/binutils/2.16.1a/110-psignal.patch
new file mode 100644
index 0000000..98fa600
--- /dev/null
+++ b/patches/binutils/2.16.1a/110-psignal.patch
@@ -0,0 +1,40 @@
+Make psignal prototype in libiberty match that in glibc.
+
+Fixes:
+
+gcc-2.95.3-glibc-2.1.3/binutils-2.15/libiberty/strsignal.c: In function `psignal':
+gcc-2.95.3-glibc-2.1.3/binutils-2.15/libiberty/strsignal.c:563: argument `signo' doesn't match prototype
+/usr/include/signal.h:131: prototype declaration
+gcc-2.95.3-glibc-2.1.3/binutils-2.15/libiberty/strsignal.c:563: argument `message' doesn't match prototype
+/usr/include/signal.h:131: prototype declaration
+gcc-2.95.3-glibc-2.1.3/binutils-2.15/libiberty/strsignal.c:568: warning: comparison between signed and unsigned
+mprotect... make[1]: *** [strsignal.o] Error 1
+make[1]: Leaving directory `/export/hda3/dkegel/queue/jobdir.produser_cpsm17/crosstool-0.32/build/i686-unknown-linux-gnu/gcc-2.95.3-glibc-2.1.3/build-binutils/libiberty'
+make: *** [all-libiberty] Error 2
+
+when building on red hat 7.1
+though it's a bit of a mystery why libiberty's psignal is being compiled at
+all, since red hat 7.1's glibc supports psignal (hence the error message)
+
+--- binutils-2.15/libiberty/strsignal.c.old 2005-04-18 13:57:40.000000000 -0700
++++ binutils-2.15/libiberty/strsignal.c 2005-04-18 13:59:09.000000000 -0700
+@@ -544,7 +544,7 @@
+
+ /*
+
+-@deftypefn Supplemental void psignal (unsigned @var{signo}, char *@var{message})
++@deftypefn Supplemental void psignal (int @var{signo}, const char *@var{message})
+
+ Print @var{message} to the standard error, followed by a colon,
+ followed by the description of the signal specified by @var{signo},
+@@ -557,9 +557,7 @@
+ #ifndef HAVE_PSIGNAL
+
+ void
+-psignal (signo, message)
+- unsigned signo;
+- char *message;
++psignal (int signo, const char *message)
+ {
+ if (signal_names == NULL)
+ {
diff --git a/patches/binutils/2.16.1a/120-skip-comments.patch b/patches/binutils/2.16.1a/120-skip-comments.patch
new file mode 100644
index 0000000..0ca9a47
--- /dev/null
+++ b/patches/binutils/2.16.1a/120-skip-comments.patch
@@ -0,0 +1,95 @@
+[removed first hunk so it would apply to 2.16.1 - copyright date already updated - dank]
+
+Retrieved from http://sources.redhat.com/ml/binutils/2004-04/msg00646.html
+Fixes
+localealias.s:544: Error: junk at end of line, first unrecognized character is `,'
+when building glibc-2.3.2 with gcc-3.4.0 and binutils-2.15.90.0.3
+
+Paths adjusted to match crosstool's patcher.
+
+Message-Id: m3n052qw2g.fsf@whitebox.m5r.de
+From: Andreas Schwab <schwab at suse dot de>
+To: Nathan Sidwell <nathan at codesourcery dot com>
+Cc: Ian Lance Taylor <ian at wasabisystems dot com>, binutils at sources dot redhat dot com
+Date: Fri, 23 Apr 2004 22:27:19 +0200
+Subject: Re: demand_empty_rest_of_line and ignore_rest_of_line
+
+Nathan Sidwell <nathan@codesourcery.com> writes:
+
+> Index: read.c
+> ===================================================================
+> RCS file: /cvs/src/src/gas/read.c,v
+> retrieving revision 1.76
+> diff -c -3 -p -r1.76 read.c
+> *** read.c 12 Mar 2004 17:48:12 -0000 1.76
+> --- read.c 18 Mar 2004 09:56:05 -0000
+> *************** read_a_source_file (char *name)
+> *** 1053,1059 ****
+> #endif
+> input_line_pointer--;
+> /* Report unknown char as ignored. */
+> ! ignore_rest_of_line ();
+> }
+>
+> #ifdef md_after_pass_hook
+> --- 1053,1059 ----
+> #endif
+> input_line_pointer--;
+> /* Report unknown char as ignored. */
+> ! demand_empty_rest_of_line ();
+> }
+>
+> #ifdef md_after_pass_hook
+
+This means that the unknown character is no longer ignored, despite the
+comment. As a side effect a line starting with a line comment character
+not followed by APP in NO_APP mode now triggers an error instead of just a
+warning, breaking builds of glibc on m68k-linux. Earlier in
+read_a_source_file where #APP is handled there is another comment that
+claims that unknown comments are ignored, when in fact they aren't (only
+the initial line comment character is skipped).
+
+Note that the presence of #APP will mess up the line counters, but
+that appears to be difficult to fix.
+
+Andreas.
+
+2004-04-23 Andreas Schwab <schwab@suse.de>
+
+ * read.c (read_a_source_file): Ignore unknown text after line
+ comment character. Fix misleading comment.
+
+--- binutils/gas/read.c.~1.78.~ 2004-04-23 08:58:23.000000000 +0200
++++ binutils/gas/read.c 2004-04-23 21:49:01.000000000 +0200
+@@ -950,10 +950,14 @@ read_a_source_file (char *name)
+ unsigned int new_length;
+ char *tmp_buf = 0;
+
+- bump_line_counters ();
+ s = input_line_pointer;
+ if (strncmp (s, "APP\n", 4))
+- continue; /* We ignore it */
++ {
++ /* We ignore it */
++ ignore_rest_of_line ();
++ continue;
++ }
++ bump_line_counters ();
+ s += 4;
+
+ sb_new (&sbuf);
+@@ -1052,7 +1056,7 @@ read_a_source_file (char *name)
+ continue;
+ #endif
+ input_line_pointer--;
+- /* Report unknown char as ignored. */
++ /* Report unknown char as error. */
+ demand_empty_rest_of_line ();
+ }
+
+
+--
+Andreas Schwab, SuSE Labs, schwab@suse.de
+SuSE Linux AG, Maxfeldstra&#xC3;e 5, 90409 N&#xC3;rnberg, Germany
+Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
+"And now for something completely different."
diff --git a/patches/binutils/2.16.1a/130-callahan.patch b/patches/binutils/2.16.1a/130-callahan.patch
new file mode 100644
index 0000000..a39050f
--- /dev/null
+++ b/patches/binutils/2.16.1a/130-callahan.patch
@@ -0,0 +1,693 @@
+Signed-off-by: dank@kegel.com
+Fixes ld speed issue.
+See http://weblogs.mozillazine.org/roc/archives/2005/02/optimizing_gnu.html
+See thread "Re: optimizations for 3x speedup in ld",
+http://sources.redhat.com/ml/binutils/2005-03/msg00847.html
+
+Wildcard section matching enhancement, backported from the binutils CVS tree.
+Here's the CVS log comment from the original change to ldlang.c:
+
+revision 1.177
+date: 2005/04/06 15:33:02; author: jakub; state: Exp; lines: +438 -51
+2005-04-06 Jakub Jelinek <jakub@redhat.com>
+
+ * ldlang.c: Formatting.
+ (walk_wild_consider_section): Remember return value from wildcardp.
+ (is_simple_wild): Use strcspn instead of 2 strpbrk calls and strlen.
+ (wild_spec_can_overlap): Use strcspn instead of strpbrk and strlen.
+
+2005-04-06 Robert O'Callahan <rocallahan@novell.com>
+
+ * ld.h (lean_section_userdata_type): Remove.
+ (fat_section_userdata_type): Remove file field.
+ (SECTION_USERDATA_SIZE): Remove.
+ * ldlang.c (init_os): Eliminate initialization of unused
+ lean_section_userdata_type.
+
+ * ldlang.h (callback_t, walk_wild_section_handler_t): New
+ typedefs.
+ (struct lang_wild_statement_struct): Add walk_wild_section_handler
+ and handler_data fields.
+ * ldlang.c (callback_t): Removed.
+ (walk_wild_consider_section, walk_wild_section_general,
+ section_iterator_callback, find_section, is_simple_wild,
+ match_simple_wild, walk_wild_section_specs1_wild0,
+ walk_wild_section_specs1_wild1, walk_wild_section_specs2_wild1,
+ walk_wild_section_specs3_wild2, walk_wild_section_specs4_wild2,
+ wild_spec_can_overlap, analyze_walk_wild_section_handler): New
+ functions.
+ (lang_add_wild): Call analyze_walk_wild_section_handler.
+ (walk_wild_section): Renamed to walk_wild_section_general and
+ created a wrapper function.
+ (section_iterator_callback_data): New typedef.
+
+
+Index: src/ld/ld.h
+===================================================================
+RCS file: /cvs/src/src/ld/ld.h,v
+retrieving revision 1.26
+retrieving revision 1.27
+diff -u -r1.26 -r1.27
+--- binutils/ld/ld.h.old 16 Mar 2005 21:52:42 -0000 1.26
++++ binutils/ld/ld.h 6 Apr 2005 15:33:02 -0000 1.27
+@@ -1,6 +1,6 @@
+ /* ld.h -- general linker header file
+ Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+- 2001, 2002, 2003, 2004
++ 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+@@ -89,28 +89,15 @@
+ struct map_symbol_def *next;
+ };
+
+-/* Extra information we hold on sections */
+-typedef struct lean_user_section_struct {
+- /* For output sections: pointer to the section where this data will go. */
+- struct lang_input_statement_struct *file;
+-} lean_section_userdata_type;
+-
+ /* The initial part of fat_user_section_struct has to be idential with
+ lean_user_section_struct. */
+ typedef struct fat_user_section_struct {
+- /* For output sections: pointer to the section where this data will go. */
+- struct lang_input_statement_struct *file;
+ /* For input sections, when writing a map file: head / tail of a linked
+ list of hash table entries for symbols defined in this section. */
+ struct map_symbol_def *map_symbol_def_head;
+ struct map_symbol_def **map_symbol_def_tail;
+ } fat_section_userdata_type;
+
+-#define SECTION_USERDATA_SIZE \
+- (command_line.reduce_memory_overheads \
+- ? sizeof (lean_section_userdata_type) \
+- : sizeof (fat_section_userdata_type))
+-
+ #define get_userdata(x) ((x)->userdata)
+
+ #define BYTE_SIZE (1)
+Index: src/ld/ldlang.c
+===================================================================
+RCS file: /cvs/src/src/ld/ldlang.c,v
+retrieving revision 1.176
+retrieving revision 1.177
+diff -u -r1.176 -r1.177
+--- binutils/ld/ldlang.c.old 18 Mar 2005 13:56:26 -0000 1.176
++++ binutils/ld/ldlang.c 6 Apr 2005 15:33:02 -0000 1.177
+@@ -84,9 +84,6 @@
+ static void lang_record_phdrs (void);
+ static void lang_do_version_exports_section (void);
+
+-typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
+- asection *, lang_input_statement_type *, void *);
+-
+ /* Exported variables. */
+ lang_output_section_statement_type *abs_output_section;
+ lang_statement_list_type lang_output_section_statement;
+@@ -155,21 +152,71 @@
+
+ /* Generic traversal routines for finding matching sections. */
+
++/* Try processing a section against a wildcard. This just calls
++ the callback unless the filename exclusion list is present
++ and excludes the file. It's hardly ever present so this
++ function is very fast. */
++
++static void
++walk_wild_consider_section (lang_wild_statement_type *ptr,
++ lang_input_statement_type *file,
++ asection *s,
++ struct wildcard_list *sec,
++ callback_t callback,
++ void *data)
++{
++ bfd_boolean skip = FALSE;
++ struct name_list *list_tmp;
++
++ /* Don't process sections from files which were
++ excluded. */
++ for (list_tmp = sec->spec.exclude_name_list;
++ list_tmp;
++ list_tmp = list_tmp->next)
++ {
++ bfd_boolean is_wildcard = wildcardp (list_tmp->name);
++ if (is_wildcard)
++ skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
++ else
++ skip = strcmp (list_tmp->name, file->filename) == 0;
++
++ /* If this file is part of an archive, and the archive is
++ excluded, exclude this file. */
++ if (! skip && file->the_bfd != NULL
++ && file->the_bfd->my_archive != NULL
++ && file->the_bfd->my_archive->filename != NULL)
++ {
++ if (is_wildcard)
++ skip = fnmatch (list_tmp->name,
++ file->the_bfd->my_archive->filename,
++ 0) == 0;
++ else
++ skip = strcmp (list_tmp->name,
++ file->the_bfd->my_archive->filename) == 0;
++ }
++
++ if (skip)
++ break;
++ }
++
++ if (!skip)
++ (*callback) (ptr, sec, s, file, data);
++}
++
++/* Lowest common denominator routine that can handle everything correctly,
++ but slowly. */
++
+ static void
+-walk_wild_section (lang_wild_statement_type *ptr,
+- lang_input_statement_type *file,
+- callback_t callback,
+- void *data)
++walk_wild_section_general (lang_wild_statement_type *ptr,
++ lang_input_statement_type *file,
++ callback_t callback,
++ void *data)
+ {
+ asection *s;
+-
+- if (file->just_syms_flag)
+- return;
++ struct wildcard_list *sec;
+
+ for (s = file->the_bfd->sections; s != NULL; s = s->next)
+ {
+- struct wildcard_list *sec;
+-
+ sec = ptr->section_list;
+ if (sec == NULL)
+ (*callback) (ptr, sec, s, file, data);
+@@ -177,39 +224,8 @@
+ while (sec != NULL)
+ {
+ bfd_boolean skip = FALSE;
+- struct name_list *list_tmp;
+
+- /* Don't process sections from files which were
+- excluded. */
+- for (list_tmp = sec->spec.exclude_name_list;
+- list_tmp;
+- list_tmp = list_tmp->next)
+- {
+- if (wildcardp (list_tmp->name))
+- skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
+- else
+- skip = strcmp (list_tmp->name, file->filename) == 0;
+-
+- /* If this file is part of an archive, and the archive is
+- excluded, exclude this file. */
+- if (! skip && file->the_bfd != NULL
+- && file->the_bfd->my_archive != NULL
+- && file->the_bfd->my_archive->filename != NULL)
+- {
+- if (wildcardp (list_tmp->name))
+- skip = fnmatch (list_tmp->name,
+- file->the_bfd->my_archive->filename,
+- 0) == 0;
+- else
+- skip = strcmp (list_tmp->name,
+- file->the_bfd->my_archive->filename) == 0;
+- }
+-
+- if (skip)
+- break;
+- }
+-
+- if (!skip && sec->spec.name != NULL)
++ if (sec->spec.name != NULL)
+ {
+ const char *sname = bfd_get_section_name (file->the_bfd, s);
+
+@@ -220,13 +236,381 @@
+ }
+
+ if (!skip)
+- (*callback) (ptr, sec, s, file, data);
++ walk_wild_consider_section (ptr, file, s, sec, callback, data);
+
+ sec = sec->next;
+ }
+ }
+ }
+
++/* Routines to find a single section given its name. If there's more
++ than one section with that name, we report that. */
++
++typedef struct
++{
++ asection *found_section;
++ bfd_boolean multiple_sections_found;
++} section_iterator_callback_data;
++
++static bfd_boolean
++section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data)
++{
++ section_iterator_callback_data *d = data;
++
++ if (d->found_section != NULL)
++ {
++ d->multiple_sections_found = TRUE;
++ return TRUE;
++ }
++
++ d->found_section = s;
++ return FALSE;
++}
++
++static asection *
++find_section (lang_input_statement_type *file,
++ struct wildcard_list *sec,
++ bfd_boolean *multiple_sections_found)
++{
++ section_iterator_callback_data cb_data = { NULL, FALSE };
++
++ bfd_get_section_by_name_if (file->the_bfd, sec->spec.name,
++ section_iterator_callback, &cb_data);
++ *multiple_sections_found = cb_data.multiple_sections_found;
++ return cb_data.found_section;
++}
++
++/* Code for handling simple wildcards without going through fnmatch,
++ which can be expensive because of charset translations etc. */
++
++/* A simple wild is a literal string followed by a single '*',
++ where the literal part is at least 4 characters long. */
++
++static bfd_boolean
++is_simple_wild (const char *name)
++{
++ size_t len = strcspn (name, "*?[");
++ return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
++}
++
++static bfd_boolean
++match_simple_wild (const char *pattern, const char *name)
++{
++ /* The first four characters of the pattern are guaranteed valid
++ non-wildcard characters. So we can go faster. */
++ if (pattern[0] != name[0] || pattern[1] != name[1]
++ || pattern[2] != name[2] || pattern[3] != name[3])
++ return FALSE;
++
++ pattern += 4;
++ name += 4;
++ while (*pattern != '*')
++ if (*name++ != *pattern++)
++ return FALSE;
++
++ return TRUE;
++}
++
++/* Specialized, optimized routines for handling different kinds of
++ wildcards */
++
++static void
++walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
++ lang_input_statement_type *file,
++ callback_t callback,
++ void *data)
++{
++ /* We can just do a hash lookup for the section with the right name.
++ But if that lookup discovers more than one section with the name
++ (should be rare), we fall back to the general algorithm because
++ we would otherwise have to sort the sections to make sure they
++ get processed in the bfd's order. */
++ bfd_boolean multiple_sections_found;
++ struct wildcard_list *sec0 = ptr->handler_data[0];
++ asection *s0 = find_section (file, sec0, &multiple_sections_found);
++
++ if (multiple_sections_found)
++ walk_wild_section_general (ptr, file, callback, data);
++ else if (s0)
++ walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
++}
++
++static void
++walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
++ lang_input_statement_type *file,
++ callback_t callback,
++ void *data)
++{
++ asection *s;
++ struct wildcard_list *wildsec0 = ptr->handler_data[0];
++
++ for (s = file->the_bfd->sections; s != NULL; s = s->next)
++ {
++ const char *sname = bfd_get_section_name (file->the_bfd, s);
++ bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname);
++
++ if (!skip)
++ walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
++ }
++}
++
++static void
++walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
++ lang_input_statement_type *file,
++ callback_t callback,
++ void *data)
++{
++ asection *s;
++ struct wildcard_list *sec0 = ptr->handler_data[0];
++ struct wildcard_list *wildsec1 = ptr->handler_data[1];
++ bfd_boolean multiple_sections_found;
++ asection *s0 = find_section (file, sec0, &multiple_sections_found);
++
++ if (multiple_sections_found)
++ {
++ walk_wild_section_general (ptr, file, callback, data);
++ return;
++ }
++
++ /* Note that if the section was not found, s0 is NULL and
++ we'll simply never succeed the s == s0 test below. */
++ for (s = file->the_bfd->sections; s != NULL; s = s->next)
++ {
++ /* Recall that in this code path, a section cannot satisfy more
++ than one spec, so if s == s0 then it cannot match
++ wildspec1. */
++ if (s == s0)
++ walk_wild_consider_section (ptr, file, s, sec0, callback, data);
++ else
++ {
++ const char *sname = bfd_get_section_name (file->the_bfd, s);
++ bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
++
++ if (!skip)
++ walk_wild_consider_section (ptr, file, s, wildsec1, callback,
++ data);
++ }
++ }
++}
++
++static void
++walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
++ lang_input_statement_type *file,
++ callback_t callback,
++ void *data)
++{
++ asection *s;
++ struct wildcard_list *sec0 = ptr->handler_data[0];
++ struct wildcard_list *wildsec1 = ptr->handler_data[1];
++ struct wildcard_list *wildsec2 = ptr->handler_data[2];
++ bfd_boolean multiple_sections_found;
++ asection *s0 = find_section (file, sec0, &multiple_sections_found);
++
++ if (multiple_sections_found)
++ {
++ walk_wild_section_general (ptr, file, callback, data);
++ return;
++ }
++
++ for (s = file->the_bfd->sections; s != NULL; s = s->next)
++ {
++ if (s == s0)
++ walk_wild_consider_section (ptr, file, s, sec0, callback, data);
++ else
++ {
++ const char *sname = bfd_get_section_name (file->the_bfd, s);
++ bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
++
++ if (!skip)
++ walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
++ else
++ {
++ skip = !match_simple_wild (wildsec2->spec.name, sname);
++ if (!skip)
++ walk_wild_consider_section (ptr, file, s, wildsec2, callback,
++ data);
++ }
++ }
++ }
++}
++
++static void
++walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
++ lang_input_statement_type *file,
++ callback_t callback,
++ void *data)
++{
++ asection *s;
++ struct wildcard_list *sec0 = ptr->handler_data[0];
++ struct wildcard_list *sec1 = ptr->handler_data[1];
++ struct wildcard_list *wildsec2 = ptr->handler_data[2];
++ struct wildcard_list *wildsec3 = ptr->handler_data[3];
++ bfd_boolean multiple_sections_found;
++ asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
++
++ if (multiple_sections_found)
++ {
++ walk_wild_section_general (ptr, file, callback, data);
++ return;
++ }
++
++ s1 = find_section (file, sec1, &multiple_sections_found);
++ if (multiple_sections_found)
++ {
++ walk_wild_section_general (ptr, file, callback, data);
++ return;
++ }
++
++ for (s = file->the_bfd->sections; s != NULL; s = s->next)
++ {
++ if (s == s0)
++ walk_wild_consider_section (ptr, file, s, sec0, callback, data);
++ else
++ if (s == s1)
++ walk_wild_consider_section (ptr, file, s, sec1, callback, data);
++ else
++ {
++ const char *sname = bfd_get_section_name (file->the_bfd, s);
++ bfd_boolean skip = !match_simple_wild (wildsec2->spec.name,
++ sname);
++
++ if (!skip)
++ walk_wild_consider_section (ptr, file, s, wildsec2, callback,
++ data);
++ else
++ {
++ skip = !match_simple_wild (wildsec3->spec.name, sname);
++ if (!skip)
++ walk_wild_consider_section (ptr, file, s, wildsec3,
++ callback, data);
++ }
++ }
++ }
++}
++
++static void
++walk_wild_section (lang_wild_statement_type *ptr,
++ lang_input_statement_type *file,
++ callback_t callback,
++ void *data)
++{
++ if (file->just_syms_flag)
++ return;
++
++ (*ptr->walk_wild_section_handler) (ptr, file, callback, data);
++}
++
++/* Returns TRUE when name1 is a wildcard spec that might match
++ something name2 can match. We're conservative: we return FALSE
++ only if the prefixes of name1 and name2 are different up to the
++ first wildcard character. */
++
++static bfd_boolean
++wild_spec_can_overlap (const char *name1, const char *name2)
++{
++ size_t prefix1_len = strcspn (name1, "?*[");
++ size_t prefix2_len = strcspn (name2, "?*[");
++ size_t min_prefix_len;
++
++ /* Note that if there is no wildcard character, then we treat the
++ terminating 0 as part of the prefix. Thus ".text" won't match
++ ".text." or ".text.*", for example. */
++ if (name1[prefix1_len] == '\0')
++ prefix1_len++;
++ if (name2[prefix2_len] == '\0')
++ prefix2_len++;
++
++ min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
++
++ return memcmp (name1, name2, min_prefix_len) == 0;
++}
++
++/* Select specialized code to handle various kinds of wildcard
++ statements. */
++
++static void
++analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
++{
++ int sec_count = 0;
++ int wild_name_count = 0;
++ struct wildcard_list *sec;
++ int signature;
++ int data_counter;
++
++ ptr->walk_wild_section_handler = walk_wild_section_general;
++
++ /* Count how many wildcard_specs there are, and how many of those
++ actually use wildcards in the name. Also, bail out if any of the
++ wildcard names are NULL. (Can this actually happen?
++ walk_wild_section used to test for it.) And bail out if any
++ of the wildcards are more complex than a simple string
++ ending in a single '*'. */
++ for (sec = ptr->section_list; sec != NULL; sec = sec->next)
++ {
++ ++sec_count;
++ if (sec->spec.name == NULL)
++ return;
++ if (wildcardp (sec->spec.name))
++ {
++ ++wild_name_count;
++ if (!is_simple_wild (sec->spec.name))
++ return;
++ }
++ }
++
++ /* The zero-spec case would be easy to optimize but it doesn't
++ happen in practice. Likewise, more than 4 specs doesn't
++ happen in practice. */
++ if (sec_count == 0 || sec_count > 4)
++ return;
++
++ /* Check that no two specs can match the same section. */
++ for (sec = ptr->section_list; sec != NULL; sec = sec->next)
++ {
++ struct wildcard_list *sec2;
++ for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
++ {
++ if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
++ return;
++ }
++ }
++
++ signature = (sec_count << 8) + wild_name_count;
++ switch (signature)
++ {
++ case 0x0100:
++ ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
++ break;
++ case 0x0101:
++ ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
++ break;
++ case 0x0201:
++ ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
++ break;
++ case 0x0302:
++ ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
++ break;
++ case 0x0402:
++ ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
++ break;
++ default:
++ return;
++ }
++
++ /* Now fill the data array with pointers to the specs, first the
++ specs with non-wildcard names, then the specs with wildcard
++ names. It's OK to process the specs in different order from the
++ given order, because we've already determined that no section
++ will match more than one spec. */
++ data_counter = 0;
++ for (sec = ptr->section_list; sec != NULL; sec = sec->next)
++ if (!wildcardp (sec->spec.name))
++ ptr->handler_data[data_counter++] = sec;
++ for (sec = ptr->section_list; sec != NULL; sec = sec->next)
++ if (wildcardp (sec->spec.name))
++ ptr->handler_data[data_counter++] = sec;
++}
++
+ /* Handle a wild statement for a single file F. */
+
+ static void
+@@ -1175,17 +1559,12 @@
+ static void
+ init_os (lang_output_section_statement_type *s)
+ {
+- lean_section_userdata_type *new;
+-
+ if (s->bfd_section != NULL)
+ return;
+
+ if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
+ einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
+
+- new = stat_alloc (SECTION_USERDATA_SIZE);
+- memset (new, 0, SECTION_USERDATA_SIZE);
+-
+ s->bfd_section = bfd_get_section_by_name (output_bfd, s->name);
+ if (s->bfd_section == NULL)
+ s->bfd_section = bfd_make_section (output_bfd, s->name);
+@@ -1199,7 +1578,14 @@
+ /* We initialize an output sections output offset to minus its own
+ vma to allow us to output a section through itself. */
+ s->bfd_section->output_offset = 0;
+- get_userdata (s->bfd_section) = new;
++ if (!command_line.reduce_memory_overheads)
++ {
++ fat_section_userdata_type *new
++ = stat_alloc (sizeof (fat_section_userdata_type));
++ memset (new, 0, sizeof (fat_section_userdata_type));
++ get_userdata (s->bfd_section) = new;
++ }
++
+
+ /* If there is a base address, make sure that any sections it might
+ mention are initialized. */
+@@ -4939,6 +5325,7 @@
+ new->section_list = section_list;
+ new->keep_sections = keep_sections;
+ lang_list_init (&new->children);
++ analyze_walk_wild_section_handler (new);
+ }
+
+ void
+Index: src/ld/ldlang.h
+===================================================================
+RCS file: /cvs/src/src/ld/ldlang.h,v
+retrieving revision 1.44
+retrieving revision 1.45
+diff -u -r1.44 -r1.45
+--- binutils/ld/ldlang.h.old 3 Mar 2005 11:51:58 -0000 1.44
++++ binutils/ld/ldlang.h 6 Apr 2005 15:33:03 -0000 1.45
+@@ -298,7 +298,17 @@
+ union lang_statement_union *file;
+ } lang_afile_asection_pair_statement_type;
+
+-typedef struct lang_wild_statement_struct
++typedef struct lang_wild_statement_struct lang_wild_statement_type;
++
++typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
++ asection *, lang_input_statement_type *, void *);
++
++typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *,
++ lang_input_statement_type *,
++ callback_t callback,
++ void *data);
++
++struct lang_wild_statement_struct
+ {
+ lang_statement_header_type header;
+ const char *filename;
+@@ -306,7 +316,10 @@
+ struct wildcard_list *section_list;
+ bfd_boolean keep_sections;
+ lang_statement_list_type children;
+-} lang_wild_statement_type;
++
++ walk_wild_section_handler_t walk_wild_section_handler;
++ struct wildcard_list *handler_data[4];
++};
+
+ typedef struct lang_address_statement_struct
+ {
diff --git a/patches/binutils/2.16.1a/140-cross-gprof.patch b/patches/binutils/2.16.1a/140-cross-gprof.patch
new file mode 100644
index 0000000..ea6c18f
--- /dev/null
+++ b/patches/binutils/2.16.1a/140-cross-gprof.patch
@@ -0,0 +1,22 @@
+--- binutils-2.15/configure.old 2004-07-21 21:36:47.000000000 -0700
++++ binutils-2.15/configure 2004-07-21 21:37:08.000000000 -0700
+@@ -999,7 +999,7 @@
+
+ # Some tools are only suitable for building in a "native" situation.
+ # Remove these if host!=target.
+-native_only="autoconf automake libtool fileutils find gawk gettext gzip hello indent m4 rcs recode sed shellutils tar textutils uudecode wdiff gprof target-groff guile perl time ash bash bzip2 prms gnuserv target-gperf"
++native_only="autoconf automake libtool fileutils find gawk gettext gzip hello indent m4 rcs recode sed shellutils tar textutils uudecode wdiff target-groff guile perl time ash bash bzip2 prms gnuserv target-gperf"
+
+ # Similarly, some are only suitable for cross toolchains.
+ # Remove these if host=target.
+--- binutils-2.15/configure.in.old 2004-07-21 21:37:19.000000000 -0700
++++ binutils-2.15/configure.in 2004-07-21 21:37:34.000000000 -0700
+@@ -236,7 +236,7 @@
+
+ # Some tools are only suitable for building in a "native" situation.
+ # Remove these if host!=target.
+-native_only="autoconf automake libtool fileutils find gawk gettext gzip hello indent m4 rcs recode sed shellutils tar textutils uudecode wdiff gprof target-groff guile perl time ash bash bzip2 prms gnuserv target-gperf"
++native_only="autoconf automake libtool fileutils find gawk gettext gzip hello indent m4 rcs recode sed shellutils tar textutils uudecode wdiff target-groff guile perl time ash bash bzip2 prms gnuserv target-gperf"
+
+ # Similarly, some are only suitable for cross toolchains.
+ # Remove these if host=target.
diff --git a/patches/binutils/2.16.1a/150-stabs-tweak.patch b/patches/binutils/2.16.1a/150-stabs-tweak.patch
new file mode 100644
index 0000000..86e3611
--- /dev/null
+++ b/patches/binutils/2.16.1a/150-stabs-tweak.patch
@@ -0,0 +1,28 @@
+Signed-off-by: dank@kegel.com
+
+See http://sourceware.org/ml/binutils/2005-12/msg00270.html
+http://sourceware.org/ml/binutils-cvs/2005-12/msg00139.html
+
+STABS hash table size change, backported from the binutils CVS tree. Here's
+the CVS log comment for the original change:
+
+revision 1.25
+date: 2005/12/29 10:29:23; author: nickc; state: Exp; lines: +2 -3
+(_bfd_link_section_stabs): Use bfd_hash_table_init rather than
+bfd_hash_table_init_n(...,251) so that the size of the hash table can be
+controlled by the user.
+
+--- binutils/bfd/stabs.c.old 4 May 2005 15:53:39 -0000 1.24
++++ binutils/bfd/stabs.c 29 Dec 2005 10:29:23 -0000 1.25
+@@ -194,9 +194,8 @@
+ goto error_return;
+ /* Make sure the first byte is zero. */
+ (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
+- if (! bfd_hash_table_init_n (&sinfo->includes,
+- stab_link_includes_newfunc,
+- 251))
++ if (! bfd_hash_table_init (&sinfo->includes,
++ stab_link_includes_newfunc))
+ goto error_return;
+ sinfo->stabstr = bfd_make_section_anyway (abfd, ".stabstr");
+ if (sinfo->stabstr == NULL)
diff --git a/patches/binutils/2.16.1a/160-i386-no-divide-comment.patch b/patches/binutils/2.16.1a/160-i386-no-divide-comment.patch
new file mode 100644
index 0000000..046a55f
--- /dev/null
+++ b/patches/binutils/2.16.1a/160-i386-no-divide-comment.patch
@@ -0,0 +1,40 @@
+diff -durN binutils-2.16.1.orig/gas/config/tc-i386.c binutils-2.16.1/gas/config/tc-i386.c
+--- binutils-2.16.1.orig/gas/config/tc-i386.c 2005-04-13 19:58:42.000000000 +0200
++++ binutils-2.16.1/gas/config/tc-i386.c 2008-09-22 09:00:09.000000000 +0200
+@@ -192,16 +192,10 @@
+ #endif
+ ;
+
+-#if (defined (TE_I386AIX) \
+- || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) \
+- && !defined (TE_LINUX) \
+- && !defined (TE_NETWARE) \
+- && !defined (TE_FreeBSD) \
+- && !defined (TE_NetBSD)))
+ /* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful. */
+-const char comment_chars[] = "#/";
+-#define PREFIX_SEPARATOR '\\'
++const char comment_chars[] = "#";
++#define PREFIX_SEPARATOR '/'
+
+ /* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+@@ -211,16 +205,7 @@
+ #NO_APP at the beginning of its output.
+ Also note that comments started like this one will always work if
+ '/' isn't otherwise defined. */
+-const char line_comment_chars[] = "#";
+-
+-#else
+-/* Putting '/' here makes it impossible to use the divide operator.
+- However, we need it for compatibility with SVR4 systems. */
+-const char comment_chars[] = "#";
+-#define PREFIX_SEPARATOR '/'
+-
+-const char line_comment_chars[] = "/#";
+-#endif
++const char line_comment_chars[] = "#/";
+
+ const char line_separator_chars[] = ";";
+