* elf-bfd.h (enum elf_link_info_type): New.
[platform/upstream/binutils.git] / bfd / elf-eh-frame.c
1 /* .eh_frame section optimization.
2    Copyright 2001 Free Software Foundation, Inc.
3    Written by Jakub Jelinek <jakub@redhat.com>.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25 #include "elf/dwarf2.h"
26
27 #define EH_FRAME_HDR_SIZE 8
28
29 struct cie_header
30 {
31   unsigned int length;
32   unsigned int id;
33 };
34
35 struct cie
36 {
37   struct cie_header hdr;
38   unsigned char version;
39   unsigned char augmentation[20];
40   unsigned int code_align;
41   int data_align;
42   unsigned int ra_column;
43   unsigned int augmentation_size;
44   struct elf_link_hash_entry *personality;
45   unsigned char per_encoding;
46   unsigned char lsda_encoding;
47   unsigned char fde_encoding;
48   unsigned char initial_insn_length;
49   unsigned char make_relative;
50   unsigned char initial_instructions[50];
51 };
52
53 struct eh_cie_fde
54 {
55   unsigned int offset;
56   unsigned int size;
57   asection *sec;
58   unsigned int new_offset;
59   unsigned char fde_encoding;
60   unsigned char cie : 1;
61   unsigned char removed : 1;
62   unsigned char make_relative : 1;
63 };
64
65 struct eh_frame_sec_info
66 {
67   unsigned int count;
68   unsigned int alloced;
69   struct eh_cie_fde entry[1];
70 };
71
72 struct eh_frame_array_ent
73 {
74   bfd_vma initial_loc;
75   bfd_vma fde;
76 };
77
78 struct eh_frame_hdr_info
79 {
80   struct cie last_cie;
81   asection *last_cie_sec;
82   unsigned int last_cie_offset;
83   unsigned int fde_count, array_count;
84   struct eh_frame_array_ent *array;
85   /* TRUE if .eh_frame_hdr should contain the sorted search table.
86      We build it if we successfully read all .eh_frame input sections
87      and recognize them.  */
88   boolean table;
89 };
90
91 static bfd_vma read_unsigned_leb128
92   PARAMS ((bfd *, char *, unsigned int *));
93 static bfd_signed_vma read_signed_leb128
94   PARAMS ((bfd *, char *, unsigned int *));
95 static int get_DW_EH_PE_width
96   PARAMS ((int, int));
97 static int cie_compare
98   PARAMS ((struct cie *, struct cie *));
99 static int vma_compare
100   PARAMS ((const PTR a, const PTR b));
101
102 /* Helper function for reading uleb128 encoded data.  */
103
104 static bfd_vma
105 read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
106      bfd *abfd ATTRIBUTE_UNUSED;
107      char *buf;
108      unsigned int *bytes_read_ptr;
109 {
110   bfd_vma  result;
111   unsigned int  num_read;
112   int           shift;
113   unsigned char byte;
114
115   result   = 0;
116   shift    = 0;
117   num_read = 0;
118   do
119     {
120       byte = bfd_get_8 (abfd, (bfd_byte *) buf);
121       buf ++;
122       num_read ++;
123       result |= (((bfd_vma) byte & 0x7f) << shift);
124       shift += 7;
125     }
126   while (byte & 0x80);
127   * bytes_read_ptr = num_read;
128   return result;
129 }
130
131 /* Helper function for reading sleb128 encoded data.  */
132
133 static bfd_signed_vma
134 read_signed_leb128 (abfd, buf, bytes_read_ptr)
135      bfd *abfd ATTRIBUTE_UNUSED;
136      char *buf;
137      unsigned int * bytes_read_ptr;
138 {
139   bfd_vma       result;
140   int           shift;
141   int           num_read;
142   unsigned char byte;
143
144   result = 0;
145   shift = 0;
146   num_read = 0;
147   do
148     {
149       byte = bfd_get_8 (abfd, (bfd_byte *) buf);
150       buf ++;
151       num_read ++;
152       result |= (((bfd_vma) byte & 0x7f) << shift);
153       shift += 7;
154     }
155   while (byte & 0x80);
156   if (byte & 0x40)
157     result |= (((bfd_vma) -1) << (shift - 7)) << 7;
158   * bytes_read_ptr = num_read;
159   return result;
160 }
161
162 #define read_uleb128(VAR, BUF)                                  \
163 do                                                              \
164   {                                                             \
165     (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp);      \
166     (BUF) += leb128_tmp;                                        \
167   }                                                             \
168 while (0)
169
170 #define read_sleb128(VAR, BUF)                                  \
171 do                                                              \
172   {                                                             \
173     (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp);        \
174     (BUF) += leb128_tmp;                                        \
175   }                                                             \
176 while (0)
177
178 /* Return 0 if either encoding is variable width, or not yet known to bfd.  */
179
180 static
181 int get_DW_EH_PE_width (encoding, ptr_size)
182      int encoding, ptr_size;
183 {
184   /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
185      was added to bfd.  */
186   if ((encoding & 0x60) == 0x60)
187     return 0;
188
189   switch (encoding & 7)
190     {
191     case DW_EH_PE_udata2: return 2;
192     case DW_EH_PE_udata4: return 4;
193     case DW_EH_PE_udata8: return 8;
194     case DW_EH_PE_absptr: return ptr_size;
195     default:
196       break;
197     }
198
199   return 0;
200 }
201
202 /* Return zero if C1 and C2 CIEs can be merged.  */
203
204 static
205 int cie_compare (c1, c2)
206      struct cie *c1, *c2;
207 {
208   if (c1->hdr.length == c2->hdr.length
209       && c1->version == c2->version
210       && strcmp (c1->augmentation, c2->augmentation) == 0
211       && strcmp (c1->augmentation, "eh") != 0
212       && c1->code_align == c2->code_align
213       && c1->data_align == c2->data_align
214       && c1->ra_column == c2->ra_column
215       && c1->augmentation_size == c2->augmentation_size
216       && c1->personality == c2->personality
217       && c1->per_encoding == c2->per_encoding
218       && c1->lsda_encoding == c2->lsda_encoding
219       && c1->fde_encoding == c2->fde_encoding
220       && (c1->initial_insn_length
221           == c2->initial_insn_length)
222       && memcmp (c1->initial_instructions,
223                  c2->initial_instructions,
224                  c1->initial_insn_length) == 0)
225     return 0;
226
227   return 1;
228 }
229
230 /* This function is called for each input file before the .eh_frame
231    section is relocated.  It discards duplicate CIEs and FDEs for discarded
232    functions.  The function returns true iff any entries have been
233    deleted.  */
234
235 boolean
236 _bfd_elf_discard_section_eh_frame (abfd, info, sec, ehdrsec,
237                                    reloc_symbol_deleted_p, cookie)
238      bfd *abfd;
239      struct bfd_link_info *info;
240      asection *sec, *ehdrsec;
241      boolean (*reloc_symbol_deleted_p) (bfd_vma, PTR);
242      struct elf_reloc_cookie *cookie;
243 {
244   bfd_byte *ehbuf = NULL, *buf;
245   bfd_byte *last_cie, *last_fde;
246   struct cie_header hdr;
247   struct cie cie;
248   struct eh_frame_hdr_info *hdr_info;
249   struct eh_frame_sec_info *sec_info;
250   unsigned int leb128_tmp;
251   unsigned int cie_usage_count, last_cie_ndx, i, offset, make_relative;
252   Elf_Internal_Rela *rel;
253   bfd_size_type new_size;
254   unsigned int ptr_size;
255
256   if (sec->_raw_size == 0)
257     {
258       /* This file does not contain .eh_frame information.  */
259       return false;
260     }
261
262   if ((sec->output_section != NULL
263        && bfd_is_abs_section (sec->output_section)))
264     {
265       /* At least one of the sections is being discarded from the
266          link, so we should just ignore them.  */
267       return false;
268     }
269
270   /* Read the frame unwind information from abfd.  */
271
272   ehbuf = (bfd_byte *) bfd_malloc (sec->_raw_size);
273   if (ehbuf == NULL
274       || ! bfd_get_section_contents (abfd, sec, ehbuf, (bfd_vma) 0,
275                                      sec->_raw_size))
276     {
277       if (elf_section_data (ehdrsec)->sec_info_type
278           != ELF_INFO_TYPE_EH_FRAME_HDR)
279         {
280           elf_section_data (ehdrsec)->sec_info
281             = bfd_zmalloc (sizeof (struct eh_frame_hdr_info));
282           elf_section_data (ehdrsec)->sec_info_type
283             = ELF_INFO_TYPE_EH_FRAME_HDR;
284         }
285       return false;
286     }
287
288   if (sec->_raw_size >= 4
289       && bfd_get_32 (abfd, ehbuf) == 0
290       && cookie->rel == cookie->relend)
291     {
292       /* Empty .eh_frame section.  */
293       free (ehbuf);
294       return false;
295     }
296
297   if (elf_section_data (ehdrsec)->sec_info_type
298       != ELF_INFO_TYPE_EH_FRAME_HDR)
299     {
300       hdr_info = (struct eh_frame_hdr_info *)      
301                  bfd_zmalloc (sizeof (struct eh_frame_hdr_info));
302       hdr_info->table = true;
303       elf_section_data (ehdrsec)->sec_info = hdr_info;
304       elf_section_data (ehdrsec)->sec_info_type
305         = ELF_INFO_TYPE_EH_FRAME_HDR;
306     }
307   else
308     hdr_info = (struct eh_frame_hdr_info *)
309                elf_section_data (ehdrsec)->sec_info;
310
311   /* If .eh_frame section size doesn't fit into int, we cannot handle
312      it (it would need to use 64-bit .eh_frame format anyway).  */
313   if (sec->_raw_size != (unsigned int) sec->_raw_size)
314     return false;
315
316   ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
317               == ELFCLASS64) ? 8 : 4;
318   buf = ehbuf;
319   last_cie = NULL;
320   last_cie_ndx = 0;
321   memset (&cie, 0, sizeof (cie));
322   cie_usage_count = 0;
323   new_size = sec->_raw_size;
324   make_relative = hdr_info->last_cie.make_relative;
325   sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)
326                           + 99 * sizeof (struct eh_cie_fde));
327   if (sec_info == NULL)
328     goto free_no_table;
329   sec_info->alloced = 100;
330
331 #define ENSURE_NO_RELOCS(buf)                           \
332   if (cookie->rel < cookie->relend                      \
333       && (cookie->rel->r_offset                         \
334           < (bfd_size_type) ((buf) - ehbuf)))           \
335     goto free_no_table
336
337 #define SKIP_RELOCS(buf)                                \
338   while (cookie->rel < cookie->relend                   \
339          && (cookie->rel->r_offset                      \
340              < (bfd_size_type) ((buf) - ehbuf)))        \
341     cookie->rel++
342
343 #define GET_RELOC(buf)                                  \
344   ((cookie->rel < cookie->relend                        \
345     && (cookie->rel->r_offset                           \
346         == (bfd_size_type) ((buf) - ehbuf)))            \
347    ? cookie->rel : NULL)
348
349   for (;;)
350     {
351       unsigned char *aug;
352
353       if (sec_info->count == sec_info->alloced)
354         {
355           sec_info = bfd_realloc (sec_info,
356                                   sizeof (struct eh_frame_sec_info)
357                                   + (sec_info->alloced + 99)
358                                      * sizeof (struct eh_cie_fde));
359           if (sec_info == NULL)
360             goto free_no_table;
361
362           memset (&sec_info->entry[sec_info->alloced], 0,
363                   100 * sizeof (struct eh_cie_fde));
364           sec_info->alloced += 100;
365         }
366
367       last_fde = buf;
368       /* If we are at the end of the section, we still need to decide
369          on whether to output or discard last encountered CIE (if any).  */
370       if ((bfd_size_type) (buf - ehbuf) == sec->_raw_size)
371         hdr.id = (unsigned int) -1;
372       else
373         {
374           if ((bfd_size_type) (buf + 4 - ehbuf) > sec->_raw_size)
375             /* No space for CIE/FDE header length.  */
376             goto free_no_table;
377
378           hdr.length = bfd_get_32 (abfd, buf);
379           if (hdr.length == 0xffffffff)
380             /* 64-bit .eh_frame is not supported.  */
381             goto free_no_table;
382           buf += 4;
383           if ((buf - ehbuf) + hdr.length > sec->_raw_size)
384             /* CIE/FDE not contained fully in this .eh_frame input section.  */
385             goto free_no_table;
386
387           sec_info->entry[sec_info->count].offset = last_fde - ehbuf;
388           sec_info->entry[sec_info->count].size = 4 + hdr.length;
389
390           if (hdr.length == 0)
391             {
392               /* CIE with length 0 must be only the last in the section.  */
393               if ((bfd_size_type) (buf - ehbuf) < sec->_raw_size)
394                 goto free_no_table;
395               ENSURE_NO_RELOCS (buf);
396               sec_info->count++;
397               /* Now just finish last encountered CIE processing and break
398                  the loop.  */
399               hdr.id = (unsigned int) -1;
400             }
401           else
402             {
403               hdr.id = bfd_get_32 (abfd, buf);
404               buf += 4;
405               if (hdr.id == (unsigned int) -1)
406                 goto free_no_table;
407             }
408         }
409
410       if (hdr.id == 0 || hdr.id == (unsigned int) -1)
411         {
412           unsigned int initial_insn_length;
413
414           /* CIE  */
415           if (last_cie != NULL)
416             {
417               /* Now check if this CIE is identical to last CIE, in which case
418                  we can remove it, provided we adjust all FDEs.
419                  Also, it can be removed if we have removed all FDEs using
420                  that. */
421               if (cie_compare (&cie, &hdr_info->last_cie) == 0
422                   || cie_usage_count == 0)
423                 {
424                   new_size -= cie.hdr.length + 4;
425                   sec_info->entry[last_cie_ndx].removed = 1;
426                   sec_info->entry[last_cie_ndx].sec = hdr_info->last_cie_sec;
427                   sec_info->entry[last_cie_ndx].new_offset
428                     = hdr_info->last_cie_offset;
429                 }
430               else
431                 {
432                   hdr_info->last_cie = cie;
433                   hdr_info->last_cie_sec = sec;
434                   hdr_info->last_cie_offset = last_cie - ehbuf;
435                   sec_info->entry[last_cie_ndx].make_relative
436                     = cie.make_relative;
437                 }
438             }
439
440           if (hdr.id == (unsigned int) -1)
441             break;
442
443           last_cie_ndx = sec_info->count;
444           sec_info->entry[sec_info->count].cie = 1;
445
446           cie_usage_count = 0;
447           memset (&cie, 0, sizeof (cie));
448           cie.hdr = hdr;
449           cie.version = *buf++;
450
451           /* Cannot handle unknown versions.  */
452           if (cie.version != 1)
453             goto free_no_table;
454           if (strlen (buf) > sizeof (cie.augmentation) - 1)
455             goto free_no_table;
456
457           strcpy (cie.augmentation, buf);
458           buf = strchr (buf, '\0') + 1;
459           ENSURE_NO_RELOCS (buf);
460           if (buf[0] == 'e' && buf[1] == 'h')
461             {
462               /* GCC < 3.0 .eh_frame CIE */
463               /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
464                  is private to each CIE, so we don't need it for anything.
465                  Just skip it.  */
466               buf += ptr_size;
467               SKIP_RELOCS (buf);
468             }
469           read_uleb128 (cie.code_align, buf);
470           read_sleb128 (cie.data_align, buf);
471           read_uleb128 (cie.ra_column, buf);
472           ENSURE_NO_RELOCS (buf);
473           cie.lsda_encoding = DW_EH_PE_omit;
474           cie.fde_encoding = DW_EH_PE_omit;
475           cie.per_encoding = DW_EH_PE_omit;
476           aug = cie.augmentation;
477           if (aug[0] != 'e' || aug[1] != 'h')
478             {
479               if (*aug == 'z')
480                 {
481                   aug++;
482                   read_uleb128 (cie.augmentation_size, buf);
483                   ENSURE_NO_RELOCS (buf);
484                 }
485
486               while (*aug != '\0')
487                 switch (*aug++)
488                   {
489                   case 'L':
490                     cie.lsda_encoding = *buf++;
491                     ENSURE_NO_RELOCS (buf);
492                     if (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size) == 0)
493                       goto free_no_table;
494                     break;
495                   case 'R':
496                     cie.fde_encoding = *buf++;
497                     ENSURE_NO_RELOCS (buf);
498                     if (get_DW_EH_PE_width (cie.fde_encoding, ptr_size) == 0)
499                       goto free_no_table;
500                     break;
501                   case 'P':
502                     {
503                       int per_width;
504
505                       cie.per_encoding = *buf++;
506                       per_width = get_DW_EH_PE_width (cie.per_encoding,
507                                                       ptr_size);
508                       if (per_width == 0)
509                         goto free_no_table;
510                       if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
511                         buf = (ehbuf
512                                + ((buf - ehbuf + per_width - 1)
513                                   & ~((bfd_size_type) per_width - 1)));
514                       ENSURE_NO_RELOCS (buf);
515                       rel = GET_RELOC (buf);
516                       /* Ensure we have a reloc here, against
517                          a global symbol.  */
518                       if (rel != NULL)
519                         {
520                           unsigned long r_symndx;
521
522 #ifdef BFD64
523                           if (ptr_size == 8)
524                             r_symndx = ELF64_R_SYM (cookie->rel->r_info);
525                           else
526 #endif
527                             r_symndx = ELF32_R_SYM (cookie->rel->r_info);
528                           if (r_symndx >= cookie->locsymcount)
529                             {
530                               struct elf_link_hash_entry *h;
531
532                               r_symndx -= cookie->extsymoff;
533                               h = cookie->sym_hashes[r_symndx];
534
535                               while (h->root.type == bfd_link_hash_indirect
536                                      || h->root.type == bfd_link_hash_warning)
537                                 h = (struct elf_link_hash_entry *)
538                                     h->root.u.i.link;
539
540                               cie.personality = h;
541                             }
542                           cookie->rel++;
543                         }
544                       buf += per_width;
545                     }
546                     break;
547                   default:
548                     /* Unrecognized augmentation. Better bail out.  */
549                     goto free_no_table;
550                   }
551             }
552
553           /* For shared libraries, try to get rid of as many RELATIVE relocs
554              as possible.
555              FIXME: For this to work, ELF backends need to perform the
556              relocation if omitting dynamic relocs, not skip it.  */
557           if (0
558               && info->shared
559               && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
560             cie.make_relative = 1;
561
562           /* If FDE encoding was not specified, it defaults to
563              DW_EH_absptr.  */
564           if (cie.fde_encoding == DW_EH_PE_omit)
565             cie.fde_encoding = DW_EH_PE_absptr;
566
567           initial_insn_length = cie.hdr.length - (buf - last_fde - 4);
568           if (initial_insn_length <= 50)
569             {
570               cie.initial_insn_length = initial_insn_length;
571               memcpy (cie.initial_instructions, buf, initial_insn_length);
572             }
573           buf += initial_insn_length;
574           ENSURE_NO_RELOCS (buf);
575           last_cie = last_fde;
576         }
577       else
578         {
579           /* Ensure this FDE uses the last CIE encountered.  */
580           if (last_cie == NULL
581               || hdr.id != (unsigned int) (buf - 4 - last_cie))
582             goto free_no_table;
583
584           ENSURE_NO_RELOCS (buf);
585           rel = GET_RELOC (buf);
586           if (rel == NULL)
587             /* This should not happen.  */
588             goto free_no_table;
589           if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
590             {
591               cookie->rel = rel;
592               /* This is a FDE against discarded section, it should
593                  be deleted.  */
594               new_size -= hdr.length + 4;
595               sec_info->entry[sec_info->count].removed = 1;
596             }
597           else
598             {
599               cie_usage_count++;
600               hdr_info->fde_count++;
601             }
602           cookie->rel = rel;
603           buf = last_fde + 4 + hdr.length;
604           SKIP_RELOCS (buf);
605         }
606
607       sec_info->entry[sec_info->count].fde_encoding = cie.fde_encoding;
608       sec_info->count++;
609     }
610
611   elf_section_data (sec)->sec_info = sec_info;
612   elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
613
614   /* Ok, now we can assign new offsets.  */
615   offset = 0;
616   last_cie_ndx = 0;
617   for (i = 0; i < sec_info->count; i++)
618     {
619       if (! sec_info->entry[i].removed)
620         {
621           sec_info->entry[i].new_offset = offset;
622           offset += sec_info->entry[i].size;
623           if (sec_info->entry[i].cie)
624             {
625               last_cie_ndx = i;
626               make_relative = sec_info->entry[i].make_relative;
627             }
628           else
629             sec_info->entry[i].make_relative = make_relative;
630         }
631       else if (sec_info->entry[i].cie && sec_info->entry[i].sec == sec)
632         {
633           /* Need to adjust new_offset too.  */
634           BFD_ASSERT (sec_info->entry[last_cie_ndx].offset
635                       == sec_info->entry[i].new_offset);
636           sec_info->entry[i].new_offset
637             = sec_info->entry[last_cie_ndx].new_offset;
638         }
639     }
640   if (hdr_info->last_cie_sec == sec)
641     {
642       BFD_ASSERT (sec_info->entry[last_cie_ndx].offset
643                   == hdr_info->last_cie_offset);
644       hdr_info->last_cie_offset = sec_info->entry[last_cie_ndx].new_offset;
645     }
646
647   /* Shrink the sec as needed.  */
648   
649   sec->_cooked_size = new_size;
650   if (sec->_cooked_size == 0)
651     sec->flags |= SEC_EXCLUDE;
652
653   return new_size != sec->_raw_size;
654
655 free_no_table:
656   if (sec_info)
657     free (sec_info);
658   hdr_info->table = false;
659   hdr_info->last_cie.hdr.length = 0;
660   return false;
661 }
662
663 /* This function is called for .eh_frame_hdr section after
664    _bfd_elf_discard_section_eh_frame has been called on all .eh_frame
665    input sections.  It finalizes the size of .eh_frame_hdr section.  */
666
667 boolean
668 _bfd_elf_discard_section_eh_frame_hdr (abfd, info, sec)
669      bfd *abfd;
670      struct bfd_link_info *info;
671      asection *sec;
672 {
673   struct eh_frame_hdr_info *hdr_info;
674   unsigned int ptr_size;
675
676   ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
677               == ELFCLASS64) ? 8 : 4;
678
679   if ((elf_section_data (sec)->sec_info_type
680        != ELF_INFO_TYPE_EH_FRAME_HDR)
681       || ! info->eh_frame_hdr)
682     {
683       _bfd_strip_section_from_output (info, sec);
684       return false;
685     }
686
687   hdr_info = (struct eh_frame_hdr_info *)
688              elf_section_data (sec)->sec_info;
689   sec->_cooked_size = EH_FRAME_HDR_SIZE;
690   if (hdr_info->table)
691     sec->_cooked_size += 4 + hdr_info->fde_count * 8;
692
693   /* Request program headers to be recalculated.  */
694   elf_tdata (abfd)->program_header_size = 0;
695   elf_tdata (abfd)->eh_frame_hdr = true;
696   return true;
697 }
698
699 /* Adjust an address in the .eh_frame section.  Given OFFSET within
700    SEC, this returns the new offset in the adjusted .eh_frame section,
701    or -1 if the address refers to a CIE/FDE which has been removed
702    or to offset with dynamic relocation which is no longer needed.  */
703
704 bfd_vma
705 _bfd_elf_eh_frame_section_offset (output_bfd, sec, offset)
706      bfd *output_bfd ATTRIBUTE_UNUSED;
707      asection *sec;
708      bfd_vma offset;
709 {
710   struct eh_frame_sec_info *sec_info;
711   unsigned int lo, hi, mid;
712
713   if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
714     return offset;
715   sec_info = (struct eh_frame_sec_info *)
716              elf_section_data (sec)->sec_info;
717
718   if (offset >= sec->_raw_size)
719     return offset - (sec->_cooked_size - sec->_raw_size);
720
721   lo = 0;
722   hi = sec_info->count;
723   mid = 0;
724   while (lo < hi)
725     {
726       mid = (lo + hi) / 2;
727       if (offset < sec_info->entry[mid].offset)
728         hi = mid;
729       else if (offset
730                >= sec_info->entry[mid].offset + sec_info->entry[mid].size)
731         lo = mid + 1;
732       else
733         break;
734     }
735
736   BFD_ASSERT (lo < hi);
737
738   /* FDE or CIE was removed.  */
739   if (sec_info->entry[mid].removed)
740     return (bfd_vma) -1;
741
742   /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
743      relocation against FDE's initial_location field.  */
744   if (sec_info->entry[mid].make_relative
745       && ! sec_info->entry[mid].cie
746       && offset == sec_info->entry[mid].offset + 8)
747     return (bfd_vma) -1;
748
749   return (offset
750           + (sec_info->entry[mid].new_offset - sec_info->entry[mid].offset));
751 }
752
753 /* Write out .eh_frame section.  This is called with the relocated
754    contents.  */
755
756 boolean
757 _bfd_elf_write_section_eh_frame (abfd, sec, ehdrsec, contents)
758      bfd *abfd;
759      asection *sec, *ehdrsec;
760      bfd_byte *contents;
761 {
762   struct eh_frame_sec_info *sec_info;
763   struct eh_frame_hdr_info *hdr_info;
764   unsigned int i;
765   bfd_byte *p, *buf;
766   unsigned int leb128_tmp;
767   unsigned int cie_offset = 0;
768   unsigned int ptr_size;
769
770   ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
771               == ELFCLASS64) ? 8 : 4;
772
773   if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
774     return bfd_set_section_contents (abfd, sec->output_section,
775                                      contents,
776                                      (file_ptr) sec->output_offset,
777                                      sec->_raw_size);
778   sec_info = (struct eh_frame_sec_info *)
779              elf_section_data (sec)->sec_info;
780   hdr_info = NULL;
781   if (ehdrsec
782       && (elf_section_data (ehdrsec)->sec_info_type
783           == ELF_INFO_TYPE_EH_FRAME_HDR))
784     {
785       hdr_info = (struct eh_frame_hdr_info *)
786                  elf_section_data (ehdrsec)->sec_info;
787       if (hdr_info->table && hdr_info->array == NULL)
788         hdr_info->array
789           = bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
790       if (hdr_info->array == NULL)
791         hdr_info = NULL;
792     }
793
794   p = contents;
795   for (i = 0; i < sec_info->count; ++i)
796     {
797       if (sec_info->entry[i].removed)
798         {
799           if (sec_info->entry[i].cie)
800             {
801               cie_offset = sec_info->entry[i].new_offset;
802               cie_offset += (sec_info->entry[i].sec->output_section->vma
803                              + sec_info->entry[i].sec->output_offset
804                              - sec->output_section->vma
805                              - sec->output_offset);
806             }
807           continue;
808         }
809       if (sec_info->entry[i].cie)
810         {
811           /* CIE */
812           cie_offset = sec_info->entry[i].new_offset;
813           if (sec_info->entry[i].make_relative)
814             {
815               unsigned char *aug;
816               unsigned int dummy, per_width, per_encoding;
817
818               /* Need to find 'R' augmentation's argument and modify
819                  DW_EH_PE_* value.  */
820               buf = contents + sec_info->entry[i].offset;
821               /* Skip length, id and version.  */
822               buf += 9;
823               aug = buf;
824               buf = strchr (buf, '\0') + 1;
825               read_uleb128 (dummy, buf);
826               read_sleb128 (dummy, buf);
827               read_uleb128 (dummy, buf);
828               if (*aug == 'z')
829                 {
830                   read_uleb128 (dummy, buf);
831                   aug++;
832                 }
833
834               while (*aug != 'R')
835                 switch (*aug++)
836                   {
837                   case 'L':
838                     buf++;
839                     break;
840                   case 'P':
841                     per_encoding = *buf++;
842                     per_width = get_DW_EH_PE_width (per_encoding,
843                                                     ptr_size);
844                     BFD_ASSERT (per_width != 0);
845                     if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
846                       buf = (contents
847                              + ((buf - contents + per_width - 1)
848                                 & ~((bfd_size_type) per_width - 1)));
849                     buf += per_width;
850                     break;
851                   default:
852                     BFD_FAIL ();
853                   }
854
855               BFD_ASSERT (*buf == sec_info->entry[i].fde_encoding);
856               *buf |= DW_EH_PE_pcrel;
857             }
858         }
859       else
860         {
861           /* FDE */
862           bfd_vma value = 0, address;
863           unsigned int fde_width;
864
865           buf = contents + sec_info->entry[i].offset;
866           /* Skip length.  */   
867           buf += 4;
868           bfd_put_32 (abfd,
869                       sec_info->entry[i].new_offset + 4 - cie_offset, buf);
870           buf += 4;
871           fde_width = get_DW_EH_PE_width (sec_info->entry[i].fde_encoding,
872                                           ptr_size);
873           switch (fde_width)
874             {
875             case 2: value = bfd_get_16 (abfd, buf); break;
876             case 4: value = bfd_get_32 (abfd, buf); break;
877             case 8: value = bfd_get_64 (abfd, buf); break;
878             default: BFD_FAIL ();
879             }
880           address = value;
881           switch (sec_info->entry[i].fde_encoding & 0xf0)
882             {
883             case DW_EH_PE_indirect:
884             case DW_EH_PE_textrel:
885               BFD_ASSERT (hdr_info == NULL);
886               break;
887             case DW_EH_PE_datarel:
888               {
889                 asection *got = bfd_get_section_by_name (abfd, ".got");
890
891                 BFD_ASSERT (got != NULL);
892                 address += got->vma;
893               }
894               break;
895             case DW_EH_PE_pcrel:
896               value += (sec_info->entry[i].offset
897                         - sec_info->entry[i].new_offset);
898               address += (sec->output_section->vma + sec->output_offset
899                           + sec_info->entry[i].new_offset + 8);
900               break;
901             }
902           if (sec_info->entry[i].make_relative)
903             value -= (sec->output_section->vma + sec->output_offset
904                       + sec_info->entry[i].new_offset + 8);
905           switch (fde_width)
906             {
907             case 2: bfd_put_16 (abfd, value, buf); break;
908             case 4: bfd_put_32 (abfd, value, buf); break;
909             case 8: bfd_put_64 (abfd, value, buf); break;
910             }
911
912           if (hdr_info)
913             {
914               hdr_info->array[hdr_info->array_count].initial_loc = address;
915               hdr_info->array[hdr_info->array_count++].fde
916                 = (sec->output_section->vma + sec->output_offset
917                    + sec_info->entry[i].new_offset);
918             }
919         }
920
921       BFD_ASSERT (p == contents + sec_info->entry[i].new_offset);
922       memmove (p, contents + sec_info->entry[i].offset,
923                sec_info->entry[i].size);
924       p += sec_info->entry[i].size;
925     }
926
927   BFD_ASSERT ((bfd_size_type) (p - contents) == sec->_cooked_size);
928
929   return bfd_set_section_contents (abfd, sec->output_section,
930                                    contents, (file_ptr) sec->output_offset,
931                                    sec->_cooked_size);
932 }
933
934 /* Helper function used to sort .eh_frame_hdr search table by increasing
935    VMA of FDE initial location.  */
936
937 static int
938 vma_compare (a, b)
939      const PTR a;
940      const PTR b;
941 {
942   struct eh_frame_array_ent *p = (struct eh_frame_array_ent *) a;
943   struct eh_frame_array_ent *q = (struct eh_frame_array_ent *) b;
944   if (p->initial_loc > q->initial_loc)
945     return 1;
946   if (p->initial_loc < q->initial_loc)
947     return -1;
948   return 0;
949 }
950
951 /* Write out .eh_frame_hdr section.  This must be called after
952    _bfd_elf_write_section_eh_frame has been called on all input
953    .eh_frame sections.
954    .eh_frame_hdr format:
955    ubyte version                (currently 1)
956    ubyte eh_frame_ptr_enc       (DW_EH_PE_* encoding of pointer to start of
957                                  .eh_frame section)
958    ubyte fde_count_enc          (DW_EH_PE_* encoding of total FDE count
959                                  number (or DW_EH_PE_omit if there is no
960                                  binary search table computed))
961    ubyte table_enc              (DW_EH_PE_* encoding of binary search table,
962                                  or DW_EH_PE_omit if not present.
963                                  DW_EH_PE_datarel is using address of
964                                  .eh_frame_hdr section start as base)
965    [encoded] eh_frame_ptr       (pointer to start of .eh_frame section)
966    optionally followed by:
967    [encoded] fde_count          (total number of FDEs in .eh_frame section)
968    fde_count x [encoded] initial_loc, fde
969                                 (array of encoded pairs containing
970                                  FDE initial_location field and FDE address,
971                                  sorted by increasing initial_loc)  */
972
973 boolean
974 _bfd_elf_write_section_eh_frame_hdr (abfd, sec)
975      bfd *abfd;
976      asection *sec;
977 {
978   struct eh_frame_hdr_info *hdr_info;
979   unsigned int ptr_size;
980   bfd_byte *contents;
981   asection *eh_frame_sec;
982   bfd_size_type size;
983
984   ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
985               == ELFCLASS64) ? 8 : 4;
986
987   BFD_ASSERT (elf_section_data (sec)->sec_info_type
988               == ELF_INFO_TYPE_EH_FRAME_HDR);
989   hdr_info = (struct eh_frame_hdr_info *)
990              elf_section_data (sec)->sec_info;
991   size = EH_FRAME_HDR_SIZE;
992   if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
993     size += 4 + hdr_info->fde_count * 8;
994   contents = bfd_malloc (size);
995   if (contents == NULL)
996     return false;
997
998   eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
999   if (eh_frame_sec == NULL)
1000     return false;
1001
1002   memset (contents, 0, EH_FRAME_HDR_SIZE);
1003   contents[0] = 1;                              /* Version  */
1004   contents[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; /* .eh_frame offset  */
1005   if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
1006     {
1007       contents[2] = DW_EH_PE_udata4;            /* FDE count encoding  */
1008       contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* search table enc  */
1009     }
1010   else
1011     {
1012       contents[2] = DW_EH_PE_omit;
1013       contents[3] = DW_EH_PE_omit;
1014     }
1015   bfd_put_32 (abfd, eh_frame_sec->vma - sec->output_section->vma - 4,
1016               contents + 4);
1017   if (contents[2] != DW_EH_PE_omit)
1018     {
1019       unsigned int i;
1020
1021       bfd_put_32 (abfd, hdr_info->fde_count, contents + EH_FRAME_HDR_SIZE);
1022       qsort (hdr_info->array, hdr_info->fde_count, sizeof (*hdr_info->array),
1023              vma_compare);
1024       for (i = 0; i < hdr_info->fde_count; i++)
1025         {
1026           bfd_put_32 (abfd,
1027                       hdr_info->array[i].initial_loc
1028                       - sec->output_section->vma,
1029                       contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
1030           bfd_put_32 (abfd,
1031                       hdr_info->array[i].fde - sec->output_section->vma,
1032                       contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
1033         }
1034     }
1035
1036   return bfd_set_section_contents (abfd, sec->output_section,
1037                                    contents, (file_ptr) sec->output_offset,
1038                                    sec->_cooked_size);
1039 }