aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/0036-2011-12-19-Chung-Lin-Tang-cltang-codesourcery.com.patch
blob: 9017c250de99d72d985ad1b25a6fd2e1b796edea (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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
Upstream-Status: Backport

From 26e802720ccd055d70addadbc39f4119716f8573 Mon Sep 17 00:00:00 2001
From: cltang <cltang>
Date: Mon, 19 Dec 2011 10:39:27 +0000
Subject: [PATCH 036/262] 2011-12-19  Chung-Lin Tang 
 <cltang@codesourcery.com>

	Backport from mainline:

	2011-12-19  Chung-Lin Tang  <cltang@codesourcery.com>
		    Catherine Moore  <clm@codesourcery.com>
		    Sandra Loosemore  <sandra@codesourcery.com>
		    Richard Sandiford  <rdsandiford@googlemail.com>

	* elfxx-mips.c (mips_elf_local_pic_function_p): Return true when
	H is a MIPS16 function with a kept 32-bit stub. Update comments.
	(mips_elf_get_la25_target): New function.
	(mips_elf_add_la25_intro): Change to use mips_elf_get_la25_target().
	(mips_elf_add_la25_stub): Move compute of use_trampoline_p down,
	change to use mips_elf_get_la25_target().
	(mips_elf_relocation_needs_la25_stub): Add target_is_16_bit_code_p
	parameter, add switch case for R_MIPS16_26.
	(mips_elf_calculate_relocation): Redirect relocation to point to the
	LA25 stub if it exists, instead of the MIPS16 stub. Update arguments
	of call to mips_elf_relocation_needs_la25_stub(), don't use la25 stub
	for mips16->mips16 calls.
	(_bfd_mips_elf_check_relocs): Update arguments of call to
	mips_elf_relocation_needs_la25_stub().
	(mips_elf_create_la25_stub): Change to use mips_elf_get_la25_target().

diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 3939183..9f3833b 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -1575,9 +1575,10 @@ _bfd_mips_elf_init_stubs (struct bfd_link_info *info,
 }
 
 /* Return true if H is a locally-defined PIC function, in the sense
-   that it might need $25 to be valid on entry.  Note that MIPS16
-   functions never need $25 to be valid on entry; they set up $gp
-   using PC-relative instructions instead.  */
+   that it or its fn_stub might need $25 to be valid on entry.
+   Note that MIPS16 functions set up $gp using PC-relative instructions,
+   so they themselves never need $25 to be valid.  Only non-MIPS16
+   entry points are of interest here.  */
 
 static bfd_boolean
 mips_elf_local_pic_function_p (struct mips_elf_link_hash_entry *h)
@@ -1586,11 +1587,32 @@ mips_elf_local_pic_function_p (struct mips_elf_link_hash_entry *h)
 	   || h->root.root.type == bfd_link_hash_defweak)
 	  && h->root.def_regular
 	  && !bfd_is_abs_section (h->root.root.u.def.section)
-	  && !ELF_ST_IS_MIPS16 (h->root.other)
+	  && (!ELF_ST_IS_MIPS16 (h->root.other)
+	      || (h->fn_stub && h->need_fn_stub))
 	  && (PIC_OBJECT_P (h->root.root.u.def.section->owner)
 	      || ELF_ST_IS_MIPS_PIC (h->root.other)));
 }
 
+/* Set *SEC to the input section that contains the target of STUB.
+   Return the offset of the target from the start of that section.  */
+
+static bfd_vma
+mips_elf_get_la25_target (struct mips_elf_la25_stub *stub,
+			  asection **sec)
+{
+  if (ELF_ST_IS_MIPS16 (stub->h->root.other))
+    {
+      BFD_ASSERT (stub->h->need_fn_stub);
+      *sec = stub->h->fn_stub;
+      return 0;
+    }
+  else
+    {
+      *sec = stub->h->root.root.u.def.section;
+      return stub->h->root.root.u.def.value;
+    }
+}
+
 /* STUB describes an la25 stub that we have decided to implement
    by inserting an LUI/ADDIU pair before the target function.
    Create the section and redirect the function symbol to it.  */
@@ -1615,7 +1637,7 @@ mips_elf_add_la25_intro (struct mips_elf_la25_stub *stub,
   sprintf (name, ".text.stub.%d", (int) htab_elements (htab->la25_stubs));
 
   /* Create the section.  */
-  input_section = stub->h->root.root.u.def.section;
+  mips_elf_get_la25_target (stub, &input_section);
   s = htab->add_stub_section (name, input_section,
 			      input_section->output_section);
   if (s == NULL)
@@ -1689,12 +1711,6 @@ mips_elf_add_la25_stub (struct bfd_link_info *info,
   bfd_vma value;
   void **slot;
 
-  /* Prefer to use LUI/ADDIU stubs if the function is at the beginning
-     of the section and if we would need no more than 2 nops.  */
-  s = h->root.root.u.def.section;
-  value = h->root.root.u.def.value;
-  use_trampoline_p = (value != 0 || s->alignment_power > 4);
-
   /* Describe the stub we want.  */
   search.stub_section = NULL;
   search.offset = 0;
@@ -1724,6 +1740,11 @@ mips_elf_add_la25_stub (struct bfd_link_info *info,
   *stub = search;
   *slot = stub;
 
+  /* Prefer to use LUI/ADDIU stubs if the function is at the beginning
+     of the section and if we would need no more than 2 nops.  */
+  value = mips_elf_get_la25_target (stub, &s);
+  use_trampoline_p = (value != 0 || s->alignment_power > 4);
+
   h->la25_stub = stub;
   return (use_trampoline_p
 	  ? mips_elf_add_la25_trampoline (stub, info)
@@ -4911,7 +4932,8 @@ is_gott_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h)
    stub.  */
 
 static bfd_boolean
-mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type)
+mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type,
+				     bfd_boolean target_is_16_bit_code_p)
 {
   /* We specifically ignore branches and jumps from EF_PIC objects,
      where the onus is on the compiler or programmer to perform any
@@ -4925,7 +4947,6 @@ mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type)
     {
     case R_MIPS_26:
     case R_MIPS_PC16:
-    case R_MIPS16_26:
     case R_MICROMIPS_26_S1:
     case R_MICROMIPS_PC7_S1:
     case R_MICROMIPS_PC10_S1:
@@ -4933,6 +4954,9 @@ mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type)
     case R_MICROMIPS_PC23_S2:
       return TRUE;
 
+    case R_MIPS16_26:
+      return !target_is_16_bit_code_p;
+
     default:
       return FALSE;
     }
@@ -5193,14 +5217,28 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
 	 have already noticed that we were going to need the
 	 stub.  */
       if (local_p)
-	sec = elf_tdata (input_bfd)->local_stubs[r_symndx];
+	{
+	  sec = elf_tdata (input_bfd)->local_stubs[r_symndx];
+	  value = 0;
+	}
       else
 	{
 	  BFD_ASSERT (h->need_fn_stub);
-	  sec = h->fn_stub;
+	  if (h->la25_stub)
+	    {
+	      /* If a LA25 header for the stub itself exists, point to the
+		 prepended LUI/ADDIU sequence.  */
+	      sec = h->la25_stub->stub_section;
+	      value = h->la25_stub->offset;
+	    }
+	  else
+	    {
+	      sec = h->fn_stub;
+	      value = 0;
+	    }
 	}
 
-      symbol = sec->output_section->vma + sec->output_offset;
+      symbol = sec->output_section->vma + sec->output_offset + value;
       /* The target is 16-bit, but the stub isn't.  */
       target_is_16_bit_code_p = FALSE;
     }
@@ -5250,7 +5288,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
   /* If this is a direct call to a PIC function, redirect to the
      non-PIC stub.  */
   else if (h != NULL && h->la25_stub
-	   && mips_elf_relocation_needs_la25_stub (input_bfd, r_type))
+	   && mips_elf_relocation_needs_la25_stub (input_bfd, r_type,
+						   target_is_16_bit_code_p))
     symbol = (h->la25_stub->stub_section->output_section->vma
 	      + h->la25_stub->stub_section->output_offset
 	      + h->la25_stub->offset);
@@ -7925,7 +7964,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    return FALSE;
 	}
 
-      if (h != NULL && mips_elf_relocation_needs_la25_stub (abfd, r_type))
+      if (h != NULL
+	  && mips_elf_relocation_needs_la25_stub (abfd, r_type,
+						  ELF_ST_IS_MIPS16 (h->other)))
 	((struct mips_elf_link_hash_entry *) h)->has_nonpic_branches = TRUE;
 
       switch (r_type)
@@ -9622,9 +9663,9 @@ mips_elf_create_la25_stub (void **slot, void *data)
   offset = stub->offset;
 
   /* Work out the target address.  */
-  target = (stub->h->root.root.u.def.section->output_section->vma
-	    + stub->h->root.root.u.def.section->output_offset
-	    + stub->h->root.root.u.def.value);
+  target = mips_elf_get_la25_target (stub, &s);
+  target += s->output_section->vma + s->output_offset;
+
   target_high = ((target + 0x8000) >> 16) & 0xffff;
   target_low = (target & 0xffff);
 
-- 
1.7.9.5