1 /* .eh_frame section optimization.
2 Copyright 2001 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 initial_instructions
[50];
58 unsigned int new_offset
;
59 unsigned char fde_encoding
;
60 unsigned char cie
: 1;
61 unsigned char removed
: 1;
62 unsigned char make_relative
: 1;
65 struct eh_frame_sec_info
69 struct eh_cie_fde entry
[1];
72 struct eh_frame_array_ent
78 struct eh_frame_hdr_info
81 asection
*last_cie_sec
;
82 unsigned int last_cie_offset
;
83 unsigned int fde_count
, array_count
;
84 struct eh_frame_array_ent
*array
;
85 /* TRUE if .eh_frame_hdr should contain the sorted search table.
86 We build it if we successfully read all .eh_frame input sections
87 and recognize them. */
91 static bfd_vma read_unsigned_leb128
92 PARAMS ((bfd
*, char *, unsigned int *));
93 static bfd_signed_vma read_signed_leb128
94 PARAMS ((bfd
*, char *, unsigned int *));
95 static int get_DW_EH_PE_width
97 static int cie_compare
98 PARAMS ((struct cie
*, struct cie
*));
99 static int vma_compare
100 PARAMS ((const PTR a
, const PTR b
));
102 /* Helper function for reading uleb128 encoded data. */
105 read_unsigned_leb128 (abfd
, buf
, bytes_read_ptr
)
106 bfd
*abfd ATTRIBUTE_UNUSED
;
108 unsigned int *bytes_read_ptr
;
111 unsigned int num_read
;
120 byte
= bfd_get_8 (abfd
, (bfd_byte
*) buf
);
123 result
|= (((bfd_vma
) byte
& 0x7f) << shift
);
127 * bytes_read_ptr
= num_read
;
131 /* Helper function for reading sleb128 encoded data. */
133 static bfd_signed_vma
134 read_signed_leb128 (abfd
, buf
, bytes_read_ptr
)
135 bfd
*abfd ATTRIBUTE_UNUSED
;
137 unsigned int * bytes_read_ptr
;
149 byte
= bfd_get_8 (abfd
, (bfd_byte
*) buf
);
152 result
|= (((bfd_vma
) byte
& 0x7f) << shift
);
157 result
|= (((bfd_vma
) -1) << (shift
- 7)) << 7;
158 * bytes_read_ptr
= num_read
;
162 #define read_uleb128(VAR, BUF) \
165 (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp); \
166 (BUF) += leb128_tmp; \
170 #define read_sleb128(VAR, BUF) \
173 (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp); \
174 (BUF) += leb128_tmp; \
178 /* Return 0 if either encoding is variable width, or not yet known to bfd. */
181 int get_DW_EH_PE_width (encoding
, ptr_size
)
182 int encoding
, ptr_size
;
184 /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
186 if ((encoding
& 0x60) == 0x60)
189 switch (encoding
& 7)
191 case DW_EH_PE_udata2
: return 2;
192 case DW_EH_PE_udata4
: return 4;
193 case DW_EH_PE_udata8
: return 8;
194 case DW_EH_PE_absptr
: return ptr_size
;
202 /* Return zero if C1 and C2 CIEs can be merged. */
205 int cie_compare (c1
, c2
)
208 if (c1
->hdr
.length
== c2
->hdr
.length
209 && c1
->version
== c2
->version
210 && strcmp (c1
->augmentation
, c2
->augmentation
) == 0
211 && strcmp (c1
->augmentation
, "eh") != 0
212 && c1
->code_align
== c2
->code_align
213 && c1
->data_align
== c2
->data_align
214 && c1
->ra_column
== c2
->ra_column
215 && c1
->augmentation_size
== c2
->augmentation_size
216 && c1
->personality
== c2
->personality
217 && c1
->per_encoding
== c2
->per_encoding
218 && c1
->lsda_encoding
== c2
->lsda_encoding
219 && c1
->fde_encoding
== c2
->fde_encoding
220 && (c1
->initial_insn_length
221 == c2
->initial_insn_length
)
222 && memcmp (c1
->initial_instructions
,
223 c2
->initial_instructions
,
224 c1
->initial_insn_length
) == 0)
230 /* This function is called for each input file before the .eh_frame
231 section is relocated. It discards duplicate CIEs and FDEs for discarded
232 functions. The function returns true iff any entries have been
236 _bfd_elf_discard_section_eh_frame (abfd
, info
, sec
, ehdrsec
,
237 reloc_symbol_deleted_p
, cookie
)
239 struct bfd_link_info
*info
;
240 asection
*sec
, *ehdrsec
;
241 boolean (*reloc_symbol_deleted_p
) (bfd_vma
, PTR
);
242 struct elf_reloc_cookie
*cookie
;
244 bfd_byte
*ehbuf
= NULL
, *buf
;
245 bfd_byte
*last_cie
, *last_fde
;
246 struct cie_header hdr
;
248 struct eh_frame_hdr_info
*hdr_info
;
249 struct eh_frame_sec_info
*sec_info
;
250 unsigned int leb128_tmp
;
251 unsigned int cie_usage_count
, last_cie_ndx
, i
, offset
, make_relative
;
252 Elf_Internal_Rela
*rel
;
253 bfd_size_type new_size
;
254 unsigned int ptr_size
;
256 if (sec
->_raw_size
== 0)
258 /* This file does not contain .eh_frame information. */
262 if ((sec
->output_section
!= NULL
263 && bfd_is_abs_section (sec
->output_section
)))
265 /* At least one of the sections is being discarded from the
266 link, so we should just ignore them. */
270 /* Read the frame unwind information from abfd. */
272 ehbuf
= (bfd_byte
*) bfd_malloc (sec
->_raw_size
);
274 || ! bfd_get_section_contents (abfd
, sec
, ehbuf
, (bfd_vma
) 0,
277 if (elf_section_data (ehdrsec
)->sec_info_type
278 != ELF_INFO_TYPE_EH_FRAME_HDR
)
280 elf_section_data (ehdrsec
)->sec_info
281 = bfd_zmalloc (sizeof (struct eh_frame_hdr_info
));
282 elf_section_data (ehdrsec
)->sec_info_type
283 = ELF_INFO_TYPE_EH_FRAME_HDR
;
288 if (sec
->_raw_size
>= 4
289 && bfd_get_32 (abfd
, ehbuf
) == 0
290 && cookie
->rel
== cookie
->relend
)
292 /* Empty .eh_frame section. */
297 if (elf_section_data (ehdrsec
)->sec_info_type
298 != ELF_INFO_TYPE_EH_FRAME_HDR
)
300 hdr_info
= (struct eh_frame_hdr_info
*)
301 bfd_zmalloc (sizeof (struct eh_frame_hdr_info
));
302 hdr_info
->table
= true;
303 elf_section_data (ehdrsec
)->sec_info
= hdr_info
;
304 elf_section_data (ehdrsec
)->sec_info_type
305 = ELF_INFO_TYPE_EH_FRAME_HDR
;
308 hdr_info
= (struct eh_frame_hdr_info
*)
309 elf_section_data (ehdrsec
)->sec_info
;
311 /* If .eh_frame section size doesn't fit into int, we cannot handle
312 it (it would need to use 64-bit .eh_frame format anyway). */
313 if (sec
->_raw_size
!= (unsigned int) sec
->_raw_size
)
316 ptr_size
= (elf_elfheader (abfd
)->e_ident
[EI_CLASS
]
317 == ELFCLASS64
) ? 8 : 4;
321 memset (&cie
, 0, sizeof (cie
));
323 new_size
= sec
->_raw_size
;
324 make_relative
= hdr_info
->last_cie
.make_relative
;
325 sec_info
= bfd_zmalloc (sizeof (struct eh_frame_sec_info
)
326 + 99 * sizeof (struct eh_cie_fde
));
327 if (sec_info
== NULL
)
329 sec_info
->alloced
= 100;
331 #define ENSURE_NO_RELOCS(buf) \
332 if (cookie->rel < cookie->relend \
333 && (cookie->rel->r_offset \
334 < (bfd_size_type) ((buf) - ehbuf))) \
337 #define SKIP_RELOCS(buf) \
338 while (cookie->rel < cookie->relend \
339 && (cookie->rel->r_offset \
340 < (bfd_size_type) ((buf) - ehbuf))) \
343 #define GET_RELOC(buf) \
344 ((cookie->rel < cookie->relend \
345 && (cookie->rel->r_offset \
346 == (bfd_size_type) ((buf) - ehbuf))) \
347 ? cookie->rel : NULL)
353 if (sec_info
->count
== sec_info
->alloced
)
355 sec_info
= bfd_realloc (sec_info
,
356 sizeof (struct eh_frame_sec_info
)
357 + (sec_info
->alloced
+ 99)
358 * sizeof (struct eh_cie_fde
));
359 if (sec_info
== NULL
)
362 memset (&sec_info
->entry
[sec_info
->alloced
], 0,
363 100 * sizeof (struct eh_cie_fde
));
364 sec_info
->alloced
+= 100;
368 /* If we are at the end of the section, we still need to decide
369 on whether to output or discard last encountered CIE (if any). */
370 if ((bfd_size_type
) (buf
- ehbuf
) == sec
->_raw_size
)
371 hdr
.id
= (unsigned int) -1;
374 if ((bfd_size_type
) (buf
+ 4 - ehbuf
) > sec
->_raw_size
)
375 /* No space for CIE/FDE header length. */
378 hdr
.length
= bfd_get_32 (abfd
, buf
);
379 if (hdr
.length
== 0xffffffff)
380 /* 64-bit .eh_frame is not supported. */
383 if ((buf
- ehbuf
) + hdr
.length
> sec
->_raw_size
)
384 /* CIE/FDE not contained fully in this .eh_frame input section. */
387 sec_info
->entry
[sec_info
->count
].offset
= last_fde
- ehbuf
;
388 sec_info
->entry
[sec_info
->count
].size
= 4 + hdr
.length
;
392 /* CIE with length 0 must be only the last in the section. */
393 if ((bfd_size_type
) (buf
- ehbuf
) < sec
->_raw_size
)
395 ENSURE_NO_RELOCS (buf
);
397 /* Now just finish last encountered CIE processing and break
399 hdr
.id
= (unsigned int) -1;
403 hdr
.id
= bfd_get_32 (abfd
, buf
);
405 if (hdr
.id
== (unsigned int) -1)
410 if (hdr
.id
== 0 || hdr
.id
== (unsigned int) -1)
412 unsigned int initial_insn_length
;
415 if (last_cie
!= NULL
)
417 /* Now check if this CIE is identical to last CIE, in which case
418 we can remove it, provided we adjust all FDEs.
419 Also, it can be removed if we have removed all FDEs using
421 if (cie_compare (&cie
, &hdr_info
->last_cie
) == 0
422 || cie_usage_count
== 0)
424 new_size
-= cie
.hdr
.length
+ 4;
425 sec_info
->entry
[last_cie_ndx
].removed
= 1;
426 sec_info
->entry
[last_cie_ndx
].sec
= hdr_info
->last_cie_sec
;
427 sec_info
->entry
[last_cie_ndx
].new_offset
428 = hdr_info
->last_cie_offset
;
432 hdr_info
->last_cie
= cie
;
433 hdr_info
->last_cie_sec
= sec
;
434 hdr_info
->last_cie_offset
= last_cie
- ehbuf
;
435 sec_info
->entry
[last_cie_ndx
].make_relative
440 if (hdr
.id
== (unsigned int) -1)
443 last_cie_ndx
= sec_info
->count
;
444 sec_info
->entry
[sec_info
->count
].cie
= 1;
447 memset (&cie
, 0, sizeof (cie
));
449 cie
.version
= *buf
++;
451 /* Cannot handle unknown versions. */
452 if (cie
.version
!= 1)
454 if (strlen (buf
) > sizeof (cie
.augmentation
) - 1)
457 strcpy (cie
.augmentation
, buf
);
458 buf
= strchr (buf
, '\0') + 1;
459 ENSURE_NO_RELOCS (buf
);
460 if (buf
[0] == 'e' && buf
[1] == 'h')
462 /* GCC < 3.0 .eh_frame CIE */
463 /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
464 is private to each CIE, so we don't need it for anything.
469 read_uleb128 (cie
.code_align
, buf
);
470 read_sleb128 (cie
.data_align
, buf
);
471 read_uleb128 (cie
.ra_column
, buf
);
472 ENSURE_NO_RELOCS (buf
);
473 cie
.lsda_encoding
= DW_EH_PE_omit
;
474 cie
.fde_encoding
= DW_EH_PE_omit
;
475 cie
.per_encoding
= DW_EH_PE_omit
;
476 aug
= cie
.augmentation
;
477 if (aug
[0] != 'e' || aug
[1] != 'h')
482 read_uleb128 (cie
.augmentation_size
, buf
);
483 ENSURE_NO_RELOCS (buf
);
490 cie
.lsda_encoding
= *buf
++;
491 ENSURE_NO_RELOCS (buf
);
492 if (get_DW_EH_PE_width (cie
.lsda_encoding
, ptr_size
) == 0)
496 cie
.fde_encoding
= *buf
++;
497 ENSURE_NO_RELOCS (buf
);
498 if (get_DW_EH_PE_width (cie
.fde_encoding
, ptr_size
) == 0)
505 cie
.per_encoding
= *buf
++;
506 per_width
= get_DW_EH_PE_width (cie
.per_encoding
,
510 if ((cie
.per_encoding
& 0xf0) == DW_EH_PE_aligned
)
512 + ((buf
- ehbuf
+ per_width
- 1)
513 & ~((bfd_size_type
) per_width
- 1)));
514 ENSURE_NO_RELOCS (buf
);
515 rel
= GET_RELOC (buf
);
516 /* Ensure we have a reloc here, against
520 unsigned long r_symndx
;
524 r_symndx
= ELF64_R_SYM (cookie
->rel
->r_info
);
527 r_symndx
= ELF32_R_SYM (cookie
->rel
->r_info
);
528 if (r_symndx
>= cookie
->locsymcount
)
530 struct elf_link_hash_entry
*h
;
532 r_symndx
-= cookie
->extsymoff
;
533 h
= cookie
->sym_hashes
[r_symndx
];
535 while (h
->root
.type
== bfd_link_hash_indirect
536 || h
->root
.type
== bfd_link_hash_warning
)
537 h
= (struct elf_link_hash_entry
*)
548 /* Unrecognized augmentation. Better bail out. */
553 /* For shared libraries, try to get rid of as many RELATIVE relocs
555 FIXME: For this to work, ELF backends need to perform the
556 relocation if omitting dynamic relocs, not skip it. */
559 && (cie
.fde_encoding
& 0xf0) == DW_EH_PE_absptr
)
560 cie
.make_relative
= 1;
562 /* If FDE encoding was not specified, it defaults to
564 if (cie
.fde_encoding
== DW_EH_PE_omit
)
565 cie
.fde_encoding
= DW_EH_PE_absptr
;
567 initial_insn_length
= cie
.hdr
.length
- (buf
- last_fde
- 4);
568 if (initial_insn_length
<= 50)
570 cie
.initial_insn_length
= initial_insn_length
;
571 memcpy (cie
.initial_instructions
, buf
, initial_insn_length
);
573 buf
+= initial_insn_length
;
574 ENSURE_NO_RELOCS (buf
);
579 /* Ensure this FDE uses the last CIE encountered. */
581 || hdr
.id
!= (unsigned int) (buf
- 4 - last_cie
))
584 ENSURE_NO_RELOCS (buf
);
585 rel
= GET_RELOC (buf
);
587 /* This should not happen. */
589 if ((*reloc_symbol_deleted_p
) (buf
- ehbuf
, cookie
))
592 /* This is a FDE against discarded section, it should
594 new_size
-= hdr
.length
+ 4;
595 sec_info
->entry
[sec_info
->count
].removed
= 1;
600 hdr_info
->fde_count
++;
603 buf
= last_fde
+ 4 + hdr
.length
;
607 sec_info
->entry
[sec_info
->count
].fde_encoding
= cie
.fde_encoding
;
611 elf_section_data (sec
)->sec_info
= sec_info
;
612 elf_section_data (sec
)->sec_info_type
= ELF_INFO_TYPE_EH_FRAME
;
614 /* Ok, now we can assign new offsets. */
617 for (i
= 0; i
< sec_info
->count
; i
++)
619 if (! sec_info
->entry
[i
].removed
)
621 sec_info
->entry
[i
].new_offset
= offset
;
622 offset
+= sec_info
->entry
[i
].size
;
623 if (sec_info
->entry
[i
].cie
)
626 make_relative
= sec_info
->entry
[i
].make_relative
;
629 sec_info
->entry
[i
].make_relative
= make_relative
;
631 else if (sec_info
->entry
[i
].cie
&& sec_info
->entry
[i
].sec
== sec
)
633 /* Need to adjust new_offset too. */
634 BFD_ASSERT (sec_info
->entry
[last_cie_ndx
].offset
635 == sec_info
->entry
[i
].new_offset
);
636 sec_info
->entry
[i
].new_offset
637 = sec_info
->entry
[last_cie_ndx
].new_offset
;
640 if (hdr_info
->last_cie_sec
== sec
)
642 BFD_ASSERT (sec_info
->entry
[last_cie_ndx
].offset
643 == hdr_info
->last_cie_offset
);
644 hdr_info
->last_cie_offset
= sec_info
->entry
[last_cie_ndx
].new_offset
;
647 /* Shrink the sec as needed. */
649 sec
->_cooked_size
= new_size
;
650 if (sec
->_cooked_size
== 0)
651 sec
->flags
|= SEC_EXCLUDE
;
653 return new_size
!= sec
->_raw_size
;
658 hdr_info
->table
= false;
659 hdr_info
->last_cie
.hdr
.length
= 0;
663 /* This function is called for .eh_frame_hdr section after
664 _bfd_elf_discard_section_eh_frame has been called on all .eh_frame
665 input sections. It finalizes the size of .eh_frame_hdr section. */
668 _bfd_elf_discard_section_eh_frame_hdr (abfd
, info
, sec
)
670 struct bfd_link_info
*info
;
673 struct eh_frame_hdr_info
*hdr_info
;
674 unsigned int ptr_size
;
676 ptr_size
= (elf_elfheader (abfd
)->e_ident
[EI_CLASS
]
677 == ELFCLASS64
) ? 8 : 4;
679 if ((elf_section_data (sec
)->sec_info_type
680 != ELF_INFO_TYPE_EH_FRAME_HDR
)
681 || ! info
->eh_frame_hdr
)
683 _bfd_strip_section_from_output (info
, sec
);
687 hdr_info
= (struct eh_frame_hdr_info
*)
688 elf_section_data (sec
)->sec_info
;
689 sec
->_cooked_size
= EH_FRAME_HDR_SIZE
;
691 sec
->_cooked_size
+= 4 + hdr_info
->fde_count
* 8;
693 /* Request program headers to be recalculated. */
694 elf_tdata (abfd
)->program_header_size
= 0;
695 elf_tdata (abfd
)->eh_frame_hdr
= true;
699 /* Adjust an address in the .eh_frame section. Given OFFSET within
700 SEC, this returns the new offset in the adjusted .eh_frame section,
701 or -1 if the address refers to a CIE/FDE which has been removed
702 or to offset with dynamic relocation which is no longer needed. */
705 _bfd_elf_eh_frame_section_offset (output_bfd
, sec
, offset
)
706 bfd
*output_bfd ATTRIBUTE_UNUSED
;
710 struct eh_frame_sec_info
*sec_info
;
711 unsigned int lo
, hi
, mid
;
713 if (elf_section_data (sec
)->sec_info_type
!= ELF_INFO_TYPE_EH_FRAME
)
715 sec_info
= (struct eh_frame_sec_info
*)
716 elf_section_data (sec
)->sec_info
;
718 if (offset
>= sec
->_raw_size
)
719 return offset
- (sec
->_cooked_size
- sec
->_raw_size
);
722 hi
= sec_info
->count
;
727 if (offset
< sec_info
->entry
[mid
].offset
)
730 >= sec_info
->entry
[mid
].offset
+ sec_info
->entry
[mid
].size
)
736 BFD_ASSERT (lo
< hi
);
738 /* FDE or CIE was removed. */
739 if (sec_info
->entry
[mid
].removed
)
742 /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
743 relocation against FDE's initial_location field. */
744 if (sec_info
->entry
[mid
].make_relative
745 && ! sec_info
->entry
[mid
].cie
746 && offset
== sec_info
->entry
[mid
].offset
+ 8)
750 + (sec_info
->entry
[mid
].new_offset
- sec_info
->entry
[mid
].offset
));
753 /* Write out .eh_frame section. This is called with the relocated
757 _bfd_elf_write_section_eh_frame (abfd
, sec
, ehdrsec
, contents
)
759 asection
*sec
, *ehdrsec
;
762 struct eh_frame_sec_info
*sec_info
;
763 struct eh_frame_hdr_info
*hdr_info
;
766 unsigned int leb128_tmp
;
767 unsigned int cie_offset
= 0;
768 unsigned int ptr_size
;
770 ptr_size
= (elf_elfheader (sec
->owner
)->e_ident
[EI_CLASS
]
771 == ELFCLASS64
) ? 8 : 4;
773 if (elf_section_data (sec
)->sec_info_type
!= ELF_INFO_TYPE_EH_FRAME
)
774 return bfd_set_section_contents (abfd
, sec
->output_section
,
776 (file_ptr
) sec
->output_offset
,
778 sec_info
= (struct eh_frame_sec_info
*)
779 elf_section_data (sec
)->sec_info
;
782 && (elf_section_data (ehdrsec
)->sec_info_type
783 == ELF_INFO_TYPE_EH_FRAME_HDR
))
785 hdr_info
= (struct eh_frame_hdr_info
*)
786 elf_section_data (ehdrsec
)->sec_info
;
787 if (hdr_info
->table
&& hdr_info
->array
== NULL
)
789 = bfd_malloc (hdr_info
->fde_count
* sizeof(*hdr_info
->array
));
790 if (hdr_info
->array
== NULL
)
795 for (i
= 0; i
< sec_info
->count
; ++i
)
797 if (sec_info
->entry
[i
].removed
)
799 if (sec_info
->entry
[i
].cie
)
801 cie_offset
= sec_info
->entry
[i
].new_offset
;
802 cie_offset
+= (sec_info
->entry
[i
].sec
->output_section
->vma
803 + sec_info
->entry
[i
].sec
->output_offset
804 - sec
->output_section
->vma
805 - sec
->output_offset
);
809 if (sec_info
->entry
[i
].cie
)
812 cie_offset
= sec_info
->entry
[i
].new_offset
;
813 if (sec_info
->entry
[i
].make_relative
)
816 unsigned int dummy
, per_width
, per_encoding
;
818 /* Need to find 'R' augmentation's argument and modify
820 buf
= contents
+ sec_info
->entry
[i
].offset
;
821 /* Skip length, id and version. */
824 buf
= strchr (buf
, '\0') + 1;
825 read_uleb128 (dummy
, buf
);
826 read_sleb128 (dummy
, buf
);
827 read_uleb128 (dummy
, buf
);
830 read_uleb128 (dummy
, buf
);
841 per_encoding
= *buf
++;
842 per_width
= get_DW_EH_PE_width (per_encoding
,
844 BFD_ASSERT (per_width
!= 0);
845 if ((per_encoding
& 0xf0) == DW_EH_PE_aligned
)
847 + ((buf
- contents
+ per_width
- 1)
848 & ~((bfd_size_type
) per_width
- 1)));
855 BFD_ASSERT (*buf
== sec_info
->entry
[i
].fde_encoding
);
856 *buf
|= DW_EH_PE_pcrel
;
862 bfd_vma value
= 0, address
;
863 unsigned int fde_width
;
865 buf
= contents
+ sec_info
->entry
[i
].offset
;
869 sec_info
->entry
[i
].new_offset
+ 4 - cie_offset
, buf
);
871 fde_width
= get_DW_EH_PE_width (sec_info
->entry
[i
].fde_encoding
,
875 case 2: value
= bfd_get_16 (abfd
, buf
); break;
876 case 4: value
= bfd_get_32 (abfd
, buf
); break;
877 case 8: value
= bfd_get_64 (abfd
, buf
); break;
878 default: BFD_FAIL ();
881 switch (sec_info
->entry
[i
].fde_encoding
& 0xf0)
883 case DW_EH_PE_indirect
:
884 case DW_EH_PE_textrel
:
885 BFD_ASSERT (hdr_info
== NULL
);
887 case DW_EH_PE_datarel
:
889 asection
*got
= bfd_get_section_by_name (abfd
, ".got");
891 BFD_ASSERT (got
!= NULL
);
896 value
+= (sec_info
->entry
[i
].offset
897 - sec_info
->entry
[i
].new_offset
);
898 address
+= (sec
->output_section
->vma
+ sec
->output_offset
899 + sec_info
->entry
[i
].new_offset
+ 8);
902 if (sec_info
->entry
[i
].make_relative
)
903 value
-= (sec
->output_section
->vma
+ sec
->output_offset
904 + sec_info
->entry
[i
].new_offset
+ 8);
907 case 2: bfd_put_16 (abfd
, value
, buf
); break;
908 case 4: bfd_put_32 (abfd
, value
, buf
); break;
909 case 8: bfd_put_64 (abfd
, value
, buf
); break;
914 hdr_info
->array
[hdr_info
->array_count
].initial_loc
= address
;
915 hdr_info
->array
[hdr_info
->array_count
++].fde
916 = (sec
->output_section
->vma
+ sec
->output_offset
917 + sec_info
->entry
[i
].new_offset
);
921 BFD_ASSERT (p
== contents
+ sec_info
->entry
[i
].new_offset
);
922 memmove (p
, contents
+ sec_info
->entry
[i
].offset
,
923 sec_info
->entry
[i
].size
);
924 p
+= sec_info
->entry
[i
].size
;
927 BFD_ASSERT ((bfd_size_type
) (p
- contents
) == sec
->_cooked_size
);
929 return bfd_set_section_contents (abfd
, sec
->output_section
,
930 contents
, (file_ptr
) sec
->output_offset
,
934 /* Helper function used to sort .eh_frame_hdr search table by increasing
935 VMA of FDE initial location. */
942 struct eh_frame_array_ent
*p
= (struct eh_frame_array_ent
*) a
;
943 struct eh_frame_array_ent
*q
= (struct eh_frame_array_ent
*) b
;
944 if (p
->initial_loc
> q
->initial_loc
)
946 if (p
->initial_loc
< q
->initial_loc
)
951 /* Write out .eh_frame_hdr section. This must be called after
952 _bfd_elf_write_section_eh_frame has been called on all input
954 .eh_frame_hdr format:
955 ubyte version (currently 1)
956 ubyte eh_frame_ptr_enc (DW_EH_PE_* encoding of pointer to start of
958 ubyte fde_count_enc (DW_EH_PE_* encoding of total FDE count
959 number (or DW_EH_PE_omit if there is no
960 binary search table computed))
961 ubyte table_enc (DW_EH_PE_* encoding of binary search table,
962 or DW_EH_PE_omit if not present.
963 DW_EH_PE_datarel is using address of
964 .eh_frame_hdr section start as base)
965 [encoded] eh_frame_ptr (pointer to start of .eh_frame section)
966 optionally followed by:
967 [encoded] fde_count (total number of FDEs in .eh_frame section)
968 fde_count x [encoded] initial_loc, fde
969 (array of encoded pairs containing
970 FDE initial_location field and FDE address,
971 sorted by increasing initial_loc) */
974 _bfd_elf_write_section_eh_frame_hdr (abfd
, sec
)
978 struct eh_frame_hdr_info
*hdr_info
;
979 unsigned int ptr_size
;
981 asection
*eh_frame_sec
;
984 ptr_size
= (elf_elfheader (sec
->owner
)->e_ident
[EI_CLASS
]
985 == ELFCLASS64
) ? 8 : 4;
987 BFD_ASSERT (elf_section_data (sec
)->sec_info_type
988 == ELF_INFO_TYPE_EH_FRAME_HDR
);
989 hdr_info
= (struct eh_frame_hdr_info
*)
990 elf_section_data (sec
)->sec_info
;
991 size
= EH_FRAME_HDR_SIZE
;
992 if (hdr_info
->array
&& hdr_info
->array_count
== hdr_info
->fde_count
)
993 size
+= 4 + hdr_info
->fde_count
* 8;
994 contents
= bfd_malloc (size
);
995 if (contents
== NULL
)
998 eh_frame_sec
= bfd_get_section_by_name (abfd
, ".eh_frame");
999 if (eh_frame_sec
== NULL
)
1002 memset (contents
, 0, EH_FRAME_HDR_SIZE
);
1003 contents
[0] = 1; /* Version */
1004 contents
[1] = DW_EH_PE_pcrel
| DW_EH_PE_sdata4
; /* .eh_frame offset */
1005 if (hdr_info
->array
&& hdr_info
->array_count
== hdr_info
->fde_count
)
1007 contents
[2] = DW_EH_PE_udata4
; /* FDE count encoding */
1008 contents
[3] = DW_EH_PE_datarel
| DW_EH_PE_sdata4
; /* search table enc */
1012 contents
[2] = DW_EH_PE_omit
;
1013 contents
[3] = DW_EH_PE_omit
;
1015 bfd_put_32 (abfd
, eh_frame_sec
->vma
- sec
->output_section
->vma
- 4,
1017 if (contents
[2] != DW_EH_PE_omit
)
1021 bfd_put_32 (abfd
, hdr_info
->fde_count
, contents
+ EH_FRAME_HDR_SIZE
);
1022 qsort (hdr_info
->array
, hdr_info
->fde_count
, sizeof (*hdr_info
->array
),
1024 for (i
= 0; i
< hdr_info
->fde_count
; i
++)
1027 hdr_info
->array
[i
].initial_loc
1028 - sec
->output_section
->vma
,
1029 contents
+ EH_FRAME_HDR_SIZE
+ i
* 8 + 4);
1031 hdr_info
->array
[i
].fde
- sec
->output_section
->vma
,
1032 contents
+ EH_FRAME_HDR_SIZE
+ i
* 8 + 8);
1036 return bfd_set_section_contents (abfd
, sec
->output_section
,
1037 contents
, (file_ptr
) sec
->output_offset
,