aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain/binutils/patches/2.28/002-PR-ld-21334-Always-call-_bfd_elf_link_renumber_dynsy.patch
blob: 7cfbaa6153a41d9e8a49548da4520078073c1f86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
From 51ffcfc2c67b4c4aa1620fb4c9834c38d150e1c5 Mon Sep 17 00:00:00 2001
From: "Maciej W. Rozycki" <macro@imgtec.com>
Date: Wed, 26 Apr 2017 22:23:44 +0100
Subject: PR ld/21334: Always call `_bfd_elf_link_renumber_dynsyms' if required

Complement commit e17b0c351f0b ("MIPS/BFD: Respect the ELF gABI dynamic
symbol table sort requirement") and correct an inconsistency in dynamic
symbol accounting data causing an assertion failure in the MIPS backend:

ld: BFD (GNU Binutils) 2.28.51.20170330 assertion fail
../../binutils-gdb/bfd/elfxx-mips.c:3860

in the course of making a GOT entry in a static binary to satisfy a GOT
relocation present in input, due to the local dynamic symbol count not
having been established.

To do so let backends request `_bfd_elf_link_renumber_dynsyms' to be
always called, rather than where a dynamic binary is linked only, and
then make this request in the MIPS backend.

	bfd/
	PR ld/21334
	* elf-bfd.h (elf_backend_data): Add `always_renumber_dynsyms'
	member.
	* elfxx-target.h [!elf_backend_always_renumber_dynsyms]
	(elf_backend_always_renumber_dynsyms): Define.
	(elfNN_bed): Initialize `always_renumber_dynsyms' member.
	* elfxx-mips.h (elf_backend_always_renumber_dynsyms): Define.
	* elflink.c (bfd_elf_size_dynsym_hash_dynstr): Also call
	`_bfd_elf_link_renumber_dynsyms' if the backend has requested
	it.
	(elf_gc_sweep): Likewise.

(backported from commit 23ec1e32b1ab714649a7c25e49b5d721fe3bd3db)
---
 bfd/ChangeLog      | 14 ++++++++++++++
 bfd/elf-bfd.h      |  4 ++++
 bfd/elflink.c      | 34 +++++++++++++++++++++++-----------
 bfd/elfxx-mips.h   |  1 +
 bfd/elfxx-target.h |  6 +++++-
 5 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 537ebb5e2c..3f10bc55f2 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,19 @@
 2017-04-26  Maciej W. Rozycki  <macro@imgtec.com>
 
+	PR ld/21334
+	* elf-bfd.h (elf_backend_data): Add `always_renumber_dynsyms'
+	member.
+	* elfxx-target.h [!elf_backend_always_renumber_dynsyms]
+	(elf_backend_always_renumber_dynsyms): Define.
+	(elfNN_bed): Initialize `always_renumber_dynsyms' member.
+	* elfxx-mips.h (elf_backend_always_renumber_dynsyms): Define.
+	* elflink.c (bfd_elf_size_dynsym_hash_dynstr): Also call
+	`_bfd_elf_link_renumber_dynsyms' if the backend has requested
+	it.
+	(elf_gc_sweep): Likewise.
+
+2017-04-26  Maciej W. Rozycki  <macro@imgtec.com>
+
 	* elflink.c (elf_gc_sweep): Only call
 	`_bfd_elf_link_renumber_dynsyms' if dynamic sections have been
 	created.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 5de9ab6ca6..dc4bd87f89 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1478,6 +1478,10 @@ struct elf_backend_data
   /* Address of protected data defined in the shared library may be
      external, i.e., due to copy relocation.   */
   unsigned extern_protected_data : 1;
+
+  /* True if `_bfd_elf_link_renumber_dynsyms' must be called even for
+     static binaries.  */
+  unsigned always_renumber_dynsyms : 1;
 };
 
 /* Information about reloc sections associated with a bfd_elf_section_data
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 75d6543dcc..507f2b6259 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -6710,6 +6710,8 @@ bfd_boolean
 bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 {
   const struct elf_backend_data *bed;
+  unsigned long section_sym_count;
+  bfd_size_type dynsymcount;
 
   if (!is_elf_hash_table (info->hash))
     return TRUE;
@@ -6717,24 +6719,30 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
   bed = get_elf_backend_data (output_bfd);
   (*bed->elf_backend_init_index_section) (output_bfd, info);
 
+  /* Assign dynsym indices.  In a shared library we generate a section
+     symbol for each output section, which come first.  Next come all
+     of the back-end allocated local dynamic syms, followed by the rest
+     of the global symbols.
+
+     This is usually not needed for static binaries, however backends
+     can request to always do it, e.g. the MIPS backend uses dynamic
+     symbol counts to lay out GOT, which will be produced in the
+     presence of GOT relocations even in static binaries (holding fixed
+     data in that case, to satisfy those relocations).  */
+
+  if (elf_hash_table (info)->dynamic_sections_created
+      || bed->always_renumber_dynsyms)
+    dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
+						  &section_sym_count);
+
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       bfd *dynobj;
       asection *s;
-      bfd_size_type dynsymcount;
-      unsigned long section_sym_count;
       unsigned int dtagcount;
 
       dynobj = elf_hash_table (info)->dynobj;
 
-      /* Assign dynsym indicies.  In a shared library we generate a
-	 section symbol for each output section, which come first.
-	 Next come all of the back-end allocated local dynamic syms,
-	 followed by the rest of the global symbols.  */
-
-      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
-						    &section_sym_count);
-
       /* Work out the size of the symbol version section.  */
       s = bfd_get_linker_section (dynobj, ".gnu.version");
       BFD_ASSERT (s != NULL);
@@ -12986,7 +12994,11 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
   elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
 			  &sweep_info);
 
-  if (elf_hash_table (info)->dynamic_sections_created)
+  /* We need to reassign dynsym indices now that symbols may have
+     been removed.  See the call in `bfd_elf_size_dynsym_hash_dynstr'
+     for the details of the conditions used here.  */
+  if (elf_hash_table (info)->dynamic_sections_created
+      || bed->always_renumber_dynsyms)
     _bfd_elf_link_renumber_dynsyms (abfd, info, &section_sym_count);
   return TRUE;
 }
diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
index fa5b5d2de9..274129b2e5 100644
--- a/bfd/elfxx-mips.h
+++ b/bfd/elfxx-mips.h
@@ -196,3 +196,4 @@ literal_reloc_p (int r_type)
 #define elf_backend_post_process_headers _bfd_mips_post_process_headers
 #define elf_backend_compact_eh_encoding _bfd_mips_elf_compact_eh_encoding
 #define elf_backend_cant_unwind_opcode _bfd_mips_elf_cant_unwind_opcode
+#define elf_backend_always_renumber_dynsyms TRUE
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index d063fb7f1b..d07600c15d 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -126,6 +126,9 @@
 #ifndef elf_backend_extern_protected_data
 #define elf_backend_extern_protected_data 0
 #endif
+#ifndef elf_backend_always_renumber_dynsyms
+#define elf_backend_always_renumber_dynsyms FALSE
+#endif
 #ifndef elf_backend_stack_align
 #define elf_backend_stack_align 16
 #endif
@@ -866,7 +869,8 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_no_page_alias,
   elf_backend_default_execstack,
   elf_backend_caches_rawsize,
-  elf_backend_extern_protected_data
+  elf_backend_extern_protected_data,
+  elf_backend_always_renumber_dynsyms
 };
 
 /* Forward declaration for use when initialising alternative_target field.  */
-- 
2.11.0