1 From 4613510308cea27713e8c7424b2afee9b99f6226 Mon Sep 17 00:00:00 2001
2 From: Alan Modra <amodra@gmail.com>
3 Date: Tue, 12 Aug 2014 10:43:33 +0930
4 Subject: [PATCH] Change ld "notice" interface for better handling of
7 The main aim of this change was to have non_ir_ref set correctly on
8 new indirect symbols. I could have added a "copy" param to the "notice"
9 function, so that indirect symbols could be created in plugin_notice,
10 but it seemed cleaner to create indirect syms earlier and pass them
11 rather than "string" to "notice".
14 * bfdlink.h (struct bfd_link_callbacks <notice>): Remove "string"
17 * coff-aux.c (coff_m68k_aux_link_add_one_symbol): Only call "notice"
18 here when not calling the generic add_symbol function. Formatting.
19 Correct handling of indirect symbols. Update notice call.
20 * elflink.c (_bfd_elf_notice_as_needed): Update notice call.
21 * linker.c (_bfd_generic_link_add_one_symbol): Create indirect
22 symbols early. Update notice call. Add comments regarding weak
25 * ldmain.c (notice): Update args.
26 * plugin.c (plugin_notice): Likewise. Follow warning sym link.
27 Handle new indirect symbol.
29 bfd/coff-aux.c | 62 ++++++++++++++++++++++-------------------
31 bfd/linker.c | 82 +++++++++++++++++++++++++++++--------------------------
32 include/bfdlink.h | 13 ++++-----
34 ld/plugin.c | 33 ++++++++++++----------
35 9 files changed, 128 insertions(+), 91 deletions(-)
37 diff --git a/bfd/coff-aux.c b/bfd/coff-aux.c
38 index e79c77a..d95b98b 100644
41 @@ -73,20 +73,17 @@ coff_m68k_aux_link_add_one_symbol (struct bfd_link_info *info,
43 struct bfd_link_hash_entry **hashp)
45 - struct bfd_link_hash_entry *h;
46 + struct bfd_link_hash_entry *h, *inh, *t;
48 - if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0 &&
49 - !bfd_is_und_section (section) &&
50 - !bfd_is_com_section (section))
51 + if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0
52 + && !bfd_is_und_section (section)
53 + && !bfd_is_com_section (section))
55 /* The new symbol is a definition or an indirect definition */
57 /* This bit copied from linker.c */
58 if (hashp != NULL && *hashp != NULL)
61 - BFD_ASSERT (strcmp (h->root.string, name) == 0);
66 h = bfd_link_hash_lookup (info->hash, name, TRUE, copy, FALSE);
67 @@ -98,37 +95,46 @@ coff_m68k_aux_link_add_one_symbol (struct bfd_link_info *info,
71 - if (info->notice_hash != (struct bfd_hash_table *) NULL
72 - && (bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE)
73 - != (struct bfd_hash_entry *) NULL))
75 - if (! (*info->callbacks->notice) (info, h, abfd, section, value,
80 if (hashp != (struct bfd_link_hash_entry **) NULL)
82 /* end duplication from linker.c */
84 - if (h->type == bfd_link_hash_defined
85 - || h->type == bfd_link_hash_indirect)
88 + if (h->type == bfd_link_hash_indirect)
95 - if (h->type == bfd_link_hash_defined)
96 - msec = h->u.def.section;
98 - msec = bfd_ind_section_ptr;
99 + if (t->type == bfd_link_hash_defined)
101 + asection *msec = t->u.def.section;
102 + bfd_boolean special = FALSE;
104 if (bfd_is_abs_section (msec) && !bfd_is_abs_section (section))
106 - h->u.def.section = section;
107 - h->u.def.value = value;
109 + t->u.def.section = section;
110 + t->u.def.value = value;
113 else if (bfd_is_abs_section (section) && !bfd_is_abs_section (msec))
119 + if (info->notice_all
120 + || (info->notice_hash != NULL
121 + && bfd_hash_lookup (info->notice_hash, name,
122 + FALSE, FALSE) != NULL))
124 + if (!(*info->callbacks->notice) (info, h, inh,
125 + abfd, section, value, flags))
134 diff --git a/bfd/elflink.c b/bfd/elflink.c
135 index 69a87a6..de0a734 100644
138 @@ -3299,7 +3299,7 @@ _bfd_elf_notice_as_needed (bfd *ibfd,
139 struct bfd_link_info *info,
140 enum notice_asneeded_action act)
142 - return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL);
143 + return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0);
146 /* Add symbols from an ELF object file to the linker hash table. */
147 diff --git a/bfd/linker.c b/bfd/linker.c
148 index 1a5ecef..abdf5b0 100644
151 @@ -1442,13 +1442,23 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
154 struct bfd_link_hash_entry *h;
155 + struct bfd_link_hash_entry *inh = NULL;
158 BFD_ASSERT (section != NULL);
160 if (bfd_is_ind_section (section)
161 || (flags & BSF_INDIRECT) != 0)
165 + /* Create the indirect symbol here. This is for the benefit of
166 + the plugin "notice" function.
167 + STRING is the name of the symbol we want to indirect to. */
168 + inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
173 else if ((flags & BSF_WARNING) != 0)
175 else if ((flags & BSF_CONSTRUCTOR) != 0)
176 @@ -1493,8 +1503,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
177 || (info->notice_hash != NULL
178 && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
180 - if (! (*info->callbacks->notice) (info, h,
181 - abfd, section, value, flags, string))
182 + if (! (*info->callbacks->notice) (info, h, inh,
183 + abfd, section, value, flags))
187 @@ -1728,44 +1738,40 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
191 - /* Create an indirect symbol. */
193 - struct bfd_link_hash_entry *inh;
195 - /* STRING is the name of the symbol we want to indirect
197 - inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
200 + if (inh->type == bfd_link_hash_indirect
201 + && inh->u.i.link == h)
203 + (*_bfd_error_handler)
204 + (_("%B: indirect symbol `%s' to `%s' is a loop"),
205 + abfd, name, string);
206 + bfd_set_error (bfd_error_invalid_operation);
208 - if (inh->type == bfd_link_hash_indirect
209 - && inh->u.i.link == h)
211 - (*_bfd_error_handler)
212 - (_("%B: indirect symbol `%s' to `%s' is a loop"),
213 - abfd, name, string);
214 - bfd_set_error (bfd_error_invalid_operation);
217 - if (inh->type == bfd_link_hash_new)
219 - inh->type = bfd_link_hash_undefined;
220 - inh->u.undef.abfd = abfd;
221 - bfd_link_add_undef (info->hash, inh);
224 + if (inh->type == bfd_link_hash_new)
226 + inh->type = bfd_link_hash_undefined;
227 + inh->u.undef.abfd = abfd;
228 + bfd_link_add_undef (info->hash, inh);
231 - /* If the indirect symbol has been referenced, we need to
232 - push the reference down to the symbol we are
234 - if (h->type != bfd_link_hash_new)
239 + /* If the indirect symbol has been referenced, we need to
240 + push the reference down to the symbol we are referencing. */
241 + if (h->type != bfd_link_hash_new)
243 + /* ??? If inh->type == bfd_link_hash_undefweak this
244 + converts inh to bfd_link_hash_undefined. */
249 - h->type = bfd_link_hash_indirect;
252 + h->type = bfd_link_hash_indirect;
254 + /* Not setting h = h->u.i.link here means that when cycle is
255 + set above we'll always go to REFC, and then cycle again
256 + to the indirected symbol. This means that any successful
257 + change of an existing symbol to indirect counts as a
258 + reference. ??? That may not be correct when the existing
259 + symbol was defweak. */
263 diff --git a/include/bfdlink.h b/include/bfdlink.h
264 index 58dba2a..125683d 100644
265 --- a/include/bfdlink.h
266 +++ b/include/bfdlink.h
267 @@ -640,15 +640,14 @@ struct bfd_link_callbacks
268 (struct bfd_link_info *, const char *name,
269 bfd *abfd, asection *section, bfd_vma address);
270 /* A function which is called when a symbol in notice_hash is
271 - defined or referenced. H is the symbol. ABFD, SECTION and
272 - ADDRESS are the (new) value of the symbol. If SECTION is
273 - bfd_und_section, this is a reference. FLAGS are the symbol
274 - BSF_* flags. STRING is the name of the symbol to indirect to if
275 - the sym is indirect, or the warning string if a warning sym. */
276 + defined or referenced. H is the symbol, INH the indirect symbol
277 + if applicable. ABFD, SECTION and ADDRESS are the (new) value of
278 + the symbol. If SECTION is bfd_und_section, this is a reference.
279 + FLAGS are the symbol BSF_* flags. */
280 bfd_boolean (*notice)
281 (struct bfd_link_info *, struct bfd_link_hash_entry *h,
282 - bfd *abfd, asection *section, bfd_vma address, flagword flags,
283 - const char *string);
284 + struct bfd_link_hash_entry *inh,
285 + bfd *abfd, asection *section, bfd_vma address, flagword flags);
286 /* Error or warning link info message. */
288 (const char *fmt, ...);
289 diff --git a/ld/ldmain.c b/ld/ldmain.c
290 index ea25afe..77235d5 100644
293 @@ -137,7 +137,7 @@ static bfd_boolean unattached_reloc
294 (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
295 static bfd_boolean notice
296 (struct bfd_link_info *, struct bfd_link_hash_entry *,
297 - bfd *, asection *, bfd_vma, flagword, const char *);
298 + struct bfd_link_hash_entry *, bfd *, asection *, bfd_vma, flagword);
300 static struct bfd_link_callbacks link_callbacks =
302 @@ -1461,11 +1461,11 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
304 notice (struct bfd_link_info *info,
305 struct bfd_link_hash_entry *h,
306 + struct bfd_link_hash_entry *inh ATTRIBUTE_UNUSED,
310 - flagword flags ATTRIBUTE_UNUSED,
311 - const char *string ATTRIBUTE_UNUSED)
312 + flagword flags ATTRIBUTE_UNUSED)
316 diff --git a/ld/plugin.c b/ld/plugin.c
317 index 8d6ae05..8cca7d0 100644
320 @@ -127,8 +127,9 @@ static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
322 /* Forward references. */
323 static bfd_boolean plugin_notice (struct bfd_link_info *,
324 - struct bfd_link_hash_entry *, bfd *,
325 - asection *, bfd_vma, flagword, const char *);
326 + struct bfd_link_hash_entry *,
327 + struct bfd_link_hash_entry *,
328 + bfd *, asection *, bfd_vma, flagword);
330 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
332 @@ -962,16 +963,21 @@ plugin_call_cleanup (void)
334 plugin_notice (struct bfd_link_info *info,
335 struct bfd_link_hash_entry *h,
336 + struct bfd_link_hash_entry *inh,
341 - const char *string)
344 + struct bfd_link_hash_entry *orig_h = h;
350 + if (h->type == bfd_link_hash_warning)
353 /* Nothing to do here if this def/ref is from an IR dummy BFD. */
354 if (is_ir_dummy_bfd (abfd))
356 @@ -981,16 +987,15 @@ plugin_notice (struct bfd_link_info *info,
357 else if (bfd_is_ind_section (section)
358 || (flags & BSF_INDIRECT) != 0)
360 + /* ??? Some of this is questionable. See comments in
361 + _bfd_generic_link_add_one_symbol for case IND. */
362 if (h->type != bfd_link_hash_new)
364 - struct bfd_link_hash_entry *inh;
366 h->non_ir_ref = TRUE;
367 - inh = bfd_wrapped_link_hash_lookup (abfd, info, string, FALSE,
370 - inh->non_ir_ref = TRUE;
371 + inh->non_ir_ref = TRUE;
373 + else if (inh->type == bfd_link_hash_new)
374 + inh->non_ir_ref = TRUE;
377 /* Nothing to do here for warning symbols. */
378 @@ -1031,13 +1036,13 @@ plugin_notice (struct bfd_link_info *info,
381 /* Continue with cref/nocrossref/trace-sym processing. */
385 || (info->notice_hash != NULL
386 - && bfd_hash_lookup (info->notice_hash, h->root.string,
387 + && bfd_hash_lookup (info->notice_hash, orig_h->root.string,
388 FALSE, FALSE) != NULL))
389 - return (*orig_callbacks->notice) (info, h,
390 - abfd, section, value, flags, string);
391 + return (*orig_callbacks->notice) (info, orig_h, inh,
392 + abfd, section, value, flags);