1 /* .eh_frame section optimization.
2 Copyright 2001, 2002 Free Software Foundation, Inc.
3 Written by Jakub Jelinek <jakub@redhat.com>.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25 #include "elf/dwarf2.h"
27 #define EH_FRAME_HDR_SIZE 8
37 struct cie_header hdr
;
38 unsigned char version
;
39 unsigned char augmentation
[20];
40 unsigned int code_align
;
42 unsigned int ra_column
;
43 unsigned int augmentation_size
;
44 struct elf_link_hash_entry
*personality
;
45 unsigned char per_encoding
;
46 unsigned char lsda_encoding
;
47 unsigned char fde_encoding
;
48 unsigned char initial_insn_length
;
49 unsigned char make_relative
;
50 unsigned char make_lsda_relative
;
51 unsigned char initial_instructions
[50];
59 unsigned int new_offset
;
60 unsigned char fde_encoding
;
61 unsigned char lsda_encoding
;
62 unsigned char lsda_offset
;
63 unsigned char cie
: 1;
64 unsigned char removed
: 1;
65 unsigned char make_relative
: 1;
66 unsigned char make_lsda_relative
: 1;
67 unsigned char per_encoding_relative
: 1;
70 struct eh_frame_sec_info
74 struct eh_cie_fde entry
[1];
77 struct eh_frame_array_ent
83 struct eh_frame_hdr_info
86 asection
*last_cie_sec
;
87 unsigned int last_cie_offset
;
88 unsigned int fde_count
, array_count
;
89 struct eh_frame_array_ent
*array
;
90 /* TRUE if .eh_frame_hdr should contain the sorted search table.
91 We build it if we successfully read all .eh_frame input sections
92 and recognize them. */
97 static bfd_vma read_unsigned_leb128
98 PARAMS ((bfd
*, char *, unsigned int *));
99 static bfd_signed_vma read_signed_leb128
100 PARAMS ((bfd
*, char *, unsigned int *));
101 static int get_DW_EH_PE_width
103 static bfd_vma read_value
104 PARAMS ((bfd
*, bfd_byte
*, int));
105 static void write_value
106 PARAMS ((bfd
*, bfd_byte
*, bfd_vma
, int));
107 static int cie_compare
108 PARAMS ((struct cie
*, struct cie
*));
109 static int vma_compare
110 PARAMS ((const PTR a
, const PTR b
));
112 /* Helper function for reading uleb128 encoded data. */
115 read_unsigned_leb128 (abfd
, buf
, bytes_read_ptr
)
116 bfd
*abfd ATTRIBUTE_UNUSED
;
118 unsigned int *bytes_read_ptr
;
121 unsigned int num_read
;
130 byte
= bfd_get_8 (abfd
, (bfd_byte
*) buf
);
133 result
|= (((bfd_vma
) byte
& 0x7f) << shift
);
137 * bytes_read_ptr
= num_read
;
141 /* Helper function for reading sleb128 encoded data. */
143 static bfd_signed_vma
144 read_signed_leb128 (abfd
, buf
, bytes_read_ptr
)
145 bfd
*abfd ATTRIBUTE_UNUSED
;
147 unsigned int * bytes_read_ptr
;
159 byte
= bfd_get_8 (abfd
, (bfd_byte
*) buf
);
162 result
|= (((bfd_vma
) byte
& 0x7f) << shift
);
167 result
|= (((bfd_vma
) -1) << (shift
- 7)) << 7;
168 * bytes_read_ptr
= num_read
;
172 #define read_uleb128(VAR, BUF) \
175 (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp); \
176 (BUF) += leb128_tmp; \
180 #define read_sleb128(VAR, BUF) \
183 (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp); \
184 (BUF) += leb128_tmp; \
188 /* Return 0 if either encoding is variable width, or not yet known to bfd. */
191 int get_DW_EH_PE_width (encoding
, ptr_size
)
192 int encoding
, ptr_size
;
194 /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
196 if ((encoding
& 0x60) == 0x60)
199 switch (encoding
& 7)
201 case DW_EH_PE_udata2
: return 2;
202 case DW_EH_PE_udata4
: return 4;
203 case DW_EH_PE_udata8
: return 8;
204 case DW_EH_PE_absptr
: return ptr_size
;
212 /* Read a width sized value from memory. */
215 read_value (abfd
, buf
, width
)
224 case 2: value
= bfd_get_16 (abfd
, buf
); break;
225 case 4: value
= bfd_get_32 (abfd
, buf
); break;
226 case 8: value
= bfd_get_64 (abfd
, buf
); break;
227 default: BFD_FAIL (); return 0;
233 /* Store a width sized value to memory. */
236 write_value (abfd
, buf
, value
, width
)
244 case 2: bfd_put_16 (abfd
, value
, buf
); break;
245 case 4: bfd_put_32 (abfd
, value
, buf
); break;
246 case 8: bfd_put_64 (abfd
, value
, buf
); break;
247 default: BFD_FAIL ();
251 /* Return zero if C1 and C2 CIEs can be merged. */
254 int cie_compare (c1
, c2
)
257 if (c1
->hdr
.length
== c2
->hdr
.length
258 && c1
->version
== c2
->version
259 && strcmp (c1
->augmentation
, c2
->augmentation
) == 0
260 && strcmp (c1
->augmentation
, "eh") != 0
261 && c1
->code_align
== c2
->code_align
262 && c1
->data_align
== c2
->data_align
263 && c1
->ra_column
== c2
->ra_column
264 && c1
->augmentation_size
== c2
->augmentation_size
265 && c1
->personality
== c2
->personality
266 && c1
->per_encoding
== c2
->per_encoding
267 && c1
->lsda_encoding
== c2
->lsda_encoding
268 && c1
->fde_encoding
== c2
->fde_encoding
269 && (c1
->initial_insn_length
270 == c2
->initial_insn_length
)
271 && memcmp (c1
->initial_instructions
,
272 c2
->initial_instructions
,
273 c1
->initial_insn_length
) == 0)
279 /* This function is called for each input file before the .eh_frame
280 section is relocated. It discards duplicate CIEs and FDEs for discarded
281 functions. The function returns true iff any entries have been
285 _bfd_elf_discard_section_eh_frame (abfd
, info
, sec
, ehdrsec
,
286 reloc_symbol_deleted_p
, cookie
)
288 struct bfd_link_info
*info
;
289 asection
*sec
, *ehdrsec
;
290 boolean (*reloc_symbol_deleted_p
) (bfd_vma
, PTR
);
291 struct elf_reloc_cookie
*cookie
;
293 bfd_byte
*ehbuf
= NULL
, *buf
;
294 bfd_byte
*last_cie
, *last_fde
;
295 struct cie_header hdr
;
297 struct eh_frame_hdr_info
*hdr_info
;
298 struct eh_frame_sec_info
*sec_info
= NULL
;
299 unsigned int leb128_tmp
;
300 unsigned int cie_usage_count
, last_cie_ndx
, i
, offset
;
301 unsigned int make_relative
, make_lsda_relative
;
302 Elf_Internal_Rela
*rel
;
303 bfd_size_type new_size
;
304 unsigned int ptr_size
;
306 if (sec
->_raw_size
== 0)
308 /* This file does not contain .eh_frame information. */
312 if ((sec
->output_section
!= NULL
313 && bfd_is_abs_section (sec
->output_section
)))
315 /* At least one of the sections is being discarded from the
316 link, so we should just ignore them. */
320 BFD_ASSERT (elf_section_data (ehdrsec
)->sec_info_type
321 == ELF_INFO_TYPE_EH_FRAME_HDR
);
322 hdr_info
= (struct eh_frame_hdr_info
*)
323 elf_section_data (ehdrsec
)->sec_info
;
325 /* Read the frame unwind information from abfd. */
327 ehbuf
= (bfd_byte
*) bfd_malloc (sec
->_raw_size
);
331 if (! bfd_get_section_contents (abfd
, sec
, ehbuf
, (bfd_vma
) 0,
335 if (sec
->_raw_size
>= 4
336 && bfd_get_32 (abfd
, ehbuf
) == 0
337 && cookie
->rel
== cookie
->relend
)
339 /* Empty .eh_frame section. */
344 /* If .eh_frame section size doesn't fit into int, we cannot handle
345 it (it would need to use 64-bit .eh_frame format anyway). */
346 if (sec
->_raw_size
!= (unsigned int) sec
->_raw_size
)
349 ptr_size
= (elf_elfheader (abfd
)->e_ident
[EI_CLASS
]
350 == ELFCLASS64
) ? 8 : 4;
354 memset (&cie
, 0, sizeof (cie
));
356 new_size
= sec
->_raw_size
;
357 make_relative
= hdr_info
->last_cie
.make_relative
;
358 make_lsda_relative
= hdr_info
->last_cie
.make_lsda_relative
;
359 sec_info
= bfd_zmalloc (sizeof (struct eh_frame_sec_info
)
360 + 99 * sizeof (struct eh_cie_fde
));
361 if (sec_info
== NULL
)
363 sec_info
->alloced
= 100;
365 #define ENSURE_NO_RELOCS(buf) \
366 if (cookie->rel < cookie->relend \
367 && (cookie->rel->r_offset \
368 < (bfd_size_type) ((buf) - ehbuf))) \
371 #define SKIP_RELOCS(buf) \
372 while (cookie->rel < cookie->relend \
373 && (cookie->rel->r_offset \
374 < (bfd_size_type) ((buf) - ehbuf))) \
377 #define GET_RELOC(buf) \
378 ((cookie->rel < cookie->relend \
379 && (cookie->rel->r_offset \
380 == (bfd_size_type) ((buf) - ehbuf))) \
381 ? cookie->rel : NULL)
387 if (sec_info
->count
== sec_info
->alloced
)
389 sec_info
= bfd_realloc (sec_info
,
390 sizeof (struct eh_frame_sec_info
)
391 + (sec_info
->alloced
+ 99)
392 * sizeof (struct eh_cie_fde
));
393 if (sec_info
== NULL
)
396 memset (&sec_info
->entry
[sec_info
->alloced
], 0,
397 100 * sizeof (struct eh_cie_fde
));
398 sec_info
->alloced
+= 100;
402 /* If we are at the end of the section, we still need to decide
403 on whether to output or discard last encountered CIE (if any). */
404 if ((bfd_size_type
) (buf
- ehbuf
) == sec
->_raw_size
)
405 hdr
.id
= (unsigned int) -1;
408 if ((bfd_size_type
) (buf
+ 4 - ehbuf
) > sec
->_raw_size
)
409 /* No space for CIE/FDE header length. */
412 hdr
.length
= bfd_get_32 (abfd
, buf
);
413 if (hdr
.length
== 0xffffffff)
414 /* 64-bit .eh_frame is not supported. */
417 if ((buf
- ehbuf
) + hdr
.length
> sec
->_raw_size
)
418 /* CIE/FDE not contained fully in this .eh_frame input section. */
421 sec_info
->entry
[sec_info
->count
].offset
= last_fde
- ehbuf
;
422 sec_info
->entry
[sec_info
->count
].size
= 4 + hdr
.length
;
426 /* CIE with length 0 must be only the last in the section. */
427 if ((bfd_size_type
) (buf
- ehbuf
) < sec
->_raw_size
)
429 ENSURE_NO_RELOCS (buf
);
431 /* Now just finish last encountered CIE processing and break
433 hdr
.id
= (unsigned int) -1;
437 hdr
.id
= bfd_get_32 (abfd
, buf
);
439 if (hdr
.id
== (unsigned int) -1)
444 if (hdr
.id
== 0 || hdr
.id
== (unsigned int) -1)
446 unsigned int initial_insn_length
;
449 if (last_cie
!= NULL
)
451 /* Now check if this CIE is identical to last CIE, in which case
452 we can remove it, provided we adjust all FDEs.
453 Also, it can be removed if we have removed all FDEs using
455 if (cie_compare (&cie
, &hdr_info
->last_cie
) == 0
456 || cie_usage_count
== 0)
458 new_size
-= cie
.hdr
.length
+ 4;
459 sec_info
->entry
[last_cie_ndx
].removed
= 1;
460 sec_info
->entry
[last_cie_ndx
].sec
= hdr_info
->last_cie_sec
;
461 sec_info
->entry
[last_cie_ndx
].new_offset
462 = hdr_info
->last_cie_offset
;
466 hdr_info
->last_cie
= cie
;
467 hdr_info
->last_cie_sec
= sec
;
468 hdr_info
->last_cie_offset
= last_cie
- ehbuf
;
469 sec_info
->entry
[last_cie_ndx
].make_relative
471 sec_info
->entry
[last_cie_ndx
].make_lsda_relative
472 = cie
.make_lsda_relative
;
473 sec_info
->entry
[last_cie_ndx
].per_encoding_relative
474 = (cie
.per_encoding
& 0x70) == DW_EH_PE_pcrel
;
478 if (hdr
.id
== (unsigned int) -1)
481 last_cie_ndx
= sec_info
->count
;
482 sec_info
->entry
[sec_info
->count
].cie
= 1;
485 memset (&cie
, 0, sizeof (cie
));
487 cie
.version
= *buf
++;
489 /* Cannot handle unknown versions. */
490 if (cie
.version
!= 1)
492 if (strlen (buf
) > sizeof (cie
.augmentation
) - 1)
495 strcpy (cie
.augmentation
, buf
);
496 buf
= strchr (buf
, '\0') + 1;
497 ENSURE_NO_RELOCS (buf
);
498 if (buf
[0] == 'e' && buf
[1] == 'h')
500 /* GCC < 3.0 .eh_frame CIE */
501 /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
502 is private to each CIE, so we don't need it for anything.
507 read_uleb128 (cie
.code_align
, buf
);
508 read_sleb128 (cie
.data_align
, buf
);
509 read_uleb128 (cie
.ra_column
, buf
);
510 ENSURE_NO_RELOCS (buf
);
511 cie
.lsda_encoding
= DW_EH_PE_omit
;
512 cie
.fde_encoding
= DW_EH_PE_omit
;
513 cie
.per_encoding
= DW_EH_PE_omit
;
514 aug
= cie
.augmentation
;
515 if (aug
[0] != 'e' || aug
[1] != 'h')
520 read_uleb128 (cie
.augmentation_size
, buf
);
521 ENSURE_NO_RELOCS (buf
);
528 cie
.lsda_encoding
= *buf
++;
529 ENSURE_NO_RELOCS (buf
);
530 if (get_DW_EH_PE_width (cie
.lsda_encoding
, ptr_size
) == 0)
534 cie
.fde_encoding
= *buf
++;
535 ENSURE_NO_RELOCS (buf
);
536 if (get_DW_EH_PE_width (cie
.fde_encoding
, ptr_size
) == 0)
543 cie
.per_encoding
= *buf
++;
544 per_width
= get_DW_EH_PE_width (cie
.per_encoding
,
548 if ((cie
.per_encoding
& 0xf0) == DW_EH_PE_aligned
)
550 + ((buf
- ehbuf
+ per_width
- 1)
551 & ~((bfd_size_type
) per_width
- 1)));
552 ENSURE_NO_RELOCS (buf
);
553 rel
= GET_RELOC (buf
);
554 /* Ensure we have a reloc here, against
558 unsigned long r_symndx
;
562 r_symndx
= ELF64_R_SYM (cookie
->rel
->r_info
);
565 r_symndx
= ELF32_R_SYM (cookie
->rel
->r_info
);
566 if (r_symndx
>= cookie
->locsymcount
)
568 struct elf_link_hash_entry
*h
;
570 r_symndx
-= cookie
->extsymoff
;
571 h
= cookie
->sym_hashes
[r_symndx
];
573 while (h
->root
.type
== bfd_link_hash_indirect
574 || h
->root
.type
== bfd_link_hash_warning
)
575 h
= (struct elf_link_hash_entry
*)
586 /* Unrecognized augmentation. Better bail out. */
591 /* For shared libraries, try to get rid of as many RELATIVE relocs
594 && (cie
.fde_encoding
& 0xf0) == DW_EH_PE_absptr
)
595 cie
.make_relative
= 1;
598 && (cie
.lsda_encoding
& 0xf0) == DW_EH_PE_absptr
)
599 cie
.make_lsda_relative
= 1;
601 /* If FDE encoding was not specified, it defaults to
603 if (cie
.fde_encoding
== DW_EH_PE_omit
)
604 cie
.fde_encoding
= DW_EH_PE_absptr
;
606 initial_insn_length
= cie
.hdr
.length
- (buf
- last_fde
- 4);
607 if (initial_insn_length
<= 50)
609 cie
.initial_insn_length
= initial_insn_length
;
610 memcpy (cie
.initial_instructions
, buf
, initial_insn_length
);
612 buf
+= initial_insn_length
;
613 ENSURE_NO_RELOCS (buf
);
618 /* Ensure this FDE uses the last CIE encountered. */
620 || hdr
.id
!= (unsigned int) (buf
- 4 - last_cie
))
623 ENSURE_NO_RELOCS (buf
);
624 rel
= GET_RELOC (buf
);
626 /* This should not happen. */
628 if ((*reloc_symbol_deleted_p
) (buf
- ehbuf
, cookie
))
631 /* This is a FDE against discarded section, it should
633 new_size
-= hdr
.length
+ 4;
634 sec_info
->entry
[sec_info
->count
].removed
= 1;
639 && (((cie
.fde_encoding
& 0xf0) == DW_EH_PE_absptr
640 && cie
.make_relative
== 0)
641 || (cie
.fde_encoding
& 0xf0) == DW_EH_PE_aligned
))
643 /* If shared library uses absolute pointers
644 which we cannot turn into PC relative,
645 don't create the binary search table,
646 since it is affected by runtime relocations. */
647 hdr_info
->table
= false;
650 hdr_info
->fde_count
++;
653 if (cie
.lsda_encoding
!= DW_EH_PE_omit
)
658 buf
+= 2 * get_DW_EH_PE_width (cie
.fde_encoding
, ptr_size
);
659 if (cie
.augmentation
[0] == 'z')
660 read_uleb128 (dummy
, buf
);
661 /* If some new augmentation data is added before LSDA
662 in FDE augmentation area, this need to be adjusted. */
663 sec_info
->entry
[sec_info
->count
].lsda_offset
= (buf
- aug
);
665 buf
= last_fde
+ 4 + hdr
.length
;
669 sec_info
->entry
[sec_info
->count
].fde_encoding
= cie
.fde_encoding
;
670 sec_info
->entry
[sec_info
->count
].lsda_encoding
= cie
.lsda_encoding
;
674 elf_section_data (sec
)->sec_info
= sec_info
;
675 elf_section_data (sec
)->sec_info_type
= ELF_INFO_TYPE_EH_FRAME
;
677 /* Ok, now we can assign new offsets. */
680 for (i
= 0; i
< sec_info
->count
; i
++)
682 if (! sec_info
->entry
[i
].removed
)
684 sec_info
->entry
[i
].new_offset
= offset
;
685 offset
+= sec_info
->entry
[i
].size
;
686 if (sec_info
->entry
[i
].cie
)
689 make_relative
= sec_info
->entry
[i
].make_relative
;
690 make_lsda_relative
= sec_info
->entry
[i
].make_lsda_relative
;
694 sec_info
->entry
[i
].make_relative
= make_relative
;
695 sec_info
->entry
[i
].make_lsda_relative
= make_lsda_relative
;
696 sec_info
->entry
[i
].per_encoding_relative
= 0;
699 else if (sec_info
->entry
[i
].cie
&& sec_info
->entry
[i
].sec
== sec
)
701 /* Need to adjust new_offset too. */
702 BFD_ASSERT (sec_info
->entry
[last_cie_ndx
].offset
703 == sec_info
->entry
[i
].new_offset
);
704 sec_info
->entry
[i
].new_offset
705 = sec_info
->entry
[last_cie_ndx
].new_offset
;
708 if (hdr_info
->last_cie_sec
== sec
)
710 BFD_ASSERT (sec_info
->entry
[last_cie_ndx
].offset
711 == hdr_info
->last_cie_offset
);
712 hdr_info
->last_cie_offset
= sec_info
->entry
[last_cie_ndx
].new_offset
;
715 /* FIXME: Currently it is not possible to shrink sections to zero size at
716 this point, so build a fake minimal CIE. */
720 /* Shrink the sec as needed. */
721 sec
->_cooked_size
= new_size
;
722 if (sec
->_cooked_size
== 0)
723 sec
->flags
|= SEC_EXCLUDE
;
726 return new_size
!= sec
->_raw_size
;
733 hdr_info
->table
= false;
734 hdr_info
->last_cie
.hdr
.length
= 0;
738 /* This function is called for .eh_frame_hdr section after
739 _bfd_elf_discard_section_eh_frame has been called on all .eh_frame
740 input sections. It finalizes the size of .eh_frame_hdr section. */
743 _bfd_elf_discard_section_eh_frame_hdr (abfd
, info
, sec
)
745 struct bfd_link_info
*info
;
748 struct eh_frame_hdr_info
*hdr_info
;
749 unsigned int ptr_size
;
751 ptr_size
= (elf_elfheader (abfd
)->e_ident
[EI_CLASS
]
752 == ELFCLASS64
) ? 8 : 4;
754 if ((elf_section_data (sec
)->sec_info_type
755 != ELF_INFO_TYPE_EH_FRAME_HDR
)
756 || ! info
->eh_frame_hdr
)
758 _bfd_strip_section_from_output (info
, sec
);
762 hdr_info
= (struct eh_frame_hdr_info
*)
763 elf_section_data (sec
)->sec_info
;
766 sec
->_cooked_size
= EH_FRAME_HDR_SIZE
;
768 sec
->_cooked_size
+= 4 + hdr_info
->fde_count
* 8;
770 /* Request program headers to be recalculated. */
771 elf_tdata (abfd
)->program_header_size
= 0;
772 elf_tdata (abfd
)->eh_frame_hdr
= true;
776 /* This function is called from size_dynamic_sections.
777 It needs to decide whether .eh_frame_hdr should be output or not,
778 because later on it is too late for calling _bfd_strip_section_from_output,
779 since dynamic symbol table has been sized. */
782 _bfd_elf_maybe_strip_eh_frame_hdr (info
)
783 struct bfd_link_info
*info
;
787 struct eh_frame_hdr_info
*hdr_info
;
789 sec
= bfd_get_section_by_name (elf_hash_table (info
)->dynobj
, ".eh_frame_hdr");
790 if (sec
== NULL
|| bfd_is_abs_section (sec
->output_section
))
794 = bfd_zmalloc (sizeof (struct eh_frame_hdr_info
));
795 if (hdr_info
== NULL
)
798 elf_section_data (sec
)->sec_info
= hdr_info
;
799 elf_section_data (sec
)->sec_info_type
= ELF_INFO_TYPE_EH_FRAME_HDR
;
802 if (info
->eh_frame_hdr
)
803 for (abfd
= info
->input_bfds
; abfd
!= NULL
; abfd
= abfd
->link_next
)
805 /* Count only sections which have at least a single CIE or FDE.
806 There cannot be any CIE or FDE <= 8 bytes. */
807 o
= bfd_get_section_by_name (abfd
, ".eh_frame");
808 if (o
&& o
->_raw_size
> 8 && !bfd_is_abs_section (o
->output_section
))
814 _bfd_strip_section_from_output (info
, sec
);
815 hdr_info
->strip
= true;
818 hdr_info
->table
= true;
822 /* Adjust an address in the .eh_frame section. Given OFFSET within
823 SEC, this returns the new offset in the adjusted .eh_frame section,
824 or -1 if the address refers to a CIE/FDE which has been removed
825 or to offset with dynamic relocation which is no longer needed. */
828 _bfd_elf_eh_frame_section_offset (output_bfd
, sec
, offset
)
829 bfd
*output_bfd ATTRIBUTE_UNUSED
;
833 struct eh_frame_sec_info
*sec_info
;
834 unsigned int lo
, hi
, mid
;
836 if (elf_section_data (sec
)->sec_info_type
!= ELF_INFO_TYPE_EH_FRAME
)
838 sec_info
= (struct eh_frame_sec_info
*)
839 elf_section_data (sec
)->sec_info
;
841 if (offset
>= sec
->_raw_size
)
842 return offset
- (sec
->_cooked_size
- sec
->_raw_size
);
845 hi
= sec_info
->count
;
850 if (offset
< sec_info
->entry
[mid
].offset
)
853 >= sec_info
->entry
[mid
].offset
+ sec_info
->entry
[mid
].size
)
859 BFD_ASSERT (lo
< hi
);
861 /* FDE or CIE was removed. */
862 if (sec_info
->entry
[mid
].removed
)
865 /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
866 relocation against FDE's initial_location field. */
867 if (sec_info
->entry
[mid
].make_relative
868 && ! sec_info
->entry
[mid
].cie
869 && offset
== sec_info
->entry
[mid
].offset
+ 8)
872 /* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need
873 for run-time relocation against LSDA field. */
874 if (sec_info
->entry
[mid
].make_lsda_relative
875 && ! sec_info
->entry
[mid
].cie
877 == (sec_info
->entry
[mid
].offset
+ 8
878 + sec_info
->entry
[mid
].lsda_offset
)))
881 return (offset
+ sec_info
->entry
[mid
].new_offset
882 - sec_info
->entry
[mid
].offset
);
885 /* Write out .eh_frame section. This is called with the relocated
889 _bfd_elf_write_section_eh_frame (abfd
, sec
, ehdrsec
, contents
)
891 asection
*sec
, *ehdrsec
;
894 struct eh_frame_sec_info
*sec_info
;
895 struct eh_frame_hdr_info
*hdr_info
;
898 unsigned int leb128_tmp
;
899 unsigned int cie_offset
= 0;
900 unsigned int ptr_size
;
902 ptr_size
= (elf_elfheader (sec
->owner
)->e_ident
[EI_CLASS
]
903 == ELFCLASS64
) ? 8 : 4;
905 if (elf_section_data (sec
)->sec_info_type
!= ELF_INFO_TYPE_EH_FRAME
)
906 return bfd_set_section_contents (abfd
, sec
->output_section
,
908 (file_ptr
) sec
->output_offset
,
910 sec_info
= (struct eh_frame_sec_info
*)
911 elf_section_data (sec
)->sec_info
;
914 && (elf_section_data (ehdrsec
)->sec_info_type
915 == ELF_INFO_TYPE_EH_FRAME_HDR
))
917 hdr_info
= (struct eh_frame_hdr_info
*)
918 elf_section_data (ehdrsec
)->sec_info
;
919 if (hdr_info
->table
&& hdr_info
->array
== NULL
)
921 = bfd_malloc (hdr_info
->fde_count
* sizeof(*hdr_info
->array
));
922 if (hdr_info
->array
== NULL
)
927 for (i
= 0; i
< sec_info
->count
; ++i
)
929 if (sec_info
->entry
[i
].removed
)
931 if (sec_info
->entry
[i
].cie
)
933 /* If CIE is removed due to no remaining FDEs referencing it
934 and there were no CIEs kept before it, sec_info->entry[i].sec
936 if (sec_info
->entry
[i
].sec
== NULL
)
940 cie_offset
= sec_info
->entry
[i
].new_offset
;
941 cie_offset
+= (sec_info
->entry
[i
].sec
->output_section
->vma
942 + sec_info
->entry
[i
].sec
->output_offset
943 - sec
->output_section
->vma
944 - sec
->output_offset
);
950 if (sec_info
->entry
[i
].cie
)
953 cie_offset
= sec_info
->entry
[i
].new_offset
;
954 if (sec_info
->entry
[i
].make_relative
955 || sec_info
->entry
[i
].make_lsda_relative
956 || sec_info
->entry
[i
].per_encoding_relative
)
960 unsigned int dummy
, per_width
, per_encoding
;
962 /* Need to find 'R' or 'L' augmentation's argument and modify
964 action
= (sec_info
->entry
[i
].make_relative
? 1 : 0)
965 | (sec_info
->entry
[i
].make_lsda_relative
? 2 : 0)
966 | (sec_info
->entry
[i
].per_encoding_relative
? 4 : 0);
967 buf
= contents
+ sec_info
->entry
[i
].offset
;
968 /* Skip length, id and version. */
971 buf
= strchr (buf
, '\0') + 1;
972 read_uleb128 (dummy
, buf
);
973 read_sleb128 (dummy
, buf
);
974 read_uleb128 (dummy
, buf
);
977 read_uleb128 (dummy
, buf
);
987 BFD_ASSERT (*buf
== sec_info
->entry
[i
].lsda_encoding
);
988 *buf
|= DW_EH_PE_pcrel
;
994 per_encoding
= *buf
++;
995 per_width
= get_DW_EH_PE_width (per_encoding
,
997 BFD_ASSERT (per_width
!= 0);
998 BFD_ASSERT (((per_encoding
& 0x70) == DW_EH_PE_pcrel
)
999 == sec_info
->entry
[i
].per_encoding_relative
);
1000 if ((per_encoding
& 0xf0) == DW_EH_PE_aligned
)
1002 + ((buf
- contents
+ per_width
- 1)
1003 & ~((bfd_size_type
) per_width
- 1)));
1008 value
= read_value (abfd
, buf
, per_width
);
1009 value
+= (sec_info
->entry
[i
].offset
1010 - sec_info
->entry
[i
].new_offset
);
1011 write_value (abfd
, buf
, value
, per_width
);
1019 BFD_ASSERT (*buf
== sec_info
->entry
[i
].fde_encoding
);
1020 *buf
|= DW_EH_PE_pcrel
;
1030 else if (sec_info
->entry
[i
].size
> 4)
1033 bfd_vma value
= 0, address
;
1036 buf
= contents
+ sec_info
->entry
[i
].offset
;
1040 sec_info
->entry
[i
].new_offset
+ 4 - cie_offset
, buf
);
1042 width
= get_DW_EH_PE_width (sec_info
->entry
[i
].fde_encoding
,
1044 address
= value
= read_value (abfd
, buf
, width
);
1047 switch (sec_info
->entry
[i
].fde_encoding
& 0xf0)
1049 case DW_EH_PE_indirect
:
1050 case DW_EH_PE_textrel
:
1051 BFD_ASSERT (hdr_info
== NULL
);
1053 case DW_EH_PE_datarel
:
1055 asection
*got
= bfd_get_section_by_name (abfd
, ".got");
1057 BFD_ASSERT (got
!= NULL
);
1058 address
+= got
->vma
;
1061 case DW_EH_PE_pcrel
:
1062 value
+= (sec_info
->entry
[i
].offset
1063 - sec_info
->entry
[i
].new_offset
);
1064 address
+= (sec
->output_section
->vma
+ sec
->output_offset
1065 + sec_info
->entry
[i
].offset
+ 8);
1068 if (sec_info
->entry
[i
].make_relative
)
1069 value
-= (sec
->output_section
->vma
+ sec
->output_offset
1070 + sec_info
->entry
[i
].new_offset
+ 8);
1071 write_value (abfd
, buf
, value
, width
);
1076 hdr_info
->array
[hdr_info
->array_count
].initial_loc
= address
;
1077 hdr_info
->array
[hdr_info
->array_count
++].fde
1078 = (sec
->output_section
->vma
+ sec
->output_offset
1079 + sec_info
->entry
[i
].new_offset
);
1082 if ((sec_info
->entry
[i
].lsda_encoding
& 0xf0) == DW_EH_PE_pcrel
1083 || sec_info
->entry
[i
].make_lsda_relative
)
1085 buf
+= sec_info
->entry
[i
].lsda_offset
;
1086 width
= get_DW_EH_PE_width (sec_info
->entry
[i
].lsda_encoding
,
1088 value
= read_value (abfd
, buf
, width
);
1091 if ((sec_info
->entry
[i
].lsda_encoding
& 0xf0)
1093 value
+= (sec_info
->entry
[i
].offset
1094 - sec_info
->entry
[i
].new_offset
);
1095 else if (sec_info
->entry
[i
].make_lsda_relative
)
1096 value
-= (sec
->output_section
->vma
+ sec
->output_offset
1097 + sec_info
->entry
[i
].new_offset
+ 8
1098 + sec_info
->entry
[i
].lsda_offset
);
1099 write_value (abfd
, buf
, value
, width
);
1104 /* Terminating FDE must be at the end of .eh_frame section only. */
1105 BFD_ASSERT (i
== sec_info
->count
- 1);
1107 BFD_ASSERT (p
== contents
+ sec_info
->entry
[i
].new_offset
);
1108 memmove (p
, contents
+ sec_info
->entry
[i
].offset
,
1109 sec_info
->entry
[i
].size
);
1110 p
+= sec_info
->entry
[i
].size
;
1113 /* FIXME: Once _bfd_elf_discard_section_eh_frame will be able to
1114 shrink sections to zero size, this won't be needed any more. */
1115 if (p
== contents
&& sec
->_cooked_size
== 16)
1117 bfd_put_32 (abfd
, 12, p
); /* Fake CIE length */
1118 bfd_put_32 (abfd
, 0, p
+ 4); /* Fake CIE id */
1119 p
[8] = 1; /* Fake CIE version */
1120 memset (p
+ 9, 0, 7); /* Fake CIE augmentation, 3xleb128
1121 and 3xDW_CFA_nop as pad */
1125 BFD_ASSERT ((bfd_size_type
) (p
- contents
) == sec
->_cooked_size
);
1127 return bfd_set_section_contents (abfd
, sec
->output_section
,
1128 contents
, (file_ptr
) sec
->output_offset
,
1132 /* Helper function used to sort .eh_frame_hdr search table by increasing
1133 VMA of FDE initial location. */
1140 struct eh_frame_array_ent
*p
= (struct eh_frame_array_ent
*) a
;
1141 struct eh_frame_array_ent
*q
= (struct eh_frame_array_ent
*) b
;
1142 if (p
->initial_loc
> q
->initial_loc
)
1144 if (p
->initial_loc
< q
->initial_loc
)
1149 /* Write out .eh_frame_hdr section. This must be called after
1150 _bfd_elf_write_section_eh_frame has been called on all input
1152 .eh_frame_hdr format:
1153 ubyte version (currently 1)
1154 ubyte eh_frame_ptr_enc (DW_EH_PE_* encoding of pointer to start of
1156 ubyte fde_count_enc (DW_EH_PE_* encoding of total FDE count
1157 number (or DW_EH_PE_omit if there is no
1158 binary search table computed))
1159 ubyte table_enc (DW_EH_PE_* encoding of binary search table,
1160 or DW_EH_PE_omit if not present.
1161 DW_EH_PE_datarel is using address of
1162 .eh_frame_hdr section start as base)
1163 [encoded] eh_frame_ptr (pointer to start of .eh_frame section)
1164 optionally followed by:
1165 [encoded] fde_count (total number of FDEs in .eh_frame section)
1166 fde_count x [encoded] initial_loc, fde
1167 (array of encoded pairs containing
1168 FDE initial_location field and FDE address,
1169 sorted by increasing initial_loc) */
1172 _bfd_elf_write_section_eh_frame_hdr (abfd
, sec
)
1176 struct eh_frame_hdr_info
*hdr_info
;
1177 unsigned int ptr_size
;
1179 asection
*eh_frame_sec
;
1182 ptr_size
= (elf_elfheader (sec
->owner
)->e_ident
[EI_CLASS
]
1183 == ELFCLASS64
) ? 8 : 4;
1185 BFD_ASSERT (elf_section_data (sec
)->sec_info_type
1186 == ELF_INFO_TYPE_EH_FRAME_HDR
);
1187 hdr_info
= (struct eh_frame_hdr_info
*)
1188 elf_section_data (sec
)->sec_info
;
1189 if (hdr_info
->strip
)
1192 size
= EH_FRAME_HDR_SIZE
;
1193 if (hdr_info
->array
&& hdr_info
->array_count
== hdr_info
->fde_count
)
1194 size
+= 4 + hdr_info
->fde_count
* 8;
1195 contents
= bfd_malloc (size
);
1196 if (contents
== NULL
)
1199 eh_frame_sec
= bfd_get_section_by_name (abfd
, ".eh_frame");
1200 if (eh_frame_sec
== NULL
)
1203 memset (contents
, 0, EH_FRAME_HDR_SIZE
);
1204 contents
[0] = 1; /* Version */
1205 contents
[1] = DW_EH_PE_pcrel
| DW_EH_PE_sdata4
; /* .eh_frame offset */
1206 if (hdr_info
->array
&& hdr_info
->array_count
== hdr_info
->fde_count
)
1208 contents
[2] = DW_EH_PE_udata4
; /* FDE count encoding */
1209 contents
[3] = DW_EH_PE_datarel
| DW_EH_PE_sdata4
; /* search table enc */
1213 contents
[2] = DW_EH_PE_omit
;
1214 contents
[3] = DW_EH_PE_omit
;
1216 bfd_put_32 (abfd
, eh_frame_sec
->vma
- sec
->output_section
->vma
- 4,
1218 if (contents
[2] != DW_EH_PE_omit
)
1222 bfd_put_32 (abfd
, hdr_info
->fde_count
, contents
+ EH_FRAME_HDR_SIZE
);
1223 qsort (hdr_info
->array
, hdr_info
->fde_count
, sizeof (*hdr_info
->array
),
1225 for (i
= 0; i
< hdr_info
->fde_count
; i
++)
1228 hdr_info
->array
[i
].initial_loc
1229 - sec
->output_section
->vma
,
1230 contents
+ EH_FRAME_HDR_SIZE
+ i
* 8 + 4);
1232 hdr_info
->array
[i
].fde
- sec
->output_section
->vma
,
1233 contents
+ EH_FRAME_HDR_SIZE
+ i
* 8 + 8);
1237 return bfd_set_section_contents (abfd
, sec
->output_section
,
1238 contents
, (file_ptr
) sec
->output_offset
,