xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/elf-eh-frame.c (revision fc67150a4856b1d1eb4169a12ac608e4039644e6)
13d8817e4Smiod /* .eh_frame section optimization.
23d8817e4Smiod    Copyright 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
33d8817e4Smiod    Written by Jakub Jelinek <jakub@redhat.com>.
43d8817e4Smiod 
53d8817e4Smiod    This file is part of BFD, the Binary File Descriptor library.
63d8817e4Smiod 
73d8817e4Smiod    This program is free software; you can redistribute it and/or modify
83d8817e4Smiod    it under the terms of the GNU General Public License as published by
93d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
103d8817e4Smiod    (at your option) any later version.
113d8817e4Smiod 
123d8817e4Smiod    This program is distributed in the hope that it will be useful,
133d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
143d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
153d8817e4Smiod    GNU General Public License for more details.
163d8817e4Smiod 
173d8817e4Smiod    You should have received a copy of the GNU General Public License
183d8817e4Smiod    along with this program; if not, write to the Free Software
193d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
203d8817e4Smiod 
213d8817e4Smiod #include "bfd.h"
223d8817e4Smiod #include "sysdep.h"
233d8817e4Smiod #include "libbfd.h"
243d8817e4Smiod #include "elf-bfd.h"
253d8817e4Smiod #include "elf/dwarf2.h"
263d8817e4Smiod 
273d8817e4Smiod #define EH_FRAME_HDR_SIZE 8
283d8817e4Smiod 
29*fc67150aSkettenis struct cie
30*fc67150aSkettenis {
31*fc67150aSkettenis   unsigned int length;
32*fc67150aSkettenis   unsigned int hash;
33*fc67150aSkettenis   unsigned char version;
34*fc67150aSkettenis   char augmentation[20];
35*fc67150aSkettenis   bfd_vma code_align;
36*fc67150aSkettenis   bfd_signed_vma data_align;
37*fc67150aSkettenis   bfd_vma ra_column;
38*fc67150aSkettenis   bfd_vma augmentation_size;
39*fc67150aSkettenis   struct elf_link_hash_entry *personality;
40*fc67150aSkettenis   asection *output_sec;
41*fc67150aSkettenis   struct eh_cie_fde *cie_inf;
42*fc67150aSkettenis   unsigned char per_encoding;
43*fc67150aSkettenis   unsigned char lsda_encoding;
44*fc67150aSkettenis   unsigned char fde_encoding;
45*fc67150aSkettenis   unsigned char initial_insn_length;
46*fc67150aSkettenis   unsigned char make_relative;
47*fc67150aSkettenis   unsigned char make_lsda_relative;
48*fc67150aSkettenis   unsigned char initial_instructions[50];
49*fc67150aSkettenis };
50*fc67150aSkettenis 
51*fc67150aSkettenis 
52*fc67150aSkettenis 
533d8817e4Smiod /* If *ITER hasn't reached END yet, read the next byte into *RESULT and
543d8817e4Smiod    move onto the next byte.  Return true on success.  */
553d8817e4Smiod 
563d8817e4Smiod static inline bfd_boolean
read_byte(bfd_byte ** iter,bfd_byte * end,unsigned char * result)573d8817e4Smiod read_byte (bfd_byte **iter, bfd_byte *end, unsigned char *result)
583d8817e4Smiod {
593d8817e4Smiod   if (*iter >= end)
603d8817e4Smiod     return FALSE;
613d8817e4Smiod   *result = *((*iter)++);
623d8817e4Smiod   return TRUE;
633d8817e4Smiod }
643d8817e4Smiod 
653d8817e4Smiod /* Move *ITER over LENGTH bytes, or up to END, whichever is closer.
663d8817e4Smiod    Return true it was possible to move LENGTH bytes.  */
673d8817e4Smiod 
683d8817e4Smiod static inline bfd_boolean
skip_bytes(bfd_byte ** iter,bfd_byte * end,bfd_size_type length)693d8817e4Smiod skip_bytes (bfd_byte **iter, bfd_byte *end, bfd_size_type length)
703d8817e4Smiod {
713d8817e4Smiod   if ((bfd_size_type) (end - *iter) < length)
723d8817e4Smiod     {
733d8817e4Smiod       *iter = end;
743d8817e4Smiod       return FALSE;
753d8817e4Smiod     }
763d8817e4Smiod   *iter += length;
773d8817e4Smiod   return TRUE;
783d8817e4Smiod }
793d8817e4Smiod 
803d8817e4Smiod /* Move *ITER over an leb128, stopping at END.  Return true if the end
813d8817e4Smiod    of the leb128 was found.  */
823d8817e4Smiod 
833d8817e4Smiod static bfd_boolean
skip_leb128(bfd_byte ** iter,bfd_byte * end)843d8817e4Smiod skip_leb128 (bfd_byte **iter, bfd_byte *end)
853d8817e4Smiod {
863d8817e4Smiod   unsigned char byte;
873d8817e4Smiod   do
883d8817e4Smiod     if (!read_byte (iter, end, &byte))
893d8817e4Smiod       return FALSE;
903d8817e4Smiod   while (byte & 0x80);
913d8817e4Smiod   return TRUE;
923d8817e4Smiod }
933d8817e4Smiod 
943d8817e4Smiod /* Like skip_leb128, but treat the leb128 as an unsigned value and
953d8817e4Smiod    store it in *VALUE.  */
963d8817e4Smiod 
973d8817e4Smiod static bfd_boolean
read_uleb128(bfd_byte ** iter,bfd_byte * end,bfd_vma * value)983d8817e4Smiod read_uleb128 (bfd_byte **iter, bfd_byte *end, bfd_vma *value)
993d8817e4Smiod {
1003d8817e4Smiod   bfd_byte *start, *p;
1013d8817e4Smiod 
1023d8817e4Smiod   start = *iter;
1033d8817e4Smiod   if (!skip_leb128 (iter, end))
1043d8817e4Smiod     return FALSE;
1053d8817e4Smiod 
1063d8817e4Smiod   p = *iter;
1073d8817e4Smiod   *value = *--p;
1083d8817e4Smiod   while (p > start)
1093d8817e4Smiod     *value = (*value << 7) | (*--p & 0x7f);
1103d8817e4Smiod 
1113d8817e4Smiod   return TRUE;
1123d8817e4Smiod }
1133d8817e4Smiod 
1143d8817e4Smiod /* Like read_uleb128, but for signed values.  */
1153d8817e4Smiod 
1163d8817e4Smiod static bfd_boolean
read_sleb128(bfd_byte ** iter,bfd_byte * end,bfd_signed_vma * value)1173d8817e4Smiod read_sleb128 (bfd_byte **iter, bfd_byte *end, bfd_signed_vma *value)
1183d8817e4Smiod {
1193d8817e4Smiod   bfd_byte *start, *p;
1203d8817e4Smiod 
1213d8817e4Smiod   start = *iter;
1223d8817e4Smiod   if (!skip_leb128 (iter, end))
1233d8817e4Smiod     return FALSE;
1243d8817e4Smiod 
1253d8817e4Smiod   p = *iter;
1263d8817e4Smiod   *value = ((*--p & 0x7f) ^ 0x40) - 0x40;
1273d8817e4Smiod   while (p > start)
1283d8817e4Smiod     *value = (*value << 7) | (*--p & 0x7f);
1293d8817e4Smiod 
1303d8817e4Smiod   return TRUE;
1313d8817e4Smiod }
1323d8817e4Smiod 
1333d8817e4Smiod /* Return 0 if either encoding is variable width, or not yet known to bfd.  */
1343d8817e4Smiod 
1353d8817e4Smiod static
get_DW_EH_PE_width(int encoding,int ptr_size)1363d8817e4Smiod int get_DW_EH_PE_width (int encoding, int ptr_size)
1373d8817e4Smiod {
1383d8817e4Smiod   /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
1393d8817e4Smiod      was added to bfd.  */
1403d8817e4Smiod   if ((encoding & 0x60) == 0x60)
1413d8817e4Smiod     return 0;
1423d8817e4Smiod 
1433d8817e4Smiod   switch (encoding & 7)
1443d8817e4Smiod     {
1453d8817e4Smiod     case DW_EH_PE_udata2: return 2;
1463d8817e4Smiod     case DW_EH_PE_udata4: return 4;
1473d8817e4Smiod     case DW_EH_PE_udata8: return 8;
1483d8817e4Smiod     case DW_EH_PE_absptr: return ptr_size;
1493d8817e4Smiod     default:
1503d8817e4Smiod       break;
1513d8817e4Smiod     }
1523d8817e4Smiod 
1533d8817e4Smiod   return 0;
1543d8817e4Smiod }
1553d8817e4Smiod 
1563d8817e4Smiod #define get_DW_EH_PE_signed(encoding) (((encoding) & DW_EH_PE_signed) != 0)
1573d8817e4Smiod 
1583d8817e4Smiod /* Read a width sized value from memory.  */
1593d8817e4Smiod 
1603d8817e4Smiod static bfd_vma
read_value(bfd * abfd,bfd_byte * buf,int width,int is_signed)1613d8817e4Smiod read_value (bfd *abfd, bfd_byte *buf, int width, int is_signed)
1623d8817e4Smiod {
1633d8817e4Smiod   bfd_vma value;
1643d8817e4Smiod 
1653d8817e4Smiod   switch (width)
1663d8817e4Smiod     {
1673d8817e4Smiod     case 2:
1683d8817e4Smiod       if (is_signed)
1693d8817e4Smiod 	value = bfd_get_signed_16 (abfd, buf);
1703d8817e4Smiod       else
1713d8817e4Smiod 	value = bfd_get_16 (abfd, buf);
1723d8817e4Smiod       break;
1733d8817e4Smiod     case 4:
1743d8817e4Smiod       if (is_signed)
1753d8817e4Smiod 	value = bfd_get_signed_32 (abfd, buf);
1763d8817e4Smiod       else
1773d8817e4Smiod 	value = bfd_get_32 (abfd, buf);
1783d8817e4Smiod       break;
1793d8817e4Smiod     case 8:
1803d8817e4Smiod       if (is_signed)
1813d8817e4Smiod 	value = bfd_get_signed_64 (abfd, buf);
1823d8817e4Smiod       else
1833d8817e4Smiod 	value = bfd_get_64 (abfd, buf);
1843d8817e4Smiod       break;
1853d8817e4Smiod     default:
1863d8817e4Smiod       BFD_FAIL ();
1873d8817e4Smiod       return 0;
1883d8817e4Smiod     }
1893d8817e4Smiod 
1903d8817e4Smiod   return value;
1913d8817e4Smiod }
1923d8817e4Smiod 
1933d8817e4Smiod /* Store a width sized value to memory.  */
1943d8817e4Smiod 
1953d8817e4Smiod static void
write_value(bfd * abfd,bfd_byte * buf,bfd_vma value,int width)1963d8817e4Smiod write_value (bfd *abfd, bfd_byte *buf, bfd_vma value, int width)
1973d8817e4Smiod {
1983d8817e4Smiod   switch (width)
1993d8817e4Smiod     {
2003d8817e4Smiod     case 2: bfd_put_16 (abfd, value, buf); break;
2013d8817e4Smiod     case 4: bfd_put_32 (abfd, value, buf); break;
2023d8817e4Smiod     case 8: bfd_put_64 (abfd, value, buf); break;
2033d8817e4Smiod     default: BFD_FAIL ();
2043d8817e4Smiod     }
2053d8817e4Smiod }
2063d8817e4Smiod 
207*fc67150aSkettenis /* Return one if C1 and C2 CIEs can be merged.  */
2083d8817e4Smiod 
209*fc67150aSkettenis static int
cie_eq(const void * e1,const void * e2)210*fc67150aSkettenis cie_eq (const void *e1, const void *e2)
2113d8817e4Smiod {
212*fc67150aSkettenis   const struct cie *c1 = e1;
213*fc67150aSkettenis   const struct cie *c2 = e2;
214*fc67150aSkettenis 
215*fc67150aSkettenis   if (c1->hash == c2->hash
216*fc67150aSkettenis       && c1->length == c2->length
2173d8817e4Smiod       && c1->version == c2->version
2183d8817e4Smiod       && strcmp (c1->augmentation, c2->augmentation) == 0
2193d8817e4Smiod       && strcmp (c1->augmentation, "eh") != 0
2203d8817e4Smiod       && c1->code_align == c2->code_align
2213d8817e4Smiod       && c1->data_align == c2->data_align
2223d8817e4Smiod       && c1->ra_column == c2->ra_column
2233d8817e4Smiod       && c1->augmentation_size == c2->augmentation_size
2243d8817e4Smiod       && c1->personality == c2->personality
225*fc67150aSkettenis       && c1->output_sec == c2->output_sec
2263d8817e4Smiod       && c1->per_encoding == c2->per_encoding
2273d8817e4Smiod       && c1->lsda_encoding == c2->lsda_encoding
2283d8817e4Smiod       && c1->fde_encoding == c2->fde_encoding
2293d8817e4Smiod       && c1->initial_insn_length == c2->initial_insn_length
2303d8817e4Smiod       && memcmp (c1->initial_instructions,
2313d8817e4Smiod 		 c2->initial_instructions,
2323d8817e4Smiod 		 c1->initial_insn_length) == 0)
2333d8817e4Smiod     return 1;
234*fc67150aSkettenis 
235*fc67150aSkettenis   return 0;
236*fc67150aSkettenis }
237*fc67150aSkettenis 
238*fc67150aSkettenis static hashval_t
cie_hash(const void * e)239*fc67150aSkettenis cie_hash (const void *e)
240*fc67150aSkettenis {
241*fc67150aSkettenis   const struct cie *c = e;
242*fc67150aSkettenis   return c->hash;
243*fc67150aSkettenis }
244*fc67150aSkettenis 
245*fc67150aSkettenis static hashval_t
cie_compute_hash(struct cie * c)246*fc67150aSkettenis cie_compute_hash (struct cie *c)
247*fc67150aSkettenis {
248*fc67150aSkettenis   hashval_t h = 0;
249*fc67150aSkettenis   h = iterative_hash_object (c->length, h);
250*fc67150aSkettenis   h = iterative_hash_object (c->version, h);
251*fc67150aSkettenis   h = iterative_hash (c->augmentation, strlen (c->augmentation) + 1, h);
252*fc67150aSkettenis   h = iterative_hash_object (c->code_align, h);
253*fc67150aSkettenis   h = iterative_hash_object (c->data_align, h);
254*fc67150aSkettenis   h = iterative_hash_object (c->ra_column, h);
255*fc67150aSkettenis   h = iterative_hash_object (c->augmentation_size, h);
256*fc67150aSkettenis   h = iterative_hash_object (c->personality, h);
257*fc67150aSkettenis   h = iterative_hash_object (c->output_sec, h);
258*fc67150aSkettenis   h = iterative_hash_object (c->per_encoding, h);
259*fc67150aSkettenis   h = iterative_hash_object (c->lsda_encoding, h);
260*fc67150aSkettenis   h = iterative_hash_object (c->fde_encoding, h);
261*fc67150aSkettenis   h = iterative_hash_object (c->initial_insn_length, h);
262*fc67150aSkettenis   h = iterative_hash (c->initial_instructions, c->initial_insn_length, h);
263*fc67150aSkettenis   c->hash = h;
264*fc67150aSkettenis   return h;
2653d8817e4Smiod }
2663d8817e4Smiod 
2673d8817e4Smiod /* Return the number of extra bytes that we'll be inserting into
2683d8817e4Smiod    ENTRY's augmentation string.  */
2693d8817e4Smiod 
2703d8817e4Smiod static INLINE unsigned int
extra_augmentation_string_bytes(struct eh_cie_fde * entry)2713d8817e4Smiod extra_augmentation_string_bytes (struct eh_cie_fde *entry)
2723d8817e4Smiod {
2733d8817e4Smiod   unsigned int size = 0;
2743d8817e4Smiod   if (entry->cie)
2753d8817e4Smiod     {
2763d8817e4Smiod       if (entry->add_augmentation_size)
2773d8817e4Smiod 	size++;
2783d8817e4Smiod       if (entry->add_fde_encoding)
2793d8817e4Smiod 	size++;
2803d8817e4Smiod     }
2813d8817e4Smiod   return size;
2823d8817e4Smiod }
2833d8817e4Smiod 
2843d8817e4Smiod /* Likewise ENTRY's augmentation data.  */
2853d8817e4Smiod 
2863d8817e4Smiod static INLINE unsigned int
extra_augmentation_data_bytes(struct eh_cie_fde * entry)2873d8817e4Smiod extra_augmentation_data_bytes (struct eh_cie_fde *entry)
2883d8817e4Smiod {
2893d8817e4Smiod   unsigned int size = 0;
2903d8817e4Smiod   if (entry->cie)
2913d8817e4Smiod     {
2923d8817e4Smiod       if (entry->add_augmentation_size)
2933d8817e4Smiod 	size++;
2943d8817e4Smiod       if (entry->add_fde_encoding)
2953d8817e4Smiod 	size++;
2963d8817e4Smiod     }
2973d8817e4Smiod   else
2983d8817e4Smiod     {
2993d8817e4Smiod       if (entry->cie_inf->add_augmentation_size)
3003d8817e4Smiod 	size++;
3013d8817e4Smiod     }
3023d8817e4Smiod   return size;
3033d8817e4Smiod }
3043d8817e4Smiod 
3053d8817e4Smiod /* Return the size that ENTRY will have in the output.  ALIGNMENT is the
3063d8817e4Smiod    required alignment of ENTRY in bytes.  */
3073d8817e4Smiod 
3083d8817e4Smiod static unsigned int
size_of_output_cie_fde(struct eh_cie_fde * entry,unsigned int alignment)3093d8817e4Smiod size_of_output_cie_fde (struct eh_cie_fde *entry, unsigned int alignment)
3103d8817e4Smiod {
3113d8817e4Smiod   if (entry->removed)
3123d8817e4Smiod     return 0;
3133d8817e4Smiod   if (entry->size == 4)
3143d8817e4Smiod     return 4;
3153d8817e4Smiod   return (entry->size
3163d8817e4Smiod 	  + extra_augmentation_string_bytes (entry)
3173d8817e4Smiod 	  + extra_augmentation_data_bytes (entry)
3183d8817e4Smiod 	  + alignment - 1) & -alignment;
3193d8817e4Smiod }
3203d8817e4Smiod 
3213d8817e4Smiod /* Assume that the bytes between *ITER and END are CFA instructions.
3223d8817e4Smiod    Try to move *ITER past the first instruction and return true on
3233d8817e4Smiod    success.  ENCODED_PTR_WIDTH gives the width of pointer entries.  */
3243d8817e4Smiod 
3253d8817e4Smiod static bfd_boolean
skip_cfa_op(bfd_byte ** iter,bfd_byte * end,unsigned int encoded_ptr_width)3263d8817e4Smiod skip_cfa_op (bfd_byte **iter, bfd_byte *end, unsigned int encoded_ptr_width)
3273d8817e4Smiod {
3283d8817e4Smiod   bfd_byte op;
3293d8817e4Smiod   bfd_vma length;
3303d8817e4Smiod 
3313d8817e4Smiod   if (!read_byte (iter, end, &op))
3323d8817e4Smiod     return FALSE;
3333d8817e4Smiod 
334*fc67150aSkettenis   switch (op & 0xc0 ? op & 0xc0 : op)
3353d8817e4Smiod     {
3363d8817e4Smiod     case DW_CFA_nop:
3373d8817e4Smiod     case DW_CFA_advance_loc:
3383d8817e4Smiod     case DW_CFA_restore:
339*fc67150aSkettenis     case DW_CFA_remember_state:
340*fc67150aSkettenis     case DW_CFA_restore_state:
341*fc67150aSkettenis     case DW_CFA_GNU_window_save:
3423d8817e4Smiod       /* No arguments.  */
3433d8817e4Smiod       return TRUE;
3443d8817e4Smiod 
3453d8817e4Smiod     case DW_CFA_offset:
3463d8817e4Smiod     case DW_CFA_restore_extended:
3473d8817e4Smiod     case DW_CFA_undefined:
3483d8817e4Smiod     case DW_CFA_same_value:
3493d8817e4Smiod     case DW_CFA_def_cfa_register:
3503d8817e4Smiod     case DW_CFA_def_cfa_offset:
3513d8817e4Smiod     case DW_CFA_def_cfa_offset_sf:
3523d8817e4Smiod     case DW_CFA_GNU_args_size:
3533d8817e4Smiod       /* One leb128 argument.  */
3543d8817e4Smiod       return skip_leb128 (iter, end);
3553d8817e4Smiod 
356*fc67150aSkettenis     case DW_CFA_val_offset:
357*fc67150aSkettenis     case DW_CFA_val_offset_sf:
3583d8817e4Smiod     case DW_CFA_offset_extended:
3593d8817e4Smiod     case DW_CFA_register:
3603d8817e4Smiod     case DW_CFA_def_cfa:
3613d8817e4Smiod     case DW_CFA_offset_extended_sf:
3623d8817e4Smiod     case DW_CFA_GNU_negative_offset_extended:
3633d8817e4Smiod     case DW_CFA_def_cfa_sf:
3643d8817e4Smiod       /* Two leb128 arguments.  */
3653d8817e4Smiod       return (skip_leb128 (iter, end)
3663d8817e4Smiod 	      && skip_leb128 (iter, end));
3673d8817e4Smiod 
3683d8817e4Smiod     case DW_CFA_def_cfa_expression:
3693d8817e4Smiod       /* A variable-length argument.  */
3703d8817e4Smiod       return (read_uleb128 (iter, end, &length)
3713d8817e4Smiod 	      && skip_bytes (iter, end, length));
3723d8817e4Smiod 
3733d8817e4Smiod     case DW_CFA_expression:
374*fc67150aSkettenis     case DW_CFA_val_expression:
3753d8817e4Smiod       /* A leb128 followed by a variable-length argument.  */
3763d8817e4Smiod       return (skip_leb128 (iter, end)
3773d8817e4Smiod 	      && read_uleb128 (iter, end, &length)
3783d8817e4Smiod 	      && skip_bytes (iter, end, length));
3793d8817e4Smiod 
3803d8817e4Smiod     case DW_CFA_set_loc:
3813d8817e4Smiod       return skip_bytes (iter, end, encoded_ptr_width);
3823d8817e4Smiod 
3833d8817e4Smiod     case DW_CFA_advance_loc1:
3843d8817e4Smiod       return skip_bytes (iter, end, 1);
3853d8817e4Smiod 
3863d8817e4Smiod     case DW_CFA_advance_loc2:
3873d8817e4Smiod       return skip_bytes (iter, end, 2);
3883d8817e4Smiod 
3893d8817e4Smiod     case DW_CFA_advance_loc4:
3903d8817e4Smiod       return skip_bytes (iter, end, 4);
3913d8817e4Smiod 
3923d8817e4Smiod     case DW_CFA_MIPS_advance_loc8:
3933d8817e4Smiod       return skip_bytes (iter, end, 8);
3943d8817e4Smiod 
3953d8817e4Smiod     default:
3963d8817e4Smiod       return FALSE;
3973d8817e4Smiod     }
3983d8817e4Smiod }
3993d8817e4Smiod 
4003d8817e4Smiod /* Try to interpret the bytes between BUF and END as CFA instructions.
4013d8817e4Smiod    If every byte makes sense, return a pointer to the first DW_CFA_nop
4023d8817e4Smiod    padding byte, or END if there is no padding.  Return null otherwise.
4033d8817e4Smiod    ENCODED_PTR_WIDTH is as for skip_cfa_op.  */
4043d8817e4Smiod 
4053d8817e4Smiod static bfd_byte *
skip_non_nops(bfd_byte * buf,bfd_byte * end,unsigned int encoded_ptr_width,unsigned int * set_loc_count)406*fc67150aSkettenis skip_non_nops (bfd_byte *buf, bfd_byte *end, unsigned int encoded_ptr_width,
407*fc67150aSkettenis 	       unsigned int *set_loc_count)
4083d8817e4Smiod {
4093d8817e4Smiod   bfd_byte *last;
4103d8817e4Smiod 
4113d8817e4Smiod   last = buf;
4123d8817e4Smiod   while (buf < end)
4133d8817e4Smiod     if (*buf == DW_CFA_nop)
4143d8817e4Smiod       buf++;
4153d8817e4Smiod     else
4163d8817e4Smiod       {
417*fc67150aSkettenis 	if (*buf == DW_CFA_set_loc)
418*fc67150aSkettenis 	  ++*set_loc_count;
4193d8817e4Smiod 	if (!skip_cfa_op (&buf, end, encoded_ptr_width))
4203d8817e4Smiod 	  return 0;
4213d8817e4Smiod 	last = buf;
4223d8817e4Smiod       }
4233d8817e4Smiod   return last;
4243d8817e4Smiod }
4253d8817e4Smiod 
4263d8817e4Smiod /* This function is called for each input file before the .eh_frame
4273d8817e4Smiod    section is relocated.  It discards duplicate CIEs and FDEs for discarded
4283d8817e4Smiod    functions.  The function returns TRUE iff any entries have been
4293d8817e4Smiod    deleted.  */
4303d8817e4Smiod 
4313d8817e4Smiod bfd_boolean
_bfd_elf_discard_section_eh_frame(bfd * abfd,struct bfd_link_info * info,asection * sec,bfd_boolean (* reloc_symbol_deleted_p)(bfd_vma,void *),struct elf_reloc_cookie * cookie)4323d8817e4Smiod _bfd_elf_discard_section_eh_frame
4333d8817e4Smiod    (bfd *abfd, struct bfd_link_info *info, asection *sec,
4343d8817e4Smiod     bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
4353d8817e4Smiod     struct elf_reloc_cookie *cookie)
4363d8817e4Smiod {
4373d8817e4Smiod #define REQUIRE(COND)					\
4383d8817e4Smiod   do							\
4393d8817e4Smiod     if (!(COND))					\
4403d8817e4Smiod       goto free_no_table;				\
4413d8817e4Smiod   while (0)
4423d8817e4Smiod 
4433d8817e4Smiod   bfd_byte *ehbuf = NULL, *buf;
444*fc67150aSkettenis   bfd_byte *last_fde;
445*fc67150aSkettenis   struct eh_cie_fde *ent, *this_inf;
446*fc67150aSkettenis   unsigned int hdr_length, hdr_id;
447*fc67150aSkettenis   struct extended_cie
448*fc67150aSkettenis     {
4493d8817e4Smiod       struct cie cie;
450*fc67150aSkettenis       unsigned int offset;
451*fc67150aSkettenis       unsigned int usage_count;
452*fc67150aSkettenis       unsigned int entry;
453*fc67150aSkettenis     } *ecies = NULL, *ecie;
454*fc67150aSkettenis   unsigned int ecie_count = 0, ecie_alloced = 0;
455*fc67150aSkettenis   struct cie *cie;
4563d8817e4Smiod   struct elf_link_hash_table *htab;
4573d8817e4Smiod   struct eh_frame_hdr_info *hdr_info;
4583d8817e4Smiod   struct eh_frame_sec_info *sec_info = NULL;
459*fc67150aSkettenis   unsigned int offset;
4603d8817e4Smiod   unsigned int ptr_size;
461*fc67150aSkettenis   unsigned int entry_alloced;
4623d8817e4Smiod 
4633d8817e4Smiod   if (sec->size == 0)
4643d8817e4Smiod     {
4653d8817e4Smiod       /* This file does not contain .eh_frame information.  */
4663d8817e4Smiod       return FALSE;
4673d8817e4Smiod     }
4683d8817e4Smiod 
469*fc67150aSkettenis   if (bfd_is_abs_section (sec->output_section))
4703d8817e4Smiod     {
4713d8817e4Smiod       /* At least one of the sections is being discarded from the
4723d8817e4Smiod 	 link, so we should just ignore them.  */
4733d8817e4Smiod       return FALSE;
4743d8817e4Smiod     }
4753d8817e4Smiod 
4763d8817e4Smiod   htab = elf_hash_table (info);
4773d8817e4Smiod   hdr_info = &htab->eh_info;
4783d8817e4Smiod 
479*fc67150aSkettenis   if (hdr_info->cies == NULL && !info->relocatable)
480*fc67150aSkettenis     hdr_info->cies = htab_try_create (1, cie_hash, cie_eq, free);
481*fc67150aSkettenis 
4823d8817e4Smiod   /* Read the frame unwind information from abfd.  */
4833d8817e4Smiod 
4843d8817e4Smiod   REQUIRE (bfd_malloc_and_get_section (abfd, sec, &ehbuf));
4853d8817e4Smiod 
4863d8817e4Smiod   if (sec->size >= 4
4873d8817e4Smiod       && bfd_get_32 (abfd, ehbuf) == 0
4883d8817e4Smiod       && cookie->rel == cookie->relend)
4893d8817e4Smiod     {
4903d8817e4Smiod       /* Empty .eh_frame section.  */
4913d8817e4Smiod       free (ehbuf);
4923d8817e4Smiod       return FALSE;
4933d8817e4Smiod     }
4943d8817e4Smiod 
4953d8817e4Smiod   /* If .eh_frame section size doesn't fit into int, we cannot handle
4963d8817e4Smiod      it (it would need to use 64-bit .eh_frame format anyway).  */
4973d8817e4Smiod   REQUIRE (sec->size == (unsigned int) sec->size);
4983d8817e4Smiod 
4993d8817e4Smiod   ptr_size = (get_elf_backend_data (abfd)
5003d8817e4Smiod 	      ->elf_backend_eh_frame_address_size (abfd, sec));
5013d8817e4Smiod   REQUIRE (ptr_size != 0);
5023d8817e4Smiod 
5033d8817e4Smiod   buf = ehbuf;
5043d8817e4Smiod   sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)
5053d8817e4Smiod 			  + 99 * sizeof (struct eh_cie_fde));
5063d8817e4Smiod   REQUIRE (sec_info);
5073d8817e4Smiod 
508*fc67150aSkettenis   entry_alloced = 100;
5093d8817e4Smiod 
5103d8817e4Smiod #define ENSURE_NO_RELOCS(buf)				\
5113d8817e4Smiod   REQUIRE (!(cookie->rel < cookie->relend		\
5123d8817e4Smiod 	     && (cookie->rel->r_offset			\
5133d8817e4Smiod 		 < (bfd_size_type) ((buf) - ehbuf))	\
5143d8817e4Smiod 	     && cookie->rel->r_info != 0))
5153d8817e4Smiod 
5163d8817e4Smiod #define SKIP_RELOCS(buf)				\
5173d8817e4Smiod   while (cookie->rel < cookie->relend			\
5183d8817e4Smiod 	 && (cookie->rel->r_offset			\
5193d8817e4Smiod 	     < (bfd_size_type) ((buf) - ehbuf)))	\
5203d8817e4Smiod     cookie->rel++
5213d8817e4Smiod 
5223d8817e4Smiod #define GET_RELOC(buf)					\
5233d8817e4Smiod   ((cookie->rel < cookie->relend			\
5243d8817e4Smiod     && (cookie->rel->r_offset				\
5253d8817e4Smiod 	== (bfd_size_type) ((buf) - ehbuf)))		\
5263d8817e4Smiod    ? cookie->rel : NULL)
5273d8817e4Smiod 
5283d8817e4Smiod   for (;;)
5293d8817e4Smiod     {
5303d8817e4Smiod       char *aug;
531*fc67150aSkettenis       bfd_byte *start, *end, *insns, *insns_end;
5323d8817e4Smiod       bfd_size_type length;
533*fc67150aSkettenis       unsigned int set_loc_count;
5343d8817e4Smiod 
535*fc67150aSkettenis       if (sec_info->count == entry_alloced)
5363d8817e4Smiod 	{
5373d8817e4Smiod 	  sec_info = bfd_realloc (sec_info,
5383d8817e4Smiod 				  sizeof (struct eh_frame_sec_info)
539*fc67150aSkettenis 				  + ((entry_alloced + 99)
5403d8817e4Smiod 				     * sizeof (struct eh_cie_fde)));
5413d8817e4Smiod 	  REQUIRE (sec_info);
5423d8817e4Smiod 
543*fc67150aSkettenis 	  memset (&sec_info->entry[entry_alloced], 0,
5443d8817e4Smiod 		  100 * sizeof (struct eh_cie_fde));
545*fc67150aSkettenis 	  entry_alloced += 100;
5463d8817e4Smiod 	}
5473d8817e4Smiod 
5483d8817e4Smiod       this_inf = sec_info->entry + sec_info->count;
5493d8817e4Smiod       last_fde = buf;
550*fc67150aSkettenis 
5513d8817e4Smiod       if ((bfd_size_type) (buf - ehbuf) == sec->size)
552*fc67150aSkettenis 	break;
553*fc67150aSkettenis 
5543d8817e4Smiod       /* Read the length of the entry.  */
5553d8817e4Smiod       REQUIRE (skip_bytes (&buf, ehbuf + sec->size, 4));
556*fc67150aSkettenis       hdr_length = bfd_get_32 (abfd, buf - 4);
5573d8817e4Smiod 
5583d8817e4Smiod       /* 64-bit .eh_frame is not supported.  */
559*fc67150aSkettenis       REQUIRE (hdr_length != 0xffffffff);
5603d8817e4Smiod 
5613d8817e4Smiod       /* The CIE/FDE must be fully contained in this input section.  */
562*fc67150aSkettenis       REQUIRE ((bfd_size_type) (buf - ehbuf) + hdr_length <= sec->size);
563*fc67150aSkettenis       end = buf + hdr_length;
5643d8817e4Smiod 
5653d8817e4Smiod       this_inf->offset = last_fde - ehbuf;
566*fc67150aSkettenis       this_inf->size = 4 + hdr_length;
5673d8817e4Smiod 
568*fc67150aSkettenis       if (hdr_length == 0)
5693d8817e4Smiod 	{
5703d8817e4Smiod 	  /* A zero-length CIE should only be found at the end of
5713d8817e4Smiod 	     the section.  */
5723d8817e4Smiod 	  REQUIRE ((bfd_size_type) (buf - ehbuf) == sec->size);
5733d8817e4Smiod 	  ENSURE_NO_RELOCS (buf);
5743d8817e4Smiod 	  sec_info->count++;
575*fc67150aSkettenis 	  break;
5763d8817e4Smiod 	}
5773d8817e4Smiod 
578*fc67150aSkettenis       REQUIRE (skip_bytes (&buf, end, 4));
579*fc67150aSkettenis       hdr_id = bfd_get_32 (abfd, buf - 4);
580*fc67150aSkettenis 
581*fc67150aSkettenis       if (hdr_id == 0)
5823d8817e4Smiod 	{
5833d8817e4Smiod 	  unsigned int initial_insn_length;
5843d8817e4Smiod 
5853d8817e4Smiod 	  /* CIE  */
5863d8817e4Smiod 	  this_inf->cie = 1;
5873d8817e4Smiod 
588*fc67150aSkettenis 	  if (ecie_count == ecie_alloced)
589*fc67150aSkettenis 	    {
590*fc67150aSkettenis 	      ecies = bfd_realloc (ecies,
591*fc67150aSkettenis 				   (ecie_alloced + 20) * sizeof (*ecies));
592*fc67150aSkettenis 	      REQUIRE (ecies);
593*fc67150aSkettenis 	      memset (&ecies[ecie_alloced], 0, 20 * sizeof (*ecies));
594*fc67150aSkettenis 	      ecie_alloced += 20;
595*fc67150aSkettenis 	    }
596*fc67150aSkettenis 
597*fc67150aSkettenis 	  cie = &ecies[ecie_count].cie;
598*fc67150aSkettenis 	  ecies[ecie_count].offset = this_inf->offset;
599*fc67150aSkettenis 	  ecies[ecie_count++].entry = sec_info->count;
600*fc67150aSkettenis 	  cie->length = hdr_length;
601*fc67150aSkettenis 	  start = buf;
602*fc67150aSkettenis 	  REQUIRE (read_byte (&buf, end, &cie->version));
6033d8817e4Smiod 
6043d8817e4Smiod 	  /* Cannot handle unknown versions.  */
605*fc67150aSkettenis 	  REQUIRE (cie->version == 1 || cie->version == 3);
606*fc67150aSkettenis 	  REQUIRE (strlen ((char *) buf) < sizeof (cie->augmentation));
6073d8817e4Smiod 
608*fc67150aSkettenis 	  strcpy (cie->augmentation, (char *) buf);
6093d8817e4Smiod 	  buf = (bfd_byte *) strchr ((char *) buf, '\0') + 1;
6103d8817e4Smiod 	  ENSURE_NO_RELOCS (buf);
6113d8817e4Smiod 	  if (buf[0] == 'e' && buf[1] == 'h')
6123d8817e4Smiod 	    {
6133d8817e4Smiod 	      /* GCC < 3.0 .eh_frame CIE */
6143d8817e4Smiod 	      /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
6153d8817e4Smiod 		 is private to each CIE, so we don't need it for anything.
6163d8817e4Smiod 		 Just skip it.  */
6173d8817e4Smiod 	      REQUIRE (skip_bytes (&buf, end, ptr_size));
6183d8817e4Smiod 	      SKIP_RELOCS (buf);
6193d8817e4Smiod 	    }
620*fc67150aSkettenis 	  REQUIRE (read_uleb128 (&buf, end, &cie->code_align));
621*fc67150aSkettenis 	  REQUIRE (read_sleb128 (&buf, end, &cie->data_align));
622*fc67150aSkettenis 	  if (cie->version == 1)
6233d8817e4Smiod 	    {
6243d8817e4Smiod 	      REQUIRE (buf < end);
625*fc67150aSkettenis 	      cie->ra_column = *buf++;
6263d8817e4Smiod 	    }
6273d8817e4Smiod 	  else
628*fc67150aSkettenis 	    REQUIRE (read_uleb128 (&buf, end, &cie->ra_column));
6293d8817e4Smiod 	  ENSURE_NO_RELOCS (buf);
630*fc67150aSkettenis 	  cie->lsda_encoding = DW_EH_PE_omit;
631*fc67150aSkettenis 	  cie->fde_encoding = DW_EH_PE_omit;
632*fc67150aSkettenis 	  cie->per_encoding = DW_EH_PE_omit;
633*fc67150aSkettenis 	  aug = cie->augmentation;
6343d8817e4Smiod 	  if (aug[0] != 'e' || aug[1] != 'h')
6353d8817e4Smiod 	    {
6363d8817e4Smiod 	      if (*aug == 'z')
6373d8817e4Smiod 		{
6383d8817e4Smiod 		  aug++;
639*fc67150aSkettenis 		  REQUIRE (read_uleb128 (&buf, end, &cie->augmentation_size));
6403d8817e4Smiod 	  	  ENSURE_NO_RELOCS (buf);
6413d8817e4Smiod 		}
6423d8817e4Smiod 
6433d8817e4Smiod 	      while (*aug != '\0')
6443d8817e4Smiod 		switch (*aug++)
6453d8817e4Smiod 		  {
6463d8817e4Smiod 		  case 'L':
647*fc67150aSkettenis 		    REQUIRE (read_byte (&buf, end, &cie->lsda_encoding));
6483d8817e4Smiod 		    ENSURE_NO_RELOCS (buf);
649*fc67150aSkettenis 		    REQUIRE (get_DW_EH_PE_width (cie->lsda_encoding, ptr_size));
6503d8817e4Smiod 		    break;
6513d8817e4Smiod 		  case 'R':
652*fc67150aSkettenis 		    REQUIRE (read_byte (&buf, end, &cie->fde_encoding));
6533d8817e4Smiod 		    ENSURE_NO_RELOCS (buf);
654*fc67150aSkettenis 		    REQUIRE (get_DW_EH_PE_width (cie->fde_encoding, ptr_size));
6553d8817e4Smiod 		    break;
6563d8817e4Smiod 		  case 'S':
6573d8817e4Smiod 		    break;
6583d8817e4Smiod 		  case 'P':
6593d8817e4Smiod 		    {
6603d8817e4Smiod 		      int per_width;
6613d8817e4Smiod 
662*fc67150aSkettenis 		      REQUIRE (read_byte (&buf, end, &cie->per_encoding));
663*fc67150aSkettenis 		      per_width = get_DW_EH_PE_width (cie->per_encoding,
6643d8817e4Smiod 						      ptr_size);
6653d8817e4Smiod 		      REQUIRE (per_width);
666*fc67150aSkettenis 		      if ((cie->per_encoding & 0xf0) == DW_EH_PE_aligned)
6673d8817e4Smiod 			{
6683d8817e4Smiod 			  length = -(buf - ehbuf) & (per_width - 1);
6693d8817e4Smiod 			  REQUIRE (skip_bytes (&buf, end, length));
6703d8817e4Smiod 			}
6713d8817e4Smiod 		      ENSURE_NO_RELOCS (buf);
6723d8817e4Smiod 		      /* Ensure we have a reloc here, against
6733d8817e4Smiod 			 a global symbol.  */
6743d8817e4Smiod 		      if (GET_RELOC (buf) != NULL)
6753d8817e4Smiod 			{
6763d8817e4Smiod 			  unsigned long r_symndx;
6773d8817e4Smiod 
6783d8817e4Smiod #ifdef BFD64
6793d8817e4Smiod 			  if (ptr_size == 8)
6803d8817e4Smiod 			    r_symndx = ELF64_R_SYM (cookie->rel->r_info);
6813d8817e4Smiod 			  else
6823d8817e4Smiod #endif
6833d8817e4Smiod 			    r_symndx = ELF32_R_SYM (cookie->rel->r_info);
6843d8817e4Smiod 			  if (r_symndx >= cookie->locsymcount)
6853d8817e4Smiod 			    {
6863d8817e4Smiod 			      struct elf_link_hash_entry *h;
6873d8817e4Smiod 
6883d8817e4Smiod 			      r_symndx -= cookie->extsymoff;
6893d8817e4Smiod 			      h = cookie->sym_hashes[r_symndx];
6903d8817e4Smiod 
6913d8817e4Smiod 			      while (h->root.type == bfd_link_hash_indirect
6923d8817e4Smiod 				     || h->root.type == bfd_link_hash_warning)
6933d8817e4Smiod 				h = (struct elf_link_hash_entry *)
6943d8817e4Smiod 				    h->root.u.i.link;
6953d8817e4Smiod 
696*fc67150aSkettenis 			      cie->personality = h;
6973d8817e4Smiod 			    }
6983d8817e4Smiod 			  /* Cope with MIPS-style composite relocations.  */
6993d8817e4Smiod 			  do
7003d8817e4Smiod 			    cookie->rel++;
7013d8817e4Smiod 			  while (GET_RELOC (buf) != NULL);
7023d8817e4Smiod 			}
7033d8817e4Smiod 		      REQUIRE (skip_bytes (&buf, end, per_width));
704*fc67150aSkettenis 		      REQUIRE (cie->personality);
7053d8817e4Smiod 		    }
7063d8817e4Smiod 		    break;
7073d8817e4Smiod 		  default:
7083d8817e4Smiod 		    /* Unrecognized augmentation. Better bail out.  */
7093d8817e4Smiod 		    goto free_no_table;
7103d8817e4Smiod 		  }
7113d8817e4Smiod 	    }
7123d8817e4Smiod 
7133d8817e4Smiod 	  /* For shared libraries, try to get rid of as many RELATIVE relocs
7143d8817e4Smiod 	     as possible.  */
7153d8817e4Smiod 	  if (info->shared
7163d8817e4Smiod 	      && (get_elf_backend_data (abfd)
7173d8817e4Smiod 		  ->elf_backend_can_make_relative_eh_frame
7183d8817e4Smiod 		  (abfd, info, sec)))
7193d8817e4Smiod 	    {
720*fc67150aSkettenis 	      if ((cie->fde_encoding & 0xf0) == DW_EH_PE_absptr)
721*fc67150aSkettenis 		cie->make_relative = 1;
7223d8817e4Smiod 	      /* If the CIE doesn't already have an 'R' entry, it's fairly
7233d8817e4Smiod 		 easy to add one, provided that there's no aligned data
7243d8817e4Smiod 		 after the augmentation string.  */
725*fc67150aSkettenis 	      else if (cie->fde_encoding == DW_EH_PE_omit
726*fc67150aSkettenis 		       && (cie->per_encoding & 0xf0) != DW_EH_PE_aligned)
7273d8817e4Smiod 		{
728*fc67150aSkettenis 		  if (*cie->augmentation == 0)
7293d8817e4Smiod 		    this_inf->add_augmentation_size = 1;
7303d8817e4Smiod 		  this_inf->add_fde_encoding = 1;
731*fc67150aSkettenis 		  cie->make_relative = 1;
7323d8817e4Smiod 		}
7333d8817e4Smiod 	    }
7343d8817e4Smiod 
7353d8817e4Smiod 	  if (info->shared
7363d8817e4Smiod 	      && (get_elf_backend_data (abfd)
7373d8817e4Smiod 		  ->elf_backend_can_make_lsda_relative_eh_frame
7383d8817e4Smiod 		  (abfd, info, sec))
739*fc67150aSkettenis 	      && (cie->lsda_encoding & 0xf0) == DW_EH_PE_absptr)
740*fc67150aSkettenis 	    cie->make_lsda_relative = 1;
7413d8817e4Smiod 
7423d8817e4Smiod 	  /* If FDE encoding was not specified, it defaults to
7433d8817e4Smiod 	     DW_EH_absptr.  */
744*fc67150aSkettenis 	  if (cie->fde_encoding == DW_EH_PE_omit)
745*fc67150aSkettenis 	    cie->fde_encoding = DW_EH_PE_absptr;
7463d8817e4Smiod 
7473d8817e4Smiod 	  initial_insn_length = end - buf;
748*fc67150aSkettenis 	  if (initial_insn_length <= sizeof (cie->initial_instructions))
7493d8817e4Smiod 	    {
750*fc67150aSkettenis 	      cie->initial_insn_length = initial_insn_length;
751*fc67150aSkettenis 	      memcpy (cie->initial_instructions, buf, initial_insn_length);
7523d8817e4Smiod 	    }
7533d8817e4Smiod 	  insns = buf;
7543d8817e4Smiod 	  buf += initial_insn_length;
7553d8817e4Smiod 	  ENSURE_NO_RELOCS (buf);
7563d8817e4Smiod 	}
7573d8817e4Smiod       else
7583d8817e4Smiod 	{
759*fc67150aSkettenis 	  /* Find the corresponding CIE.  */
760*fc67150aSkettenis 	  unsigned int cie_offset = this_inf->offset + 4 - hdr_id;
761*fc67150aSkettenis 	  for (ecie = ecies; ecie < ecies + ecie_count; ++ecie)
762*fc67150aSkettenis 	    if (cie_offset == ecie->offset)
763*fc67150aSkettenis 	      break;
764*fc67150aSkettenis 
765*fc67150aSkettenis 	  /* Ensure this FDE references one of the CIEs in this input
766*fc67150aSkettenis 	     section.  */
767*fc67150aSkettenis 	  REQUIRE (ecie != ecies + ecie_count);
768*fc67150aSkettenis 	  cie = &ecie->cie;
7693d8817e4Smiod 
7703d8817e4Smiod 	  ENSURE_NO_RELOCS (buf);
7713d8817e4Smiod 	  REQUIRE (GET_RELOC (buf));
7723d8817e4Smiod 
7733d8817e4Smiod 	  if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
7743d8817e4Smiod 	    /* This is a FDE against a discarded section.  It should
7753d8817e4Smiod 	       be deleted.  */
7763d8817e4Smiod 	    this_inf->removed = 1;
7773d8817e4Smiod 	  else
7783d8817e4Smiod 	    {
7793d8817e4Smiod 	      if (info->shared
780*fc67150aSkettenis 		  && (((cie->fde_encoding & 0xf0) == DW_EH_PE_absptr
781*fc67150aSkettenis 		       && cie->make_relative == 0)
782*fc67150aSkettenis 		      || (cie->fde_encoding & 0xf0) == DW_EH_PE_aligned))
7833d8817e4Smiod 		{
7843d8817e4Smiod 		  /* If a shared library uses absolute pointers
7853d8817e4Smiod 		     which we cannot turn into PC relative,
7863d8817e4Smiod 		     don't create the binary search table,
7873d8817e4Smiod 		     since it is affected by runtime relocations.  */
7883d8817e4Smiod 		  hdr_info->table = FALSE;
7893d8817e4Smiod 		}
790*fc67150aSkettenis 	      ecie->usage_count++;
7913d8817e4Smiod 	      hdr_info->fde_count++;
792*fc67150aSkettenis 	      this_inf->cie_inf = (void *) (ecie - ecies);
7933d8817e4Smiod 	    }
794*fc67150aSkettenis 
7953d8817e4Smiod 	  /* Skip the initial location and address range.  */
7963d8817e4Smiod 	  start = buf;
797*fc67150aSkettenis 	  length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size);
7983d8817e4Smiod 	  REQUIRE (skip_bytes (&buf, end, 2 * length));
7993d8817e4Smiod 
8003d8817e4Smiod 	  /* Skip the augmentation size, if present.  */
801*fc67150aSkettenis 	  if (cie->augmentation[0] == 'z')
8023d8817e4Smiod 	    REQUIRE (read_uleb128 (&buf, end, &length));
8033d8817e4Smiod 	  else
8043d8817e4Smiod 	    length = 0;
8053d8817e4Smiod 
8063d8817e4Smiod 	  /* Of the supported augmentation characters above, only 'L'
8073d8817e4Smiod 	     adds augmentation data to the FDE.  This code would need to
8083d8817e4Smiod 	     be adjusted if any future augmentations do the same thing.  */
809*fc67150aSkettenis 	  if (cie->lsda_encoding != DW_EH_PE_omit)
8103d8817e4Smiod 	    {
8113d8817e4Smiod 	      this_inf->lsda_offset = buf - start;
8123d8817e4Smiod 	      /* If there's no 'z' augmentation, we don't know where the
8133d8817e4Smiod 		 CFA insns begin.  Assume no padding.  */
814*fc67150aSkettenis 	      if (cie->augmentation[0] != 'z')
8153d8817e4Smiod 		length = end - buf;
8163d8817e4Smiod 	    }
8173d8817e4Smiod 
8183d8817e4Smiod 	  /* Skip over the augmentation data.  */
8193d8817e4Smiod 	  REQUIRE (skip_bytes (&buf, end, length));
8203d8817e4Smiod 	  insns = buf;
8213d8817e4Smiod 
822*fc67150aSkettenis 	  buf = last_fde + 4 + hdr_length;
8233d8817e4Smiod 	  SKIP_RELOCS (buf);
8243d8817e4Smiod 	}
8253d8817e4Smiod 
8263d8817e4Smiod       /* Try to interpret the CFA instructions and find the first
8273d8817e4Smiod 	 padding nop.  Shrink this_inf's size so that it doesn't
828*fc67150aSkettenis 	 include the padding.  */
829*fc67150aSkettenis       length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size);
830*fc67150aSkettenis       set_loc_count = 0;
831*fc67150aSkettenis       insns_end = skip_non_nops (insns, end, length, &set_loc_count);
832*fc67150aSkettenis       /* If we don't understand the CFA instructions, we can't know
833*fc67150aSkettenis 	 what needs to be adjusted there.  */
834*fc67150aSkettenis       if (insns_end == NULL
835*fc67150aSkettenis 	  /* For the time being we don't support DW_CFA_set_loc in
836*fc67150aSkettenis 	     CIE instructions.  */
837*fc67150aSkettenis 	  || (set_loc_count && this_inf->cie))
838*fc67150aSkettenis 	goto free_no_table;
839*fc67150aSkettenis       this_inf->size -= end - insns_end;
840*fc67150aSkettenis       if (insns_end != end && this_inf->cie)
841*fc67150aSkettenis 	{
842*fc67150aSkettenis 	  cie->initial_insn_length -= end - insns_end;
843*fc67150aSkettenis 	  cie->length -= end - insns_end;
844*fc67150aSkettenis 	}
845*fc67150aSkettenis       if (set_loc_count
846*fc67150aSkettenis 	  && ((cie->fde_encoding & 0xf0) == DW_EH_PE_pcrel
847*fc67150aSkettenis 	      || cie->make_relative))
848*fc67150aSkettenis 	{
849*fc67150aSkettenis 	  unsigned int cnt;
850*fc67150aSkettenis 	  bfd_byte *p;
8513d8817e4Smiod 
852*fc67150aSkettenis 	  this_inf->set_loc = bfd_malloc ((set_loc_count + 1)
853*fc67150aSkettenis 					  * sizeof (unsigned int));
854*fc67150aSkettenis 	  REQUIRE (this_inf->set_loc);
855*fc67150aSkettenis 	  this_inf->set_loc[0] = set_loc_count;
856*fc67150aSkettenis 	  p = insns;
857*fc67150aSkettenis 	  cnt = 0;
858*fc67150aSkettenis 	  while (p < end)
859*fc67150aSkettenis 	    {
860*fc67150aSkettenis 	      if (*p == DW_CFA_set_loc)
861*fc67150aSkettenis 		this_inf->set_loc[++cnt] = p + 1 - start;
862*fc67150aSkettenis 	      REQUIRE (skip_cfa_op (&p, end, length));
863*fc67150aSkettenis 	    }
864*fc67150aSkettenis 	}
865*fc67150aSkettenis 
866*fc67150aSkettenis       this_inf->fde_encoding = cie->fde_encoding;
867*fc67150aSkettenis       this_inf->lsda_encoding = cie->lsda_encoding;
8683d8817e4Smiod       sec_info->count++;
8693d8817e4Smiod     }
8703d8817e4Smiod 
8713d8817e4Smiod   elf_section_data (sec)->sec_info = sec_info;
8723d8817e4Smiod   sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
8733d8817e4Smiod 
874*fc67150aSkettenis   /* Look at all CIEs in this section and determine which can be
875*fc67150aSkettenis      removed as unused, which can be merged with previous duplicate
876*fc67150aSkettenis      CIEs and which need to be kept.  */
877*fc67150aSkettenis   for (ecie = ecies; ecie < ecies + ecie_count; ++ecie)
878*fc67150aSkettenis     {
879*fc67150aSkettenis       if (ecie->usage_count == 0)
880*fc67150aSkettenis 	{
881*fc67150aSkettenis 	  sec_info->entry[ecie->entry].removed = 1;
882*fc67150aSkettenis 	  continue;
883*fc67150aSkettenis 	}
884*fc67150aSkettenis       ecie->cie.output_sec = sec->output_section;
885*fc67150aSkettenis       ecie->cie.cie_inf = sec_info->entry + ecie->entry;
886*fc67150aSkettenis       cie_compute_hash (&ecie->cie);
887*fc67150aSkettenis       if (hdr_info->cies != NULL)
888*fc67150aSkettenis 	{
889*fc67150aSkettenis 	  void **loc = htab_find_slot_with_hash (hdr_info->cies, &ecie->cie,
890*fc67150aSkettenis 						 ecie->cie.hash, INSERT);
891*fc67150aSkettenis 	  if (loc != NULL)
892*fc67150aSkettenis 	    {
893*fc67150aSkettenis 	      if (*loc != HTAB_EMPTY_ENTRY)
894*fc67150aSkettenis 		{
895*fc67150aSkettenis 		  sec_info->entry[ecie->entry].removed = 1;
896*fc67150aSkettenis 		  ecie->cie.cie_inf = ((struct cie *) *loc)->cie_inf;
897*fc67150aSkettenis 		  continue;
898*fc67150aSkettenis 		}
899*fc67150aSkettenis 
900*fc67150aSkettenis 	      *loc = malloc (sizeof (struct cie));
901*fc67150aSkettenis 	      if (*loc == NULL)
902*fc67150aSkettenis 		*loc = HTAB_DELETED_ENTRY;
903*fc67150aSkettenis 	      else
904*fc67150aSkettenis 		memcpy (*loc, &ecie->cie, sizeof (struct cie));
905*fc67150aSkettenis 	    }
906*fc67150aSkettenis 	}
907*fc67150aSkettenis       ecie->cie.cie_inf->make_relative = ecie->cie.make_relative;
908*fc67150aSkettenis       ecie->cie.cie_inf->make_lsda_relative = ecie->cie.make_lsda_relative;
909*fc67150aSkettenis       ecie->cie.cie_inf->per_encoding_relative
910*fc67150aSkettenis 	= (ecie->cie.per_encoding & 0x70) == DW_EH_PE_pcrel;
911*fc67150aSkettenis     }
912*fc67150aSkettenis 
9133d8817e4Smiod   /* Ok, now we can assign new offsets.  */
9143d8817e4Smiod   offset = 0;
9153d8817e4Smiod   for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
9163d8817e4Smiod     if (!ent->removed)
9173d8817e4Smiod       {
918*fc67150aSkettenis 	if (!ent->cie)
919*fc67150aSkettenis 	  {
920*fc67150aSkettenis 	    ecie = ecies + (unsigned long) ent->cie_inf;
921*fc67150aSkettenis 	    ent->cie_inf = ecie->cie.cie_inf;
922*fc67150aSkettenis 	  }
9233d8817e4Smiod 	ent->new_offset = offset;
9243d8817e4Smiod 	offset += size_of_output_cie_fde (ent, ptr_size);
9253d8817e4Smiod       }
9263d8817e4Smiod 
9273d8817e4Smiod   /* Resize the sec as needed.  */
9283d8817e4Smiod   sec->rawsize = sec->size;
9293d8817e4Smiod   sec->size = offset;
9303d8817e4Smiod   if (sec->size == 0)
9313d8817e4Smiod     sec->flags |= SEC_EXCLUDE;
9323d8817e4Smiod 
9333d8817e4Smiod   free (ehbuf);
934*fc67150aSkettenis   if (ecies)
935*fc67150aSkettenis     free (ecies);
9363d8817e4Smiod   return offset != sec->rawsize;
9373d8817e4Smiod 
9383d8817e4Smiod free_no_table:
9393d8817e4Smiod   if (ehbuf)
9403d8817e4Smiod     free (ehbuf);
9413d8817e4Smiod   if (sec_info)
9423d8817e4Smiod     free (sec_info);
943*fc67150aSkettenis   if (ecies)
944*fc67150aSkettenis     free (ecies);
9453d8817e4Smiod   hdr_info->table = FALSE;
9463d8817e4Smiod   return FALSE;
9473d8817e4Smiod 
9483d8817e4Smiod #undef REQUIRE
9493d8817e4Smiod }
9503d8817e4Smiod 
9513d8817e4Smiod /* This function is called for .eh_frame_hdr section after
9523d8817e4Smiod    _bfd_elf_discard_section_eh_frame has been called on all .eh_frame
9533d8817e4Smiod    input sections.  It finalizes the size of .eh_frame_hdr section.  */
9543d8817e4Smiod 
9553d8817e4Smiod bfd_boolean
_bfd_elf_discard_section_eh_frame_hdr(bfd * abfd,struct bfd_link_info * info)9563d8817e4Smiod _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
9573d8817e4Smiod {
9583d8817e4Smiod   struct elf_link_hash_table *htab;
9593d8817e4Smiod   struct eh_frame_hdr_info *hdr_info;
9603d8817e4Smiod   asection *sec;
9613d8817e4Smiod 
9623d8817e4Smiod   htab = elf_hash_table (info);
9633d8817e4Smiod   hdr_info = &htab->eh_info;
964*fc67150aSkettenis 
965*fc67150aSkettenis   if (hdr_info->cies != NULL)
966*fc67150aSkettenis     {
967*fc67150aSkettenis       htab_delete (hdr_info->cies);
968*fc67150aSkettenis       hdr_info->cies = NULL;
969*fc67150aSkettenis     }
970*fc67150aSkettenis 
9713d8817e4Smiod   sec = hdr_info->hdr_sec;
9723d8817e4Smiod   if (sec == NULL)
9733d8817e4Smiod     return FALSE;
9743d8817e4Smiod 
9753d8817e4Smiod   sec->size = EH_FRAME_HDR_SIZE;
9763d8817e4Smiod   if (hdr_info->table)
9773d8817e4Smiod     sec->size += 4 + hdr_info->fde_count * 8;
9783d8817e4Smiod 
9793d8817e4Smiod   /* Request program headers to be recalculated.  */
9803d8817e4Smiod   elf_tdata (abfd)->program_header_size = 0;
9813d8817e4Smiod   elf_tdata (abfd)->eh_frame_hdr = sec;
9823d8817e4Smiod   return TRUE;
9833d8817e4Smiod }
9843d8817e4Smiod 
9853d8817e4Smiod /* This function is called from size_dynamic_sections.
9863d8817e4Smiod    It needs to decide whether .eh_frame_hdr should be output or not,
9873d8817e4Smiod    because when the dynamic symbol table has been sized it is too late
9883d8817e4Smiod    to strip sections.  */
9893d8817e4Smiod 
9903d8817e4Smiod bfd_boolean
_bfd_elf_maybe_strip_eh_frame_hdr(struct bfd_link_info * info)9913d8817e4Smiod _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info)
9923d8817e4Smiod {
9933d8817e4Smiod   asection *o;
9943d8817e4Smiod   bfd *abfd;
9953d8817e4Smiod   struct elf_link_hash_table *htab;
9963d8817e4Smiod   struct eh_frame_hdr_info *hdr_info;
9973d8817e4Smiod 
9983d8817e4Smiod   htab = elf_hash_table (info);
9993d8817e4Smiod   hdr_info = &htab->eh_info;
10003d8817e4Smiod   if (hdr_info->hdr_sec == NULL)
10013d8817e4Smiod     return TRUE;
10023d8817e4Smiod 
10033d8817e4Smiod   if (bfd_is_abs_section (hdr_info->hdr_sec->output_section))
10043d8817e4Smiod     {
10053d8817e4Smiod       hdr_info->hdr_sec = NULL;
10063d8817e4Smiod       return TRUE;
10073d8817e4Smiod     }
10083d8817e4Smiod 
10093d8817e4Smiod   abfd = NULL;
10103d8817e4Smiod   if (info->eh_frame_hdr)
10113d8817e4Smiod     for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
10123d8817e4Smiod       {
10133d8817e4Smiod 	/* Count only sections which have at least a single CIE or FDE.
10143d8817e4Smiod 	   There cannot be any CIE or FDE <= 8 bytes.  */
10153d8817e4Smiod 	o = bfd_get_section_by_name (abfd, ".eh_frame");
10163d8817e4Smiod 	if (o && o->size > 8 && !bfd_is_abs_section (o->output_section))
10173d8817e4Smiod 	  break;
10183d8817e4Smiod       }
10193d8817e4Smiod 
10203d8817e4Smiod   if (abfd == NULL)
10213d8817e4Smiod     {
10223d8817e4Smiod       hdr_info->hdr_sec->flags |= SEC_EXCLUDE;
10233d8817e4Smiod       hdr_info->hdr_sec = NULL;
10243d8817e4Smiod       return TRUE;
10253d8817e4Smiod     }
10263d8817e4Smiod 
10273d8817e4Smiod   hdr_info->table = TRUE;
10283d8817e4Smiod   return TRUE;
10293d8817e4Smiod }
10303d8817e4Smiod 
10313d8817e4Smiod /* Adjust an address in the .eh_frame section.  Given OFFSET within
10323d8817e4Smiod    SEC, this returns the new offset in the adjusted .eh_frame section,
10333d8817e4Smiod    or -1 if the address refers to a CIE/FDE which has been removed
10343d8817e4Smiod    or to offset with dynamic relocation which is no longer needed.  */
10353d8817e4Smiod 
10363d8817e4Smiod bfd_vma
_bfd_elf_eh_frame_section_offset(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info,asection * sec,bfd_vma offset)10373d8817e4Smiod _bfd_elf_eh_frame_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
10383d8817e4Smiod 				  struct bfd_link_info *info,
10393d8817e4Smiod 				  asection *sec,
10403d8817e4Smiod 				  bfd_vma offset)
10413d8817e4Smiod {
10423d8817e4Smiod   struct eh_frame_sec_info *sec_info;
10433d8817e4Smiod   struct elf_link_hash_table *htab;
10443d8817e4Smiod   struct eh_frame_hdr_info *hdr_info;
10453d8817e4Smiod   unsigned int lo, hi, mid;
10463d8817e4Smiod 
10473d8817e4Smiod   if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
10483d8817e4Smiod     return offset;
10493d8817e4Smiod   sec_info = elf_section_data (sec)->sec_info;
10503d8817e4Smiod 
10513d8817e4Smiod   if (offset >= sec->rawsize)
10523d8817e4Smiod     return offset - sec->rawsize + sec->size;
10533d8817e4Smiod 
10543d8817e4Smiod   htab = elf_hash_table (info);
10553d8817e4Smiod   hdr_info = &htab->eh_info;
10563d8817e4Smiod   if (hdr_info->offsets_adjusted)
10573d8817e4Smiod     offset += sec->output_offset;
10583d8817e4Smiod 
10593d8817e4Smiod   lo = 0;
10603d8817e4Smiod   hi = sec_info->count;
10613d8817e4Smiod   mid = 0;
10623d8817e4Smiod   while (lo < hi)
10633d8817e4Smiod     {
10643d8817e4Smiod       mid = (lo + hi) / 2;
10653d8817e4Smiod       if (offset < sec_info->entry[mid].offset)
10663d8817e4Smiod 	hi = mid;
10673d8817e4Smiod       else if (offset
10683d8817e4Smiod 	       >= sec_info->entry[mid].offset + sec_info->entry[mid].size)
10693d8817e4Smiod 	lo = mid + 1;
10703d8817e4Smiod       else
10713d8817e4Smiod 	break;
10723d8817e4Smiod     }
10733d8817e4Smiod 
10743d8817e4Smiod   BFD_ASSERT (lo < hi);
10753d8817e4Smiod 
10763d8817e4Smiod   /* FDE or CIE was removed.  */
10773d8817e4Smiod   if (sec_info->entry[mid].removed)
10783d8817e4Smiod     return (bfd_vma) -1;
10793d8817e4Smiod 
10803d8817e4Smiod   /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
10813d8817e4Smiod      relocation against FDE's initial_location field.  */
10823d8817e4Smiod   if (!sec_info->entry[mid].cie
10833d8817e4Smiod       && sec_info->entry[mid].cie_inf->make_relative
10843d8817e4Smiod       && offset == sec_info->entry[mid].offset + 8)
10853d8817e4Smiod     return (bfd_vma) -2;
10863d8817e4Smiod 
10873d8817e4Smiod   /* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need
10883d8817e4Smiod      for run-time relocation against LSDA field.  */
10893d8817e4Smiod   if (!sec_info->entry[mid].cie
10903d8817e4Smiod       && sec_info->entry[mid].cie_inf->make_lsda_relative
10913d8817e4Smiod       && (offset == (sec_info->entry[mid].offset + 8
10923d8817e4Smiod 		     + sec_info->entry[mid].lsda_offset))
10933d8817e4Smiod       && (sec_info->entry[mid].cie_inf->need_lsda_relative
10943d8817e4Smiod 	  || !hdr_info->offsets_adjusted))
10953d8817e4Smiod     {
10963d8817e4Smiod       sec_info->entry[mid].cie_inf->need_lsda_relative = 1;
10973d8817e4Smiod       return (bfd_vma) -2;
10983d8817e4Smiod     }
10993d8817e4Smiod 
1100*fc67150aSkettenis   /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
1101*fc67150aSkettenis      relocation against DW_CFA_set_loc's arguments.  */
1102*fc67150aSkettenis   if (sec_info->entry[mid].set_loc
1103*fc67150aSkettenis       && (sec_info->entry[mid].cie
1104*fc67150aSkettenis 	  ? sec_info->entry[mid].make_relative
1105*fc67150aSkettenis 	  : sec_info->entry[mid].cie_inf->make_relative)
1106*fc67150aSkettenis       && (offset >= sec_info->entry[mid].offset + 8
1107*fc67150aSkettenis 		    + sec_info->entry[mid].set_loc[1]))
1108*fc67150aSkettenis     {
1109*fc67150aSkettenis       unsigned int cnt;
1110*fc67150aSkettenis 
1111*fc67150aSkettenis       for (cnt = 1; cnt <= sec_info->entry[mid].set_loc[0]; cnt++)
1112*fc67150aSkettenis 	if (offset == sec_info->entry[mid].offset + 8
1113*fc67150aSkettenis 		      + sec_info->entry[mid].set_loc[cnt])
1114*fc67150aSkettenis 	  return (bfd_vma) -2;
1115*fc67150aSkettenis     }
1116*fc67150aSkettenis 
11173d8817e4Smiod   if (hdr_info->offsets_adjusted)
11183d8817e4Smiod     offset -= sec->output_offset;
11193d8817e4Smiod   /* Any new augmentation bytes go before the first relocation.  */
11203d8817e4Smiod   return (offset + sec_info->entry[mid].new_offset
11213d8817e4Smiod 	  - sec_info->entry[mid].offset
11223d8817e4Smiod 	  + extra_augmentation_string_bytes (sec_info->entry + mid)
11233d8817e4Smiod 	  + extra_augmentation_data_bytes (sec_info->entry + mid));
11243d8817e4Smiod }
11253d8817e4Smiod 
11263d8817e4Smiod /* Write out .eh_frame section.  This is called with the relocated
11273d8817e4Smiod    contents.  */
11283d8817e4Smiod 
11293d8817e4Smiod bfd_boolean
_bfd_elf_write_section_eh_frame(bfd * abfd,struct bfd_link_info * info,asection * sec,bfd_byte * contents)11303d8817e4Smiod _bfd_elf_write_section_eh_frame (bfd *abfd,
11313d8817e4Smiod 				 struct bfd_link_info *info,
11323d8817e4Smiod 				 asection *sec,
11333d8817e4Smiod 				 bfd_byte *contents)
11343d8817e4Smiod {
11353d8817e4Smiod   struct eh_frame_sec_info *sec_info;
11363d8817e4Smiod   struct elf_link_hash_table *htab;
11373d8817e4Smiod   struct eh_frame_hdr_info *hdr_info;
11383d8817e4Smiod   unsigned int ptr_size;
11393d8817e4Smiod   struct eh_cie_fde *ent;
11403d8817e4Smiod 
11413d8817e4Smiod   if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
11423d8817e4Smiod     return bfd_set_section_contents (abfd, sec->output_section, contents,
11433d8817e4Smiod 				     sec->output_offset, sec->size);
11443d8817e4Smiod 
11453d8817e4Smiod   ptr_size = (get_elf_backend_data (abfd)
11463d8817e4Smiod 	      ->elf_backend_eh_frame_address_size (abfd, sec));
11473d8817e4Smiod   BFD_ASSERT (ptr_size != 0);
11483d8817e4Smiod 
11493d8817e4Smiod   sec_info = elf_section_data (sec)->sec_info;
11503d8817e4Smiod   htab = elf_hash_table (info);
11513d8817e4Smiod   hdr_info = &htab->eh_info;
11523d8817e4Smiod 
11533d8817e4Smiod   /* First convert all offsets to output section offsets, so that a
11543d8817e4Smiod      CIE offset is valid if the CIE is used by a FDE from some other
11553d8817e4Smiod      section.  This can happen when duplicate CIEs are deleted in
11563d8817e4Smiod      _bfd_elf_discard_section_eh_frame.  We do all sections here because
11573d8817e4Smiod      this function might not be called on sections in the same order as
11583d8817e4Smiod      _bfd_elf_discard_section_eh_frame.  */
11593d8817e4Smiod   if (!hdr_info->offsets_adjusted)
11603d8817e4Smiod     {
11613d8817e4Smiod       bfd *ibfd;
11623d8817e4Smiod       asection *eh;
11633d8817e4Smiod       struct eh_frame_sec_info *eh_inf;
11643d8817e4Smiod 
11653d8817e4Smiod       for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
11663d8817e4Smiod 	{
11673d8817e4Smiod 	  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
11683d8817e4Smiod 	      || (ibfd->flags & DYNAMIC) != 0)
11693d8817e4Smiod 	    continue;
11703d8817e4Smiod 
11713d8817e4Smiod 	  eh = bfd_get_section_by_name (ibfd, ".eh_frame");
11723d8817e4Smiod 	  if (eh == NULL || eh->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
11733d8817e4Smiod 	    continue;
11743d8817e4Smiod 
11753d8817e4Smiod 	  eh_inf = elf_section_data (eh)->sec_info;
11763d8817e4Smiod 	  for (ent = eh_inf->entry; ent < eh_inf->entry + eh_inf->count; ++ent)
11773d8817e4Smiod 	    {
11783d8817e4Smiod 	      ent->offset += eh->output_offset;
11793d8817e4Smiod 	      ent->new_offset += eh->output_offset;
11803d8817e4Smiod 	    }
11813d8817e4Smiod 	}
11823d8817e4Smiod       hdr_info->offsets_adjusted = TRUE;
11833d8817e4Smiod     }
11843d8817e4Smiod 
11853d8817e4Smiod   if (hdr_info->table && hdr_info->array == NULL)
11863d8817e4Smiod     hdr_info->array
11873d8817e4Smiod       = bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
11883d8817e4Smiod   if (hdr_info->array == NULL)
11893d8817e4Smiod     hdr_info = NULL;
11903d8817e4Smiod 
11913d8817e4Smiod   /* The new offsets can be bigger or smaller than the original offsets.
11923d8817e4Smiod      We therefore need to make two passes over the section: one backward
11933d8817e4Smiod      pass to move entries up and one forward pass to move entries down.
11943d8817e4Smiod      The two passes won't interfere with each other because entries are
11953d8817e4Smiod      not reordered  */
11963d8817e4Smiod   for (ent = sec_info->entry + sec_info->count; ent-- != sec_info->entry;)
11973d8817e4Smiod     if (!ent->removed && ent->new_offset > ent->offset)
11983d8817e4Smiod       memmove (contents + ent->new_offset - sec->output_offset,
11993d8817e4Smiod 	       contents + ent->offset - sec->output_offset, ent->size);
12003d8817e4Smiod 
12013d8817e4Smiod   for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
12023d8817e4Smiod     if (!ent->removed && ent->new_offset < ent->offset)
12033d8817e4Smiod       memmove (contents + ent->new_offset - sec->output_offset,
12043d8817e4Smiod 	       contents + ent->offset - sec->output_offset, ent->size);
12053d8817e4Smiod 
12063d8817e4Smiod   for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
12073d8817e4Smiod     {
12083d8817e4Smiod       unsigned char *buf, *end;
12093d8817e4Smiod       unsigned int new_size;
12103d8817e4Smiod 
12113d8817e4Smiod       if (ent->removed)
12123d8817e4Smiod 	continue;
12133d8817e4Smiod 
12143d8817e4Smiod       if (ent->size == 4)
12153d8817e4Smiod 	{
12163d8817e4Smiod 	  /* Any terminating FDE must be at the end of the section.  */
12173d8817e4Smiod 	  BFD_ASSERT (ent == sec_info->entry + sec_info->count - 1);
12183d8817e4Smiod 	  continue;
12193d8817e4Smiod 	}
12203d8817e4Smiod 
12213d8817e4Smiod       buf = contents + ent->new_offset - sec->output_offset;
12223d8817e4Smiod       end = buf + ent->size;
12233d8817e4Smiod       new_size = size_of_output_cie_fde (ent, ptr_size);
12243d8817e4Smiod 
12253d8817e4Smiod       /* Update the size.  It may be shrinked.  */
12263d8817e4Smiod       bfd_put_32 (abfd, new_size - 4, buf);
12273d8817e4Smiod 
12283d8817e4Smiod       /* Filling the extra bytes with DW_CFA_nops.  */
12293d8817e4Smiod       if (new_size != ent->size)
12303d8817e4Smiod 	memset (end, 0, new_size - ent->size);
12313d8817e4Smiod 
12323d8817e4Smiod       if (ent->cie)
12333d8817e4Smiod 	{
12343d8817e4Smiod 	  /* CIE */
12353d8817e4Smiod 	  if (ent->make_relative
12363d8817e4Smiod 	      || ent->need_lsda_relative
12373d8817e4Smiod 	      || ent->per_encoding_relative)
12383d8817e4Smiod 	    {
12393d8817e4Smiod 	      char *aug;
12403d8817e4Smiod 	      unsigned int action, extra_string, extra_data;
12413d8817e4Smiod 	      unsigned int per_width, per_encoding;
12423d8817e4Smiod 
12433d8817e4Smiod 	      /* Need to find 'R' or 'L' augmentation's argument and modify
12443d8817e4Smiod 		 DW_EH_PE_* value.  */
12453d8817e4Smiod 	      action = ((ent->make_relative ? 1 : 0)
12463d8817e4Smiod 			| (ent->need_lsda_relative ? 2 : 0)
12473d8817e4Smiod 			| (ent->per_encoding_relative ? 4 : 0));
12483d8817e4Smiod 	      extra_string = extra_augmentation_string_bytes (ent);
12493d8817e4Smiod 	      extra_data = extra_augmentation_data_bytes (ent);
12503d8817e4Smiod 
12513d8817e4Smiod 	      /* Skip length, id and version.  */
12523d8817e4Smiod 	      buf += 9;
12533d8817e4Smiod 	      aug = (char *) buf;
12543d8817e4Smiod 	      buf += strlen (aug) + 1;
12553d8817e4Smiod 	      skip_leb128 (&buf, end);
12563d8817e4Smiod 	      skip_leb128 (&buf, end);
12573d8817e4Smiod 	      skip_leb128 (&buf, end);
12583d8817e4Smiod 	      if (*aug == 'z')
12593d8817e4Smiod 		{
12603d8817e4Smiod 		  /* The uleb128 will always be a single byte for the kind
12613d8817e4Smiod 		     of augmentation strings that we're prepared to handle.  */
12623d8817e4Smiod 		  *buf++ += extra_data;
12633d8817e4Smiod 		  aug++;
12643d8817e4Smiod 		}
12653d8817e4Smiod 
12663d8817e4Smiod 	      /* Make room for the new augmentation string and data bytes.  */
12673d8817e4Smiod 	      memmove (buf + extra_string + extra_data, buf, end - buf);
12683d8817e4Smiod 	      memmove (aug + extra_string, aug, buf - (bfd_byte *) aug);
12693d8817e4Smiod 	      buf += extra_string;
12703d8817e4Smiod 	      end += extra_string + extra_data;
12713d8817e4Smiod 
12723d8817e4Smiod 	      if (ent->add_augmentation_size)
12733d8817e4Smiod 		{
12743d8817e4Smiod 		  *aug++ = 'z';
12753d8817e4Smiod 		  *buf++ = extra_data - 1;
12763d8817e4Smiod 		}
12773d8817e4Smiod 	      if (ent->add_fde_encoding)
12783d8817e4Smiod 		{
12793d8817e4Smiod 		  BFD_ASSERT (action & 1);
12803d8817e4Smiod 		  *aug++ = 'R';
12813d8817e4Smiod 		  *buf++ = DW_EH_PE_pcrel;
12823d8817e4Smiod 		  action &= ~1;
12833d8817e4Smiod 		}
12843d8817e4Smiod 
12853d8817e4Smiod 	      while (action)
12863d8817e4Smiod 		switch (*aug++)
12873d8817e4Smiod 		  {
12883d8817e4Smiod 		  case 'L':
12893d8817e4Smiod 		    if (action & 2)
12903d8817e4Smiod 		      {
12913d8817e4Smiod 			BFD_ASSERT (*buf == ent->lsda_encoding);
12923d8817e4Smiod 			*buf |= DW_EH_PE_pcrel;
12933d8817e4Smiod 			action &= ~2;
12943d8817e4Smiod 		      }
12953d8817e4Smiod 		    buf++;
12963d8817e4Smiod 		    break;
12973d8817e4Smiod 		  case 'P':
12983d8817e4Smiod 		    per_encoding = *buf++;
12993d8817e4Smiod 		    per_width = get_DW_EH_PE_width (per_encoding, ptr_size);
13003d8817e4Smiod 		    BFD_ASSERT (per_width != 0);
13013d8817e4Smiod 		    BFD_ASSERT (((per_encoding & 0x70) == DW_EH_PE_pcrel)
13023d8817e4Smiod 				== ent->per_encoding_relative);
13033d8817e4Smiod 		    if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
13043d8817e4Smiod 		      buf = (contents
13053d8817e4Smiod 			     + ((buf - contents + per_width - 1)
13063d8817e4Smiod 				& ~((bfd_size_type) per_width - 1)));
13073d8817e4Smiod 		    if (action & 4)
13083d8817e4Smiod 		      {
13093d8817e4Smiod 			bfd_vma val;
13103d8817e4Smiod 
13113d8817e4Smiod 			val = read_value (abfd, buf, per_width,
13123d8817e4Smiod 					  get_DW_EH_PE_signed (per_encoding));
13133d8817e4Smiod 			val += ent->offset - ent->new_offset;
13143d8817e4Smiod 			val -= extra_string + extra_data;
13153d8817e4Smiod 			write_value (abfd, buf, val, per_width);
13163d8817e4Smiod 			action &= ~4;
13173d8817e4Smiod 		      }
13183d8817e4Smiod 		    buf += per_width;
13193d8817e4Smiod 		    break;
13203d8817e4Smiod 		  case 'R':
13213d8817e4Smiod 		    if (action & 1)
13223d8817e4Smiod 		      {
13233d8817e4Smiod 			BFD_ASSERT (*buf == ent->fde_encoding);
13243d8817e4Smiod 			*buf |= DW_EH_PE_pcrel;
13253d8817e4Smiod 			action &= ~1;
13263d8817e4Smiod 		      }
13273d8817e4Smiod 		    buf++;
13283d8817e4Smiod 		    break;
13293d8817e4Smiod 		  case 'S':
13303d8817e4Smiod 		    break;
13313d8817e4Smiod 		  default:
13323d8817e4Smiod 		    BFD_FAIL ();
13333d8817e4Smiod 		  }
13343d8817e4Smiod 	    }
13353d8817e4Smiod 	}
13363d8817e4Smiod       else
13373d8817e4Smiod 	{
13383d8817e4Smiod 	  /* FDE */
13393d8817e4Smiod 	  bfd_vma value, address;
13403d8817e4Smiod 	  unsigned int width;
1341*fc67150aSkettenis 	  bfd_byte *start;
13423d8817e4Smiod 
13433d8817e4Smiod 	  /* Skip length.  */
13443d8817e4Smiod 	  buf += 4;
13453d8817e4Smiod 	  value = ent->new_offset + 4 - ent->cie_inf->new_offset;
13463d8817e4Smiod 	  bfd_put_32 (abfd, value, buf);
13473d8817e4Smiod 	  buf += 4;
13483d8817e4Smiod 	  width = get_DW_EH_PE_width (ent->fde_encoding, ptr_size);
13493d8817e4Smiod 	  value = read_value (abfd, buf, width,
13503d8817e4Smiod 			      get_DW_EH_PE_signed (ent->fde_encoding));
13513d8817e4Smiod 	  address = value;
13523d8817e4Smiod 	  if (value)
13533d8817e4Smiod 	    {
13543d8817e4Smiod 	      switch (ent->fde_encoding & 0xf0)
13553d8817e4Smiod 		{
13563d8817e4Smiod 		case DW_EH_PE_indirect:
13573d8817e4Smiod 		case DW_EH_PE_textrel:
13583d8817e4Smiod 		  BFD_ASSERT (hdr_info == NULL);
13593d8817e4Smiod 		  break;
13603d8817e4Smiod 		case DW_EH_PE_datarel:
13613d8817e4Smiod 		  {
13623d8817e4Smiod 		    asection *got = bfd_get_section_by_name (abfd, ".got");
13633d8817e4Smiod 
13643d8817e4Smiod 		    BFD_ASSERT (got != NULL);
13653d8817e4Smiod 		    address += got->vma;
13663d8817e4Smiod 		  }
13673d8817e4Smiod 		  break;
13683d8817e4Smiod 		case DW_EH_PE_pcrel:
13693d8817e4Smiod 		  value += ent->offset - ent->new_offset;
13703d8817e4Smiod 		  address += sec->output_section->vma + ent->offset + 8;
13713d8817e4Smiod 		  break;
13723d8817e4Smiod 		}
13733d8817e4Smiod 	      if (ent->cie_inf->make_relative)
13743d8817e4Smiod 		value -= sec->output_section->vma + ent->new_offset + 8;
13753d8817e4Smiod 	      write_value (abfd, buf, value, width);
13763d8817e4Smiod 	    }
13773d8817e4Smiod 
1378*fc67150aSkettenis 	  start = buf;
1379*fc67150aSkettenis 
13803d8817e4Smiod 	  if (hdr_info)
13813d8817e4Smiod 	    {
13823d8817e4Smiod 	      hdr_info->array[hdr_info->array_count].initial_loc = address;
13833d8817e4Smiod 	      hdr_info->array[hdr_info->array_count++].fde
13843d8817e4Smiod 		= sec->output_section->vma + ent->new_offset;
13853d8817e4Smiod 	    }
13863d8817e4Smiod 
13873d8817e4Smiod 	  if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel
13883d8817e4Smiod 	      || ent->cie_inf->need_lsda_relative)
13893d8817e4Smiod 	    {
13903d8817e4Smiod 	      buf += ent->lsda_offset;
13913d8817e4Smiod 	      width = get_DW_EH_PE_width (ent->lsda_encoding, ptr_size);
13923d8817e4Smiod 	      value = read_value (abfd, buf, width,
13933d8817e4Smiod 				  get_DW_EH_PE_signed (ent->lsda_encoding));
13943d8817e4Smiod 	      if (value)
13953d8817e4Smiod 		{
13963d8817e4Smiod 		  if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel)
13973d8817e4Smiod 		    value += ent->offset - ent->new_offset;
13983d8817e4Smiod 		  else if (ent->cie_inf->need_lsda_relative)
13993d8817e4Smiod 		    value -= (sec->output_section->vma + ent->new_offset + 8
14003d8817e4Smiod 			      + ent->lsda_offset);
14013d8817e4Smiod 		  write_value (abfd, buf, value, width);
14023d8817e4Smiod 		}
14033d8817e4Smiod 	    }
14043d8817e4Smiod 	  else if (ent->cie_inf->add_augmentation_size)
14053d8817e4Smiod 	    {
14063d8817e4Smiod 	      /* Skip the PC and length and insert a zero byte for the
14073d8817e4Smiod 		 augmentation size.  */
14083d8817e4Smiod 	      buf += width * 2;
14093d8817e4Smiod 	      memmove (buf + 1, buf, end - buf);
14103d8817e4Smiod 	      *buf = 0;
14113d8817e4Smiod 	    }
1412*fc67150aSkettenis 
1413*fc67150aSkettenis 	  if (ent->set_loc)
1414*fc67150aSkettenis 	    {
1415*fc67150aSkettenis 	      /* Adjust DW_CFA_set_loc.  */
1416*fc67150aSkettenis 	      unsigned int cnt, width;
1417*fc67150aSkettenis 	      bfd_vma new_offset;
1418*fc67150aSkettenis 
1419*fc67150aSkettenis 	      width = get_DW_EH_PE_width (ent->fde_encoding, ptr_size);
1420*fc67150aSkettenis 	      new_offset = ent->new_offset + 8
1421*fc67150aSkettenis 			   + extra_augmentation_string_bytes (ent)
1422*fc67150aSkettenis 			   + extra_augmentation_data_bytes (ent);
1423*fc67150aSkettenis 
1424*fc67150aSkettenis 	      for (cnt = 1; cnt <= ent->set_loc[0]; cnt++)
1425*fc67150aSkettenis 		{
1426*fc67150aSkettenis 		  bfd_vma value;
1427*fc67150aSkettenis 		  buf = start + ent->set_loc[cnt];
1428*fc67150aSkettenis 
1429*fc67150aSkettenis 		  value = read_value (abfd, buf, width,
1430*fc67150aSkettenis 				      get_DW_EH_PE_signed (ent->fde_encoding));
1431*fc67150aSkettenis 		  if (!value)
1432*fc67150aSkettenis 		    continue;
1433*fc67150aSkettenis 
1434*fc67150aSkettenis 		  if ((ent->fde_encoding & 0xf0) == DW_EH_PE_pcrel)
1435*fc67150aSkettenis 		    value += ent->offset + 8 - new_offset;
1436*fc67150aSkettenis 		  if (ent->cie_inf->make_relative)
1437*fc67150aSkettenis 		    value -= sec->output_section->vma + new_offset
1438*fc67150aSkettenis 			     + ent->set_loc[cnt];
1439*fc67150aSkettenis 		  write_value (abfd, buf, value, width);
1440*fc67150aSkettenis 		}
1441*fc67150aSkettenis 	    }
14423d8817e4Smiod 	}
14433d8817e4Smiod     }
14443d8817e4Smiod 
14453d8817e4Smiod   /* We don't align the section to its section alignment since the
14463d8817e4Smiod      runtime library only expects all CIE/FDE records aligned at
14473d8817e4Smiod      the pointer size. _bfd_elf_discard_section_eh_frame should
14483d8817e4Smiod      have padded CIE/FDE records to multiple of pointer size with
14493d8817e4Smiod      size_of_output_cie_fde.  */
14503d8817e4Smiod   if ((sec->size % ptr_size) != 0)
14513d8817e4Smiod     abort ();
14523d8817e4Smiod 
14533d8817e4Smiod   return bfd_set_section_contents (abfd, sec->output_section,
14543d8817e4Smiod 				   contents, (file_ptr) sec->output_offset,
14553d8817e4Smiod 				   sec->size);
14563d8817e4Smiod }
14573d8817e4Smiod 
14583d8817e4Smiod /* Helper function used to sort .eh_frame_hdr search table by increasing
14593d8817e4Smiod    VMA of FDE initial location.  */
14603d8817e4Smiod 
14613d8817e4Smiod static int
vma_compare(const void * a,const void * b)14623d8817e4Smiod vma_compare (const void *a, const void *b)
14633d8817e4Smiod {
14643d8817e4Smiod   const struct eh_frame_array_ent *p = a;
14653d8817e4Smiod   const struct eh_frame_array_ent *q = b;
14663d8817e4Smiod   if (p->initial_loc > q->initial_loc)
14673d8817e4Smiod     return 1;
14683d8817e4Smiod   if (p->initial_loc < q->initial_loc)
14693d8817e4Smiod     return -1;
14703d8817e4Smiod   return 0;
14713d8817e4Smiod }
14723d8817e4Smiod 
14733d8817e4Smiod /* Write out .eh_frame_hdr section.  This must be called after
14743d8817e4Smiod    _bfd_elf_write_section_eh_frame has been called on all input
14753d8817e4Smiod    .eh_frame sections.
14763d8817e4Smiod    .eh_frame_hdr format:
14773d8817e4Smiod    ubyte version		(currently 1)
14783d8817e4Smiod    ubyte eh_frame_ptr_enc  	(DW_EH_PE_* encoding of pointer to start of
14793d8817e4Smiod 				 .eh_frame section)
14803d8817e4Smiod    ubyte fde_count_enc		(DW_EH_PE_* encoding of total FDE count
14813d8817e4Smiod 				 number (or DW_EH_PE_omit if there is no
14823d8817e4Smiod 				 binary search table computed))
14833d8817e4Smiod    ubyte table_enc		(DW_EH_PE_* encoding of binary search table,
14843d8817e4Smiod 				 or DW_EH_PE_omit if not present.
14853d8817e4Smiod 				 DW_EH_PE_datarel is using address of
14863d8817e4Smiod 				 .eh_frame_hdr section start as base)
14873d8817e4Smiod    [encoded] eh_frame_ptr	(pointer to start of .eh_frame section)
14883d8817e4Smiod    optionally followed by:
14893d8817e4Smiod    [encoded] fde_count		(total number of FDEs in .eh_frame section)
14903d8817e4Smiod    fde_count x [encoded] initial_loc, fde
14913d8817e4Smiod 				(array of encoded pairs containing
14923d8817e4Smiod 				 FDE initial_location field and FDE address,
14933d8817e4Smiod 				 sorted by increasing initial_loc).  */
14943d8817e4Smiod 
14953d8817e4Smiod bfd_boolean
_bfd_elf_write_section_eh_frame_hdr(bfd * abfd,struct bfd_link_info * info)14963d8817e4Smiod _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
14973d8817e4Smiod {
14983d8817e4Smiod   struct elf_link_hash_table *htab;
14993d8817e4Smiod   struct eh_frame_hdr_info *hdr_info;
15003d8817e4Smiod   asection *sec;
15013d8817e4Smiod   bfd_byte *contents;
15023d8817e4Smiod   asection *eh_frame_sec;
15033d8817e4Smiod   bfd_size_type size;
15043d8817e4Smiod   bfd_boolean retval;
15053d8817e4Smiod   bfd_vma encoded_eh_frame;
15063d8817e4Smiod 
15073d8817e4Smiod   htab = elf_hash_table (info);
15083d8817e4Smiod   hdr_info = &htab->eh_info;
15093d8817e4Smiod   sec = hdr_info->hdr_sec;
15103d8817e4Smiod   if (sec == NULL)
15113d8817e4Smiod     return TRUE;
15123d8817e4Smiod 
15133d8817e4Smiod   size = EH_FRAME_HDR_SIZE;
15143d8817e4Smiod   if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
15153d8817e4Smiod     size += 4 + hdr_info->fde_count * 8;
15163d8817e4Smiod   contents = bfd_malloc (size);
15173d8817e4Smiod   if (contents == NULL)
15183d8817e4Smiod     return FALSE;
15193d8817e4Smiod 
15203d8817e4Smiod   eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
15213d8817e4Smiod   if (eh_frame_sec == NULL)
15223d8817e4Smiod     {
15233d8817e4Smiod       free (contents);
15243d8817e4Smiod       return FALSE;
15253d8817e4Smiod     }
15263d8817e4Smiod 
15273d8817e4Smiod   memset (contents, 0, EH_FRAME_HDR_SIZE);
15283d8817e4Smiod   contents[0] = 1;				/* Version.  */
15293d8817e4Smiod   contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address
15303d8817e4Smiod     (abfd, info, eh_frame_sec, 0, sec, 4,
15313d8817e4Smiod      &encoded_eh_frame);			/* .eh_frame offset.  */
15323d8817e4Smiod 
15333d8817e4Smiod   if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
15343d8817e4Smiod     {
15353d8817e4Smiod       contents[2] = DW_EH_PE_udata4;		/* FDE count encoding.  */
15363d8817e4Smiod       contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* Search table enc.  */
15373d8817e4Smiod     }
15383d8817e4Smiod   else
15393d8817e4Smiod     {
15403d8817e4Smiod       contents[2] = DW_EH_PE_omit;
15413d8817e4Smiod       contents[3] = DW_EH_PE_omit;
15423d8817e4Smiod     }
15433d8817e4Smiod   bfd_put_32 (abfd, encoded_eh_frame, contents + 4);
15443d8817e4Smiod 
15453d8817e4Smiod   if (contents[2] != DW_EH_PE_omit)
15463d8817e4Smiod     {
15473d8817e4Smiod       unsigned int i;
15483d8817e4Smiod 
15493d8817e4Smiod       bfd_put_32 (abfd, hdr_info->fde_count, contents + EH_FRAME_HDR_SIZE);
15503d8817e4Smiod       qsort (hdr_info->array, hdr_info->fde_count, sizeof (*hdr_info->array),
15513d8817e4Smiod 	     vma_compare);
15523d8817e4Smiod       for (i = 0; i < hdr_info->fde_count; i++)
15533d8817e4Smiod 	{
15543d8817e4Smiod 	  bfd_put_32 (abfd,
15553d8817e4Smiod 		      hdr_info->array[i].initial_loc
15563d8817e4Smiod 		      - sec->output_section->vma,
15573d8817e4Smiod 		      contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
15583d8817e4Smiod 	  bfd_put_32 (abfd,
15593d8817e4Smiod 		      hdr_info->array[i].fde - sec->output_section->vma,
15603d8817e4Smiod 		      contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
15613d8817e4Smiod 	}
15623d8817e4Smiod     }
15633d8817e4Smiod 
15643d8817e4Smiod   retval = bfd_set_section_contents (abfd, sec->output_section,
15653d8817e4Smiod 				     contents, (file_ptr) sec->output_offset,
15663d8817e4Smiod 				     sec->size);
15673d8817e4Smiod   free (contents);
15683d8817e4Smiod   return retval;
15693d8817e4Smiod }
15703d8817e4Smiod 
15713d8817e4Smiod /* Return the width of FDE addresses.  This is the default implementation.  */
15723d8817e4Smiod 
15733d8817e4Smiod unsigned int
_bfd_elf_eh_frame_address_size(bfd * abfd,asection * sec ATTRIBUTE_UNUSED)15743d8817e4Smiod _bfd_elf_eh_frame_address_size (bfd *abfd, asection *sec ATTRIBUTE_UNUSED)
15753d8817e4Smiod {
15763d8817e4Smiod   return elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64 ? 8 : 4;
15773d8817e4Smiod }
15783d8817e4Smiod 
15793d8817e4Smiod /* Decide whether we can use a PC-relative encoding within the given
15803d8817e4Smiod    EH frame section.  This is the default implementation.  */
15813d8817e4Smiod 
15823d8817e4Smiod bfd_boolean
_bfd_elf_can_make_relative(bfd * input_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * eh_frame_section ATTRIBUTE_UNUSED)15833d8817e4Smiod _bfd_elf_can_make_relative (bfd *input_bfd ATTRIBUTE_UNUSED,
15843d8817e4Smiod 			    struct bfd_link_info *info ATTRIBUTE_UNUSED,
15853d8817e4Smiod 			    asection *eh_frame_section ATTRIBUTE_UNUSED)
15863d8817e4Smiod {
15873d8817e4Smiod   return TRUE;
15883d8817e4Smiod }
15893d8817e4Smiod 
15903d8817e4Smiod /* Select an encoding for the given address.  Preference is given to
15913d8817e4Smiod    PC-relative addressing modes.  */
15923d8817e4Smiod 
15933d8817e4Smiod bfd_byte
_bfd_elf_encode_eh_address(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * osec,bfd_vma offset,asection * loc_sec,bfd_vma loc_offset,bfd_vma * encoded)15943d8817e4Smiod _bfd_elf_encode_eh_address (bfd *abfd ATTRIBUTE_UNUSED,
15953d8817e4Smiod 			    struct bfd_link_info *info ATTRIBUTE_UNUSED,
15963d8817e4Smiod 			    asection *osec, bfd_vma offset,
15973d8817e4Smiod 			    asection *loc_sec, bfd_vma loc_offset,
15983d8817e4Smiod 			    bfd_vma *encoded)
15993d8817e4Smiod {
16003d8817e4Smiod   *encoded = osec->vma + offset -
16013d8817e4Smiod     (loc_sec->output_section->vma + loc_sec->output_offset + loc_offset);
16023d8817e4Smiod   return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
16033d8817e4Smiod }
1604