aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-09-25 15:30:53 +0930
committerAlan Modra <amodra@gmail.com>2019-09-26 00:14:44 +0930
commit9a24a2763daa773328a788988048a7b3f344a548 (patch)
tree7986f994def57ac9cd6296cbef133128c71aed05 /ld
parent6ba2ed48c8cb591c1ccac172be7f895f59080cfa (diff)
downloadgdb-9a24a2763daa773328a788988048a7b3f344a548.zip
gdb-9a24a2763daa773328a788988048a7b3f344a548.tar.gz
gdb-9a24a2763daa773328a788988048a7b3f344a548.tar.bz2
SORT_BY_INIT_PRIORITY
I was looking at the implementation of this script keyword today and couldn't remember why we do what we do in get_init_priority, because the comments explain how the init_priority is encoded but don't say why it is necessary to extract the priority and sort on that. So after figuring out why (again), I wrote some more comments. Then I simplified get_init_priority a little, adding some sanity checking on the strtoul result. This actually makes get_init_priority support sorting by numerical suffix more generally, but I figure this feature would be better as a new keyword (without the .ctors/.dtors special case), so haven't documented the extension. * ld.texi (SORT_BY_ALIGNMENT): Reword slightly. (SORT_BY_INIT_PRIORITY): Elucidate. * ldlang.c: Include limits.h. (get_init_priority): Comment. Change param to a section, return an int. Sanity check priority digits. Support sorting more sections with trailing digits. Return -1 on error. (compare_section): Adjust.
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog10
-rw-r--r--ld/ld.texi21
-rw-r--r--ld/ldlang.c64
3 files changed, 60 insertions, 35 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index d38c861..c90a587 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,13 @@
+2019-09-25 Alan Modra <amodra@gmail.com>
+
+ * ld.texi (SORT_BY_ALIGNMENT): Reword slightly.
+ (SORT_BY_INIT_PRIORITY): Elucidate.
+ * ldlang.c: Include limits.h.
+ (get_init_priority): Comment. Change param to a section,
+ return an int. Sanity check priority digits. Support sorting
+ more sections with trailing digits. Return -1 on error.
+ (compare_section): Adjust.
+
2019-09-25 Nick Clifton <nickc@redhat.com>
* emultempl/avrelf.em (_before_allocation): Silence build warning
diff --git a/ld/ld.texi b/ld/ld.texi
index 8d5c7bc..95fa6a0 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -4630,17 +4630,20 @@ pattern in parentheses (e.g., @code{SORT_BY_NAME(.text*)}). When the
into ascending order by name before placing them in the output file.
@cindex SORT_BY_ALIGNMENT
-@code{SORT_BY_ALIGNMENT} is very similar to @code{SORT_BY_NAME}. The
-difference is @code{SORT_BY_ALIGNMENT} will sort sections into
-descending order by alignment before placing them in the output file.
-Larger alignments are placed before smaller alignments in order to
-reduce the amount of padding necessary.
+@code{SORT_BY_ALIGNMENT} is similar to @code{SORT_BY_NAME}.
+@code{SORT_BY_ALIGNMENT} will sort sections into descending order of
+alignment before placing them in the output file. Placing larger
+alignments before smaller alignments can reduce the amount of padding
+needed.
@cindex SORT_BY_INIT_PRIORITY
-@code{SORT_BY_INIT_PRIORITY} is very similar to @code{SORT_BY_NAME}. The
-difference is @code{SORT_BY_INIT_PRIORITY} will sort sections into
-ascending order by numerical value of the GCC init_priority attribute
-encoded in the section name before placing them in the output file.
+@code{SORT_BY_INIT_PRIORITY} is also similar to @code{SORT_BY_NAME}.
+@code{SORT_BY_INIT_PRIORITY} will sort sections into ascending
+numerical order of the GCC init_priority attribute encoded in the
+section name before placing them in the output file. In
+@code{.init_array.NNNNN} and @code{.fini_array.NNNNN}, @code{NNNNN} is
+the init_priority. In @code{.ctors.NNNNN} and @code{.dtors.NNNNN},
+@code{NNNNN} is 65535 minus the init_priority.
@cindex SORT
@code{SORT} is an alias for @code{SORT_BY_NAME}.
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 1a49f69..a28e9a0 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -19,6 +19,7 @@
MA 02110-1301, USA. */
#include "sysdep.h"
+#include <limits.h>
#include "bfd.h"
#include "libiberty.h"
#include "filenames.h"
@@ -403,39 +404,50 @@ match_simple_wild (const char *pattern, const char *name)
/* Return the numerical value of the init_priority attribute from
section name NAME. */
-static unsigned long
-get_init_priority (const char *name)
+static int
+get_init_priority (const asection *sec)
{
- char *end;
- unsigned long init_priority;
+ const char *name = bfd_section_name (sec);
+ const char *dot;
/* GCC uses the following section names for the init_priority
- attribute with numerical values 101 and 65535 inclusive. A
+ attribute with numerical values 101 to 65535 inclusive. A
lower value means a higher priority.
- 1: .init_array.NNNN/.fini_array.NNNN: Where NNNN is the
+ 1: .init_array.NNNNN/.fini_array.NNNNN: Where NNNNN is the
decimal numerical value of the init_priority attribute.
The order of execution in .init_array is forward and
.fini_array is backward.
- 2: .ctors.NNNN/.dtors.NNNN: Where NNNN is 65535 minus the
+ 2: .ctors.NNNNN/.dtors.NNNNN: Where NNNNN is 65535 minus the
decimal numerical value of the init_priority attribute.
The order of execution in .ctors is backward and .dtors
is forward.
- */
- if (strncmp (name, ".init_array.", 12) == 0
- || strncmp (name, ".fini_array.", 12) == 0)
- {
- init_priority = strtoul (name + 12, &end, 10);
- return *end ? 0 : init_priority;
- }
- else if (strncmp (name, ".ctors.", 7) == 0
- || strncmp (name, ".dtors.", 7) == 0)
- {
- init_priority = strtoul (name + 7, &end, 10);
- return *end ? 0 : 65535 - init_priority;
- }
- return 0;
+ .init_array.NNNNN sections would normally be placed in an output
+ .init_array section, .fini_array.NNNNN in .fini_array,
+ .ctors.NNNNN in .ctors, and .dtors.NNNNN in .dtors. This means
+ we should sort by increasing number (and could just use
+ SORT_BY_NAME in scripts). However if .ctors.NNNNN sections are
+ being placed in .init_array (which may also contain
+ .init_array.NNNNN sections) or .dtors.NNNNN sections are being
+ placed in .fini_array then we need to extract the init_priority
+ attribute and sort on that. */
+ dot = strrchr (name, '.');
+ if (dot != NULL && ISDIGIT (dot[1]))
+ {
+ char *end;
+ unsigned long init_priority = strtoul (dot + 1, &end, 10);
+ if (*end == 0)
+ {
+ if (dot == name + 6
+ && (strncmp (name, ".ctors", 6) == 0
+ || strncmp (name, ".dtors", 6) == 0))
+ init_priority = 65535 - init_priority;
+ if (init_priority <= INT_MAX)
+ return init_priority;
+ }
+ }
+ return -1;
}
/* Compare sections ASEC and BSEC according to SORT. */
@@ -444,7 +456,7 @@ static int
compare_section (sort_type sort, asection *asec, asection *bsec)
{
int ret;
- unsigned long ainit_priority, binit_priority;
+ int a_priority, b_priority;
switch (sort)
{
@@ -452,11 +464,11 @@ compare_section (sort_type sort, asection *asec, asection *bsec)
abort ();
case by_init_priority:
- ainit_priority = get_init_priority (bfd_section_name (asec));
- binit_priority = get_init_priority (bfd_section_name (bsec));
- if (ainit_priority == 0 || binit_priority == 0)
+ a_priority = get_init_priority (asec);
+ b_priority = get_init_priority (bsec);
+ if (a_priority < 0 || b_priority < 0)
goto sort_by_name;
- ret = ainit_priority - binit_priority;
+ ret = a_priority - b_priority;
if (ret)
break;
else