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 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;
69 struct eh_frame_sec_info
73 struct eh_cie_fde entry
[1];
76 struct eh_frame_array_ent
82 struct eh_frame_hdr_info
85 asection
*last_cie_sec
;
86 unsigned int last_cie_offset
;
87 unsigned int fde_count
, array_count
;
88 struct eh_frame_array_ent
*array
;
89 /* TRUE if .eh_frame_hdr should contain the sorted search table.
90 We build it if we successfully read all .eh_frame input sections
91 and recognize them. */
96 static bfd_vma read_unsigned_leb128
97 PARAMS ((bfd
*, char *, unsigned int *));
98 static bfd_signed_vma read_signed_leb128
99 PARAMS ((bfd
*, char *, unsigned int *));
100 static int get_DW_EH_PE_width
102 static bfd_vma read_value
103 PARAMS ((bfd
*, bfd_byte
*, int));
104 static void write_value
105 PARAMS ((bfd
*, bfd_byte
*, bfd_vma
, int));
106 static int cie_compare
107 PARAMS ((struct cie
*, struct cie
*));
108 static int vma_compare
109 PARAMS ((const PTR a
, const PTR b
));
111 /* Helper function for reading uleb128 encoded data. */
114 read_unsigned_leb128 (abfd
, buf
, bytes_read_ptr
)
115 bfd
*abfd ATTRIBUTE_UNUSED
;
117 unsigned int *bytes_read_ptr
;
120 unsigned int num_read
;
129 byte
= bfd_get_8 (abfd
, (bfd_byte
*) buf
);
132 result
|= (((bfd_vma
) byte
& 0x7f) << shift
);
136 * bytes_read_ptr
= num_read
;
140 /* Helper function for reading sleb128 encoded data. */
142 static bfd_signed_vma
143 read_signed_leb128 (abfd
, buf
, bytes_read_ptr
)
144 bfd
*abfd ATTRIBUTE_UNUSED
;
146 unsigned int * bytes_read_ptr
;
158 byte
= bfd_get_8 (abfd
, (bfd_byte
*) buf
);
161 result
|= (((bfd_vma
) byte
& 0x7f) << shift
);
166 result
|= (((bfd_vma
) -1) << (shift
- 7)) << 7;
167 * bytes_read_ptr
= num_read
;
171 #define read_uleb128(VAR, BUF) \
174 (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp); \
175 (BUF) += leb128_tmp; \
179 #define read_sleb128(VAR, BUF) \
182 (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp); \
183 (BUF) += leb128_tmp; \
187 /* Return 0 if either encoding is variable width, or not yet known to bfd. */
190 int get_DW_EH_PE_width (encoding
, ptr_size
)
191 int encoding
, ptr_size
;
193 /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
195 if ((encoding
& 0x60) == 0x60)
198 switch (encoding
& 7)
200 case DW_EH_PE_udata2
: return 2;
201 case DW_EH_PE_udata4
: return 4;
202 case DW_EH_PE_udata8
: return 8;
203 case DW_EH_PE_absptr
: return ptr_size
;
211 /* Read a width sized value from memory. */
214 read_value (abfd
, buf
, width
)
223 case 2: value
= bfd_get_16 (abfd
, buf
); break;
224 case 4: value
= bfd_get_32 (abfd
, buf
); break;
225 case 8: value
= bfd_get_64 (abfd
, buf
); break;
226 default: BFD_FAIL (); return 0;
232 /* Store a width sized value to memory. */
235 write_value (abfd
, buf
, value
, width
)
243 case 2: bfd_put_16 (abfd
, value
, buf
); break;
244 case 4: bfd_put_32 (abfd
, value
, buf
); break;
245 case 8: bfd_put_64 (abfd
, value
, buf
); break;
246 default: BFD_FAIL ();
250 /* Return zero if C1 and C2 CIEs can be merged. */
253 int cie_compare (c1
, c2
)
256 if (c1
->hdr
.length
== c2
->hdr
.length
257 && c1
->version
== c2
->version
258 && strcmp (c1
->augmentation
, c2
->augmentation
) == 0
259 && strcmp (c1
->augmentation
, "eh") != 0
260 && c1
->code_align
== c2
->code_align
261 && c1
->data_align
== c2
->data_align
262 && c1
->ra_column
== c2
->ra_column
263 && c1
->augmentation_size
== c2
->augmentation_size
264 && c1
->personality
== c2
->personality
265 && c1
->per_encoding
== c2
->per_encoding
266 && c1
->lsda_encoding
== c2
->lsda_encoding
267 && c1
->fde_encoding
== c2
->fde_encoding
268 && (c1
->initial_insn_length
269 == c2
->initial_insn_length
)
270 && memcmp (c1
->initial_instructions
,
271 c2
->initial_instructions
,
272 c1
->initial_insn_length
) == 0)
278 /* This function is called for each input file before the .eh_frame
279 section is relocated. It discards duplicate CIEs and FDEs for discarded
280 functions. The function returns true iff any entries have been
284 _bfd_elf_discard_section_eh_frame (abfd
, info
, sec
, ehdrsec
,
285 reloc_symbol_deleted_p
, cookie
)
287 struct bfd_link_info
*info
;
288 asection
*sec
, *ehdrsec
;
289 boolean (*reloc_symbol_deleted_p
) (bfd_vma
, PTR
);
290 struct elf_reloc_cookie
*cookie
;
292 bfd_byte
*ehbuf
= NULL
, *buf
;
293 bfd_byte
*last_cie
, *last_fde
;
294 struct cie_header hdr
;
296 struct eh_frame_hdr_info
*hdr_info
;
297 struct eh_frame_sec_info
*sec_info
= NULL
;
298 unsigned int leb128_tmp
;
299 unsigned int cie_usage_count
, last_cie_ndx
, i
, offset
;
300 unsigned int make_relative
, make_lsda_relative
;
301 Elf_Internal_Rela
*rel
;
302 bfd_size_type new_size
;
303 unsigned int ptr_size
;
305 if (sec
->_raw_size
== 0)
307 /* This file does not contain .eh_frame information. */
311 if ((sec
->output_section
!= NULL
312 && bfd_is_abs_section (sec
->output_section
)))
314 /* At least one of the sections is being discarded from the
315 link, so we should just ignore them. */
319 BFD_ASSERT (elf_section_data (ehdrsec
)->sec_info_type
320 == ELF_INFO_TYPE_EH_FRAME_HDR
);
321 hdr_info
= (struct eh_frame_hdr_info
*)
322 elf_section_data (ehdrsec
)->sec_info
;
324 /* Read the frame unwind information from abfd. */
326 ehbuf
= (bfd_byte
*) bfd_malloc (sec
->_raw_size
);
330 if (! bfd_get_section_contents (abfd
, sec
, ehbuf
, (bfd_vma
) 0,
334 if (sec
->_raw_size
>= 4
335 && bfd_get_32 (abfd
, ehbuf
) == 0
336 && cookie
->rel
== cookie
->relend
)
338 /* Empty .eh_frame section. */
343 /* If .eh_frame section size doesn't fit into int, we cannot handle
344 it (it would need to use 64-bit .eh_frame format anyway). */
345 if (sec
->_raw_size
!= (unsigned int) sec
->_raw_size
)
348 ptr_size
= (elf_elfheader (abfd
)->e_ident
[EI_CLASS
]
349 == ELFCLASS64
) ? 8 : 4;
353 memset (&cie
, 0, sizeof (cie
));
355 new_size
= sec
->_raw_size
;
356 make_relative
= hdr_info
->last_cie
.make_relative
;
357 make_lsda_relative
= hdr_info
->last_cie
.make_lsda_relative
;
358 sec_info
= bfd_zmalloc (sizeof (struct eh_frame_sec_info
)
359 + 99 * sizeof (struct eh_cie_fde
));
360 if (sec_info
== NULL
)
362 sec_info
->alloced
= 100;
364 #define ENSURE_NO_RELOCS(buf) \
365 if (cookie->rel < cookie->relend \
366 && (cookie->rel->r_offset \
367 < (bfd_size_type) ((buf) - ehbuf))) \
370 #define SKIP_RELOCS(buf) \
371 while (cookie->rel < cookie->relend \
372 && (cookie->rel->r_offset \
373 < (bfd_size_type) ((buf) - ehbuf))) \
376 #define GET_RELOC(buf) \
377 ((cookie->rel < cookie->relend \
378 && (cookie->rel->r_offset \
379 == (bfd_size_type) ((buf) - ehbuf))) \
380 ? cookie->rel : NULL)
386 if (sec_info
->count
== sec_info
->alloced
)
388 sec_info
= bfd_realloc (sec_info
,
389 sizeof (struct eh_frame_sec_info
)
390 + (sec_info
->alloced
+ 99)
391 * sizeof (struct eh_cie_fde
));
392 if (sec_info
== NULL
)
395 memset (&sec_info
->entry
[sec_info
->alloced
], 0,
396 100 * sizeof (struct eh_cie_fde
));
397 sec_info
->alloced
+= 100;
401 /* If we are at the end of the section, we still need to decide
402 on whether to output or discard last encountered CIE (if any). */
403 if ((bfd_size_type
) (buf
- ehbuf
) == sec
->_raw_size
)
404 hdr
.id
= (unsigned int) -1;
407 if ((bfd_size_type
) (buf
+ 4 - ehbuf
) > sec
->_raw_size
)
408 /* No space for CIE/FDE header length. */
411 hdr
.length
= bfd_get_32 (abfd
, buf
);
412 if (hdr
.length
== 0xffffffff)
413 /* 64-bit .eh_frame is not supported. */
416 if ((buf
- ehbuf
) + hdr
.length
> sec
->_raw_size
)
417 /* CIE/FDE not contained fully in this .eh_frame input section. */
420 sec_info
->entry
[sec_info
->count
].offset
= last_fde
- ehbuf
;
421 sec_info
->entry
[sec_info
->count
].size
= 4 + hdr
.length
;
425 /* CIE with length 0 must be only the last in the section. */
426 if ((bfd_size_type
) (buf
- ehbuf
) < sec
->_raw_size
)
428 ENSURE_NO_RELOCS (buf
);
430 /* Now just finish last encountered CIE processing and break
432 hdr
.id
= (unsigned int) -1;
436 hdr
.id
= bfd_get_32 (abfd
, buf
);
438 if (hdr
.id
== (unsigned int) -1)
443 if (hdr
.id
== 0 || hdr
.id
== (unsigned int) -1)
445 unsigned int initial_insn_length
;
448 if (last_cie
!= NULL
)
450 /* Now check if this CIE is identical to last CIE, in which case
451 we can remove it, provided we adjust all FDEs.
452 Also, it can be removed if we have removed all FDEs using
454 if (cie_compare (&cie
, &hdr_info
->last_cie
) == 0
455 || cie_usage_count
== 0)
457 new_size
-= cie
.hdr
.length
+ 4;
458 sec_info
->entry
[last_cie_ndx
].removed
= 1;
459 sec_info
->entry
[last_cie_ndx
].sec
= hdr_info
->last_cie_sec
;
460 sec_info
->entry
[last_cie_ndx
].new_offset
461 = hdr_info
->last_cie_offset
;
465 hdr_info
->last_cie
= cie
;
466 hdr_info
->last_cie_sec
= sec
;
467 hdr_info
->last_cie_offset
= last_cie
- ehbuf
;
468 sec_info
->entry
[last_cie_ndx
].make_relative
470 sec_info
->entry
[last_cie_ndx
].make_lsda_relative
471 = cie
.make_lsda_relative
;
475 if (hdr
.id
== (unsigned int) -1)
478 last_cie_ndx
= sec_info
->count
;
479 sec_info
->entry
[sec_info
->count
].cie
= 1;
482 memset (&cie
, 0, sizeof (cie
));
484 cie
.version
= *buf
++;
486 /* Cannot handle unknown versions. */
487 if (cie
.version
!= 1)
489 if (strlen (buf
) > sizeof (cie
.augmentation
) - 1)
492 strcpy (cie
.augmentation
, buf
);
493 buf
= strchr (buf
, '\0') + 1;
494 ENSURE_NO_RELOCS (buf
);
495 if (buf
[0] == 'e' && buf
[1] == 'h')
497 /* GCC < 3.0 .eh_frame CIE */
498 /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
499 is private to each CIE, so we don't need it for anything.
504 read_uleb128 (cie
.code_align
, buf
);
505 read_sleb128 (cie
.data_align
, buf
);
506 read_uleb128 (cie
.ra_column
, buf
);
507 ENSURE_NO_RELOCS (buf
);
508 cie
.lsda_encoding
= DW_EH_PE_omit
;
509 cie
.fde_encoding
= DW_EH_PE_omit
;
510 cie
.per_encoding
= DW_EH_PE_omit
;
511 aug
= cie
.augmentation
;
512 if (aug
[0] != 'e' || aug
[1] != 'h')
517 read_uleb128 (cie
.augmentation_size
, buf
);
518 ENSURE_NO_RELOCS (buf
);
525 cie
.lsda_encoding
= *buf
++;
526 ENSURE_NO_RELOCS (buf
);
527 if (get_DW_EH_PE_width (cie
.lsda_encoding
, ptr_size
) == 0)
531 cie
.fde_encoding
= *buf
++;
532 ENSURE_NO_RELOCS (buf
);
533 if (get_DW_EH_PE_width (cie
.fde_encoding
, ptr_size
) == 0)
540 cie
.per_encoding
= *buf
++;
541 per_width
= get_DW_EH_PE_width (cie
.per_encoding
,
545 if ((cie
.per_encoding
& 0xf0) == DW_EH_PE_aligned
)
547 + ((buf
- ehbuf
+ per_width
- 1)
548 & ~((bfd_size_type
) per_width
- 1)));
549 ENSURE_NO_RELOCS (buf
);
550 rel
= GET_RELOC (buf
);
551 /* Ensure we have a reloc here, against
555 unsigned long r_symndx
;
559 r_symndx
= ELF64_R_SYM (cookie
->rel
->r_info
);
562 r_symndx
= ELF32_R_SYM (cookie
->rel
->r_info
);
563 if (r_symndx
>= cookie
->locsymcount
)
565 struct elf_link_hash_entry
*h
;
567 r_symndx
-= cookie
->extsymoff
;
568 h
= cookie
->sym_hashes
[r_symndx
];
570 while (h
->root
.type
== bfd_link_hash_indirect
571 || h
->root
.type
== bfd_link_hash_warning
)
572 h
= (struct elf_link_hash_entry
*)
583 /* Unrecognized augmentation. Better bail out. */
588 /* For shared libraries, try to get rid of as many RELATIVE relocs
590 FIXME: For this to work, ELF backends need to perform the
591 relocation if omitting dynamic relocs, not skip it. */
594 && (cie
.fde_encoding
& 0xf0) == DW_EH_PE_absptr
)
595 cie
.make_relative
= 1;
599 && (cie
.lsda_encoding
& 0xf0) == DW_EH_PE_absptr
)
600 cie
.make_lsda_relative
= 1;
602 /* If FDE encoding was not specified, it defaults to
604 if (cie
.fde_encoding
== DW_EH_PE_omit
)
605 cie
.fde_encoding
= DW_EH_PE_absptr
;
607 initial_insn_length
= cie
.hdr
.length
- (buf
- last_fde
- 4);
608 if (initial_insn_length
<= 50)
610 cie
.initial_insn_length
= initial_insn_length
;
611 memcpy (cie
.initial_instructions
, buf
, initial_insn_length
);
613 buf
+= initial_insn_length
;
614 ENSURE_NO_RELOCS (buf
);
619 /* Ensure this FDE uses the last CIE encountered. */
621 || hdr
.id
!= (unsigned int) (buf
- 4 - last_cie
))
624 ENSURE_NO_RELOCS (buf
);
625 rel
= GET_RELOC (buf
);
627 /* This should not happen. */
629 if ((*reloc_symbol_deleted_p
) (buf
- ehbuf
, cookie
))
632 /* This is a FDE against discarded section, it should
634 new_size
-= hdr
.length
+ 4;
635 sec_info
->entry
[sec_info
->count
].removed
= 1;
640 hdr_info
->fde_count
++;
643 if (cie
.lsda_encoding
!= DW_EH_PE_omit
)
648 buf
+= 2 * get_DW_EH_PE_width (cie
.fde_encoding
, ptr_size
);
649 if (cie
.augmentation
[0] == 'z')
650 read_uleb128 (dummy
, buf
);
651 /* If some new augmentation data is added before LSDA
652 in FDE augmentation area, this need to be adjusted. */
653 sec_info
->entry
[sec_info
->count
].lsda_offset
= (buf
- aug
);
655 buf
= last_fde
+ 4 + hdr
.length
;
659 sec_info
->entry
[sec_info
->count
].fde_encoding
= cie
.fde_encoding
;
660 sec_info
->entry
[sec_info
->count
].lsda_encoding
= cie
.lsda_encoding
;
664 elf_section_data (sec
)->sec_info
= sec_info
;
665 elf_section_data (sec
)->sec_info_type
= ELF_INFO_TYPE_EH_FRAME
;
667 /* Ok, now we can assign new offsets. */
670 for (i
= 0; i
< sec_info
->count
; i
++)
672 if (! sec_info
->entry
[i
].removed
)
674 sec_info
->entry
[i
].new_offset
= offset
;
675 offset
+= sec_info
->entry
[i
].size
;
676 if (sec_info
->entry
[i
].cie
)
679 make_relative
= sec_info
->entry
[i
].make_relative
;
680 make_lsda_relative
= sec_info
->entry
[i
].make_lsda_relative
;
684 sec_info
->entry
[i
].make_relative
= make_relative
;
685 sec_info
->entry
[i
].make_lsda_relative
= make_lsda_relative
;
688 else if (sec_info
->entry
[i
].cie
&& sec_info
->entry
[i
].sec
== sec
)
690 /* Need to adjust new_offset too. */
691 BFD_ASSERT (sec_info
->entry
[last_cie_ndx
].offset
692 == sec_info
->entry
[i
].new_offset
);
693 sec_info
->entry
[i
].new_offset
694 = sec_info
->entry
[last_cie_ndx
].new_offset
;
697 if (hdr_info
->last_cie_sec
== sec
)
699 BFD_ASSERT (sec_info
->entry
[last_cie_ndx
].offset
700 == hdr_info
->last_cie_offset
);
701 hdr_info
->last_cie_offset
= sec_info
->entry
[last_cie_ndx
].new_offset
;
704 /* Shrink the sec as needed. */
706 sec
->_cooked_size
= new_size
;
707 if (sec
->_cooked_size
== 0)
708 sec
->flags
|= SEC_EXCLUDE
;
711 return new_size
!= sec
->_raw_size
;
718 hdr_info
->table
= false;
719 hdr_info
->last_cie
.hdr
.length
= 0;
723 /* This function is called for .eh_frame_hdr section after
724 _bfd_elf_discard_section_eh_frame has been called on all .eh_frame
725 input sections. It finalizes the size of .eh_frame_hdr section. */
728 _bfd_elf_discard_section_eh_frame_hdr (abfd
, info
, sec
)
730 struct bfd_link_info
*info
;
733 struct eh_frame_hdr_info
*hdr_info
;
734 unsigned int ptr_size
;
736 ptr_size
= (elf_elfheader (abfd
)->e_ident
[EI_CLASS
]
737 == ELFCLASS64
) ? 8 : 4;
739 if ((elf_section_data (sec
)->sec_info_type
740 != ELF_INFO_TYPE_EH_FRAME_HDR
)
741 || ! info
->eh_frame_hdr
)
743 _bfd_strip_section_from_output (info
, sec
);
747 hdr_info
= (struct eh_frame_hdr_info
*)
748 elf_section_data (sec
)->sec_info
;
751 sec
->_cooked_size
= EH_FRAME_HDR_SIZE
;
753 sec
->_cooked_size
+= 4 + hdr_info
->fde_count
* 8;
755 /* Request program headers to be recalculated. */
756 elf_tdata (abfd
)->program_header_size
= 0;
757 elf_tdata (abfd
)->eh_frame_hdr
= true;
761 /* This function is called from size_dynamic_sections.
762 It needs to decide whether .eh_frame_hdr should be output or not,
763 because later on it is too late for calling _bfd_strip_section_from_output,
764 since dynamic symbol table has been sized. */
767 _bfd_elf_maybe_strip_eh_frame_hdr (info
)
768 struct bfd_link_info
*info
;
772 struct eh_frame_hdr_info
*hdr_info
;
774 sec
= bfd_get_section_by_name (elf_hash_table (info
)->dynobj
, ".eh_frame_hdr");
779 = bfd_zmalloc (sizeof (struct eh_frame_hdr_info
));
780 if (hdr_info
== NULL
)
783 elf_section_data (sec
)->sec_info
= hdr_info
;
784 elf_section_data (sec
)->sec_info_type
= ELF_INFO_TYPE_EH_FRAME_HDR
;
787 if (info
->eh_frame_hdr
)
788 for (abfd
= info
->input_bfds
; abfd
!= NULL
; abfd
= abfd
->link_next
)
790 /* Count only sections which have at least a single CIE or FDE.
791 There cannot be any CIE or FDE <= 8 bytes. */
792 o
= bfd_get_section_by_name (abfd
, ".eh_frame");
793 if (o
&& o
->_raw_size
> 8)
799 _bfd_strip_section_from_output (info
, sec
);
800 hdr_info
->strip
= true;
803 hdr_info
->table
= true;
807 /* Adjust an address in the .eh_frame section. Given OFFSET within
808 SEC, this returns the new offset in the adjusted .eh_frame section,
809 or -1 if the address refers to a CIE/FDE which has been removed
810 or to offset with dynamic relocation which is no longer needed. */
813 _bfd_elf_eh_frame_section_offset (output_bfd
, sec
, offset
)
814 bfd
*output_bfd ATTRIBUTE_UNUSED
;
818 struct eh_frame_sec_info
*sec_info
;
819 unsigned int lo
, hi
, mid
;
821 if (elf_section_data (sec
)->sec_info_type
!= ELF_INFO_TYPE_EH_FRAME
)
823 sec_info
= (struct eh_frame_sec_info
*)
824 elf_section_data (sec
)->sec_info
;
826 if (offset
>= sec
->_raw_size
)
827 return offset
- (sec
->_cooked_size
- sec
->_raw_size
);
830 hi
= sec_info
->count
;
835 if (offset
< sec_info
->entry
[mid
].offset
)
838 >= sec_info
->entry
[mid
].offset
+ sec_info
->entry
[mid
].size
)
844 BFD_ASSERT (lo
< hi
);
846 /* FDE or CIE was removed. */
847 if (sec_info
->entry
[mid
].removed
)
850 /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
851 relocation against FDE's initial_location field. */
852 if (sec_info
->entry
[mid
].make_relative
853 && ! sec_info
->entry
[mid
].cie
854 && offset
== sec_info
->entry
[mid
].offset
+ 8)
857 /* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need
858 for run-time relocation against LSDA field. */
859 if (sec_info
->entry
[mid
].make_lsda_relative
860 && ! sec_info
->entry
[mid
].cie
862 == (sec_info
->entry
[mid
].offset
+ 8
863 + sec_info
->entry
[mid
].lsda_offset
)))
867 + (sec_info
->entry
[mid
].new_offset
- sec_info
->entry
[mid
].offset
));
870 /* Write out .eh_frame section. This is called with the relocated
874 _bfd_elf_write_section_eh_frame (abfd
, sec
, ehdrsec
, contents
)
876 asection
*sec
, *ehdrsec
;
879 struct eh_frame_sec_info
*sec_info
;
880 struct eh_frame_hdr_info
*hdr_info
;
883 unsigned int leb128_tmp
;
884 unsigned int cie_offset
= 0;
885 unsigned int ptr_size
;
887 ptr_size
= (elf_elfheader (sec
->owner
)->e_ident
[EI_CLASS
]
888 == ELFCLASS64
) ? 8 : 4;
890 if (elf_section_data (sec
)->sec_info_type
!= ELF_INFO_TYPE_EH_FRAME
)
891 return bfd_set_section_contents (abfd
, sec
->output_section
,
893 (file_ptr
) sec
->output_offset
,
895 sec_info
= (struct eh_frame_sec_info
*)
896 elf_section_data (sec
)->sec_info
;
899 && (elf_section_data (ehdrsec
)->sec_info_type
900 == ELF_INFO_TYPE_EH_FRAME_HDR
))
902 hdr_info
= (struct eh_frame_hdr_info
*)
903 elf_section_data (ehdrsec
)->sec_info
;
904 if (hdr_info
->table
&& hdr_info
->array
== NULL
)
906 = bfd_malloc (hdr_info
->fde_count
* sizeof(*hdr_info
->array
));
907 if (hdr_info
->array
== NULL
)
912 for (i
= 0; i
< sec_info
->count
; ++i
)
914 if (sec_info
->entry
[i
].removed
)
916 if (sec_info
->entry
[i
].cie
)
918 cie_offset
= sec_info
->entry
[i
].new_offset
;
919 cie_offset
+= (sec_info
->entry
[i
].sec
->output_section
->vma
920 + sec_info
->entry
[i
].sec
->output_offset
921 - sec
->output_section
->vma
922 - sec
->output_offset
);
926 if (sec_info
->entry
[i
].cie
)
929 cie_offset
= sec_info
->entry
[i
].new_offset
;
930 if (sec_info
->entry
[i
].make_relative
931 || sec_info
->entry
[i
].make_lsda_relative
)
935 unsigned int dummy
, per_width
, per_encoding
;
937 /* Need to find 'R' or 'L' augmentation's argument and modify
939 action
= (sec_info
->entry
[i
].make_relative
? 1 : 0)
940 | (sec_info
->entry
[i
].make_lsda_relative
? 2 : 0);
941 buf
= contents
+ sec_info
->entry
[i
].offset
;
942 /* Skip length, id and version. */
945 buf
= strchr (buf
, '\0') + 1;
946 read_uleb128 (dummy
, buf
);
947 read_sleb128 (dummy
, buf
);
948 read_uleb128 (dummy
, buf
);
951 read_uleb128 (dummy
, buf
);
961 BFD_ASSERT (*buf
== sec_info
->entry
[i
].lsda_encoding
);
962 *buf
|= DW_EH_PE_pcrel
;
968 per_encoding
= *buf
++;
969 per_width
= get_DW_EH_PE_width (per_encoding
,
971 BFD_ASSERT (per_width
!= 0);
972 if ((per_encoding
& 0xf0) == DW_EH_PE_aligned
)
974 + ((buf
- contents
+ per_width
- 1)
975 & ~((bfd_size_type
) per_width
- 1)));
981 BFD_ASSERT (*buf
== sec_info
->entry
[i
].fde_encoding
);
982 *buf
|= DW_EH_PE_pcrel
;
995 bfd_vma value
= 0, address
;
998 buf
= contents
+ sec_info
->entry
[i
].offset
;
1002 sec_info
->entry
[i
].new_offset
+ 4 - cie_offset
, buf
);
1004 width
= get_DW_EH_PE_width (sec_info
->entry
[i
].fde_encoding
,
1006 address
= value
= read_value (abfd
, buf
, width
);
1009 switch (sec_info
->entry
[i
].fde_encoding
& 0xf0)
1011 case DW_EH_PE_indirect
:
1012 case DW_EH_PE_textrel
:
1013 BFD_ASSERT (hdr_info
== NULL
);
1015 case DW_EH_PE_datarel
:
1017 asection
*got
= bfd_get_section_by_name (abfd
, ".got");
1019 BFD_ASSERT (got
!= NULL
);
1020 address
+= got
->vma
;
1023 case DW_EH_PE_pcrel
:
1024 value
+= (sec_info
->entry
[i
].offset
1025 - sec_info
->entry
[i
].new_offset
);
1026 address
+= (sec
->output_section
->vma
+ sec
->output_offset
1027 + sec_info
->entry
[i
].offset
+ 8);
1030 if (sec_info
->entry
[i
].make_relative
)
1031 value
-= (sec
->output_section
->vma
+ sec
->output_offset
1032 + sec_info
->entry
[i
].new_offset
+ 8);
1033 write_value (abfd
, buf
, value
, width
);
1038 hdr_info
->array
[hdr_info
->array_count
].initial_loc
= address
;
1039 hdr_info
->array
[hdr_info
->array_count
++].fde
1040 = (sec
->output_section
->vma
+ sec
->output_offset
1041 + sec_info
->entry
[i
].new_offset
);
1044 if ((sec_info
->entry
[i
].lsda_encoding
& 0xf0) == DW_EH_PE_pcrel
1045 || sec_info
->entry
[i
].make_lsda_relative
)
1047 buf
+= sec_info
->entry
[i
].lsda_offset
;
1048 width
= get_DW_EH_PE_width (sec_info
->entry
[i
].lsda_encoding
,
1050 value
= read_value (abfd
, buf
, width
);
1053 if ((sec_info
->entry
[i
].lsda_encoding
& 0xf0)
1055 value
+= (sec_info
->entry
[i
].offset
1056 - sec_info
->entry
[i
].new_offset
);
1057 else if (sec_info
->entry
[i
].make_lsda_relative
)
1058 value
-= (sec
->output_section
->vma
+ sec
->output_offset
1059 + sec_info
->entry
[i
].new_offset
+ 8
1060 + sec_info
->entry
[i
].lsda_offset
);
1061 write_value (abfd
, buf
, value
, width
);
1066 BFD_ASSERT (p
== contents
+ sec_info
->entry
[i
].new_offset
);
1067 memmove (p
, contents
+ sec_info
->entry
[i
].offset
,
1068 sec_info
->entry
[i
].size
);
1069 p
+= sec_info
->entry
[i
].size
;
1072 BFD_ASSERT ((bfd_size_type
) (p
- contents
) == sec
->_cooked_size
);
1074 return bfd_set_section_contents (abfd
, sec
->output_section
,
1075 contents
, (file_ptr
) sec
->output_offset
,
1079 /* Helper function used to sort .eh_frame_hdr search table by increasing
1080 VMA of FDE initial location. */
1087 struct eh_frame_array_ent
*p
= (struct eh_frame_array_ent
*) a
;
1088 struct eh_frame_array_ent
*q
= (struct eh_frame_array_ent
*) b
;
1089 if (p
->initial_loc
> q
->initial_loc
)
1091 if (p
->initial_loc
< q
->initial_loc
)
1096 /* Write out .eh_frame_hdr section. This must be called after
1097 _bfd_elf_write_section_eh_frame has been called on all input
1099 .eh_frame_hdr format:
1100 ubyte version (currently 1)
1101 ubyte eh_frame_ptr_enc (DW_EH_PE_* encoding of pointer to start of
1103 ubyte fde_count_enc (DW_EH_PE_* encoding of total FDE count
1104 number (or DW_EH_PE_omit if there is no
1105 binary search table computed))
1106 ubyte table_enc (DW_EH_PE_* encoding of binary search table,
1107 or DW_EH_PE_omit if not present.
1108 DW_EH_PE_datarel is using address of
1109 .eh_frame_hdr section start as base)
1110 [encoded] eh_frame_ptr (pointer to start of .eh_frame section)
1111 optionally followed by:
1112 [encoded] fde_count (total number of FDEs in .eh_frame section)
1113 fde_count x [encoded] initial_loc, fde
1114 (array of encoded pairs containing
1115 FDE initial_location field and FDE address,
1116 sorted by increasing initial_loc) */
1119 _bfd_elf_write_section_eh_frame_hdr (abfd
, sec
)
1123 struct eh_frame_hdr_info
*hdr_info
;
1124 unsigned int ptr_size
;
1126 asection
*eh_frame_sec
;
1129 ptr_size
= (elf_elfheader (sec
->owner
)->e_ident
[EI_CLASS
]
1130 == ELFCLASS64
) ? 8 : 4;
1132 BFD_ASSERT (elf_section_data (sec
)->sec_info_type
1133 == ELF_INFO_TYPE_EH_FRAME_HDR
);
1134 hdr_info
= (struct eh_frame_hdr_info
*)
1135 elf_section_data (sec
)->sec_info
;
1136 size
= EH_FRAME_HDR_SIZE
;
1137 if (hdr_info
->array
&& hdr_info
->array_count
== hdr_info
->fde_count
)
1138 size
+= 4 + hdr_info
->fde_count
* 8;
1139 contents
= bfd_malloc (size
);
1140 if (contents
== NULL
)
1143 eh_frame_sec
= bfd_get_section_by_name (abfd
, ".eh_frame");
1144 if (eh_frame_sec
== NULL
)
1147 memset (contents
, 0, EH_FRAME_HDR_SIZE
);
1148 contents
[0] = 1; /* Version */
1149 contents
[1] = DW_EH_PE_pcrel
| DW_EH_PE_sdata4
; /* .eh_frame offset */
1150 if (hdr_info
->array
&& hdr_info
->array_count
== hdr_info
->fde_count
)
1152 contents
[2] = DW_EH_PE_udata4
; /* FDE count encoding */
1153 contents
[3] = DW_EH_PE_datarel
| DW_EH_PE_sdata4
; /* search table enc */
1157 contents
[2] = DW_EH_PE_omit
;
1158 contents
[3] = DW_EH_PE_omit
;
1160 bfd_put_32 (abfd
, eh_frame_sec
->vma
- sec
->output_section
->vma
- 4,
1162 if (contents
[2] != DW_EH_PE_omit
)
1166 bfd_put_32 (abfd
, hdr_info
->fde_count
, contents
+ EH_FRAME_HDR_SIZE
);
1167 qsort (hdr_info
->array
, hdr_info
->fde_count
, sizeof (*hdr_info
->array
),
1169 for (i
= 0; i
< hdr_info
->fde_count
; i
++)
1172 hdr_info
->array
[i
].initial_loc
1173 - sec
->output_section
->vma
,
1174 contents
+ EH_FRAME_HDR_SIZE
+ i
* 8 + 4);
1176 hdr_info
->array
[i
].fde
- sec
->output_section
->vma
,
1177 contents
+ EH_FRAME_HDR_SIZE
+ i
* 8 + 8);
1181 return bfd_set_section_contents (abfd
, sec
->output_section
,
1182 contents
, (file_ptr
) sec
->output_offset
,