/[gcl]/gcl/binutils/bfd/elf-eh-frame.c
ViewVC logotype

Diff of /gcl/binutils/bfd/elf-eh-frame.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.1.1 by camm, Fri Aug 9 05:36:01 2002 UTC revision 1.2 by camm, Fri Sep 9 23:32:08 2005 UTC
# Line 1  Line 1 
1  /* .eh_frame section optimization.  /* .eh_frame section optimization.
2     Copyright 2001, 2002 Free Software Foundation, Inc.     Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3     Written by Jakub Jelinek <jakub@redhat.com>.     Written by Jakub Jelinek <jakub@redhat.com>.
4    
5  This file is part of BFD, the Binary File Descriptor library.     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     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     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     the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.     (at your option) any later version.
11    
12  This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU General Public License for more details.     GNU General Public License for more details.
16    
17  You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20    
21  #include "bfd.h"  #include "bfd.h"
22  #include "sysdep.h"  #include "sysdep.h"
# Line 26  Foundation, Inc., 59 Temple Place - Suit Line 26  Foundation, Inc., 59 Temple Place - Suit
26    
27  #define EH_FRAME_HDR_SIZE 8  #define EH_FRAME_HDR_SIZE 8
28    
29  struct cie_header  /* If *ITER hasn't reached END yet, read the next byte into *RESULT and
30  {     move onto the next byte.  Return true on success.  */
   unsigned int length;  
   unsigned int id;  
 };  
31    
32  struct cie  static inline bfd_boolean
33    read_byte (bfd_byte **iter, bfd_byte *end, unsigned char *result)
34  {  {
35    struct cie_header hdr;    if (*iter >= end)
36    unsigned char version;      return FALSE;
37    unsigned char augmentation[20];    *result = *((*iter)++);
38    unsigned int code_align;    return TRUE;
39    int data_align;  }
   unsigned int ra_column;  
   unsigned int augmentation_size;  
   struct elf_link_hash_entry *personality;  
   unsigned char per_encoding;  
   unsigned char lsda_encoding;  
   unsigned char fde_encoding;  
   unsigned char initial_insn_length;  
   unsigned char make_relative;  
   unsigned char make_lsda_relative;  
   unsigned char initial_instructions[50];  
 };  
40    
41  struct eh_cie_fde  /* Move *ITER over LENGTH bytes, or up to END, whichever is closer.
42       Return true it was possible to move LENGTH bytes.  */
43    
44    static inline bfd_boolean
45    skip_bytes (bfd_byte **iter, bfd_byte *end, bfd_size_type length)
46  {  {
47    unsigned int offset;    if ((bfd_size_type) (end - *iter) < length)
48    unsigned int size;      {
49    asection *sec;        *iter = end;
50    unsigned int new_offset;        return FALSE;
51    unsigned char fde_encoding;      }
52    unsigned char lsda_encoding;    *iter += length;
53    unsigned char lsda_offset;    return TRUE;
54    unsigned char cie : 1;  }
   unsigned char removed : 1;  
   unsigned char make_relative : 1;  
   unsigned char make_lsda_relative : 1;  
   unsigned char per_encoding_relative : 1;  
 };  
   
 struct eh_frame_sec_info  
 {  
   unsigned int count;  
   unsigned int alloced;  
   struct eh_cie_fde entry[1];  
 };  
   
 struct eh_frame_array_ent  
 {  
   bfd_vma initial_loc;  
   bfd_vma fde;  
 };  
   
 struct eh_frame_hdr_info  
 {  
   struct cie last_cie;  
   asection *last_cie_sec;  
   unsigned int last_cie_offset;  
   unsigned int fde_count, array_count;  
   struct eh_frame_array_ent *array;  
   /* TRUE if .eh_frame_hdr should contain the sorted search table.  
      We build it if we successfully read all .eh_frame input sections  
      and recognize them.  */  
   boolean table;  
   boolean strip;  
 };  
   
 static bfd_vma read_unsigned_leb128  
   PARAMS ((bfd *, char *, unsigned int *));  
 static bfd_signed_vma read_signed_leb128  
   PARAMS ((bfd *, char *, unsigned int *));  
 static int get_DW_EH_PE_width  
   PARAMS ((int, int));  
 static bfd_vma read_value  
   PARAMS ((bfd *, bfd_byte *, int));  
 static void write_value  
   PARAMS ((bfd *, bfd_byte *, bfd_vma, int));  
 static int cie_compare  
   PARAMS ((struct cie *, struct cie *));  
 static int vma_compare  
   PARAMS ((const PTR a, const PTR b));  
55    
56  /* Helper function for reading uleb128 encoded data.  */  /* Move *ITER over an leb128, stopping at END.  Return true if the end
57       of the leb128 was found.  */
58    
59  static bfd_vma  static bfd_boolean
60  read_unsigned_leb128 (abfd, buf, bytes_read_ptr)  skip_leb128 (bfd_byte **iter, bfd_byte *end)
61       bfd *abfd ATTRIBUTE_UNUSED;  {
      char *buf;  
      unsigned int *bytes_read_ptr;  
 {  
   bfd_vma  result;  
   unsigned int  num_read;  
   int           shift;  
62    unsigned char byte;    unsigned char byte;
   
   result   = 0;  
   shift    = 0;  
   num_read = 0;  
63    do    do
64      {      if (!read_byte (iter, end, &byte))
65        byte = bfd_get_8 (abfd, (bfd_byte *) buf);        return FALSE;
       buf ++;  
       num_read ++;  
       result |= (((bfd_vma) byte & 0x7f) << shift);  
       shift += 7;  
     }  
66    while (byte & 0x80);    while (byte & 0x80);
67    * bytes_read_ptr = num_read;    return TRUE;
   return result;  
68  }  }
69    
70  /* Helper function for reading sleb128 encoded data.  */  /* Like skip_leb128, but treat the leb128 as an unsigned value and
71       store it in *VALUE.  */
72    
73  static bfd_signed_vma  static bfd_boolean
74  read_signed_leb128 (abfd, buf, bytes_read_ptr)  read_uleb128 (bfd_byte **iter, bfd_byte *end, bfd_vma *value)
      bfd *abfd ATTRIBUTE_UNUSED;  
      char *buf;  
      unsigned int * bytes_read_ptr;  
75  {  {
76    bfd_vma       result;    bfd_byte *start, *p;
   int           shift;  
   int           num_read;  
   unsigned char byte;  
77    
78    result = 0;    start = *iter;
79    shift = 0;    if (!skip_leb128 (iter, end))
80    num_read = 0;      return FALSE;
81    do  
82      {    p = *iter;
83        byte = bfd_get_8 (abfd, (bfd_byte *) buf);    *value = *--p;
84        buf ++;    while (p > start)
85        num_read ++;      *value = (*value << 7) | (*--p & 0x7f);
86        result |= (((bfd_vma) byte & 0x7f) << shift);  
87        shift += 7;    return TRUE;
88      }  }
89    while (byte & 0x80);  
90    if (byte & 0x40)  /* Like read_uleb128, but for signed values.  */
91      result |= (((bfd_vma) -1) << (shift - 7)) << 7;  
92    * bytes_read_ptr = num_read;  static bfd_boolean
93    return result;  read_sleb128 (bfd_byte **iter, bfd_byte *end, bfd_signed_vma *value)
94  }  {
95      bfd_byte *start, *p;
96  #define read_uleb128(VAR, BUF)                                  \  
97  do                                                              \    start = *iter;
98    {                                                             \    if (!skip_leb128 (iter, end))
99      (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp);      \      return FALSE;
100      (BUF) += leb128_tmp;                                        \  
101    }                                                             \    p = *iter;
102  while (0)    *value = ((*--p & 0x7f) ^ 0x40) - 0x40;
103      while (p > start)
104  #define read_sleb128(VAR, BUF)                                  \      *value = (*value << 7) | (*--p & 0x7f);
105  do                                                              \  
106    {                                                             \    return TRUE;
107      (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp);        \  }
     (BUF) += leb128_tmp;                                        \  
   }                                                             \  
 while (0)  
108    
109  /* Return 0 if either encoding is variable width, or not yet known to bfd.  */  /* Return 0 if either encoding is variable width, or not yet known to bfd.  */
110    
111  static  static
112  int get_DW_EH_PE_width (encoding, ptr_size)  int get_DW_EH_PE_width (int encoding, int ptr_size)
      int encoding, ptr_size;  
113  {  {
114    /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame    /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
115       was added to bfd.  */       was added to bfd.  */
# Line 209  int get_DW_EH_PE_width (encoding, ptr_si Line 129  int get_DW_EH_PE_width (encoding, ptr_si
129    return 0;    return 0;
130  }  }
131    
132    #define get_DW_EH_PE_signed(encoding) (((encoding) & DW_EH_PE_signed) != 0)
133    
134  /* Read a width sized value from memory.  */  /* Read a width sized value from memory.  */
135    
136  static bfd_vma  static bfd_vma
137  read_value (abfd, buf, width)  read_value (bfd *abfd, bfd_byte *buf, int width, int is_signed)
      bfd *abfd;  
      bfd_byte *buf;  
      int width;  
138  {  {
139    bfd_vma value;    bfd_vma value;
140    
141    switch (width)    switch (width)
142      {      {
143      case 2: value = bfd_get_16 (abfd, buf); break;      case 2:
144      case 4: value = bfd_get_32 (abfd, buf); break;        if (is_signed)
145      case 8: value = bfd_get_64 (abfd, buf); break;          value = bfd_get_signed_16 (abfd, buf);
146      default: BFD_FAIL (); return 0;        else
147            value = bfd_get_16 (abfd, buf);
148          break;
149        case 4:
150          if (is_signed)
151            value = bfd_get_signed_32 (abfd, buf);
152          else
153            value = bfd_get_32 (abfd, buf);
154          break;
155        case 8:
156          if (is_signed)
157            value = bfd_get_signed_64 (abfd, buf);
158          else
159            value = bfd_get_64 (abfd, buf);
160          break;
161        default:
162          BFD_FAIL ();
163          return 0;
164      }      }
165    
166    return value;    return value;
167  }  }
168        
169  /* Store a width sized value to memory.  */  /* Store a width sized value to memory.  */
170    
171  static void  static void
172  write_value (abfd, buf, value, width)  write_value (bfd *abfd, bfd_byte *buf, bfd_vma value, int width)
      bfd *abfd;  
      bfd_byte *buf;  
      bfd_vma value;  
      int width;  
173  {  {
174    switch (width)    switch (width)
175      {      {
# Line 251  write_value (abfd, buf, value, width) Line 183  write_value (abfd, buf, value, width)
183  /* Return zero if C1 and C2 CIEs can be merged.  */  /* Return zero if C1 and C2 CIEs can be merged.  */
184    
185  static  static
186  int cie_compare (c1, c2)  int cie_compare (struct cie *c1, struct cie *c2)
      struct cie *c1, *c2;  
187  {  {
188    if (c1->hdr.length == c2->hdr.length    if (c1->hdr.length == c2->hdr.length
189        && c1->version == c2->version        && c1->version == c2->version
# Line 266  int cie_compare (c1, c2) Line 197  int cie_compare (c1, c2)
197        && c1->per_encoding == c2->per_encoding        && c1->per_encoding == c2->per_encoding
198        && c1->lsda_encoding == c2->lsda_encoding        && c1->lsda_encoding == c2->lsda_encoding
199        && c1->fde_encoding == c2->fde_encoding        && c1->fde_encoding == c2->fde_encoding
200        && (c1->initial_insn_length        && c1->initial_insn_length == c2->initial_insn_length
           == c2->initial_insn_length)  
201        && memcmp (c1->initial_instructions,        && memcmp (c1->initial_instructions,
202                   c2->initial_instructions,                   c2->initial_instructions,
203                   c1->initial_insn_length) == 0)                   c1->initial_insn_length) == 0)
# Line 276  int cie_compare (c1, c2) Line 206  int cie_compare (c1, c2)
206    return 1;    return 1;
207  }  }
208    
209    /* Return the number of extra bytes that we'll be inserting into
210       ENTRY's augmentation string.  */
211    
212    static INLINE unsigned int
213    extra_augmentation_string_bytes (struct eh_cie_fde *entry)
214    {
215      unsigned int size = 0;
216      if (entry->cie)
217        {
218          if (entry->add_augmentation_size)
219            size++;
220          if (entry->add_fde_encoding)
221            size++;
222        }
223      return size;
224    }
225    
226    /* Likewise ENTRY's augmentation data.  */
227    
228    static INLINE unsigned int
229    extra_augmentation_data_bytes (struct eh_cie_fde *entry)
230    {
231      unsigned int size = 0;
232      if (entry->cie)
233        {
234          if (entry->add_augmentation_size)
235            size++;
236          if (entry->add_fde_encoding)
237            size++;
238        }
239      else
240        {
241          if (entry->cie_inf->add_augmentation_size)
242            size++;
243        }
244      return size;
245    }
246    
247    /* Return the size that ENTRY will have in the output.  ALIGNMENT is the
248       required alignment of ENTRY in bytes.  */
249    
250    static unsigned int
251    size_of_output_cie_fde (struct eh_cie_fde *entry, unsigned int alignment)
252    {
253      if (entry->removed)
254        return 0;
255      if (entry->size == 4)
256        return 4;
257      return (entry->size
258              + extra_augmentation_string_bytes (entry)
259              + extra_augmentation_data_bytes (entry)
260              + alignment - 1) & -alignment;
261    }
262    
263    /* Assume that the bytes between *ITER and END are CFA instructions.
264       Try to move *ITER past the first instruction and return true on
265       success.  ENCODED_PTR_WIDTH gives the width of pointer entries.  */
266    
267    static bfd_boolean
268    skip_cfa_op (bfd_byte **iter, bfd_byte *end, unsigned int encoded_ptr_width)
269    {
270      bfd_byte op;
271      bfd_vma length;
272    
273      if (!read_byte (iter, end, &op))
274        return FALSE;
275    
276      switch (op & 0x80 ? op & 0xc0 : op)
277        {
278        case DW_CFA_nop:
279        case DW_CFA_advance_loc:
280        case DW_CFA_restore:
281          /* No arguments.  */
282          return TRUE;
283    
284        case DW_CFA_offset:
285        case DW_CFA_restore_extended:
286        case DW_CFA_undefined:
287        case DW_CFA_same_value:
288        case DW_CFA_def_cfa_register:
289        case DW_CFA_def_cfa_offset:
290        case DW_CFA_def_cfa_offset_sf:
291        case DW_CFA_GNU_args_size:
292          /* One leb128 argument.  */
293          return skip_leb128 (iter, end);
294    
295        case DW_CFA_offset_extended:
296        case DW_CFA_register:
297        case DW_CFA_def_cfa:
298        case DW_CFA_offset_extended_sf:
299        case DW_CFA_GNU_negative_offset_extended:
300        case DW_CFA_def_cfa_sf:
301          /* Two leb128 arguments.  */
302          return (skip_leb128 (iter, end)
303                  && skip_leb128 (iter, end));
304    
305        case DW_CFA_def_cfa_expression:
306          /* A variable-length argument.  */
307          return (read_uleb128 (iter, end, &length)
308                  && skip_bytes (iter, end, length));
309    
310        case DW_CFA_expression:
311          /* A leb128 followed by a variable-length argument.  */
312          return (skip_leb128 (iter, end)
313                  && read_uleb128 (iter, end, &length)
314                  && skip_bytes (iter, end, length));
315    
316        case DW_CFA_set_loc:
317          return skip_bytes (iter, end, encoded_ptr_width);
318    
319        case DW_CFA_advance_loc1:
320          return skip_bytes (iter, end, 1);
321    
322        case DW_CFA_advance_loc2:
323          return skip_bytes (iter, end, 2);
324    
325        case DW_CFA_advance_loc4:
326          return skip_bytes (iter, end, 4);
327    
328        case DW_CFA_MIPS_advance_loc8:
329          return skip_bytes (iter, end, 8);
330    
331        default:
332          return FALSE;
333        }
334    }
335    
336    /* Try to interpret the bytes between BUF and END as CFA instructions.
337       If every byte makes sense, return a pointer to the first DW_CFA_nop
338       padding byte, or END if there is no padding.  Return null otherwise.
339       ENCODED_PTR_WIDTH is as for skip_cfa_op.  */
340    
341    static bfd_byte *
342    skip_non_nops (bfd_byte *buf, bfd_byte *end, unsigned int encoded_ptr_width)
343    {
344      bfd_byte *last;
345    
346      last = buf;
347      while (buf < end)
348        if (*buf == DW_CFA_nop)
349          buf++;
350        else
351          {
352            if (!skip_cfa_op (&buf, end, encoded_ptr_width))
353              return 0;
354            last = buf;
355          }
356      return last;
357    }
358    
359  /* This function is called for each input file before the .eh_frame  /* This function is called for each input file before the .eh_frame
360     section is relocated.  It discards duplicate CIEs and FDEs for discarded     section is relocated.  It discards duplicate CIEs and FDEs for discarded
361     functions.  The function returns true iff any entries have been     functions.  The function returns TRUE iff any entries have been
362     deleted.  */     deleted.  */
363    
364  boolean  bfd_boolean
365  _bfd_elf_discard_section_eh_frame (abfd, info, sec, ehdrsec,  _bfd_elf_discard_section_eh_frame
366                                     reloc_symbol_deleted_p, cookie)     (bfd *abfd, struct bfd_link_info *info, asection *sec,
367       bfd *abfd;      bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
368       struct bfd_link_info *info;      struct elf_reloc_cookie *cookie)
      asection *sec, *ehdrsec;  
      boolean (*reloc_symbol_deleted_p) (bfd_vma, PTR);  
      struct elf_reloc_cookie *cookie;  
369  {  {
370    #define REQUIRE(COND)                                   \
371      do                                                    \
372        if (!(COND))                                        \
373          goto free_no_table;                               \
374      while (0)
375    
376    bfd_byte *ehbuf = NULL, *buf;    bfd_byte *ehbuf = NULL, *buf;
377    bfd_byte *last_cie, *last_fde;    bfd_byte *last_cie, *last_fde;
378      struct eh_cie_fde *ent, *last_cie_inf, *this_inf;
379    struct cie_header hdr;    struct cie_header hdr;
380    struct cie cie;    struct cie cie;
381      struct elf_link_hash_table *htab;
382    struct eh_frame_hdr_info *hdr_info;    struct eh_frame_hdr_info *hdr_info;
383    struct eh_frame_sec_info *sec_info = NULL;    struct eh_frame_sec_info *sec_info = NULL;
384    unsigned int leb128_tmp;    unsigned int cie_usage_count, offset;
   unsigned int cie_usage_count, last_cie_ndx, i, offset;  
   unsigned int make_relative, make_lsda_relative;  
   Elf_Internal_Rela *rel;  
   bfd_size_type new_size;  
385    unsigned int ptr_size;    unsigned int ptr_size;
386    
387    if (sec->_raw_size == 0)    if (sec->size == 0)
388      {      {
389        /* This file does not contain .eh_frame information.  */        /* This file does not contain .eh_frame information.  */
390        return false;        return FALSE;
391      }      }
392    
393    if ((sec->output_section != NULL    if ((sec->output_section != NULL
394         && bfd_is_abs_section (sec->output_section)))         && bfd_is_abs_section (sec->output_section)))
395      {      {
396        /* At least one of the sections is being discarded from the        /* At least one of the sections is being discarded from the
397           link, so we should just ignore them.  */           link, so we should just ignore them.  */
398        return false;        return FALSE;
399      }      }
400    
401    BFD_ASSERT (elf_section_data (ehdrsec)->sec_info_type    htab = elf_hash_table (info);
402                == ELF_INFO_TYPE_EH_FRAME_HDR);    hdr_info = &htab->eh_info;
   hdr_info = (struct eh_frame_hdr_info *)  
              elf_section_data (ehdrsec)->sec_info;  
403    
404    /* Read the frame unwind information from abfd.  */    /* Read the frame unwind information from abfd.  */
405    
406    ehbuf = (bfd_byte *) bfd_malloc (sec->_raw_size);    REQUIRE (bfd_malloc_and_get_section (abfd, sec, &ehbuf));
   if (ehbuf == NULL)  
     goto free_no_table;  
   
   if (! bfd_get_section_contents (abfd, sec, ehbuf, (bfd_vma) 0,  
                                   sec->_raw_size))  
     goto free_no_table;  
407    
408    if (sec->_raw_size >= 4    if (sec->size >= 4
409        && bfd_get_32 (abfd, ehbuf) == 0        && bfd_get_32 (abfd, ehbuf) == 0
410        && cookie->rel == cookie->relend)        && cookie->rel == cookie->relend)
411      {      {
412        /* Empty .eh_frame section.  */        /* Empty .eh_frame section.  */
413        free (ehbuf);        free (ehbuf);
414        return false;        return FALSE;
415      }      }
416    
417    /* If .eh_frame section size doesn't fit into int, we cannot handle    /* If .eh_frame section size doesn't fit into int, we cannot handle
418       it (it would need to use 64-bit .eh_frame format anyway).  */       it (it would need to use 64-bit .eh_frame format anyway).  */
419    if (sec->_raw_size != (unsigned int) sec->_raw_size)    REQUIRE (sec->size == (unsigned int) sec->size);
420      goto free_no_table;  
421      ptr_size = (get_elf_backend_data (abfd)
422                  ->elf_backend_eh_frame_address_size (abfd, sec));
423      REQUIRE (ptr_size != 0);
424    
   ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]  
               == ELFCLASS64) ? 8 : 4;  
425    buf = ehbuf;    buf = ehbuf;
426    last_cie = NULL;    last_cie = NULL;
427    last_cie_ndx = 0;    last_cie_inf = NULL;
428    memset (&cie, 0, sizeof (cie));    memset (&cie, 0, sizeof (cie));
429    cie_usage_count = 0;    cie_usage_count = 0;
   new_size = sec->_raw_size;  
   make_relative = hdr_info->last_cie.make_relative;  
   make_lsda_relative = hdr_info->last_cie.make_lsda_relative;  
430    sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)    sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)
431                            + 99 * sizeof (struct eh_cie_fde));                            + 99 * sizeof (struct eh_cie_fde));
432    if (sec_info == NULL)    REQUIRE (sec_info);
433      goto free_no_table;  
434    sec_info->alloced = 100;    sec_info->alloced = 100;
435    
436  #define ENSURE_NO_RELOCS(buf)                           \  #define ENSURE_NO_RELOCS(buf)                           \
437    if (cookie->rel < cookie->relend                      \    REQUIRE (!(cookie->rel < cookie->relend               \
438        && (cookie->rel->r_offset                         \               && (cookie->rel->r_offset                  \
439            < (bfd_size_type) ((buf) - ehbuf)))           \                   < (bfd_size_type) ((buf) - ehbuf))     \
440      goto free_no_table               && cookie->rel->r_info != 0))
441    
442  #define SKIP_RELOCS(buf)                                \  #define SKIP_RELOCS(buf)                                \
443    while (cookie->rel < cookie->relend                   \    while (cookie->rel < cookie->relend                   \
444           && (cookie->rel->r_offset                      \           && (cookie->rel->r_offset                      \
445               < (bfd_size_type) ((buf) - ehbuf)))        \               < (bfd_size_type) ((buf) - ehbuf)))        \
446      cookie->rel++      cookie->rel++
447    
448  #define GET_RELOC(buf)                                  \  #define GET_RELOC(buf)                                  \
449    ((cookie->rel < cookie->relend                        \    ((cookie->rel < cookie->relend                        \
450      && (cookie->rel->r_offset                           \      && (cookie->rel->r_offset                           \
451          == (bfd_size_type) ((buf) - ehbuf)))            \          == (bfd_size_type) ((buf) - ehbuf)))            \
452     ? cookie->rel : NULL)     ? cookie->rel : NULL)
453    
454    for (;;)    for (;;)
455      {      {
456        unsigned char *aug;        char *aug;
457          bfd_byte *start, *end, *insns;
458          bfd_size_type length;
459    
460        if (sec_info->count == sec_info->alloced)        if (sec_info->count == sec_info->alloced)
461          {          {
462              struct eh_cie_fde *old_entry = sec_info->entry;
463            sec_info = bfd_realloc (sec_info,            sec_info = bfd_realloc (sec_info,
464                                    sizeof (struct eh_frame_sec_info)                                    sizeof (struct eh_frame_sec_info)
465                                    + (sec_info->alloced + 99)                                    + ((sec_info->alloced + 99)
466                                       * sizeof (struct eh_cie_fde));                                       * sizeof (struct eh_cie_fde)));
467            if (sec_info == NULL)            REQUIRE (sec_info);
             goto free_no_table;  
468    
469            memset (&sec_info->entry[sec_info->alloced], 0,            memset (&sec_info->entry[sec_info->alloced], 0,
470                    100 * sizeof (struct eh_cie_fde));                    100 * sizeof (struct eh_cie_fde));
471            sec_info->alloced += 100;            sec_info->alloced += 100;
472    
473              /* Now fix any pointers into the array.  */
474              if (last_cie_inf >= old_entry
475                  && last_cie_inf < old_entry + sec_info->count)
476                last_cie_inf = sec_info->entry + (last_cie_inf - old_entry);
477          }          }
478    
479          this_inf = sec_info->entry + sec_info->count;
480        last_fde = buf;        last_fde = buf;
481        /* If we are at the end of the section, we still need to decide        /* If we are at the end of the section, we still need to decide
482           on whether to output or discard last encountered CIE (if any).  */           on whether to output or discard last encountered CIE (if any).  */
483        if ((bfd_size_type) (buf - ehbuf) == sec->_raw_size)        if ((bfd_size_type) (buf - ehbuf) == sec->size)
484          hdr.id = (unsigned int) -1;          {
485              hdr.length = 0;
486              hdr.id = (unsigned int) -1;
487              end = buf;
488            }
489        else        else
490          {          {
491            if ((bfd_size_type) (buf + 4 - ehbuf) > sec->_raw_size)            /* Read the length of the entry.  */
492              /* No space for CIE/FDE header length.  */            REQUIRE (skip_bytes (&buf, ehbuf + sec->size, 4));
493              goto free_no_table;            hdr.length = bfd_get_32 (abfd, buf - 4);
494    
495            hdr.length = bfd_get_32 (abfd, buf);            /* 64-bit .eh_frame is not supported.  */
496            if (hdr.length == 0xffffffff)            REQUIRE (hdr.length != 0xffffffff);
497              /* 64-bit .eh_frame is not supported.  */  
498              goto free_no_table;            /* The CIE/FDE must be fully contained in this input section.  */
499            buf += 4;            REQUIRE ((bfd_size_type) (buf - ehbuf) + hdr.length <= sec->size);
500            if ((buf - ehbuf) + hdr.length > sec->_raw_size)            end = buf + hdr.length;
             /* CIE/FDE not contained fully in this .eh_frame input section.  */  
             goto free_no_table;  
501    
502            sec_info->entry[sec_info->count].offset = last_fde - ehbuf;            this_inf->offset = last_fde - ehbuf;
503            sec_info->entry[sec_info->count].size = 4 + hdr.length;            this_inf->size = 4 + hdr.length;
504    
505            if (hdr.length == 0)            if (hdr.length == 0)
506              {              {
507                /* CIE with length 0 must be only the last in the section.  */                /* A zero-length CIE should only be found at the end of
508                if ((bfd_size_type) (buf - ehbuf) < sec->_raw_size)                   the section.  */
509                  goto free_no_table;                REQUIRE ((bfd_size_type) (buf - ehbuf) == sec->size);
510                ENSURE_NO_RELOCS (buf);                ENSURE_NO_RELOCS (buf);
511                sec_info->count++;                sec_info->count++;
512                /* Now just finish last encountered CIE processing and break                /* Now just finish last encountered CIE processing and break
# Line 434  _bfd_elf_discard_section_eh_frame (abfd, Line 515  _bfd_elf_discard_section_eh_frame (abfd,
515              }              }
516            else            else
517              {              {
518                hdr.id = bfd_get_32 (abfd, buf);                REQUIRE (skip_bytes (&buf, end, 4));
519                buf += 4;                hdr.id = bfd_get_32 (abfd, buf - 4);
520                if (hdr.id == (unsigned int) -1)                REQUIRE (hdr.id != (unsigned int) -1);
                 goto free_no_table;  
521              }              }
522          }          }
523    
# Line 448  _bfd_elf_discard_section_eh_frame (abfd, Line 528  _bfd_elf_discard_section_eh_frame (abfd,
528            /* CIE  */            /* CIE  */
529            if (last_cie != NULL)            if (last_cie != NULL)
530              {              {
531                /* Now check if this CIE is identical to last CIE, in which case                /* Now check if this CIE is identical to the last CIE,
532                   we can remove it, provided we adjust all FDEs.                   in which case we can remove it provided we adjust
533                   Also, it can be removed if we have removed all FDEs using                   all FDEs.  Also, it can be removed if we have removed
534                   that. */                   all FDEs using it.  */
535                if (cie_compare (&cie, &hdr_info->last_cie) == 0                if ((!info->relocatable
536                       && hdr_info->last_cie_sec
537                       && (sec->output_section
538                           == hdr_info->last_cie_sec->output_section)
539                       && cie_compare (&cie, &hdr_info->last_cie) == 0)
540                    || cie_usage_count == 0)                    || cie_usage_count == 0)
541                  {                  last_cie_inf->removed = 1;
                   new_size -= cie.hdr.length + 4;  
                   sec_info->entry[last_cie_ndx].removed = 1;  
                   sec_info->entry[last_cie_ndx].sec = hdr_info->last_cie_sec;  
                   sec_info->entry[last_cie_ndx].new_offset  
                     = hdr_info->last_cie_offset;  
                 }  
542                else                else
543                  {                  {
544                    hdr_info->last_cie = cie;                    hdr_info->last_cie = cie;
545                    hdr_info->last_cie_sec = sec;                    hdr_info->last_cie_sec = sec;
546                    hdr_info->last_cie_offset = last_cie - ehbuf;                    last_cie_inf->make_relative = cie.make_relative;
547                    sec_info->entry[last_cie_ndx].make_relative                    last_cie_inf->make_lsda_relative = cie.make_lsda_relative;
548                      = cie.make_relative;                    last_cie_inf->per_encoding_relative
                   sec_info->entry[last_cie_ndx].make_lsda_relative  
                     = cie.make_lsda_relative;  
                   sec_info->entry[last_cie_ndx].per_encoding_relative  
549                      = (cie.per_encoding & 0x70) == DW_EH_PE_pcrel;                      = (cie.per_encoding & 0x70) == DW_EH_PE_pcrel;
550                  }                  }
551              }              }
# Line 478  _bfd_elf_discard_section_eh_frame (abfd, Line 553  _bfd_elf_discard_section_eh_frame (abfd,
553            if (hdr.id == (unsigned int) -1)            if (hdr.id == (unsigned int) -1)
554              break;              break;
555    
556            last_cie_ndx = sec_info->count;            last_cie_inf = this_inf;
557            sec_info->entry[sec_info->count].cie = 1;            this_inf->cie = 1;
558    
559            cie_usage_count = 0;            cie_usage_count = 0;
560            memset (&cie, 0, sizeof (cie));            memset (&cie, 0, sizeof (cie));
561            cie.hdr = hdr;            cie.hdr = hdr;
562            cie.version = *buf++;            REQUIRE (read_byte (&buf, end, &cie.version));
563    
564            /* Cannot handle unknown versions.  */            /* Cannot handle unknown versions.  */
565            if (cie.version != 1)            REQUIRE (cie.version == 1 || cie.version == 3);
566              goto free_no_table;            REQUIRE (strlen ((char *) buf) < sizeof (cie.augmentation));
           if (strlen (buf) > sizeof (cie.augmentation) - 1)  
             goto free_no_table;  
567    
568            strcpy (cie.augmentation, buf);            strcpy (cie.augmentation, (char *) buf);
569            buf = strchr (buf, '\0') + 1;            buf = (bfd_byte *) strchr ((char *) buf, '\0') + 1;
570            ENSURE_NO_RELOCS (buf);            ENSURE_NO_RELOCS (buf);
571            if (buf[0] == 'e' && buf[1] == 'h')            if (buf[0] == 'e' && buf[1] == 'h')
572              {              {
# Line 501  _bfd_elf_discard_section_eh_frame (abfd, Line 574  _bfd_elf_discard_section_eh_frame (abfd,
574                /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__                /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
575                   is private to each CIE, so we don't need it for anything.                   is private to each CIE, so we don't need it for anything.
576                   Just skip it.  */                   Just skip it.  */
577                buf += ptr_size;                REQUIRE (skip_bytes (&buf, end, ptr_size));
578                SKIP_RELOCS (buf);                SKIP_RELOCS (buf);
579              }              }
580            read_uleb128 (cie.code_align, buf);            REQUIRE (read_uleb128 (&buf, end, &cie.code_align));
581            read_sleb128 (cie.data_align, buf);            REQUIRE (read_sleb128 (&buf, end, &cie.data_align));
582            read_uleb128 (cie.ra_column, buf);            if (cie.version == 1)
583                {
584                  REQUIRE (buf < end);
585                  cie.ra_column = *buf++;
586                }
587              else
588                REQUIRE (read_uleb128 (&buf, end, &cie.ra_column));
589            ENSURE_NO_RELOCS (buf);            ENSURE_NO_RELOCS (buf);
590            cie.lsda_encoding = DW_EH_PE_omit;            cie.lsda_encoding = DW_EH_PE_omit;
591            cie.fde_encoding = DW_EH_PE_omit;            cie.fde_encoding = DW_EH_PE_omit;
# Line 517  _bfd_elf_discard_section_eh_frame (abfd, Line 596  _bfd_elf_discard_section_eh_frame (abfd,
596                if (*aug == 'z')                if (*aug == 'z')
597                  {                  {
598                    aug++;                    aug++;
599                    read_uleb128 (cie.augmentation_size, buf);                    REQUIRE (read_uleb128 (&buf, end, &cie.augmentation_size));
600                    ENSURE_NO_RELOCS (buf);                    ENSURE_NO_RELOCS (buf);
601                  }                  }
602    
# Line 525  _bfd_elf_discard_section_eh_frame (abfd, Line 604  _bfd_elf_discard_section_eh_frame (abfd,
604                  switch (*aug++)                  switch (*aug++)
605                    {                    {
606                    case 'L':                    case 'L':
607                      cie.lsda_encoding = *buf++;                      REQUIRE (read_byte (&buf, end, &cie.lsda_encoding));
608                      ENSURE_NO_RELOCS (buf);                      ENSURE_NO_RELOCS (buf);
609                      if (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size) == 0)                      REQUIRE (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size));
                       goto free_no_table;  
610                      break;                      break;
611                    case 'R':                    case 'R':
612                      cie.fde_encoding = *buf++;                      REQUIRE (read_byte (&buf, end, &cie.fde_encoding));
613                      ENSURE_NO_RELOCS (buf);                      ENSURE_NO_RELOCS (buf);
614                      if (get_DW_EH_PE_width (cie.fde_encoding, ptr_size) == 0)                      REQUIRE (get_DW_EH_PE_width (cie.fde_encoding, ptr_size));
                       goto free_no_table;  
615                      break;                      break;
616                    case 'P':                    case 'P':
617                      {                      {
618                        int per_width;                        int per_width;
619    
620                        cie.per_encoding = *buf++;                        REQUIRE (read_byte (&buf, end, &cie.per_encoding));
621                        per_width = get_DW_EH_PE_width (cie.per_encoding,                        per_width = get_DW_EH_PE_width (cie.per_encoding,
622                                                        ptr_size);                                                        ptr_size);
623                        if (per_width == 0)                        REQUIRE (per_width);
                         goto free_no_table;  
624                        if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)                        if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
625                          buf = (ehbuf                          {
626                                 + ((buf - ehbuf + per_width - 1)                            length = -(buf - ehbuf) & (per_width - 1);
627                                    & ~((bfd_size_type) per_width - 1)));                            REQUIRE (skip_bytes (&buf, end, length));
628                            }
629                        ENSURE_NO_RELOCS (buf);                        ENSURE_NO_RELOCS (buf);
                       rel = GET_RELOC (buf);  
630                        /* Ensure we have a reloc here, against                        /* Ensure we have a reloc here, against
631                           a global symbol.  */                           a global symbol.  */
632                        if (rel != NULL)                        if (GET_RELOC (buf) != NULL)
633                          {                          {
634                            unsigned long r_symndx;                            unsigned long r_symndx;
635    
# Line 577  _bfd_elf_discard_section_eh_frame (abfd, Line 653  _bfd_elf_discard_section_eh_frame (abfd,
653    
654                                cie.personality = h;                                cie.personality = h;
655                              }                              }
656                            cookie->rel++;                            /* Cope with MIPS-style composite relocations.  */
657                              do
658                                cookie->rel++;
659                              while (GET_RELOC (buf) != NULL);
660                          }                          }
661                        buf += per_width;                        REQUIRE (skip_bytes (&buf, end, per_width));
662                      }                      }
663                      break;                      break;
664                    default:                    default:
# Line 590  _bfd_elf_discard_section_eh_frame (abfd, Line 669  _bfd_elf_discard_section_eh_frame (abfd,
669    
670            /* For shared libraries, try to get rid of as many RELATIVE relocs            /* For shared libraries, try to get rid of as many RELATIVE relocs
671               as possible.  */               as possible.  */
672            if (info->shared            if (info->shared
673                && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)                && (get_elf_backend_data (abfd)
674              cie.make_relative = 1;                    ->elf_backend_can_make_relative_eh_frame
675                      (abfd, info, sec)))
676                {
677                  if ((cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
678                    cie.make_relative = 1;
679                  /* If the CIE doesn't already have an 'R' entry, it's fairly
680                     easy to add one, provided that there's no aligned data
681                     after the augmentation string.  */
682                  else if (cie.fde_encoding == DW_EH_PE_omit
683                           && (cie.per_encoding & 0xf0) != DW_EH_PE_aligned)
684                    {
685                      if (*cie.augmentation == 0)
686                        this_inf->add_augmentation_size = 1;
687                      this_inf->add_fde_encoding = 1;
688                      cie.make_relative = 1;
689                    }
690                }
691    
692            if (info->shared            if (info->shared
693                  && (get_elf_backend_data (abfd)
694                      ->elf_backend_can_make_lsda_relative_eh_frame
695                      (abfd, info, sec))
696                && (cie.lsda_encoding & 0xf0) == DW_EH_PE_absptr)                && (cie.lsda_encoding & 0xf0) == DW_EH_PE_absptr)
697              cie.make_lsda_relative = 1;              cie.make_lsda_relative = 1;
698    
# Line 603  _bfd_elf_discard_section_eh_frame (abfd, Line 701  _bfd_elf_discard_section_eh_frame (abfd,
701            if (cie.fde_encoding == DW_EH_PE_omit)            if (cie.fde_encoding == DW_EH_PE_omit)
702              cie.fde_encoding = DW_EH_PE_absptr;              cie.fde_encoding = DW_EH_PE_absptr;
703    
704            initial_insn_length = cie.hdr.length - (buf - last_fde - 4);            initial_insn_length = end - buf;
705            if (initial_insn_length <= 50)            if (initial_insn_length <= 50)
706              {              {
707                cie.initial_insn_length = initial_insn_length;                cie.initial_insn_length = initial_insn_length;
708                memcpy (cie.initial_instructions, buf, initial_insn_length);                memcpy (cie.initial_instructions, buf, initial_insn_length);
709              }              }
710              insns = buf;
711            buf += initial_insn_length;            buf += initial_insn_length;
712            ENSURE_NO_RELOCS (buf);            ENSURE_NO_RELOCS (buf);
713            last_cie = last_fde;            last_cie = last_fde;
# Line 616  _bfd_elf_discard_section_eh_frame (abfd, Line 715  _bfd_elf_discard_section_eh_frame (abfd,
715        else        else
716          {          {
717            /* Ensure this FDE uses the last CIE encountered.  */            /* Ensure this FDE uses the last CIE encountered.  */
718            if (last_cie == NULL            REQUIRE (last_cie);
719                || hdr.id != (unsigned int) (buf - 4 - last_cie))            REQUIRE (hdr.id == (unsigned int) (buf - 4 - last_cie));
             goto free_no_table;  
720    
721            ENSURE_NO_RELOCS (buf);            ENSURE_NO_RELOCS (buf);
722            rel = GET_RELOC (buf);            REQUIRE (GET_RELOC (buf));
723            if (rel == NULL)  
             /* This should not happen.  */  
             goto free_no_table;  
724            if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))            if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
725              {              /* This is a FDE against a discarded section.  It should
726                cookie->rel = rel;                 be deleted.  */
727                /* This is a FDE against discarded section, it should              this_inf->removed = 1;
                  be deleted.  */  
               new_size -= hdr.length + 4;  
               sec_info->entry[sec_info->count].removed = 1;  
             }  
728            else            else
729              {              {
730                if (info->shared                if (info->shared
# Line 640  _bfd_elf_discard_section_eh_frame (abfd, Line 732  _bfd_elf_discard_section_eh_frame (abfd,
732                         && cie.make_relative == 0)                         && cie.make_relative == 0)
733                        || (cie.fde_encoding & 0xf0) == DW_EH_PE_aligned))                        || (cie.fde_encoding & 0xf0) == DW_EH_PE_aligned))
734                  {                  {
735                    /* If shared library uses absolute pointers                    /* If a shared library uses absolute pointers
736                       which we cannot turn into PC relative,                       which we cannot turn into PC relative,
737                       don't create the binary search table,                       don't create the binary search table,
738                       since it is affected by runtime relocations.  */                       since it is affected by runtime relocations.  */
739                    hdr_info->table = false;                    hdr_info->table = FALSE;
740                  }                  }
741                cie_usage_count++;                cie_usage_count++;
742                hdr_info->fde_count++;                hdr_info->fde_count++;
743              }              }
744            cookie->rel = rel;            /* Skip the initial location and address range.  */
745              start = buf;
746              length = get_DW_EH_PE_width (cie.fde_encoding, ptr_size);
747              REQUIRE (skip_bytes (&buf, end, 2 * length));
748    
749              /* Skip the augmentation size, if present.  */
750              if (cie.augmentation[0] == 'z')
751                REQUIRE (read_uleb128 (&buf, end, &length));
752              else
753                length = 0;
754    
755              /* Of the supported augmentation characters above, only 'L'
756                 adds augmentation data to the FDE.  This code would need to
757                 be adjusted if any future augmentations do the same thing.  */
758            if (cie.lsda_encoding != DW_EH_PE_omit)            if (cie.lsda_encoding != DW_EH_PE_omit)
759              {              {
760                unsigned int dummy;                this_inf->lsda_offset = buf - start;
761                  /* If there's no 'z' augmentation, we don't know where the
762                aug = buf;                   CFA insns begin.  Assume no padding.  */
763                buf += 2 * get_DW_EH_PE_width (cie.fde_encoding, ptr_size);                if (cie.augmentation[0] != 'z')
764                if (cie.augmentation[0] == 'z')                  length = end - buf;
                 read_uleb128 (dummy, buf);  
               /* If some new augmentation data is added before LSDA  
                  in FDE augmentation area, this need to be adjusted.  */  
               sec_info->entry[sec_info->count].lsda_offset = (buf - aug);  
765              }              }
766    
767              /* Skip over the augmentation data.  */
768              REQUIRE (skip_bytes (&buf, end, length));
769              insns = buf;
770    
771            buf = last_fde + 4 + hdr.length;            buf = last_fde + 4 + hdr.length;
772            SKIP_RELOCS (buf);            SKIP_RELOCS (buf);
773          }          }
774    
775        sec_info->entry[sec_info->count].fde_encoding = cie.fde_encoding;        /* Try to interpret the CFA instructions and find the first
776        sec_info->entry[sec_info->count].lsda_encoding = cie.lsda_encoding;           padding nop.  Shrink this_inf's size so that it doesn't
777             including the padding.  */
778          length = get_DW_EH_PE_width (cie.fde_encoding, ptr_size);
779          insns = skip_non_nops (insns, end, length);
780          if (insns != 0)
781            this_inf->size -= end - insns;
782    
783          this_inf->fde_encoding = cie.fde_encoding;
784          this_inf->lsda_encoding = cie.lsda_encoding;
785        sec_info->count++;        sec_info->count++;
786      }      }
787    
788    elf_section_data (sec)->sec_info = sec_info;    elf_section_data (sec)->sec_info = sec_info;
789    elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME;    sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
790    
791    /* Ok, now we can assign new offsets.  */    /* Ok, now we can assign new offsets.  */
792    offset = 0;    offset = 0;
793    last_cie_ndx = 0;    last_cie_inf = hdr_info->last_cie_inf;
794    for (i = 0; i < sec_info->count; i++)    for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
795      {      if (!ent->removed)
796        if (! sec_info->entry[i].removed)        {
797          {          if (ent->cie)
798            sec_info->entry[i].new_offset = offset;            last_cie_inf = ent;
799            offset += sec_info->entry[i].size;          else
800            if (sec_info->entry[i].cie)            ent->cie_inf = last_cie_inf;
801              {          ent->new_offset = offset;
802                last_cie_ndx = i;          offset += size_of_output_cie_fde (ent, ptr_size);
803                make_relative = sec_info->entry[i].make_relative;        }
804                make_lsda_relative = sec_info->entry[i].make_lsda_relative;    hdr_info->last_cie_inf = last_cie_inf;
             }  
           else  
             {  
               sec_info->entry[i].make_relative = make_relative;  
               sec_info->entry[i].make_lsda_relative = make_lsda_relative;  
               sec_info->entry[i].per_encoding_relative = 0;  
             }  
         }  
       else if (sec_info->entry[i].cie && sec_info->entry[i].sec == sec)  
         {  
           /* Need to adjust new_offset too.  */  
           BFD_ASSERT (sec_info->entry[last_cie_ndx].offset  
                       == sec_info->entry[i].new_offset);  
           sec_info->entry[i].new_offset  
             = sec_info->entry[last_cie_ndx].new_offset;  
         }  
     }  
   if (hdr_info->last_cie_sec == sec)  
     {  
       BFD_ASSERT (sec_info->entry[last_cie_ndx].offset  
                   == hdr_info->last_cie_offset);  
       hdr_info->last_cie_offset = sec_info->entry[last_cie_ndx].new_offset;  
     }  
   
   /* FIXME: Currently it is not possible to shrink sections to zero size at  
      this point, so build a fake minimal CIE.  */  
   if (new_size == 0)  
     new_size = 16;  
805    
806    /* Shrink the sec as needed.  */    /* Resize the sec as needed.  */
807    sec->_cooked_size = new_size;    sec->rawsize = sec->size;
808    if (sec->_cooked_size == 0)    sec->size = offset;
809      if (sec->size == 0)
810      sec->flags |= SEC_EXCLUDE;      sec->flags |= SEC_EXCLUDE;
811    
812    free (ehbuf);    free (ehbuf);
813    return new_size != sec->_raw_size;    return offset != sec->rawsize;
814    
815  free_no_table:  free_no_table:
816    if (ehbuf)    if (ehbuf)
817      free (ehbuf);      free (ehbuf);
818    if (sec_info)    if (sec_info)
819      free (sec_info);      free (sec_info);
820    hdr_info->table = false;    hdr_info->table = FALSE;
821    hdr_info->last_cie.hdr.length = 0;    hdr_info->last_cie.hdr.length = 0;
822    return false;    return FALSE;
823    
824    #undef REQUIRE
825  }  }
826    
827  /* This function is called for .eh_frame_hdr section after  /* This function is called for .eh_frame_hdr section after
828     _bfd_elf_discard_section_eh_frame has been called on all .eh_frame     _bfd_elf_discard_section_eh_frame has been called on all .eh_frame
829     input sections.  It finalizes the size of .eh_frame_hdr section.  */     input sections.  It finalizes the size of .eh_frame_hdr section.  */
830    
831  boolean  bfd_boolean
832  _bfd_elf_discard_section_eh_frame_hdr (abfd, info, sec)  _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
      bfd *abfd;  
      struct bfd_link_info *info;  
      asection *sec;  
833  {  {
834      struct elf_link_hash_table *htab;
835    struct eh_frame_hdr_info *hdr_info;    struct eh_frame_hdr_info *hdr_info;
836    unsigned int ptr_size;    asection *sec;
837    
838    ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]    htab = elf_hash_table (info);
839                == ELFCLASS64) ? 8 : 4;    hdr_info = &htab->eh_info;
840      sec = hdr_info->hdr_sec;
841      if (sec == NULL)
842        return FALSE;
843    
844    if ((elf_section_data (sec)->sec_info_type    sec->size = EH_FRAME_HDR_SIZE;
        != ELF_INFO_TYPE_EH_FRAME_HDR)  
       || ! info->eh_frame_hdr)  
     {  
       _bfd_strip_section_from_output (info, sec);  
       return false;  
     }  
   
   hdr_info = (struct eh_frame_hdr_info *)  
              elf_section_data (sec)->sec_info;  
   if (hdr_info->strip)  
     return false;  
   sec->_cooked_size = EH_FRAME_HDR_SIZE;  
845    if (hdr_info->table)    if (hdr_info->table)
846      sec->_cooked_size += 4 + hdr_info->fde_count * 8;      sec->size += 4 + hdr_info->fde_count * 8;
847    
848    /* Request program headers to be recalculated.  */    /* Request program headers to be recalculated.  */
849    elf_tdata (abfd)->program_header_size = 0;    elf_tdata (abfd)->program_header_size = 0;
850    elf_tdata (abfd)->eh_frame_hdr = true;    elf_tdata (abfd)->eh_frame_hdr = sec;
851    return true;    return TRUE;
852  }  }
853    
854  /* This function is called from size_dynamic_sections.  /* This function is called from size_dynamic_sections.
# Line 778  _bfd_elf_discard_section_eh_frame_hdr (a Line 856  _bfd_elf_discard_section_eh_frame_hdr (a
856     because later on it is too late for calling _bfd_strip_section_from_output,     because later on it is too late for calling _bfd_strip_section_from_output,
857     since dynamic symbol table has been sized.  */     since dynamic symbol table has been sized.  */
858    
859  boolean  bfd_boolean
860  _bfd_elf_maybe_strip_eh_frame_hdr (info)  _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info)
      struct bfd_link_info *info;  
861  {  {
862    asection *sec, *o;    asection *o;
863    bfd *abfd;    bfd *abfd;
864      struct elf_link_hash_table *htab;
865    struct eh_frame_hdr_info *hdr_info;    struct eh_frame_hdr_info *hdr_info;
866    
867    sec = bfd_get_section_by_name (elf_hash_table (info)->dynobj, ".eh_frame_hdr");    htab = elf_hash_table (info);
868    if (sec == NULL || bfd_is_abs_section (sec->output_section))    hdr_info = &htab->eh_info;
869      return true;    if (hdr_info->hdr_sec == NULL)
870        return TRUE;
   hdr_info  
     = bfd_zmalloc (sizeof (struct eh_frame_hdr_info));  
   if (hdr_info == NULL)  
     return false;  
871    
872    elf_section_data (sec)->sec_info = hdr_info;    if (bfd_is_abs_section (hdr_info->hdr_sec->output_section))
873    elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME_HDR;      {
874          hdr_info->hdr_sec = NULL;
875          return TRUE;
876        }
877    
878    abfd = NULL;    abfd = NULL;
879    if (info->eh_frame_hdr)    if (info->eh_frame_hdr)
# Line 805  _bfd_elf_maybe_strip_eh_frame_hdr (info) Line 882  _bfd_elf_maybe_strip_eh_frame_hdr (info)
882          /* Count only sections which have at least a single CIE or FDE.          /* Count only sections which have at least a single CIE or FDE.
883             There cannot be any CIE or FDE <= 8 bytes.  */             There cannot be any CIE or FDE <= 8 bytes.  */
884          o = bfd_get_section_by_name (abfd, ".eh_frame");          o = bfd_get_section_by_name (abfd, ".eh_frame");
885          if (o && o->_raw_size > 8 && !bfd_is_abs_section (o->output_section))          if (o && o->size > 8 && !bfd_is_abs_section (o->output_section))
886            break;            break;
887        }        }
888    
889    if (abfd == NULL)    if (abfd == NULL)
890      {      {
891        _bfd_strip_section_from_output (info, sec);        _bfd_strip_section_from_output (info, hdr_info->hdr_sec);
892        hdr_info->strip = true;        hdr_info->hdr_sec = NULL;
893          return TRUE;
894      }      }
895    else  
896      hdr_info->table = true;    hdr_info->table = TRUE;
897    return true;    return TRUE;
898  }  }
899    
900  /* Adjust an address in the .eh_frame section.  Given OFFSET within  /* Adjust an address in the .eh_frame section.  Given OFFSET within
# Line 825  _bfd_elf_maybe_strip_eh_frame_hdr (info) Line 903  _bfd_elf_maybe_strip_eh_frame_hdr (info)
903     or to offset with dynamic relocation which is no longer needed.  */     or to offset with dynamic relocation which is no longer needed.  */
904    
905  bfd_vma  bfd_vma
906  _bfd_elf_eh_frame_section_offset (output_bfd, sec, offset)  _bfd_elf_eh_frame_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
907       bfd *output_bfd ATTRIBUTE_UNUSED;                                    struct bfd_link_info *info,
908       asection *sec;                                    asection *sec,
909       bfd_vma offset;                                    bfd_vma offset)
910  {  {
911    struct eh_frame_sec_info *sec_info;    struct eh_frame_sec_info *sec_info;
912      struct elf_link_hash_table *htab;
913      struct eh_frame_hdr_info *hdr_info;
914    unsigned int lo, hi, mid;    unsigned int lo, hi, mid;
915    
916    if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)    if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
917      return offset;      return offset;
918    sec_info = (struct eh_frame_sec_info *)    sec_info = elf_section_data (sec)->sec_info;
919               elf_section_data (sec)->sec_info;  
920      if (offset >= sec->rawsize)
921        return offset - sec->rawsize + sec->size;
922    
923    if (offset >= sec->_raw_size)    htab = elf_hash_table (info);
924      return offset - (sec->_cooked_size - sec->_raw_size);    hdr_info = &htab->eh_info;
925      if (hdr_info->offsets_adjusted)
926        offset += sec->output_offset;
927    
928    lo = 0;    lo = 0;
929    hi = sec_info->count;    hi = sec_info->count;
# Line 864  _bfd_elf_eh_frame_section_offset (output Line 948  _bfd_elf_eh_frame_section_offset (output
948    
949    /* If converting to DW_EH_PE_pcrel, there will be no need for run-time    /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
950       relocation against FDE's initial_location field.  */       relocation against FDE's initial_location field.  */
951    if (sec_info->entry[mid].make_relative    if (!sec_info->entry[mid].cie
952        && ! sec_info->entry[mid].cie        && sec_info->entry[mid].cie_inf->make_relative
953        && offset == sec_info->entry[mid].offset + 8)        && offset == sec_info->entry[mid].offset + 8)
954      return (bfd_vma) -2;      return (bfd_vma) -2;
955    
956    /* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need    /* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need
957       for run-time relocation against LSDA field.  */       for run-time relocation against LSDA field.  */
958    if (sec_info->entry[mid].make_lsda_relative    if (!sec_info->entry[mid].cie
959        && ! sec_info->entry[mid].cie        && sec_info->entry[mid].cie_inf->make_lsda_relative
960        && (offset        && (offset == (sec_info->entry[mid].offset + 8
961            == (sec_info->entry[mid].offset + 8                       + sec_info->entry[mid].lsda_offset))
962                + sec_info->entry[mid].lsda_offset)))        && (sec_info->entry[mid].cie_inf->need_lsda_relative
963      return (bfd_vma) -2;            || !hdr_info->offsets_adjusted))
964        {
965          sec_info->entry[mid].cie_inf->need_lsda_relative = 1;
966          return (bfd_vma) -2;
967        }
968    
969      if (hdr_info->offsets_adjusted)
970        offset -= sec->output_offset;
971      /* Any new augmentation bytes go before the first relocation.  */
972    return (offset + sec_info->entry[mid].new_offset    return (offset + sec_info->entry[mid].new_offset
973            - sec_info->entry[mid].offset);            - sec_info->entry[mid].offset
974              + extra_augmentation_string_bytes (sec_info->entry + mid)
975              + extra_augmentation_data_bytes (sec_info->entry + mid));
976  }  }
977    
978  /* Write out .eh_frame section.  This is called with the relocated  /* Write out .eh_frame section.  This is called with the relocated
979     contents.  */     contents.  */
980    
981  boolean  bfd_boolean
982  _bfd_elf_write_section_eh_frame (abfd, sec, ehdrsec, contents)  _bfd_elf_write_section_eh_frame (bfd *abfd,
983       bfd *abfd;                                   struct bfd_link_info *info,
984       asection *sec, *ehdrsec;                                   asection *sec,
985       bfd_byte *contents;                                   bfd_byte *contents)
986  {  {
987    struct eh_frame_sec_info *sec_info;    struct eh_frame_sec_info *sec_info;
988      struct elf_link_hash_table *htab;
989    struct eh_frame_hdr_info *hdr_info;    struct eh_frame_hdr_info *hdr_info;
   unsigned int i;  
   bfd_byte *p, *buf;  
   unsigned int leb128_tmp;  
   unsigned int cie_offset = 0;  
990    unsigned int ptr_size;    unsigned int ptr_size;
991      struct eh_cie_fde *ent;
992    
993    ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]    if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
994                == ELFCLASS64) ? 8 : 4;      return bfd_set_section_contents (abfd, sec->output_section, contents,
995                                         sec->output_offset, sec->size);
996    
997      ptr_size = (get_elf_backend_data (abfd)
998                  ->elf_backend_eh_frame_address_size (abfd, sec));
999      BFD_ASSERT (ptr_size != 0);
1000    
1001      sec_info = elf_section_data (sec)->sec_info;
1002      htab = elf_hash_table (info);
1003      hdr_info = &htab->eh_info;
1004    
1005      /* First convert all offsets to output section offsets, so that a
1006         CIE offset is valid if the CIE is used by a FDE from some other
1007         section.  This can happen when duplicate CIEs are deleted in
1008         _bfd_elf_discard_section_eh_frame.  We do all sections here because
1009         this function might not be called on sections in the same order as
1010         _bfd_elf_discard_section_eh_frame.  */
1011      if (!hdr_info->offsets_adjusted)
1012        {
1013          bfd *ibfd;
1014          asection *eh;
1015          struct eh_frame_sec_info *eh_inf;
1016    
1017          for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
1018            {
1019              if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1020                  || (ibfd->flags & DYNAMIC) != 0)
1021                continue;
1022    
1023              eh = bfd_get_section_by_name (ibfd, ".eh_frame");
1024              if (eh == NULL || eh->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
1025                continue;
1026    
1027    if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)            eh_inf = elf_section_data (eh)->sec_info;
1028      return bfd_set_section_contents (abfd, sec->output_section,            for (ent = eh_inf->entry; ent < eh_inf->entry + eh_inf->count; ++ent)
1029                                       contents,              {
1030                                       (file_ptr) sec->output_offset,                ent->offset += eh->output_offset;
1031                                       sec->_raw_size);                ent->new_offset += eh->output_offset;
1032    sec_info = (struct eh_frame_sec_info *)              }
1033               elf_section_data (sec)->sec_info;          }
1034    hdr_info = NULL;        hdr_info->offsets_adjusted = TRUE;
   if (ehdrsec  
       && (elf_section_data (ehdrsec)->sec_info_type  
           == ELF_INFO_TYPE_EH_FRAME_HDR))  
     {  
       hdr_info = (struct eh_frame_hdr_info *)  
                  elf_section_data (ehdrsec)->sec_info;  
       if (hdr_info->table && hdr_info->array == NULL)  
         hdr_info->array  
           = bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));  
       if (hdr_info->array == NULL)  
         hdr_info = NULL;  
1035      }      }
1036    
1037    p = contents;    if (hdr_info->table && hdr_info->array == NULL)
1038    for (i = 0; i < sec_info->count; ++i)      hdr_info->array
1039          = bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
1040      if (hdr_info->array == NULL)
1041        hdr_info = NULL;
1042    
1043      /* The new offsets can be bigger or smaller than the original offsets.
1044         We therefore need to make two passes over the section: one backward
1045         pass to move entries up and one forward pass to move entries down.
1046         The two passes won't interfere with each other because entries are
1047         not reordered  */
1048      for (ent = sec_info->entry + sec_info->count; ent-- != sec_info->entry;)
1049        if (!ent->removed && ent->new_offset > ent->offset)
1050          memmove (contents + ent->new_offset - sec->output_offset,
1051                   contents + ent->offset - sec->output_offset, ent->size);
1052    
1053      for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
1054        if (!ent->removed && ent->new_offset < ent->offset)
1055          memmove (contents + ent->new_offset - sec->output_offset,
1056                   contents + ent->offset - sec->output_offset, ent->size);
1057    
1058      for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
1059      {      {
1060        if (sec_info->entry[i].removed)        unsigned char *buf, *end;
1061          unsigned int new_size;
1062    
1063          if (ent->removed)
1064            continue;
1065    
1066          if (ent->size == 4)
1067          {          {
1068            if (sec_info->entry[i].cie)            /* Any terminating FDE must be at the end of the section.  */
1069              {            BFD_ASSERT (ent == sec_info->entry + sec_info->count - 1);
               /* If CIE is removed due to no remaining FDEs referencing it  
                  and there were no CIEs kept before it, sec_info->entry[i].sec  
                  will be zero.  */  
               if (sec_info->entry[i].sec == NULL)  
                 cie_offset = 0;  
               else  
                 {  
                   cie_offset = sec_info->entry[i].new_offset;  
                   cie_offset += (sec_info->entry[i].sec->output_section->vma  
                                  + sec_info->entry[i].sec->output_offset  
                                  - sec->output_section->vma  
                                  - sec->output_offset);  
                 }  
             }  
1070            continue;            continue;
1071          }          }
1072    
1073        if (sec_info->entry[i].cie)        buf = contents + ent->new_offset - sec->output_offset;
1074          end = buf + ent->size;
1075          new_size = size_of_output_cie_fde (ent, ptr_size);
1076    
1077          /* Install the new size, filling the extra bytes with DW_CFA_nops.  */
1078          if (new_size != ent->size)
1079            {
1080              memset (end, 0, new_size - ent->size);
1081              bfd_put_32 (abfd, new_size - 4, buf);
1082            }
1083    
1084          if (ent->cie)
1085          {          {
1086            /* CIE */            /* CIE */
1087            cie_offset = sec_info->entry[i].new_offset;            if (ent->make_relative
1088            if (sec_info->entry[i].make_relative                || ent->need_lsda_relative
1089                || sec_info->entry[i].make_lsda_relative                || ent->per_encoding_relative)
               || sec_info->entry[i].per_encoding_relative)  
1090              {              {
1091                unsigned char *aug;                char *aug;
1092                unsigned int action;                unsigned int action, extra_string, extra_data;
1093                unsigned int dummy, per_width, per_encoding;                unsigned int per_width, per_encoding;
1094    
1095                /* Need to find 'R' or 'L' augmentation's argument and modify                /* Need to find 'R' or 'L' augmentation's argument and modify
1096                   DW_EH_PE_* value.  */                   DW_EH_PE_* value.  */
1097                action = (sec_info->entry[i].make_relative ? 1 : 0)                action = ((ent->make_relative ? 1 : 0)
1098                         | (sec_info->entry[i].make_lsda_relative ? 2 : 0)                          | (ent->need_lsda_relative ? 2 : 0)
1099                         | (sec_info->entry[i].per_encoding_relative ? 4 : 0);                          | (ent->per_encoding_relative ? 4 : 0));
1100                buf = contents + sec_info->entry[i].offset;                extra_string = extra_augmentation_string_bytes (ent);
1101                  extra_data = extra_augmentation_data_bytes (ent);
1102    
1103                /* Skip length, id and version.  */                /* Skip length, id and version.  */
1104                buf += 9;                buf += 9;
1105                aug = buf;                aug = (char *) buf;
1106                buf = strchr (buf, '\0') + 1;                buf += strlen (aug) + 1;
1107                read_uleb128 (dummy, buf);                skip_leb128 (&buf, end);
1108                read_sleb128 (dummy, buf);                skip_leb128 (&buf, end);
1109                read_uleb128 (dummy, buf);                skip_leb128 (&buf, end);
1110                if (*aug == 'z')                if (*aug == 'z')
1111                  {                  {
1112                    read_uleb128 (dummy, buf);                    /* The uleb128 will always be a single byte for the kind
1113                         of augmentation strings that we're prepared to handle.  */
1114                      *buf++ += extra_data;
1115                    aug++;                    aug++;
1116                  }                  }
1117    
1118                  /* Make room for the new augmentation string and data bytes.  */
1119                  memmove (buf + extra_string + extra_data, buf, end - buf);
1120                  memmove (aug + extra_string, aug, buf - (bfd_byte *) aug);
1121                  buf += extra_string;
1122                  end += extra_string + extra_data;
1123    
1124                  if (ent->add_augmentation_size)
1125                    {
1126                      *aug++ = 'z';
1127                      *buf++ = extra_data - 1;
1128                    }
1129                  if (ent->add_fde_encoding)
1130                    {
1131                      BFD_ASSERT (action & 1);
1132                      *aug++ = 'R';
1133                      *buf++ = DW_EH_PE_pcrel;
1134                      action &= ~1;
1135                    }
1136    
1137                while (action)                while (action)
1138                  switch (*aug++)                  switch (*aug++)
1139                    {                    {
1140                    case 'L':                    case 'L':
1141                      if (action & 2)                      if (action & 2)
1142                        {                        {
1143                          BFD_ASSERT (*buf == sec_info->entry[i].lsda_encoding);                          BFD_ASSERT (*buf == ent->lsda_encoding);
1144                          *buf |= DW_EH_PE_pcrel;                          *buf |= DW_EH_PE_pcrel;
1145                          action &= ~2;                          action &= ~2;
1146                        }                        }
# Line 992  _bfd_elf_write_section_eh_frame (abfd, s Line 1148  _bfd_elf_write_section_eh_frame (abfd, s
1148                      break;                      break;
1149                    case 'P':                    case 'P':
1150                      per_encoding = *buf++;                      per_encoding = *buf++;
1151                      per_width = get_DW_EH_PE_width (per_encoding,                      per_width = get_DW_EH_PE_width (per_encoding, ptr_size);
                                                     ptr_size);  
1152                      BFD_ASSERT (per_width != 0);                      BFD_ASSERT (per_width != 0);
1153                      BFD_ASSERT (((per_encoding & 0x70) == DW_EH_PE_pcrel)                      BFD_ASSERT (((per_encoding & 0x70) == DW_EH_PE_pcrel)
1154                                  == sec_info->entry[i].per_encoding_relative);                                  == ent->per_encoding_relative);
1155                      if ((per_encoding & 0xf0) == DW_EH_PE_aligned)                      if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
1156                        buf = (contents                        buf = (contents
1157                               + ((buf - contents + per_width - 1)                               + ((buf - contents + per_width - 1)
1158                                  & ~((bfd_size_type) per_width - 1)));                                  & ~((bfd_size_type) per_width - 1)));
1159                      if (action & 4)                      if (action & 4)
1160                        {                        {
1161                          bfd_vma value;                          bfd_vma val;
1162    
1163                          value = read_value (abfd, buf, per_width);                          val = read_value (abfd, buf, per_width,
1164                          value += (sec_info->entry[i].offset                                            get_DW_EH_PE_signed (per_encoding));
1165                                    - sec_info->entry[i].new_offset);                          val += ent->offset - ent->new_offset;
1166                          write_value (abfd, buf, value, per_width);                          val -= extra_string + extra_data;
1167                            write_value (abfd, buf, val, per_width);
1168                          action &= ~4;                          action &= ~4;
1169                        }                        }
1170                      buf += per_width;                      buf += per_width;
# Line 1016  _bfd_elf_write_section_eh_frame (abfd, s Line 1172  _bfd_elf_write_section_eh_frame (abfd, s
1172                    case 'R':                    case 'R':
1173                      if (action & 1)                      if (action & 1)
1174                        {                        {
1175                          BFD_ASSERT (*buf == sec_info->entry[i].fde_encoding);                          BFD_ASSERT (*buf == ent->fde_encoding);
1176                          *buf |= DW_EH_PE_pcrel;                          *buf |= DW_EH_PE_pcrel;
1177                          action &= ~1;                          action &= ~1;
1178                        }                        }
# Line 1027  _bfd_elf_write_section_eh_frame (abfd, s Line 1183  _bfd_elf_write_section_eh_frame (abfd, s
1183                    }                    }
1184              }              }
1185          }          }
1186        else if (sec_info->entry[i].size > 4)        else
1187          {          {
1188            /* FDE */            /* FDE */
1189            bfd_vma value = 0, address;            bfd_vma value, address;
1190            unsigned int width;            unsigned int width;
1191    
1192            buf = contents + sec_info->entry[i].offset;            /* Skip length.  */
           /* Skip length.  */    
1193            buf += 4;            buf += 4;
1194            bfd_put_32 (abfd,            value = ent->new_offset + 4 - ent->cie_inf->new_offset;
1195                        sec_info->entry[i].new_offset + 4 - cie_offset, buf);            bfd_put_32 (abfd, value, buf);
1196            buf += 4;            buf += 4;
1197            width = get_DW_EH_PE_width (sec_info->entry[i].fde_encoding,            width = get_DW_EH_PE_width (ent->fde_encoding, ptr_size);
1198                                        ptr_size);            value = read_value (abfd, buf, width,
1199            address = value = read_value (abfd, buf, width);                                get_DW_EH_PE_signed (ent->fde_encoding));
1200              address = value;
1201            if (value)            if (value)
1202              {              {
1203                switch (sec_info->entry[i].fde_encoding & 0xf0)                switch (ent->fde_encoding & 0xf0)
1204                  {                  {
1205                  case DW_EH_PE_indirect:                  case DW_EH_PE_indirect:
1206                  case DW_EH_PE_textrel:                  case DW_EH_PE_textrel:
# Line 1059  _bfd_elf_write_section_eh_frame (abfd, s Line 1215  _bfd_elf_write_section_eh_frame (abfd, s
1215                    }                    }
1216                    break;                    break;
1217                  case DW_EH_PE_pcrel:                  case DW_EH_PE_pcrel:
1218                    value += (sec_info->entry[i].offset                    value += ent->offset - ent->new_offset;
1219                              - sec_info->entry[i].new_offset);                    address += sec->output_section->vma + ent->offset + 8;
                   address += (sec->output_section->vma + sec->output_offset  
                               + sec_info->entry[i].offset + 8);  
1220                    break;                    break;
1221                  }                  }
1222                if (sec_info->entry[i].make_relative)                if (ent->cie_inf->make_relative)
1223                  value -= (sec->output_section->vma + sec->output_offset                  value -= sec->output_section->vma + ent->new_offset + 8;
                           + sec_info->entry[i].new_offset + 8);  
1224                write_value (abfd, buf, value, width);                write_value (abfd, buf, value, width);
1225              }              }
1226    
# Line 1075  _bfd_elf_write_section_eh_frame (abfd, s Line 1228  _bfd_elf_write_section_eh_frame (abfd, s
1228              {              {
1229                hdr_info->array[hdr_info->array_count].initial_loc = address;                hdr_info->array[hdr_info->array_count].initial_loc = address;
1230                hdr_info->array[hdr_info->array_count++].fde                hdr_info->array[hdr_info->array_count++].fde
1231                  = (sec->output_section->vma + sec->output_offset                  = sec->output_section->vma + ent->new_offset;
                    + sec_info->entry[i].new_offset);  
1232              }              }
1233    
1234            if ((sec_info->entry[i].lsda_encoding & 0xf0) == DW_EH_PE_pcrel            if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel
1235                || sec_info->entry[i].make_lsda_relative)                || ent->cie_inf->need_lsda_relative)
1236              {              {
1237                buf += sec_info->entry[i].lsda_offset;                buf += ent->lsda_offset;
1238                width = get_DW_EH_PE_width (sec_info->entry[i].lsda_encoding,                width = get_DW_EH_PE_width (ent->lsda_encoding, ptr_size);
1239                                            ptr_size);                value = read_value (abfd, buf, width,
1240                value = read_value (abfd, buf, width);                                    get_DW_EH_PE_signed (ent->lsda_encoding));
1241                if (value)                if (value)
1242                  {                  {
1243                    if ((sec_info->entry[i].lsda_encoding & 0xf0)                    if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel)
1244                        == DW_EH_PE_pcrel)                      value += ent->offset - ent->new_offset;
1245                      value += (sec_info->entry[i].offset                    else if (ent->cie_inf->need_lsda_relative)
1246                                - sec_info->entry[i].new_offset);                      value -= (sec->output_section->vma + ent->new_offset + 8
1247                    else if (sec_info->entry[i].make_lsda_relative)                                + ent->lsda_offset);
                     value -= (sec->output_section->vma + sec->output_offset  
                               + sec_info->entry[i].new_offset + 8  
                               + sec_info->entry[i].lsda_offset);  
1248                    write_value (abfd, buf, value, width);                    write_value (abfd, buf, value, width);
1249                  }                  }
1250              }              }
1251              else if (ent->cie_inf->add_augmentation_size)
1252                {
1253                  /* Skip the PC and length and insert a zero byte for the
1254                     augmentation size.  */
1255                  buf += width * 2;
1256                  memmove (buf + 1, buf, end - buf);
1257                  *buf = 0;
1258                }
1259          }          }
       else  
         /* Terminating FDE must be at the end of .eh_frame section only.  */  
         BFD_ASSERT (i == sec_info->count - 1);  
   
       BFD_ASSERT (p == contents + sec_info->entry[i].new_offset);  
       memmove (p, contents + sec_info->entry[i].offset,  
                sec_info->entry[i].size);  
       p += sec_info->entry[i].size;  
1260      }      }
1261    
   /* FIXME: Once _bfd_elf_discard_section_eh_frame will be able to  
      shrink sections to zero size, this won't be needed any more.  */  
   if (p == contents && sec->_cooked_size == 16)  
1262      {      {
1263        bfd_put_32 (abfd, 12, p);         /* Fake CIE length */        unsigned int alignment = 1 << sec->alignment_power;
1264        bfd_put_32 (abfd, 0, p + 4);      /* Fake CIE id */        unsigned int pad = sec->size % alignment;
1265        p[8] = 1;                         /* Fake CIE version */  
1266        memset (p + 9, 0, 7);             /* Fake CIE augmentation, 3xleb128        /* Don't pad beyond the raw size of the output section. It
1267                                             and 3xDW_CFA_nop as pad  */           can happen at the last input section.  */
1268        p += 16;        if (pad
1269      }            && ((sec->output_offset + sec->size + pad)
1270                  <= sec->output_section->size))
1271            {
1272              bfd_byte *buf;
1273              unsigned int new_size;
1274    
1275    BFD_ASSERT ((bfd_size_type) (p - contents) == sec->_cooked_size);            /* Find the last CIE/FDE.  */
1276              ent = sec_info->entry + sec_info->count;
1277              while (--ent != sec_info->entry)
1278                if (!ent->removed)
1279                  break;
1280    
1281              /* The size of the last CIE/FDE must be at least 4.  */
1282              if (ent->removed || ent->size < 4)
1283                abort ();
1284    
1285              pad = alignment - pad;
1286              buf = contents + ent->new_offset - sec->output_offset;
1287              new_size = size_of_output_cie_fde (ent, ptr_size);
1288    
1289              /* Pad it with DW_CFA_nop  */
1290              memset (buf + new_size, 0, pad);
1291              bfd_put_32 (abfd, new_size + pad - 4, buf);
1292    
1293              sec->size += pad;
1294            }
1295        }
1296    
1297    return bfd_set_section_contents (abfd, sec->output_section,    return bfd_set_section_contents (abfd, sec->output_section,
1298                                     contents, (file_ptr) sec->output_offset,                                     contents, (file_ptr) sec->output_offset,
1299                                     sec->_cooked_size);                                     sec->size);
1300  }  }
1301    
1302  /* Helper function used to sort .eh_frame_hdr search table by increasing  /* Helper function used to sort .eh_frame_hdr search table by increasing
1303     VMA of FDE initial location.  */     VMA of FDE initial location.  */
1304    
1305  static int  static int
1306  vma_compare (a, b)  vma_compare (const void *a, const void *b)
      const PTR a;  
      const PTR b;  
1307  {  {
1308    struct eh_frame_array_ent *p = (struct eh_frame_array_ent *) a;    const struct eh_frame_array_ent *p = a;
1309    struct eh_frame_array_ent *q = (struct eh_frame_array_ent *) b;    const struct eh_frame_array_ent *q = b;
1310    if (p->initial_loc > q->initial_loc)    if (p->initial_loc > q->initial_loc)
1311      return 1;      return 1;
1312    if (p->initial_loc < q->initial_loc)    if (p->initial_loc < q->initial_loc)
# Line 1166  vma_compare (a, b) Line 1334  vma_compare (a, b)
1334     fde_count x [encoded] initial_loc, fde     fde_count x [encoded] initial_loc, fde
1335                                  (array of encoded pairs containing                                  (array of encoded pairs containing
1336                                   FDE initial_location field and FDE address,                                   FDE initial_location field and FDE address,
1337                                   sorted by increasing initial_loc)  */                                   sorted by increasing initial_loc).  */
1338    
1339  boolean  bfd_boolean
1340  _bfd_elf_write_section_eh_frame_hdr (abfd, sec)  _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
      bfd *abfd;  
      asection *sec;  
1341  {  {
1342      struct elf_link_hash_table *htab;
1343    struct eh_frame_hdr_info *hdr_info;    struct eh_frame_hdr_info *hdr_info;
1344    unsigned int ptr_size;    asection *sec;
1345    bfd_byte *contents;    bfd_byte *contents;
1346    asection *eh_frame_sec;    asection *eh_frame_sec;
1347    bfd_size_type size;    bfd_size_type size;
1348      bfd_boolean retval;
1349      bfd_vma encoded_eh_frame;
1350    
1351    ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]    htab = elf_hash_table (info);
1352                == ELFCLASS64) ? 8 : 4;    hdr_info = &htab->eh_info;
1353      sec = hdr_info->hdr_sec;
1354    BFD_ASSERT (elf_section_data (sec)->sec_info_type    if (sec == NULL)
1355                == ELF_INFO_TYPE_EH_FRAME_HDR);      return TRUE;
   hdr_info = (struct eh_frame_hdr_info *)  
              elf_section_data (sec)->sec_info;  
   if (hdr_info->strip)  
     return true;  
1356    
1357    size = EH_FRAME_HDR_SIZE;    size = EH_FRAME_HDR_SIZE;
1358    if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)    if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
1359      size += 4 + hdr_info->fde_count * 8;      size += 4 + hdr_info->fde_count * 8;
1360    contents = bfd_malloc (size);    contents = bfd_malloc (size);
1361    if (contents == NULL)    if (contents == NULL)
1362      return false;      return FALSE;
1363    
1364    eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");    eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
1365    if (eh_frame_sec == NULL)    if (eh_frame_sec == NULL)
1366      return false;      {
1367          free (contents);
1368          return FALSE;
1369        }
1370    
1371    memset (contents, 0, EH_FRAME_HDR_SIZE);    memset (contents, 0, EH_FRAME_HDR_SIZE);
1372    contents[0] = 1;                              /* Version  */    contents[0] = 1;                              /* Version.  */
1373    contents[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; /* .eh_frame offset  */    contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address
1374        (abfd, info, eh_frame_sec, 0, sec, 4,
1375         &encoded_eh_frame);                        /* .eh_frame offset.  */
1376    
1377    if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)    if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
1378      {      {
1379        contents[2] = DW_EH_PE_udata4;            /* FDE count encoding  */        contents[2] = DW_EH_PE_udata4;            /* FDE count encoding.  */
1380        contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* search table enc  */        contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* Search table enc.  */
1381      }      }
1382    else    else
1383      {      {
1384        contents[2] = DW_EH_PE_omit;        contents[2] = DW_EH_PE_omit;
1385        contents[3] = DW_EH_PE_omit;        contents[3] = DW_EH_PE_omit;
1386      }      }
1387    bfd_put_32 (abfd, eh_frame_sec->vma - sec->output_section->vma - 4,    bfd_put_32 (abfd, encoded_eh_frame, contents + 4);
1388                contents + 4);  
1389    if (contents[2] != DW_EH_PE_omit)    if (contents[2] != DW_EH_PE_omit)
1390      {      {
1391        unsigned int i;        unsigned int i;
# Line 1234  _bfd_elf_write_section_eh_frame_hdr (abf Line 1405  _bfd_elf_write_section_eh_frame_hdr (abf
1405          }          }
1406      }      }
1407    
1408    return bfd_set_section_contents (abfd, sec->output_section,    retval = bfd_set_section_contents (abfd, sec->output_section,
1409                                     contents, (file_ptr) sec->output_offset,                                       contents, (file_ptr) sec->output_offset,
1410                                     sec->_cooked_size);                                       sec->size);
1411      free (contents);
1412      return retval;
1413    }
1414    
1415    /* Return the width of FDE addresses.  This is the default implementation.  */
1416    
1417    unsigned int
1418    _bfd_elf_eh_frame_address_size (bfd *abfd, asection *sec ATTRIBUTE_UNUSED)
1419    {
1420      return elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64 ? 8 : 4;
1421    }
1422    
1423    /* Decide whether we can use a PC-relative encoding within the given
1424       EH frame section.  This is the default implementation.  */
1425    
1426    bfd_boolean
1427    _bfd_elf_can_make_relative (bfd *input_bfd ATTRIBUTE_UNUSED,
1428                                struct bfd_link_info *info ATTRIBUTE_UNUSED,
1429                                asection *eh_frame_section ATTRIBUTE_UNUSED)
1430    {
1431      return TRUE;
1432    }
1433    
1434    /* Select an encoding for the given address.  Preference is given to
1435       PC-relative addressing modes.  */
1436    
1437    bfd_byte
1438    _bfd_elf_encode_eh_address (bfd *abfd ATTRIBUTE_UNUSED,
1439                                struct bfd_link_info *info ATTRIBUTE_UNUSED,
1440                                asection *osec, bfd_vma offset,
1441                                asection *loc_sec, bfd_vma loc_offset,
1442                                bfd_vma *encoded)
1443    {
1444      *encoded = osec->vma + offset -
1445        (loc_sec->output_section->vma + loc_sec->output_offset + loc_offset);
1446      return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
1447  }  }

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26