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. */
92 static bfd_vma read_unsigned_leb128
93 PARAMS ((bfd
*, char *, unsigned int *));
94 static bfd_signed_vma read_signed_leb128
95 PARAMS ((bfd
*, char *, unsigned int *));
96 static int get_DW_EH_PE_width
98 static int cie_compare
99 PARAMS ((struct cie
*, struct cie
*));
100 static int vma_compare
101 PARAMS ((const PTR a
, const PTR b
));
103 /* Helper function for reading uleb128 encoded data. */
106 read_unsigned_leb128 (abfd
, buf
, bytes_read_ptr
)
107 bfd
*abfd ATTRIBUTE_UNUSED
;
109 unsigned int *bytes_read_ptr
;
112 unsigned int num_read
;
121 byte
= bfd_get_8 (abfd
, (bfd_byte
*) buf
);
124 result
|= (((bfd_vma
) byte
& 0x7f) << shift
);
128 * bytes_read_ptr
= num_read
;
132 /* Helper function for reading sleb128 encoded data. */
134 static bfd_signed_vma
135 read_signed_leb128 (abfd
, buf
, bytes_read_ptr
)
136 bfd
*abfd ATTRIBUTE_UNUSED
;
138 unsigned int * bytes_read_ptr
;
150 byte
= bfd_get_8 (abfd
, (bfd_byte
*) buf
);
153 result
|= (((bfd_vma
) byte
& 0x7f) << shift
);
158 result
|= (((bfd_vma
) -1) << (shift
- 7)) << 7;
159 * bytes_read_ptr
= num_read
;
163 #define read_uleb128(VAR, BUF) \
166 (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp); \
167 (BUF) += leb128_tmp; \
171 #define read_sleb128(VAR, BUF) \
174 (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp); \
175 (BUF) += leb128_tmp; \
179 /* Return 0 if either encoding is variable width, or not yet known to bfd. */
182 int get_DW_EH_PE_width (encoding
, ptr_size
)
183 int encoding
, ptr_size
;
185 /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
187 if ((encoding
& 0x60) == 0x60)
190 switch (encoding
& 7)
192 case DW_EH_PE_udata2
: return 2;
193 case DW_EH_PE_udata4
: return 4;
194 case DW_EH_PE_udata8
: return 8;
195 case DW_EH_PE_absptr
: return ptr_size
;
203 /* Return zero if C1 and C2 CIEs can be merged. */
206 int cie_compare (c1
, c2
)
209 if (c1
->hdr
.length
== c2
->hdr
.length
210 && c1
->version
== c2
->version
211 && strcmp (c1
->augmentation
, c2
->augmentation
) == 0
212 && strcmp (c1
->augmentation
, "eh") != 0
213 && c1
->code_align
== c2
->code_align
214 && c1
->data_align
== c2
->data_align
215 && c1
->ra_column
== c2
->ra_column
216 && c1
->augmentation_size
== c2
->augmentation_size
217 && c1
->personality
== c2
->personality
218 && c1
->per_encoding
== c2
->per_encoding
219 && c1
->lsda_encoding
== c2
->lsda_encoding
220 && c1
->fde_encoding
== c2
->fde_encoding
221 && (c1
->initial_insn_length
222 == c2
->initial_insn_length
)
223 && memcmp (c1
->initial_instructions
,
224 c2
->initial_instructions
,
225 c1
->initial_insn_length
) == 0)
231 /* This function is called for each input file before the .eh_frame
232 section is relocated. It discards duplicate CIEs and FDEs for discarded
233 functions. The function returns true iff any entries have been
237 _bfd_elf_discard_section_eh_frame (abfd
, info
, sec
, ehdrsec
,
238 reloc_symbol_deleted_p
, cookie
)
240 struct bfd_link_info
*info
;
241 asection
*sec
, *ehdrsec
;
242 boolean (*reloc_symbol_deleted_p
) (bfd_vma
, PTR
);
243 struct elf_reloc_cookie
*cookie
;
245 bfd_byte
*ehbuf
= NULL
, *buf
;
246 bfd_byte
*last_cie
, *last_fde
;
247 struct cie_header hdr
;
249 struct eh_frame_hdr_info
*hdr_info
;
250 struct eh_frame_sec_info
*sec_info
= NULL
;
251 unsigned int leb128_tmp
;
252 unsigned int cie_usage_count
, last_cie_ndx
, i
, offset
, make_relative
;
253 Elf_Internal_Rela
*rel
;
254 bfd_size_type new_size
;
255 unsigned int ptr_size
;
257 if (sec
->_raw_size
== 0)
259 /* This file does not contain .eh_frame information. */
263 if ((sec
->output_section
!= NULL
264 && bfd_is_abs_section (sec
->output_section
)))
266 /* At least one of the sections is being discarded from the
267 link, so we should just ignore them. */
271 BFD_ASSERT (elf_section_data (ehdrsec
)->sec_info_type
272 == ELF_INFO_TYPE_EH_FRAME_HDR
);
273 hdr_info
= (struct eh_frame_hdr_info
*)
274 elf_section_data (ehdrsec
)->sec_info
;
276 /* Read the frame unwind information from abfd. */
278 ehbuf
= (bfd_byte
*) bfd_malloc (sec
->_raw_size
);
282 if (! bfd_get_section_contents (abfd
, sec
, ehbuf
, (bfd_vma
) 0,
286 if (sec
->_raw_size
>= 4
287 && bfd_get_32 (abfd
, ehbuf
) == 0
288 && cookie
->rel
== cookie
->relend
)
290 /* Empty .eh_frame section. */
295 /* If .eh_frame section size doesn't fit into int, we cannot handle
296 it (it would need to use 64-bit .eh_frame format anyway). */
297 if (sec
->_raw_size
!= (unsigned int) sec
->_raw_size
)
300 ptr_size
= (elf_elfheader (abfd
)->e_ident
[EI_CLASS
]
301 == ELFCLASS64
) ? 8 : 4;
305 memset (&cie
, 0, sizeof (cie
));
307 new_size
= sec
->_raw_size
;
308 make_relative
= hdr_info
->last_cie
.make_relative
;
309 sec_info
= bfd_zmalloc (sizeof (struct eh_frame_sec_info
)
310 + 99 * sizeof (struct eh_cie_fde
));
311 if (sec_info
== NULL
)
313 sec_info
->alloced
= 100;
315 #define ENSURE_NO_RELOCS(buf) \
316 if (cookie->rel < cookie->relend \
317 && (cookie->rel->r_offset \
318 < (bfd_size_type) ((buf) - ehbuf))) \
321 #define SKIP_RELOCS(buf) \
322 while (cookie->rel < cookie->relend \
323 && (cookie->rel->r_offset \
324 < (bfd_size_type) ((buf) - ehbuf))) \
327 #define GET_RELOC(buf) \
328 ((cookie->rel < cookie->relend \
329 && (cookie->rel->r_offset \
330 == (bfd_size_type) ((buf) - ehbuf))) \
331 ? cookie->rel : NULL)
337 if (sec_info
->count
== sec_info
->alloced
)
339 sec_info
= bfd_realloc (sec_info
,
340 sizeof (struct eh_frame_sec_info
)
341 + (sec_info
->alloced
+ 99)
342 * sizeof (struct eh_cie_fde
));
343 if (sec_info
== NULL
)
346 memset (&sec_info
->entry
[sec_info
->alloced
], 0,
347 100 * sizeof (struct eh_cie_fde
));
348 sec_info
->alloced
+= 100;
352 /* If we are at the end of the section, we still need to decide
353 on whether to output or discard last encountered CIE (if any). */
354 if ((bfd_size_type
) (buf
- ehbuf
) == sec
->_raw_size
)
355 hdr
.id
= (unsigned int) -1;
358 if ((bfd_size_type
) (buf
+ 4 - ehbuf
) > sec
->_raw_size
)
359 /* No space for CIE/FDE header length. */
362 hdr
.length
= bfd_get_32 (abfd
, buf
);
363 if (hdr
.length
== 0xffffffff)
364 /* 64-bit .eh_frame is not supported. */
367 if ((buf
- ehbuf
) + hdr
.length
> sec
->_raw_size
)
368 /* CIE/FDE not contained fully in this .eh_frame input section. */
371 sec_info
->entry
[sec_info
->count
].offset
= last_fde
- ehbuf
;
372 sec_info
->entry
[sec_info
->count
].size
= 4 + hdr
.length
;
376 /* CIE with length 0 must be only the last in the section. */
377 if ((bfd_size_type
) (buf
- ehbuf
) < sec
->_raw_size
)
379 ENSURE_NO_RELOCS (buf
);
381 /* Now just finish last encountered CIE processing and break
383 hdr
.id
= (unsigned int) -1;
387 hdr
.id
= bfd_get_32 (abfd
, buf
);
389 if (hdr
.id
== (unsigned int) -1)
394 if (hdr
.id
== 0 || hdr
.id
== (unsigned int) -1)
396 unsigned int initial_insn_length
;
399 if (last_cie
!= NULL
)
401 /* Now check if this CIE is identical to last CIE, in which case
402 we can remove it, provided we adjust all FDEs.
403 Also, it can be removed if we have removed all FDEs using
405 if (cie_compare (&cie
, &hdr_info
->last_cie
) == 0
406 || cie_usage_count
== 0)
408 new_size
-= cie
.hdr
.length
+ 4;
409 sec_info
->entry
[last_cie_ndx
].removed
= 1;
410 sec_info
->entry
[last_cie_ndx
].sec
= hdr_info
->last_cie_sec
;
411 sec_info
->entry
[last_cie_ndx
].new_offset
412 = hdr_info
->last_cie_offset
;
416 hdr_info
->last_cie
= cie
;
417 hdr_info
->last_cie_sec
= sec
;
418 hdr_info
->last_cie_offset
= last_cie
- ehbuf
;
419 sec_info
->entry
[last_cie_ndx
].make_relative
424 if (hdr
.id
== (unsigned int) -1)
427 last_cie_ndx
= sec_info
->count
;
428 sec_info
->entry
[sec_info
->count
].cie
= 1;
431 memset (&cie
, 0, sizeof (cie
));
433 cie
.version
= *buf
++;
435 /* Cannot handle unknown versions. */
436 if (cie
.version
!= 1)
438 if (strlen (buf
) > sizeof (cie
.augmentation
) - 1)
441 strcpy (cie
.augmentation
, buf
);
442 buf
= strchr (buf
, '\0') + 1;
443 ENSURE_NO_RELOCS (buf
);
444 if (buf
[0] == 'e' && buf
[1] == 'h')
446 /* GCC < 3.0 .eh_frame CIE */
447 /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
448 is private to each CIE, so we don't need it for anything.
453 read_uleb128 (cie
.code_align
, buf
);
454 read_sleb128 (cie
.data_align
, buf
);
455 read_uleb128 (cie
.ra_column
, buf
);
456 ENSURE_NO_RELOCS (buf
);
457 cie
.lsda_encoding
= DW_EH_PE_omit
;
458 cie
.fde_encoding
= DW_EH_PE_omit
;
459 cie
.per_encoding
= DW_EH_PE_omit
;
460 aug
= cie
.augmentation
;
461 if (aug
[0] != 'e' || aug
[1] != 'h')
466 read_uleb128 (cie
.augmentation_size
, buf
);
467 ENSURE_NO_RELOCS (buf
);
474 cie
.lsda_encoding
= *buf
++;
475 ENSURE_NO_RELOCS (buf
);
476 if (get_DW_EH_PE_width (cie
.lsda_encoding
, ptr_size
) == 0)
480 cie
.fde_encoding
= *buf
++;
481 ENSURE_NO_RELOCS (buf
);
482 if (get_DW_EH_PE_width (cie
.fde_encoding
, ptr_size
) == 0)
489 cie
.per_encoding
= *buf
++;
490 per_width
= get_DW_EH_PE_width (cie
.per_encoding
,
494 if ((cie
.per_encoding
& 0xf0) == DW_EH_PE_aligned
)
496 + ((buf
- ehbuf
+ per_width
- 1)
497 & ~((bfd_size_type
) per_width
- 1)));
498 ENSURE_NO_RELOCS (buf
);
499 rel
= GET_RELOC (buf
);
500 /* Ensure we have a reloc here, against
504 unsigned long r_symndx
;
508 r_symndx
= ELF64_R_SYM (cookie
->rel
->r_info
);
511 r_symndx
= ELF32_R_SYM (cookie
->rel
->r_info
);
512 if (r_symndx
>= cookie
->locsymcount
)
514 struct elf_link_hash_entry
*h
;
516 r_symndx
-= cookie
->extsymoff
;
517 h
= cookie
->sym_hashes
[r_symndx
];
519 while (h
->root
.type
== bfd_link_hash_indirect
520 || h
->root
.type
== bfd_link_hash_warning
)
521 h
= (struct elf_link_hash_entry
*)
532 /* Unrecognized augmentation. Better bail out. */
537 /* For shared libraries, try to get rid of as many RELATIVE relocs
539 FIXME: For this to work, ELF backends need to perform the
540 relocation if omitting dynamic relocs, not skip it. */
543 && (cie
.fde_encoding
& 0xf0) == DW_EH_PE_absptr
)
544 cie
.make_relative
= 1;
546 /* If FDE encoding was not specified, it defaults to
548 if (cie
.fde_encoding
== DW_EH_PE_omit
)
549 cie
.fde_encoding
= DW_EH_PE_absptr
;
551 initial_insn_length
= cie
.hdr
.length
- (buf
- last_fde
- 4);
552 if (initial_insn_length
<= 50)
554 cie
.initial_insn_length
= initial_insn_length
;
555 memcpy (cie
.initial_instructions
, buf
, initial_insn_length
);
557 buf
+= initial_insn_length
;
558 ENSURE_NO_RELOCS (buf
);
563 /* Ensure this FDE uses the last CIE encountered. */
565 || hdr
.id
!= (unsigned int) (buf
- 4 - last_cie
))
568 ENSURE_NO_RELOCS (buf
);
569 rel
= GET_RELOC (buf
);
571 /* This should not happen. */
573 if ((*reloc_symbol_deleted_p
) (buf
- ehbuf
, cookie
))
576 /* This is a FDE against discarded section, it should
578 new_size
-= hdr
.length
+ 4;
579 sec_info
->entry
[sec_info
->count
].removed
= 1;
584 hdr_info
->fde_count
++;
587 buf
= last_fde
+ 4 + hdr
.length
;
591 sec_info
->entry
[sec_info
->count
].fde_encoding
= cie
.fde_encoding
;
595 elf_section_data (sec
)->sec_info
= sec_info
;
596 elf_section_data (sec
)->sec_info_type
= ELF_INFO_TYPE_EH_FRAME
;
598 /* Ok, now we can assign new offsets. */
601 for (i
= 0; i
< sec_info
->count
; i
++)
603 if (! sec_info
->entry
[i
].removed
)
605 sec_info
->entry
[i
].new_offset
= offset
;
606 offset
+= sec_info
->entry
[i
].size
;
607 if (sec_info
->entry
[i
].cie
)
610 make_relative
= sec_info
->entry
[i
].make_relative
;
613 sec_info
->entry
[i
].make_relative
= make_relative
;
615 else if (sec_info
->entry
[i
].cie
&& sec_info
->entry
[i
].sec
== sec
)
617 /* Need to adjust new_offset too. */
618 BFD_ASSERT (sec_info
->entry
[last_cie_ndx
].offset
619 == sec_info
->entry
[i
].new_offset
);
620 sec_info
->entry
[i
].new_offset
621 = sec_info
->entry
[last_cie_ndx
].new_offset
;
624 if (hdr_info
->last_cie_sec
== sec
)
626 BFD_ASSERT (sec_info
->entry
[last_cie_ndx
].offset
627 == hdr_info
->last_cie_offset
);
628 hdr_info
->last_cie_offset
= sec_info
->entry
[last_cie_ndx
].new_offset
;
631 /* Shrink the sec as needed. */
633 sec
->_cooked_size
= new_size
;
634 if (sec
->_cooked_size
== 0)
635 sec
->flags
|= SEC_EXCLUDE
;
638 return new_size
!= sec
->_raw_size
;
645 hdr_info
->table
= false;
646 hdr_info
->last_cie
.hdr
.length
= 0;
650 /* This function is called for .eh_frame_hdr section after
651 _bfd_elf_discard_section_eh_frame has been called on all .eh_frame
652 input sections. It finalizes the size of .eh_frame_hdr section. */
655 _bfd_elf_discard_section_eh_frame_hdr (abfd
, info
, sec
)
657 struct bfd_link_info
*info
;
660 struct eh_frame_hdr_info
*hdr_info
;
661 unsigned int ptr_size
;
663 ptr_size
= (elf_elfheader (abfd
)->e_ident
[EI_CLASS
]
664 == ELFCLASS64
) ? 8 : 4;
666 if ((elf_section_data (sec
)->sec_info_type
667 != ELF_INFO_TYPE_EH_FRAME_HDR
)
668 || ! info
->eh_frame_hdr
)
670 _bfd_strip_section_from_output (info
, sec
);
674 hdr_info
= (struct eh_frame_hdr_info
*)
675 elf_section_data (sec
)->sec_info
;
678 sec
->_cooked_size
= EH_FRAME_HDR_SIZE
;
680 sec
->_cooked_size
+= 4 + hdr_info
->fde_count
* 8;
682 /* Request program headers to be recalculated. */
683 elf_tdata (abfd
)->program_header_size
= 0;
684 elf_tdata (abfd
)->eh_frame_hdr
= true;
688 /* This function is called from size_dynamic_sections.
689 It needs to decide whether .eh_frame_hdr should be output or not,
690 because later on it is too late for calling _bfd_strip_section_from_output,
691 since dynamic symbol table has been sized. */
694 _bfd_elf_maybe_strip_eh_frame_hdr (info
)
695 struct bfd_link_info
*info
;
699 struct eh_frame_hdr_info
*hdr_info
;
701 sec
= bfd_get_section_by_name (elf_hash_table (info
)->dynobj
, ".eh_frame_hdr");
706 = bfd_zmalloc (sizeof (struct eh_frame_hdr_info
));
707 if (hdr_info
== NULL
)
710 elf_section_data (sec
)->sec_info
= hdr_info
;
711 elf_section_data (sec
)->sec_info_type
= ELF_INFO_TYPE_EH_FRAME_HDR
;
714 if (info
->eh_frame_hdr
)
715 for (abfd
= info
->input_bfds
; abfd
!= NULL
; abfd
= abfd
->link_next
)
717 /* Count only sections which have at least a single CIE or FDE.
718 There cannot be any CIE or FDE <= 8 bytes. */
719 o
= bfd_get_section_by_name (abfd
, ".eh_frame");
720 if (o
&& o
->_raw_size
> 8)
726 _bfd_strip_section_from_output (info
, sec
);
727 hdr_info
->strip
= true;
730 hdr_info
->table
= true;
734 /* Adjust an address in the .eh_frame section. Given OFFSET within
735 SEC, this returns the new offset in the adjusted .eh_frame section,
736 or -1 if the address refers to a CIE/FDE which has been removed
737 or to offset with dynamic relocation which is no longer needed. */
740 _bfd_elf_eh_frame_section_offset (output_bfd
, sec
, offset
)
741 bfd
*output_bfd ATTRIBUTE_UNUSED
;
745 struct eh_frame_sec_info
*sec_info
;
746 unsigned int lo
, hi
, mid
;
748 if (elf_section_data (sec
)->sec_info_type
!= ELF_INFO_TYPE_EH_FRAME
)
750 sec_info
= (struct eh_frame_sec_info
*)
751 elf_section_data (sec
)->sec_info
;
753 if (offset
>= sec
->_raw_size
)
754 return offset
- (sec
->_cooked_size
- sec
->_raw_size
);
757 hi
= sec_info
->count
;
762 if (offset
< sec_info
->entry
[mid
].offset
)
765 >= sec_info
->entry
[mid
].offset
+ sec_info
->entry
[mid
].size
)
771 BFD_ASSERT (lo
< hi
);
773 /* FDE or CIE was removed. */
774 if (sec_info
->entry
[mid
].removed
)
777 /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
778 relocation against FDE's initial_location field. */
779 if (sec_info
->entry
[mid
].make_relative
780 && ! sec_info
->entry
[mid
].cie
781 && offset
== sec_info
->entry
[mid
].offset
+ 8)
785 + (sec_info
->entry
[mid
].new_offset
- sec_info
->entry
[mid
].offset
));
788 /* Write out .eh_frame section. This is called with the relocated
792 _bfd_elf_write_section_eh_frame (abfd
, sec
, ehdrsec
, contents
)
794 asection
*sec
, *ehdrsec
;
797 struct eh_frame_sec_info
*sec_info
;
798 struct eh_frame_hdr_info
*hdr_info
;
801 unsigned int leb128_tmp
;
802 unsigned int cie_offset
= 0;
803 unsigned int ptr_size
;
805 ptr_size
= (elf_elfheader (sec
->owner
)->e_ident
[EI_CLASS
]
806 == ELFCLASS64
) ? 8 : 4;
808 if (elf_section_data (sec
)->sec_info_type
!= ELF_INFO_TYPE_EH_FRAME
)
809 return bfd_set_section_contents (abfd
, sec
->output_section
,
811 (file_ptr
) sec
->output_offset
,
813 sec_info
= (struct eh_frame_sec_info
*)
814 elf_section_data (sec
)->sec_info
;
817 && (elf_section_data (ehdrsec
)->sec_info_type
818 == ELF_INFO_TYPE_EH_FRAME_HDR
))
820 hdr_info
= (struct eh_frame_hdr_info
*)
821 elf_section_data (ehdrsec
)->sec_info
;
822 if (hdr_info
->table
&& hdr_info
->array
== NULL
)
824 = bfd_malloc (hdr_info
->fde_count
* sizeof(*hdr_info
->array
));
825 if (hdr_info
->array
== NULL
)
830 for (i
= 0; i
< sec_info
->count
; ++i
)
832 if (sec_info
->entry
[i
].removed
)
834 if (sec_info
->entry
[i
].cie
)
836 cie_offset
= sec_info
->entry
[i
].new_offset
;
837 cie_offset
+= (sec_info
->entry
[i
].sec
->output_section
->vma
838 + sec_info
->entry
[i
].sec
->output_offset
839 - sec
->output_section
->vma
840 - sec
->output_offset
);
844 if (sec_info
->entry
[i
].cie
)
847 cie_offset
= sec_info
->entry
[i
].new_offset
;
848 if (sec_info
->entry
[i
].make_relative
)
851 unsigned int dummy
, per_width
, per_encoding
;
853 /* Need to find 'R' augmentation's argument and modify
855 buf
= contents
+ sec_info
->entry
[i
].offset
;
856 /* Skip length, id and version. */
859 buf
= strchr (buf
, '\0') + 1;
860 read_uleb128 (dummy
, buf
);
861 read_sleb128 (dummy
, buf
);
862 read_uleb128 (dummy
, buf
);
865 read_uleb128 (dummy
, buf
);
876 per_encoding
= *buf
++;
877 per_width
= get_DW_EH_PE_width (per_encoding
,
879 BFD_ASSERT (per_width
!= 0);
880 if ((per_encoding
& 0xf0) == DW_EH_PE_aligned
)
882 + ((buf
- contents
+ per_width
- 1)
883 & ~((bfd_size_type
) per_width
- 1)));
890 BFD_ASSERT (*buf
== sec_info
->entry
[i
].fde_encoding
);
891 *buf
|= DW_EH_PE_pcrel
;
897 bfd_vma value
= 0, address
;
898 unsigned int fde_width
;
900 buf
= contents
+ sec_info
->entry
[i
].offset
;
904 sec_info
->entry
[i
].new_offset
+ 4 - cie_offset
, buf
);
906 fde_width
= get_DW_EH_PE_width (sec_info
->entry
[i
].fde_encoding
,
910 case 2: value
= bfd_get_16 (abfd
, buf
); break;
911 case 4: value
= bfd_get_32 (abfd
, buf
); break;
912 case 8: value
= bfd_get_64 (abfd
, buf
); break;
913 default: BFD_FAIL ();
916 switch (sec_info
->entry
[i
].fde_encoding
& 0xf0)
918 case DW_EH_PE_indirect
:
919 case DW_EH_PE_textrel
:
920 BFD_ASSERT (hdr_info
== NULL
);
922 case DW_EH_PE_datarel
:
924 asection
*got
= bfd_get_section_by_name (abfd
, ".got");
926 BFD_ASSERT (got
!= NULL
);
931 value
+= (sec_info
->entry
[i
].offset
932 - sec_info
->entry
[i
].new_offset
);
933 address
+= (sec
->output_section
->vma
+ sec
->output_offset
934 + sec_info
->entry
[i
].new_offset
+ 8);
937 if (sec_info
->entry
[i
].make_relative
)
938 value
-= (sec
->output_section
->vma
+ sec
->output_offset
939 + sec_info
->entry
[i
].new_offset
+ 8);
942 case 2: bfd_put_16 (abfd
, value
, buf
); break;
943 case 4: bfd_put_32 (abfd
, value
, buf
); break;
944 case 8: bfd_put_64 (abfd
, value
, buf
); break;
949 hdr_info
->array
[hdr_info
->array_count
].initial_loc
= address
;
950 hdr_info
->array
[hdr_info
->array_count
++].fde
951 = (sec
->output_section
->vma
+ sec
->output_offset
952 + sec_info
->entry
[i
].new_offset
);
956 BFD_ASSERT (p
== contents
+ sec_info
->entry
[i
].new_offset
);
957 memmove (p
, contents
+ sec_info
->entry
[i
].offset
,
958 sec_info
->entry
[i
].size
);
959 p
+= sec_info
->entry
[i
].size
;
962 BFD_ASSERT ((bfd_size_type
) (p
- contents
) == sec
->_cooked_size
);
964 return bfd_set_section_contents (abfd
, sec
->output_section
,
965 contents
, (file_ptr
) sec
->output_offset
,
969 /* Helper function used to sort .eh_frame_hdr search table by increasing
970 VMA of FDE initial location. */
977 struct eh_frame_array_ent
*p
= (struct eh_frame_array_ent
*) a
;
978 struct eh_frame_array_ent
*q
= (struct eh_frame_array_ent
*) b
;
979 if (p
->initial_loc
> q
->initial_loc
)
981 if (p
->initial_loc
< q
->initial_loc
)
986 /* Write out .eh_frame_hdr section. This must be called after
987 _bfd_elf_write_section_eh_frame has been called on all input
989 .eh_frame_hdr format:
990 ubyte version (currently 1)
991 ubyte eh_frame_ptr_enc (DW_EH_PE_* encoding of pointer to start of
993 ubyte fde_count_enc (DW_EH_PE_* encoding of total FDE count
994 number (or DW_EH_PE_omit if there is no
995 binary search table computed))
996 ubyte table_enc (DW_EH_PE_* encoding of binary search table,
997 or DW_EH_PE_omit if not present.
998 DW_EH_PE_datarel is using address of
999 .eh_frame_hdr section start as base)
1000 [encoded] eh_frame_ptr (pointer to start of .eh_frame section)
1001 optionally followed by:
1002 [encoded] fde_count (total number of FDEs in .eh_frame section)
1003 fde_count x [encoded] initial_loc, fde
1004 (array of encoded pairs containing
1005 FDE initial_location field and FDE address,
1006 sorted by increasing initial_loc) */
1009 _bfd_elf_write_section_eh_frame_hdr (abfd
, sec
)
1013 struct eh_frame_hdr_info
*hdr_info
;
1014 unsigned int ptr_size
;
1016 asection
*eh_frame_sec
;
1019 ptr_size
= (elf_elfheader (sec
->owner
)->e_ident
[EI_CLASS
]
1020 == ELFCLASS64
) ? 8 : 4;
1022 BFD_ASSERT (elf_section_data (sec
)->sec_info_type
1023 == ELF_INFO_TYPE_EH_FRAME_HDR
);
1024 hdr_info
= (struct eh_frame_hdr_info
*)
1025 elf_section_data (sec
)->sec_info
;
1026 size
= EH_FRAME_HDR_SIZE
;
1027 if (hdr_info
->array
&& hdr_info
->array_count
== hdr_info
->fde_count
)
1028 size
+= 4 + hdr_info
->fde_count
* 8;
1029 contents
= bfd_malloc (size
);
1030 if (contents
== NULL
)
1033 eh_frame_sec
= bfd_get_section_by_name (abfd
, ".eh_frame");
1034 if (eh_frame_sec
== NULL
)
1037 memset (contents
, 0, EH_FRAME_HDR_SIZE
);
1038 contents
[0] = 1; /* Version */
1039 contents
[1] = DW_EH_PE_pcrel
| DW_EH_PE_sdata4
; /* .eh_frame offset */
1040 if (hdr_info
->array
&& hdr_info
->array_count
== hdr_info
->fde_count
)
1042 contents
[2] = DW_EH_PE_udata4
; /* FDE count encoding */
1043 contents
[3] = DW_EH_PE_datarel
| DW_EH_PE_sdata4
; /* search table enc */
1047 contents
[2] = DW_EH_PE_omit
;
1048 contents
[3] = DW_EH_PE_omit
;
1050 bfd_put_32 (abfd
, eh_frame_sec
->vma
- sec
->output_section
->vma
- 4,
1052 if (contents
[2] != DW_EH_PE_omit
)
1056 bfd_put_32 (abfd
, hdr_info
->fde_count
, contents
+ EH_FRAME_HDR_SIZE
);
1057 qsort (hdr_info
->array
, hdr_info
->fde_count
, sizeof (*hdr_info
->array
),
1059 for (i
= 0; i
< hdr_info
->fde_count
; i
++)
1062 hdr_info
->array
[i
].initial_loc
1063 - sec
->output_section
->vma
,
1064 contents
+ EH_FRAME_HDR_SIZE
+ i
* 8 + 4);
1066 hdr_info
->array
[i
].fde
- sec
->output_section
->vma
,
1067 contents
+ EH_FRAME_HDR_SIZE
+ i
* 8 + 8);
1071 return bfd_set_section_contents (abfd
, sec
->output_section
,
1072 contents
, (file_ptr
) sec
->output_offset
,