aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog8
-rw-r--r--gas/config/tc-arm.c66
-rw-r--r--gas/testsuite/ChangeLog8
-rw-r--r--gas/testsuite/gas/arm/weakdef-1.d20
-rw-r--r--gas/testsuite/gas/arm/weakdef-1.s18
-rw-r--r--gas/testsuite/gas/arm/weakdef-2.d5
-rw-r--r--gas/testsuite/gas/arm/weakdef-2.l3
-rw-r--r--gas/testsuite/gas/arm/weakdef-2.s10
-rw-r--r--gas/write.c4
9 files changed, 110 insertions, 32 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 961b716..c2b3faa 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,11 @@
+2010-04-29 Nathan Sidwell <nathan@codesourcery.com>
+
+ * write.c (fixup_segment): Do not assume we know the section a
+ defined weak symbol is in.
+ * config/tc-arm.c (relax_adr, relax_branch, md_apply_fix): Treat
+ weak symbols as not known to be in the same section, even if they
+ are defined.
+
2010-04-27 Joseph Myers <joseph@codesourcery.com>
* config/tc-tic6x.h (tic6x_label_list): New.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index b7ea21b..a50ac1d 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -18530,7 +18530,8 @@ relax_adr (fragS *fragp, asection *sec, long stretch)
/* Assume worst case for symbols not known to be in the same section. */
if (fragp->fr_symbol == NULL
|| !S_IS_DEFINED (fragp->fr_symbol)
- || sec != S_GET_SEGMENT (fragp->fr_symbol))
+ || sec != S_GET_SEGMENT (fragp->fr_symbol)
+ || S_IS_WEAK (fragp->fr_symbol))
return 4;
val = relaxed_symbol_addr (fragp, stretch);
@@ -18573,7 +18574,8 @@ relax_branch (fragS *fragp, asection *sec, int bits, long stretch)
/* Assume worst case for symbols not known to be in the same section. */
if (!S_IS_DEFINED (fragp->fr_symbol)
- || sec != S_GET_SEGMENT (fragp->fr_symbol))
+ || sec != S_GET_SEGMENT (fragp->fr_symbol)
+ || S_IS_WEAK (fragp->fr_symbol))
return 4;
#ifdef OBJ_ELF
@@ -19784,22 +19786,23 @@ md_apply_fix (fixS * fixP,
not have a reloc for it, so tc_gen_reloc will reject it. */
fixP->fx_done = 1;
- if (fixP->fx_addsy
- && ! S_IS_DEFINED (fixP->fx_addsy))
+ if (fixP->fx_addsy)
{
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("undefined symbol %s used as an immediate value"),
- S_GET_NAME (fixP->fx_addsy));
- break;
- }
+ const char *msg = 0;
- if (fixP->fx_addsy
- && S_GET_SEGMENT (fixP->fx_addsy) != seg)
- {
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("symbol %s is in a different section"),
- S_GET_NAME (fixP->fx_addsy));
- break;
+ if (! S_IS_DEFINED (fixP->fx_addsy))
+ msg = _("undefined symbol %s used as an immediate value");
+ else if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
+ msg = _("symbol %s is in a different section");
+ else if (S_IS_WEAK (fixP->fx_addsy))
+ msg = _("symbol %s is weak and may be overridden later");
+
+ if (msg)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ msg, S_GET_NAME (fixP->fx_addsy));
+ break;
+ }
}
newimm = encode_arm_immediate (value);
@@ -19825,24 +19828,25 @@ md_apply_fix (fixS * fixP,
unsigned int highpart = 0;
unsigned int newinsn = 0xe1a00000; /* nop. */
- if (fixP->fx_addsy
- && ! S_IS_DEFINED (fixP->fx_addsy))
+ if (fixP->fx_addsy)
{
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("undefined symbol %s used as an immediate value"),
- S_GET_NAME (fixP->fx_addsy));
- break;
- }
+ const char *msg = 0;
- if (fixP->fx_addsy
- && S_GET_SEGMENT (fixP->fx_addsy) != seg)
- {
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("symbol %s is in a different section"),
- S_GET_NAME (fixP->fx_addsy));
- break;
- }
+ if (! S_IS_DEFINED (fixP->fx_addsy))
+ msg = _("undefined symbol %s used as an immediate value");
+ else if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
+ msg = _("symbol %s is in a different section");
+ else if (S_IS_WEAK (fixP->fx_addsy))
+ msg = _("symbol %s is weak and may be overridden later");
+ if (msg)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ msg, S_GET_NAME (fixP->fx_addsy));
+ break;
+ }
+ }
+
newimm = encode_arm_immediate (value);
temp = md_chars_to_number (buf, INSN_SIZE);
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index f381115..c9eae54 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2010-04-29 Nathan Sidwell <nathan@codesourcery.com>
+
+ * gas/arm/weakdef-1.s: New.
+ * gas/arm/weakdef-1.d: New.
+ * gas/arm/weakdef-2.s: New.
+ * gas/arm/weakdef-2.d: New.
+ * gas/arm/weakdef-2.l: New.
+
2010-04-27 Joseph Myers <joseph@codesourcery.com>
* gas/tic6x/align-1-be.d, gas/tic6x/align-1.d,
diff --git a/gas/testsuite/gas/arm/weakdef-1.d b/gas/testsuite/gas/arm/weakdef-1.d
new file mode 100644
index 0000000..8351fc2
--- /dev/null
+++ b/gas/testsuite/gas/arm/weakdef-1.d
@@ -0,0 +1,20 @@
+# name: Thumb branch to weak
+# as:
+# objdump: -dr
+# This test is only valid on ELF based ports.
+#not-target: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+
+.*: +file format .*arm.*
+
+
+Disassembly of section .text:
+
+0+000 <Weak>:
+ 0: e7fe b.n 2 <Strong>
+ 0: R_ARM_THM_JUMP11 Strong
+
+0+002 <Strong>:
+ 2: f7ff bffe b.w 0 <Random>
+ 2: R_ARM_THM_JUMP24 Random
+ 6: f7ff bffe b.w 0 <Weak>
+ 6: R_ARM_THM_JUMP24 Weak
diff --git a/gas/testsuite/gas/arm/weakdef-1.s b/gas/testsuite/gas/arm/weakdef-1.s
new file mode 100644
index 0000000..4aa6bc4
--- /dev/null
+++ b/gas/testsuite/gas/arm/weakdef-1.s
@@ -0,0 +1,18 @@
+ .syntax unified
+ .text
+ .thumb
+
+ .globl Weak
+ .weak Weak
+ .thumb_func
+ .type Weak, %function
+Weak:
+ b Strong
+ .size Weak, .-Weak
+
+ .globl Strong
+ .type Strong, %function
+Strong:
+ b Random
+ b Weak
+ .size Strong, .-Strong
diff --git a/gas/testsuite/gas/arm/weakdef-2.d b/gas/testsuite/gas/arm/weakdef-2.d
new file mode 100644
index 0000000..e0ff272
--- /dev/null
+++ b/gas/testsuite/gas/arm/weakdef-2.d
@@ -0,0 +1,5 @@
+# name: adr of weak
+# as:
+# error-output: weakdef-2.l
+# This test is only valid on ELF based ports.
+#not-target: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
diff --git a/gas/testsuite/gas/arm/weakdef-2.l b/gas/testsuite/gas/arm/weakdef-2.l
new file mode 100644
index 0000000..7aec5e1
--- /dev/null
+++ b/gas/testsuite/gas/arm/weakdef-2.l
@@ -0,0 +1,3 @@
+[^:]*: Assembler messages:
+[^:]*:9: Error: symbol Weak is weak and may be overridden later
+[^:]*:10: Error: symbol Weak is weak and may be overridden later
diff --git a/gas/testsuite/gas/arm/weakdef-2.s b/gas/testsuite/gas/arm/weakdef-2.s
new file mode 100644
index 0000000..08da196
--- /dev/null
+++ b/gas/testsuite/gas/arm/weakdef-2.s
@@ -0,0 +1,10 @@
+ .syntax unified
+ .text
+ .globl Strong
+Strong:
+ adrl r0,Strong
+ adr r0,Strong
+ .globl Weak
+ .weak Weak
+Weak: adrl r0,Weak
+ adr r0,Weak
diff --git a/gas/write.c b/gas/write.c
index a148b24..b50b0d4 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -992,7 +992,9 @@ fixup_segment (fixS *fixP, segT this_segment)
if (fixP->fx_addsy)
{
- if (add_symbol_segment == this_segment
+ if (S_IS_WEAK (fixP->fx_addsy))
+ ; // even if it is defined, it might be overridden later
+ else if (add_symbol_segment == this_segment
&& !TC_FORCE_RELOCATION_LOCAL (fixP))
{
/* This fixup was made when the symbol's segment was