From 5c3049d2ef5d591dadd42bd074f4866616ef8231 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 20 Dec 2010 13:00:14 +0000 Subject: [PATCH] * ld.texinfo (Expression Section): Describe treatment of numbers and absolute symbols. * ldemul.c (after_open_default): Look up __ld_compatibility. * ldexp.c (fold_name): Convert absolute symbols to numbers when inside output section definitions, or when __ld_compatibility >= 221. (exp_fold_tree_1): Convert numbers to absolute when not in output section definition and __ld_compatibility < 221. Don't always convert values outside an output section definition to absolute. * ldexp.h (uses_defined): Comment. * ldlang.c (ld_compatibility): New variable. * ldlang.h (ld_compatibility): Declare. * emultempl/aix.em, * emultempl/armcoff.em, * emultempl/beos.em, * emultempl/elf32.em, * emultempl/genelf.em, * emultempl/lnk960.em, * emultempl/m68kcoff.em, * emultempl/mmo.em, * emultempl/pe.em, * emultempl/pep.em, * emultempl/sunos.em, * emultempl/z80.em: Call after_open_default from after_open function. --- ld/ChangeLog | 19 +++++++++++++++++++ ld/emultempl/aix.em | 2 ++ ld/emultempl/armcoff.em | 2 ++ ld/emultempl/beos.em | 2 ++ ld/emultempl/elf32.em | 2 ++ ld/emultempl/genelf.em | 2 ++ ld/emultempl/lnk960.em | 2 +- ld/emultempl/m68kcoff.em | 2 ++ ld/emultempl/mmo.em | 1 + ld/emultempl/pe.em | 2 ++ ld/emultempl/pep.em | 2 ++ ld/emultempl/sunos.em | 2 ++ ld/emultempl/z80.em | 2 ++ ld/ld.texinfo | 27 +++++++++++++-------------- ld/ldemul.c | 10 ++++++++++ ld/ldexp.c | 16 ++++++++-------- ld/ldexp.h | 1 + ld/ldlang.c | 1 + ld/ldlang.h | 1 + 19 files changed, 75 insertions(+), 23 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 13aa681..4e6f974 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,24 @@ 2010-12-20 Alan Modra + * ld.texinfo (Expression Section): Describe treatment of numbers + and absolute symbols. + * ldemul.c (after_open_default): Look up __ld_compatibility. + * ldexp.c (fold_name): Convert absolute symbols to numbers when + inside output section definitions, or when __ld_compatibility >= 221. + (exp_fold_tree_1): Convert numbers to absolute when not in output + section definition and __ld_compatibility < 221. Don't always + convert values outside an output section definition to absolute. + * ldexp.h (uses_defined): Comment. + * ldlang.c (ld_compatibility): New variable. + * ldlang.h (ld_compatibility): Declare. + * emultempl/aix.em, * emultempl/armcoff.em, * emultempl/beos.em, + * emultempl/elf32.em, * emultempl/genelf.em, * emultempl/lnk960.em, + * emultempl/m68kcoff.em, * emultempl/mmo.em, * emultempl/pe.em, + * emultempl/pep.em, * emultempl/sunos.em, * emultempl/z80.em: Call + after_open_default from after_open function. + +2010-12-20 Alan Modra + PR ld/12001 Revert 2010-11-03 Nick Clifton * ldlang.c (ldlang_def_chain_list): Delete. diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index 5ccb25c..60c4fc6 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -608,6 +608,8 @@ gld${EMULATION_NAME}_after_open (void) bfd_boolean r; struct set_info *p; + after_open_default (); + /* Call ldctor_build_sets, after pretending that this is a relocatable link. We do this because AIX requires relocation entries for all references to symbols, even in a final diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em index b3cdde9..20bff14 100644 --- a/ld/emultempl/armcoff.em +++ b/ld/emultempl/armcoff.em @@ -133,6 +133,8 @@ gld${EMULATION_NAME}_before_allocation (void) static void gld${EMULATION_NAME}_after_open (void) { + after_open_default (); + if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL) { /* The arm backend needs special fields in the output hash structure. diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em index 370dbac..abd3979 100644 --- a/ld/emultempl/beos.em +++ b/ld/emultempl/beos.em @@ -376,6 +376,8 @@ gld_${EMULATION_NAME}_set_symbols (void) static void gld_${EMULATION_NAME}_after_open (void) { + after_open_default (); + /* Pass the wacky PE command line options into the output bfd. FIXME: This should be done via a function, rather than by including an internal BFD header. */ diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 34cc82c7..9120f85 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -1059,6 +1059,8 @@ gld${EMULATION_NAME}_after_open (void) struct bfd_link_needed_list *needed, *l; struct elf_link_hash_table *htab; + after_open_default (); + htab = elf_hash_table (&link_info); if (!is_elf_hash_table (htab)) return; diff --git a/ld/emultempl/genelf.em b/ld/emultempl/genelf.em index 62af4de..ce416eb 100644 --- a/ld/emultempl/genelf.em +++ b/ld/emultempl/genelf.em @@ -35,6 +35,8 @@ gld${EMULATION_NAME}_after_open (void) asection *sec; asymbol **syms; + after_open_default (); + if (link_info.relocatable) for (ibfd = link_info.input_bfds; ibfd != NULL; ibfd = ibfd->link_next) if ((syms = bfd_get_outsymbols (ibfd)) != NULL diff --git a/ld/emultempl/lnk960.em b/ld/emultempl/lnk960.em index e13233c..7120329 100644 --- a/ld/emultempl/lnk960.em +++ b/ld/emultempl/lnk960.em @@ -265,7 +265,7 @@ struct ld_emulation_xfer_struct ld_lnk960_emulation = lnk960_syslib, lnk960_hll, lnk960_after_parse, - NULL, /* after_open */ + after_open_default, lnk960_after_allocation, lnk960_set_output_arch, lnk960_choose_target, diff --git a/ld/emultempl/m68kcoff.em b/ld/emultempl/m68kcoff.em index 276c3b2..b09a223 100644 --- a/ld/emultempl/m68kcoff.em +++ b/ld/emultempl/m68kcoff.em @@ -62,6 +62,8 @@ gld${EMULATION_NAME}_after_open (void) { bfd *abfd; + after_open_default (); + if (! command_line.embedded_relocs || link_info.relocatable) return; diff --git a/ld/emultempl/mmo.em b/ld/emultempl/mmo.em index d1a6f14..9b18186 100644 --- a/ld/emultempl/mmo.em +++ b/ld/emultempl/mmo.em @@ -151,6 +151,7 @@ mmo_after_open (void) is->the_bfd); } } + after_open_default (); } EOF diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index df0678d..b4d7a63 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -1219,6 +1219,8 @@ debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj) static void gld_${EMULATION_NAME}_after_open (void) { + after_open_default (); + #ifdef DLL_SUPPORT if (pe_dll_extra_pe_debug) { diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 4ab7489..e407296 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1151,6 +1151,8 @@ debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj) static void gld_${EMULATION_NAME}_after_open (void) { + after_open_default (); + is_underscoring (); #ifdef DLL_SUPPORT if (pep_dll_extra_pe_debug) diff --git a/ld/emultempl/sunos.em b/ld/emultempl/sunos.em index 5c6c0a6..567b8e2 100644 --- a/ld/emultempl/sunos.em +++ b/ld/emultempl/sunos.em @@ -366,6 +366,8 @@ gld${EMULATION_NAME}_after_open (void) { struct bfd_link_needed_list *needed, *l; + after_open_default (); + /* We only need to worry about this when doing a final link. */ if (link_info.relocatable || link_info.shared) return; diff --git a/ld/emultempl/z80.em b/ld/emultempl/z80.em index 100ebd0..eeb3213 100644 --- a/ld/emultempl/z80.em +++ b/ld/emultempl/z80.em @@ -79,6 +79,8 @@ gldz80_after_open (void) { unsigned long mach_type; + after_open_default (); + switch (result_mach_type) { case M_Z80STRICT: diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 6d36dfb..d4419aa 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -5503,17 +5503,17 @@ section relative symbols and for builtin functions that return an address, such as @code{ADDR}, @code{LOADADDR}, @code{ORIGIN} and @code{SEGMENT_START}. Other terms are simply numbers, or are builtin functions that return a non-address value, such as @code{LENGTH}. - -When the linker evaluates an expression, the result depends on where -the expression is located in a linker script. Expressions appearing -outside an output section definitions are evaluated with all terms -first being converted to absolute addresses before applying operators, -and evaluate to an absolute address result. Expressions appearing -inside an output section definition are evaluated with more complex -rules, but the aim is to treat terms as relative addresses and produce -a relative address result. In particular, an assignment of a number -to a symbol results in a symbol relative to the output section with an -offset given by the number. So, in the following simple example, +One complication is that unless you assign @code{__ld_compatibility} +a value of 221 or larger, numbers and absolute symbols are treated +differently depending on their location, for compatibility with older +versions of @code{ld}. Expressions appearing outside an output +section definition treat all numbers as absolute addresses. +Expressions appearing inside an output section definition treat +absolute symbols as numbers. If @code{__ld_compatibility} is assigned +a value larger than 221, then absolute symbols and numbers are simply +treated as numbers everywhere. + +In the following simple example, @smallexample @group @@ -5537,9 +5537,8 @@ address 0x100 in the first two assignments, then both @code{.} and @code{__data_start} are set to 0x10 relative to the @code{.data} section in the second two assignments. -For expressions appearing inside an output section definition -involving numbers, relative addresses and absolute addresses, ld -follows these rules to evaluate terms: +For expressions involving numbers, relative addresses and absolute +addresses, ld follows these rules to evaluate terms: @itemize @bullet @item diff --git a/ld/ldemul.c b/ld/ldemul.c index f1f3979..3c07ceb 100644 --- a/ld/ldemul.c +++ b/ld/ldemul.c @@ -226,6 +226,16 @@ after_parse_default (void) void after_open_default (void) { + struct bfd_link_hash_entry *h; + + h = bfd_wrapped_link_hash_lookup (link_info.output_bfd, + &link_info, + "__ld_compatibility", + FALSE, FALSE, TRUE); + if (h != NULL + && (h->type == bfd_link_hash_defined + || h->type == bfd_link_hash_defweak)) + ld_compatibility = h->u.def.value; } void diff --git a/ld/ldexp.c b/ld/ldexp.c index 71b957c..3261884 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -553,7 +553,9 @@ fold_name (etree_type *tree) " referenced in expression\n"), tree->name.name); } - else if (output_section == bfd_abs_section_ptr) + else if (output_section == bfd_abs_section_ptr + && (expld.section != bfd_abs_section_ptr + || ld_compatibility >= 221)) new_number (h->u.def.value + h->u.def.section->output_offset); else new_rel (h->u.def.value + h->u.def.section->output_offset, @@ -700,7 +702,11 @@ exp_fold_tree_1 (etree_type *tree) switch (tree->type.node_class) { case etree_value: - new_number (tree->value.value); + if (expld.section == bfd_abs_section_ptr + && ld_compatibility < 221) + new_abs (tree->value.value); + else + new_number (tree->value.value); expld.result.str = tree->value.str; break; @@ -860,12 +866,6 @@ exp_fold_tree_1 (etree_type *tree) memset (&expld.result, 0, sizeof (expld.result)); break; } - - /* Any value not inside an output section statement is an - absolute value. */ - if (expld.result.valid_p - && expld.section == bfd_abs_section_ptr) - make_abs (); } void diff --git a/ld/ldexp.h b/ld/ldexp.h index ac73bd1..31a06ac 100644 --- a/ld/ldexp.h +++ b/ld/ldexp.h @@ -127,6 +127,7 @@ struct ldexp_control { /* Working results. */ etree_value_type result; bfd_vma dot; + /* Set if an expression contains DEFINED(). */ bfd_boolean uses_defined; /* Current dot and section passed to ldexp folder. */ diff --git a/ld/ldlang.c b/ld/ldlang.c index 6f4e200..097c390 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -109,6 +109,7 @@ bfd_boolean delete_output_file_on_failure = FALSE; struct lang_phdr *lang_phdr_list; struct lang_nocrossrefs *nocrossref_list; bfd_boolean missing_file = FALSE; +int ld_compatibility; /* Functions that traverse the linker script and might evaluate DEFINED() need to increment this. */ diff --git a/ld/ldlang.h b/ld/ldlang.h index 15e55875..5850fcb 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -469,6 +469,7 @@ extern bfd_boolean entry_from_cmdline; extern lang_statement_list_type file_chain; extern lang_statement_list_type input_file_chain; +extern int ld_compatibility; extern int lang_statement_iteration; extern bfd_boolean missing_file; -- 2.7.4