diff options
author | Alan Modra <amodra@gmail.com> | 2019-09-25 15:30:53 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2019-09-26 00:14:44 +0930 |
commit | 9a24a2763daa773328a788988048a7b3f344a548 (patch) | |
tree | 7986f994def57ac9cd6296cbef133128c71aed05 /ld/ldlang.c | |
parent | 6ba2ed48c8cb591c1ccac172be7f895f59080cfa (diff) | |
download | binutils-gdb-9a24a2763daa773328a788988048a7b3f344a548.tar.gz |
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/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 64 |
1 files changed, 38 insertions, 26 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index 1a49f69d908..a28e9a04535 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 |