Upload Tizen:Base source
[external/binutils.git] / packaging / 162_pr12730.diff
1 # DP: Fix PR ld/12730, taken from the trunk
2
3 2011-05-07  H.J. Lu  <hongjiu.lu@intel.com>
4
5         PR ld/12730
6         * elf.c (_bfd_elf_section_offset): Check SEC_ELF_REVERSE_COPY.
7
8         * elflink.c (elf_link_input_bfd): Reverse copy .ctors/.dtors
9         sections if needed. 
10
11         * section.c (SEC_ELF_REVERSE_COPY): New.
12         * bfd-in2.h: Regenerated.
13
14 2011-05-07  H.J. Lu  <hongjiu.lu@intel.com>
15
16         PR ld/12730
17         * ld-elf/elf.exp (array_tests): Add "pr12730".
18         (array_tests_pie): New.
19         (array_tests_static): Add -static for "static init array mixed".
20         Add "static pr12730".  Run array_tests_pie for Linux.
21
22         * ld-elf/init-mixed.c (ctor1007): Renamed to ...
23         (ctor1007a): This.
24         (ctor1007b): New.
25         (ctors1007): Remove ctor1007.  Add ctor1007b and ctor1007a.
26         (dtor1007): Renamed to ...
27         (dtor1007a): This.
28         (dtor1007b): New.
29         (dtors1007): Remove dtor1007.  Add dtor1007b and dtor1007a.
30         (ctor65535): Renamed to ...
31         (ctor65535a): This.
32         (ctor65535b): New.
33         (ctors65535): Remove ctor65535.  Add ctor65535b and ctor65535a.
34         (dtor65535): Renamed to ...
35         (dtor65535a): This.
36         (dtor65535b): New.
37         (dtors65535): Remove dtor65535.  Add dtor65535b and dtor65535a.
38
39         * ld-elf/pr12730.cc: New.
40         * ld-elf/pr12730.out: Likewise.
41
42 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
43 index aa12c8a..5076ccf 100644
44 --- a/bfd/bfd-in2.h
45 +++ b/bfd/bfd-in2.h
46 @@ -1320,6 +1320,11 @@ typedef struct bfd_section
47       sections.  */
48  #define SEC_COFF_SHARED_LIBRARY 0x4000000
49  
50 +  /* This input section should be copied to output in reverse order
51 +     as an array of pointers.  This is for ELF linker internal use
52 +     only.  */
53 +#define SEC_ELF_REVERSE_COPY 0x4000000
54 +
55    /* This section contains data which may be shared with other
56       executables or shared objects. This is for COFF only.  */
57  #define SEC_COFF_SHARED 0x8000000
58 diff --git a/bfd/elf.c b/bfd/elf.c
59 index b5a1952..6fccf42 100644
60 --- a/bfd/elf.c
61 +++ b/bfd/elf.c
62 @@ -9379,6 +9379,12 @@ _bfd_elf_section_offset (bfd *abfd,
63      case ELF_INFO_TYPE_EH_FRAME:
64        return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset);
65      default:
66 +      if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0)
67 +       {
68 +         const struct elf_backend_data *bed = get_elf_backend_data (abfd);
69 +         bfd_size_type address_size = bed->s->arch_size / 8;
70 +         offset = sec->size - offset - address_size;
71 +       }
72        return offset;
73      }
74  }
75 diff --git a/bfd/elflink.c b/bfd/elflink.c
76 index 082355d..e4f728d 100644
77 --- a/bfd/elflink.c
78 +++ b/bfd/elflink.c
79 @@ -9120,6 +9120,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
80    asection *o;
81    const struct elf_backend_data *bed;
82    struct elf_link_hash_entry **sym_hashes;
83 +  bfd_size_type address_size;
84 +  bfd_vma r_type_mask;
85 +  int r_sym_shift;
86  
87    output_bfd = finfo->output_bfd;
88    bed = get_elf_backend_data (output_bfd);
89 @@ -9290,6 +9293,19 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
90         *pindex = indx;
91      }
92  
93 +  if (bed->s->arch_size == 32)
94 +    {
95 +      r_type_mask = 0xff;
96 +      r_sym_shift = 8;
97 +      address_size = 4;
98 +    }
99 +  else
100 +    {
101 +      r_type_mask = 0xffffffff;
102 +      r_sym_shift = 32;
103 +      address_size = 8;
104 +    }
105 +
106    /* Relocate the contents of each section.  */
107    sym_hashes = elf_sym_hashes (input_bfd);
108    for (o = input_bfd->sections; o != NULL; o = o->next)
109 @@ -9394,8 +9410,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
110         {
111           Elf_Internal_Rela *internal_relocs;
112           Elf_Internal_Rela *rel, *relend;
113 -         bfd_vma r_type_mask;
114 -         int r_sym_shift;
115           int action_discarded;
116           int ret;
117  
118 @@ -9407,15 +9421,27 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
119               && o->reloc_count > 0)
120             return FALSE;
121  
122 -         if (bed->s->arch_size == 32)
123 +         /* We need to reverse-copy input .ctors/.dtors sections if
124 +            they are placed in .init_array/.finit_array for output.  */
125 +         if (o->size > address_size
126 +             && ((strncmp (o->name, ".ctors", 6) == 0
127 +                  && strcmp (o->output_section->name,
128 +                             ".init_array") == 0)
129 +                 || (strncmp (o->name, ".dtors", 6) == 0
130 +                     && strcmp (o->output_section->name,
131 +                                ".fini_array") == 0))
132 +             && (o->name[6] == 0 || o->name[6] == '.'))
133             {
134 -             r_type_mask = 0xff;
135 -             r_sym_shift = 8;
136 -           }
137 -         else
138 -           {
139 -             r_type_mask = 0xffffffff;
140 -             r_sym_shift = 32;
141 +             if (o->size != o->reloc_count * address_size)
142 +               {
143 +                 (*_bfd_error_handler)
144 +                   (_("error: %B: size of section %A is not "
145 +                      "multiple of address size"),
146 +                    input_bfd, o);
147 +                 bfd_set_error (bfd_error_on_input);
148 +                 return FALSE;
149 +               }
150 +             o->flags |= SEC_ELF_REVERSE_COPY;
151             }
152  
153           action_discarded = -1;
154 @@ -9876,12 +9902,34 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
155         default:
156           {
157             /* FIXME: octets_per_byte.  */
158 -           if (! (o->flags & SEC_EXCLUDE)
159 -               && ! bfd_set_section_contents (output_bfd, o->output_section,
160 -                                              contents,
161 -                                              (file_ptr) o->output_offset,
162 -                                              o->size))
163 -             return FALSE;
164 +           if (! (o->flags & SEC_EXCLUDE))
165 +             {
166 +               file_ptr offset = (file_ptr) o->output_offset;
167 +               bfd_size_type todo = o->size;
168 +               if ((o->flags & SEC_ELF_REVERSE_COPY))
169 +                 {
170 +                   /* Reverse-copy input section to output.  */
171 +                   do
172 +                     {
173 +                       todo -= address_size;
174 +                       if (! bfd_set_section_contents (output_bfd,
175 +                                                       o->output_section,
176 +                                                       contents + todo,
177 +                                                       offset,
178 +                                                       address_size))
179 +                         return FALSE;
180 +                       if (todo == 0)
181 +                         break;
182 +                       offset += address_size;
183 +                     }
184 +                   while (1);
185 +                 }
186 +               else if (! bfd_set_section_contents (output_bfd,
187 +                                                    o->output_section,
188 +                                                    contents,
189 +                                                    offset, todo))
190 +                 return FALSE;
191 +             }
192           }
193           break;
194         }
195 diff --git a/bfd/section.c b/bfd/section.c
196 index 65ac5e6..3cd7e65 100644
197 --- a/bfd/section.c
198 +++ b/bfd/section.c
199 @@ -327,6 +327,11 @@ CODE_FRAGMENT
200  .     sections.  *}
201  .#define SEC_COFF_SHARED_LIBRARY 0x4000000
202  .
203 +.  {* This input section should be copied to output in reverse order
204 +.     as an array of pointers.  This is for ELF linker internal use
205 +.     only.  *}
206 +.#define SEC_ELF_REVERSE_COPY 0x4000000
207 +.
208  .  {* This section contains data which may be shared with other
209  .     executables or shared objects. This is for COFF only.  *}
210  .#define SEC_COFF_SHARED 0x8000000
211 diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
212 index 73a417c..6808d8a 100644
213 --- a/ld/testsuite/ld-elf/elf.exp
214 +++ b/ld/testsuite/ld-elf/elf.exp
215 @@ -81,17 +81,32 @@ set array_tests {
216      {"init array" "" "" {init.c} "init" "init.out"}
217      {"fini array" "" "" {fini.c} "fini" "fini.out"}
218      {"init array mixed" "" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."}
219 +    {"pr12730" "" "" {pr12730.cc} "pr12730" "pr12730.out" "" "c++"}
220 +}
221 +set array_tests_pie {
222 +    {"PIE preinit array" "-pie" "" {preinit.c} "preinit" "preinit.out" "-fPIE" }
223 +    {"PIE init array" "-pie" "" {init.c} "init" "init.out" "-fPIE"}
224 +    {"PIE fini array" "-pie" "" {fini.c} "fini" "fini.out" "-fPIE"}
225 +    {"PIE init array mixed" "-pie" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I. -fPIE"}
226 +    {"PIE pr12730" "-pie" "" {pr12730.cc} "pr12730" "pr12730.out" "-fPIE" "c++"}
227  }
228  set array_tests_static {
229      {"static preinit array" "-static" "" {preinit.c} "preinit" "preinit.out"}
230      {"static init array" "-static" "" {init.c} "init" "init.out"}
231      {"static fini array" "-static" "" {fini.c} "fini" "fini.out"}
232 -    {"static init array mixed" "" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."}
233 +    {"static init array mixed" "-static" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."}
234 +    {"static pr12730" "-static" "" {pr12730.cc} "pr12730" "pr12730.out" "" "c++"}
235  }
236  
237  # NetBSD ELF systems do not currently support the .*_array sections.
238  set xfails [list "*-*-netbsdelf*"]
239  run_ld_link_exec_tests $xfails $array_tests
240 +
241 +# Run PIE tests only on Linux.
242 +if { [istarget "*-*-linux*"] } {
243 +    run_ld_link_exec_tests $xfails $array_tests_pie
244 +}
245 +
246  # Be cautious to not XFAIL for *-*-linux-gnu*, *-*-kfreebsd-gnu*, etc.
247  switch -regexp $target_triplet {
248      ^\[^-\]*-\[^-\]*-gnu.*$ {
249 diff --git a/ld/testsuite/ld-elf/init-mixed.c b/ld/testsuite/ld-elf/init-mixed.c
250 index 1d0c727..770a4b5 100644
251 --- a/ld/testsuite/ld-elf/init-mixed.c
252 +++ b/ld/testsuite/ld-elf/init-mixed.c
253 @@ -27,25 +27,39 @@ void (*const fini_array1005[]) ()
254    = { fini1005 };
255  
256  static void
257 -ctor1007 ()
258 +ctor1007a ()
259  {
260    if (count != 1005)
261      abort ();
262 +  count = 1006;
263 +}
264 +static void
265 +ctor1007b ()
266 +{
267 +  if (count != 1006)
268 +    abort ();
269    count = 1007;
270  }
271  void (*const ctors1007[]) ()
272    __attribute__ ((section (".ctors.64528"), aligned (sizeof (void *))))
273 -  = { ctor1007 };
274 +  = { ctor1007b, ctor1007a };
275  static void
276 -dtor1007 ()
277 +dtor1007a ()
278  {
279 -  if (count != 1007)
280 +  if (count != 1006)
281      abort ();
282    count = 1005;
283  }
284 +static void
285 +dtor1007b ()
286 +{
287 +  if (count != 1007)
288 +    abort ();
289 +  count = 1006;
290 +}
291  void (*const dtors1007[]) ()
292    __attribute__ ((section (".dtors.64528"), aligned (sizeof (void *))))
293 -  = { dtor1007 };
294 +  = { dtor1007b, dtor1007a };
295  
296  static void
297  init65530 ()
298 @@ -69,17 +83,31 @@ void (*const fini_array65530[]) ()
299    = { fini65530 };
300  
301  static void
302 -ctor65535 ()
303 +ctor65535a ()
304  {
305    if (count != 65530)
306      abort ();
307    count = 65535;
308  }
309 +static void
310 +ctor65535b ()
311 +{
312 +  if (count != 65535)
313 +    abort ();
314 +  count = 65536;
315 +}
316  void (*const ctors65535[]) ()
317    __attribute__ ((section (".ctors"), aligned (sizeof (void *))))
318 -  = { ctor65535 };
319 +  = { ctor65535b, ctor65535a };
320 +static void
321 +dtor65535b ()
322 +{
323 +  if (count != 65536)
324 +    abort ();
325 +  count = 65535;
326 +}
327  static void
328 -dtor65535 ()
329 +dtor65535a ()
330  {
331    if (count != 65535)
332      abort ();
333 @@ -87,7 +115,7 @@ dtor65535 ()
334  }
335  void (*const dtors65535[]) ()
336    __attribute__ ((section (".dtors"), aligned (sizeof (void *))))
337 -  = { dtor65535 };
338 +  = { dtor65535b, dtor65535a };
339  #endif
340  
341  int
342 diff --git a/ld/testsuite/ld-elf/pr12730.cc b/ld/testsuite/ld-elf/pr12730.cc
343 new file mode 100644
344 index 0000000..69f57f9
345 --- /dev/null
346 +++ b/ld/testsuite/ld-elf/pr12730.cc
347 @@ -0,0 +1,38 @@
348 +#include <iostream>
349 +
350 +class Hello
351 +{
352 +public:
353 +   Hello ()
354 +    {}
355 +
356 +  ~Hello ()
357 +    {}
358 +
359 +  void act ()
360 +    { std::cout << "Hello, world!" << std::endl; }
361 +};
362 +
363 +
364 +template <class T>
365 +struct Foo
366 +{
367 +  T* _M_allocate_single_object ()
368 +    {
369 +      return new T;
370 +    }
371 +};
372 +
373 +static void __attribute__ (( constructor )) PWLIB_StaticLoader() {
374 +  Foo<Hello> allocator;
375 +  Hello* salut = allocator._M_allocate_single_object ();
376 +  salut->act ();
377 +}
378 +
379 +
380 +int
381 +main (int /*argc*/,
382 +      char* /*argv*/[])
383 +{
384 +  return 0;
385 +}
386 diff --git a/ld/testsuite/ld-elf/pr12730.out b/ld/testsuite/ld-elf/pr12730.out
387 new file mode 100644
388 index 0000000..af5626b
389 --- /dev/null
390 +++ b/ld/testsuite/ld-elf/pr12730.out
391 @@ -0,0 +1 @@
392 +Hello, world!