* elf-strtab.c (struct elf_strtab_hash_entry): Add u.next.
[deliverable/binutils-gdb.git] / bfd / elf-eh-frame.c
CommitLineData
65765700
JJ
1/* .eh_frame section optimization.
2 Copyright 2001 Free Software Foundation, Inc.
3 Written by Jakub Jelinek <jakub@redhat.com>.
4
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "libbfd.h"
24#include "elf-bfd.h"
25#include "elf/dwarf2.h"
26
27#define EH_FRAME_HDR_SIZE 8
28
29struct cie_header
30{
31 unsigned int length;
32 unsigned int id;
33};
34
35struct cie
36{
37 struct cie_header hdr;
38 unsigned char version;
39 unsigned char augmentation[20];
40 unsigned int code_align;
41 int data_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];
51};
52
53struct eh_cie_fde
54{
55 unsigned int offset;
56 unsigned int size;
57 asection *sec;
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;
63};
64
65struct eh_frame_sec_info
66{
67 unsigned int count;
68 unsigned int alloced;
69 struct eh_cie_fde entry[1];
70};
71
72struct eh_frame_array_ent
73{
74 bfd_vma initial_loc;
75 bfd_vma fde;
76};
77
78struct eh_frame_hdr_info
79{
80 struct cie last_cie;
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. */
88 boolean table;
68f69152 89 boolean strip;
65765700
JJ
90};
91
92static bfd_vma read_unsigned_leb128
93 PARAMS ((bfd *, char *, unsigned int *));
94static bfd_signed_vma read_signed_leb128
95 PARAMS ((bfd *, char *, unsigned int *));
96static int get_DW_EH_PE_width
97 PARAMS ((int, int));
98static int cie_compare
99 PARAMS ((struct cie *, struct cie *));
100static int vma_compare
101 PARAMS ((const PTR a, const PTR b));
102
103/* Helper function for reading uleb128 encoded data. */
104
105static bfd_vma
106read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
107 bfd *abfd ATTRIBUTE_UNUSED;
108 char *buf;
109 unsigned int *bytes_read_ptr;
110{
111 bfd_vma result;
112 unsigned int num_read;
113 int shift;
114 unsigned char byte;
115
116 result = 0;
117 shift = 0;
118 num_read = 0;
119 do
120 {
121 byte = bfd_get_8 (abfd, (bfd_byte *) buf);
122 buf ++;
123 num_read ++;
124 result |= (((bfd_vma) byte & 0x7f) << shift);
125 shift += 7;
126 }
127 while (byte & 0x80);
128 * bytes_read_ptr = num_read;
129 return result;
130}
131
132/* Helper function for reading sleb128 encoded data. */
133
134static bfd_signed_vma
135read_signed_leb128 (abfd, buf, bytes_read_ptr)
136 bfd *abfd ATTRIBUTE_UNUSED;
137 char *buf;
138 unsigned int * bytes_read_ptr;
139{
140 bfd_vma result;
141 int shift;
142 int num_read;
143 unsigned char byte;
144
145 result = 0;
146 shift = 0;
147 num_read = 0;
148 do
149 {
150 byte = bfd_get_8 (abfd, (bfd_byte *) buf);
151 buf ++;
152 num_read ++;
153 result |= (((bfd_vma) byte & 0x7f) << shift);
154 shift += 7;
155 }
156 while (byte & 0x80);
157 if (byte & 0x40)
158 result |= (((bfd_vma) -1) << (shift - 7)) << 7;
159 * bytes_read_ptr = num_read;
160 return result;
161}
162
163#define read_uleb128(VAR, BUF) \
164do \
165 { \
166 (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp); \
167 (BUF) += leb128_tmp; \
168 } \
169while (0)
170
171#define read_sleb128(VAR, BUF) \
172do \
173 { \
174 (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp); \
175 (BUF) += leb128_tmp; \
176 } \
177while (0)
178
179/* Return 0 if either encoding is variable width, or not yet known to bfd. */
180
181static
182int get_DW_EH_PE_width (encoding, ptr_size)
183 int encoding, ptr_size;
184{
185 /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
186 was added to bfd. */
187 if ((encoding & 0x60) == 0x60)
188 return 0;
189
190 switch (encoding & 7)
191 {
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;
196 default:
197 break;
198 }
199
200 return 0;
201}
202
203/* Return zero if C1 and C2 CIEs can be merged. */
204
205static
206int cie_compare (c1, c2)
207 struct cie *c1, *c2;
208{
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)
226 return 0;
227
228 return 1;
229}
230
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
234 deleted. */
235
236boolean
237_bfd_elf_discard_section_eh_frame (abfd, info, sec, ehdrsec,
238 reloc_symbol_deleted_p, cookie)
239 bfd *abfd;
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;
244{
245 bfd_byte *ehbuf = NULL, *buf;
246 bfd_byte *last_cie, *last_fde;
247 struct cie_header hdr;
248 struct cie cie;
249 struct eh_frame_hdr_info *hdr_info;
68f69152 250 struct eh_frame_sec_info *sec_info = NULL;
65765700
JJ
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;
256
257 if (sec->_raw_size == 0)
258 {
259 /* This file does not contain .eh_frame information. */
260 return false;
261 }
262
263 if ((sec->output_section != NULL
264 && bfd_is_abs_section (sec->output_section)))
265 {
266 /* At least one of the sections is being discarded from the
267 link, so we should just ignore them. */
268 return false;
269 }
270
68f69152
JJ
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;
275
65765700
JJ
276 /* Read the frame unwind information from abfd. */
277
278 ehbuf = (bfd_byte *) bfd_malloc (sec->_raw_size);
68f69152
JJ
279 if (ehbuf == NULL)
280 goto free_no_table;
281
282 if (! bfd_get_section_contents (abfd, sec, ehbuf, (bfd_vma) 0,
283 sec->_raw_size))
284 goto free_no_table;
65765700
JJ
285
286 if (sec->_raw_size >= 4
287 && bfd_get_32 (abfd, ehbuf) == 0
288 && cookie->rel == cookie->relend)
289 {
290 /* Empty .eh_frame section. */
291 free (ehbuf);
292 return false;
293 }
294
65765700
JJ
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)
68f69152 298 goto free_no_table;
65765700
JJ
299
300 ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
301 == ELFCLASS64) ? 8 : 4;
302 buf = ehbuf;
303 last_cie = NULL;
304 last_cie_ndx = 0;
305 memset (&cie, 0, sizeof (cie));
306 cie_usage_count = 0;
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)
312 goto free_no_table;
313 sec_info->alloced = 100;
314
315#define ENSURE_NO_RELOCS(buf) \
316 if (cookie->rel < cookie->relend \
317 && (cookie->rel->r_offset \
318 < (bfd_size_type) ((buf) - ehbuf))) \
319 goto free_no_table
320
321#define SKIP_RELOCS(buf) \
322 while (cookie->rel < cookie->relend \
323 && (cookie->rel->r_offset \
324 < (bfd_size_type) ((buf) - ehbuf))) \
325 cookie->rel++
326
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)
332
333 for (;;)
334 {
335 unsigned char *aug;
336
337 if (sec_info->count == sec_info->alloced)
338 {
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)
344 goto free_no_table;
345
346 memset (&sec_info->entry[sec_info->alloced], 0,
347 100 * sizeof (struct eh_cie_fde));
348 sec_info->alloced += 100;
349 }
350
351 last_fde = buf;
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;
356 else
357 {
358 if ((bfd_size_type) (buf + 4 - ehbuf) > sec->_raw_size)
359 /* No space for CIE/FDE header length. */
360 goto free_no_table;
361
362 hdr.length = bfd_get_32 (abfd, buf);
363 if (hdr.length == 0xffffffff)
364 /* 64-bit .eh_frame is not supported. */
365 goto free_no_table;
366 buf += 4;
367 if ((buf - ehbuf) + hdr.length > sec->_raw_size)
368 /* CIE/FDE not contained fully in this .eh_frame input section. */
369 goto free_no_table;
370
371 sec_info->entry[sec_info->count].offset = last_fde - ehbuf;
372 sec_info->entry[sec_info->count].size = 4 + hdr.length;
373
374 if (hdr.length == 0)
375 {
376 /* CIE with length 0 must be only the last in the section. */
377 if ((bfd_size_type) (buf - ehbuf) < sec->_raw_size)
378 goto free_no_table;
379 ENSURE_NO_RELOCS (buf);
380 sec_info->count++;
381 /* Now just finish last encountered CIE processing and break
382 the loop. */
383 hdr.id = (unsigned int) -1;
384 }
385 else
386 {
387 hdr.id = bfd_get_32 (abfd, buf);
388 buf += 4;
389 if (hdr.id == (unsigned int) -1)
390 goto free_no_table;
391 }
392 }
393
394 if (hdr.id == 0 || hdr.id == (unsigned int) -1)
395 {
396 unsigned int initial_insn_length;
397
398 /* CIE */
399 if (last_cie != NULL)
400 {
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
404 that. */
405 if (cie_compare (&cie, &hdr_info->last_cie) == 0
406 || cie_usage_count == 0)
407 {
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;
413 }
414 else
415 {
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
420 = cie.make_relative;
421 }
422 }
423
424 if (hdr.id == (unsigned int) -1)
425 break;
426
427 last_cie_ndx = sec_info->count;
428 sec_info->entry[sec_info->count].cie = 1;
429
430 cie_usage_count = 0;
431 memset (&cie, 0, sizeof (cie));
432 cie.hdr = hdr;
433 cie.version = *buf++;
434
435 /* Cannot handle unknown versions. */
436 if (cie.version != 1)
437 goto free_no_table;
438 if (strlen (buf) > sizeof (cie.augmentation) - 1)
439 goto free_no_table;
440
441 strcpy (cie.augmentation, buf);
442 buf = strchr (buf, '\0') + 1;
443 ENSURE_NO_RELOCS (buf);
444 if (buf[0] == 'e' && buf[1] == 'h')
445 {
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.
449 Just skip it. */
450 buf += ptr_size;
451 SKIP_RELOCS (buf);
452 }
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')
462 {
463 if (*aug == 'z')
464 {
465 aug++;
466 read_uleb128 (cie.augmentation_size, buf);
467 ENSURE_NO_RELOCS (buf);
468 }
469
470 while (*aug != '\0')
471 switch (*aug++)
472 {
473 case 'L':
474 cie.lsda_encoding = *buf++;
475 ENSURE_NO_RELOCS (buf);
476 if (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size) == 0)
477 goto free_no_table;
478 break;
479 case 'R':
480 cie.fde_encoding = *buf++;
481 ENSURE_NO_RELOCS (buf);
482 if (get_DW_EH_PE_width (cie.fde_encoding, ptr_size) == 0)
483 goto free_no_table;
484 break;
485 case 'P':
486 {
487 int per_width;
488
489 cie.per_encoding = *buf++;
490 per_width = get_DW_EH_PE_width (cie.per_encoding,
491 ptr_size);
492 if (per_width == 0)
493 goto free_no_table;
494 if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
495 buf = (ehbuf
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
501 a global symbol. */
502 if (rel != NULL)
503 {
504 unsigned long r_symndx;
505
506#ifdef BFD64
507 if (ptr_size == 8)
508 r_symndx = ELF64_R_SYM (cookie->rel->r_info);
509 else
510#endif
511 r_symndx = ELF32_R_SYM (cookie->rel->r_info);
512 if (r_symndx >= cookie->locsymcount)
513 {
514 struct elf_link_hash_entry *h;
515
516 r_symndx -= cookie->extsymoff;
517 h = cookie->sym_hashes[r_symndx];
518
519 while (h->root.type == bfd_link_hash_indirect
520 || h->root.type == bfd_link_hash_warning)
521 h = (struct elf_link_hash_entry *)
522 h->root.u.i.link;
523
524 cie.personality = h;
525 }
526 cookie->rel++;
527 }
528 buf += per_width;
529 }
530 break;
531 default:
532 /* Unrecognized augmentation. Better bail out. */
533 goto free_no_table;
534 }
535 }
536
537 /* For shared libraries, try to get rid of as many RELATIVE relocs
538 as possible.
539 FIXME: For this to work, ELF backends need to perform the
540 relocation if omitting dynamic relocs, not skip it. */
541 if (0
542 && info->shared
543 && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
544 cie.make_relative = 1;
545
546 /* If FDE encoding was not specified, it defaults to
547 DW_EH_absptr. */
548 if (cie.fde_encoding == DW_EH_PE_omit)
549 cie.fde_encoding = DW_EH_PE_absptr;
550
551 initial_insn_length = cie.hdr.length - (buf - last_fde - 4);
552 if (initial_insn_length <= 50)
553 {
554 cie.initial_insn_length = initial_insn_length;
555 memcpy (cie.initial_instructions, buf, initial_insn_length);
556 }
557 buf += initial_insn_length;
558 ENSURE_NO_RELOCS (buf);
559 last_cie = last_fde;
560 }
561 else
562 {
563 /* Ensure this FDE uses the last CIE encountered. */
564 if (last_cie == NULL
565 || hdr.id != (unsigned int) (buf - 4 - last_cie))
566 goto free_no_table;
567
568 ENSURE_NO_RELOCS (buf);
569 rel = GET_RELOC (buf);
570 if (rel == NULL)
571 /* This should not happen. */
572 goto free_no_table;
573 if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
574 {
575 cookie->rel = rel;
576 /* This is a FDE against discarded section, it should
577 be deleted. */
578 new_size -= hdr.length + 4;
579 sec_info->entry[sec_info->count].removed = 1;
580 }
581 else
582 {
583 cie_usage_count++;
584 hdr_info->fde_count++;
585 }
586 cookie->rel = rel;
587 buf = last_fde + 4 + hdr.length;
588 SKIP_RELOCS (buf);
589 }
590
591 sec_info->entry[sec_info->count].fde_encoding = cie.fde_encoding;
592 sec_info->count++;
593 }
594
595 elf_section_data (sec)->sec_info = sec_info;
596 elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
597
598 /* Ok, now we can assign new offsets. */
599 offset = 0;
600 last_cie_ndx = 0;
601 for (i = 0; i < sec_info->count; i++)
602 {
603 if (! sec_info->entry[i].removed)
604 {
605 sec_info->entry[i].new_offset = offset;
606 offset += sec_info->entry[i].size;
607 if (sec_info->entry[i].cie)
608 {
609 last_cie_ndx = i;
610 make_relative = sec_info->entry[i].make_relative;
611 }
612 else
613 sec_info->entry[i].make_relative = make_relative;
614 }
615 else if (sec_info->entry[i].cie && sec_info->entry[i].sec == sec)
616 {
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;
622 }
623 }
624 if (hdr_info->last_cie_sec == sec)
625 {
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;
629 }
630
631 /* Shrink the sec as needed. */
632
633 sec->_cooked_size = new_size;
634 if (sec->_cooked_size == 0)
635 sec->flags |= SEC_EXCLUDE;
636
68f69152 637 free (ehbuf);
65765700
JJ
638 return new_size != sec->_raw_size;
639
640free_no_table:
68f69152
JJ
641 if (ehbuf)
642 free (ehbuf);
65765700
JJ
643 if (sec_info)
644 free (sec_info);
645 hdr_info->table = false;
646 hdr_info->last_cie.hdr.length = 0;
647 return false;
648}
649
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. */
653
654boolean
655_bfd_elf_discard_section_eh_frame_hdr (abfd, info, sec)
656 bfd *abfd;
657 struct bfd_link_info *info;
658 asection *sec;
659{
660 struct eh_frame_hdr_info *hdr_info;
661 unsigned int ptr_size;
662
663 ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
664 == ELFCLASS64) ? 8 : 4;
665
666 if ((elf_section_data (sec)->sec_info_type
667 != ELF_INFO_TYPE_EH_FRAME_HDR)
668 || ! info->eh_frame_hdr)
669 {
670 _bfd_strip_section_from_output (info, sec);
671 return false;
672 }
673
674 hdr_info = (struct eh_frame_hdr_info *)
675 elf_section_data (sec)->sec_info;
68f69152
JJ
676 if (hdr_info->strip)
677 return false;
65765700
JJ
678 sec->_cooked_size = EH_FRAME_HDR_SIZE;
679 if (hdr_info->table)
680 sec->_cooked_size += 4 + hdr_info->fde_count * 8;
681
682 /* Request program headers to be recalculated. */
683 elf_tdata (abfd)->program_header_size = 0;
684 elf_tdata (abfd)->eh_frame_hdr = true;
685 return true;
686}
687
68f69152
JJ
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. */
692
693boolean
694_bfd_elf_maybe_strip_eh_frame_hdr (info)
695 struct bfd_link_info *info;
696{
697 asection *sec, *o;
698 bfd *abfd;
699 struct eh_frame_hdr_info *hdr_info;
700
701 sec = bfd_get_section_by_name (elf_hash_table (info)->dynobj, ".eh_frame_hdr");
702 if (sec == NULL)
703 return true;
704
705 hdr_info
706 = bfd_zmalloc (sizeof (struct eh_frame_hdr_info));
707 if (hdr_info == NULL)
708 return false;
709
710 elf_section_data (sec)->sec_info = hdr_info;
711 elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME_HDR;
712
713 abfd = NULL;
714 if (info->eh_frame_hdr)
715 for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
716 {
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)
721 break;
722 }
723
724 if (abfd == NULL)
725 {
726 _bfd_strip_section_from_output (info, sec);
727 hdr_info->strip = true;
728 }
729 else
730 hdr_info->table = true;
731 return true;
732}
733
65765700
JJ
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. */
738
739bfd_vma
740_bfd_elf_eh_frame_section_offset (output_bfd, sec, offset)
741 bfd *output_bfd ATTRIBUTE_UNUSED;
742 asection *sec;
743 bfd_vma offset;
744{
745 struct eh_frame_sec_info *sec_info;
746 unsigned int lo, hi, mid;
747
748 if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
749 return offset;
750 sec_info = (struct eh_frame_sec_info *)
751 elf_section_data (sec)->sec_info;
752
753 if (offset >= sec->_raw_size)
754 return offset - (sec->_cooked_size - sec->_raw_size);
755
756 lo = 0;
757 hi = sec_info->count;
758 mid = 0;
759 while (lo < hi)
760 {
761 mid = (lo + hi) / 2;
762 if (offset < sec_info->entry[mid].offset)
763 hi = mid;
764 else if (offset
765 >= sec_info->entry[mid].offset + sec_info->entry[mid].size)
766 lo = mid + 1;
767 else
768 break;
769 }
770
771 BFD_ASSERT (lo < hi);
772
773 /* FDE or CIE was removed. */
774 if (sec_info->entry[mid].removed)
775 return (bfd_vma) -1;
776
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)
782 return (bfd_vma) -1;
783
784 return (offset
785 + (sec_info->entry[mid].new_offset - sec_info->entry[mid].offset));
786}
787
788/* Write out .eh_frame section. This is called with the relocated
789 contents. */
790
791boolean
792_bfd_elf_write_section_eh_frame (abfd, sec, ehdrsec, contents)
793 bfd *abfd;
794 asection *sec, *ehdrsec;
795 bfd_byte *contents;
796{
797 struct eh_frame_sec_info *sec_info;
798 struct eh_frame_hdr_info *hdr_info;
799 unsigned int i;
800 bfd_byte *p, *buf;
801 unsigned int leb128_tmp;
802 unsigned int cie_offset = 0;
803 unsigned int ptr_size;
804
805 ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
806 == ELFCLASS64) ? 8 : 4;
807
808 if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
809 return bfd_set_section_contents (abfd, sec->output_section,
810 contents,
811 (file_ptr) sec->output_offset,
812 sec->_raw_size);
813 sec_info = (struct eh_frame_sec_info *)
814 elf_section_data (sec)->sec_info;
815 hdr_info = NULL;
816 if (ehdrsec
817 && (elf_section_data (ehdrsec)->sec_info_type
818 == ELF_INFO_TYPE_EH_FRAME_HDR))
819 {
820 hdr_info = (struct eh_frame_hdr_info *)
821 elf_section_data (ehdrsec)->sec_info;
822 if (hdr_info->table && hdr_info->array == NULL)
823 hdr_info->array
824 = bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
825 if (hdr_info->array == NULL)
826 hdr_info = NULL;
827 }
828
829 p = contents;
830 for (i = 0; i < sec_info->count; ++i)
831 {
832 if (sec_info->entry[i].removed)
833 {
834 if (sec_info->entry[i].cie)
835 {
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);
841 }
842 continue;
843 }
844 if (sec_info->entry[i].cie)
845 {
846 /* CIE */
847 cie_offset = sec_info->entry[i].new_offset;
848 if (sec_info->entry[i].make_relative)
849 {
850 unsigned char *aug;
851 unsigned int dummy, per_width, per_encoding;
852
853 /* Need to find 'R' augmentation's argument and modify
854 DW_EH_PE_* value. */
855 buf = contents + sec_info->entry[i].offset;
856 /* Skip length, id and version. */
857 buf += 9;
858 aug = buf;
859 buf = strchr (buf, '\0') + 1;
860 read_uleb128 (dummy, buf);
861 read_sleb128 (dummy, buf);
862 read_uleb128 (dummy, buf);
863 if (*aug == 'z')
864 {
865 read_uleb128 (dummy, buf);
866 aug++;
867 }
868
869 while (*aug != 'R')
870 switch (*aug++)
871 {
872 case 'L':
873 buf++;
874 break;
875 case 'P':
876 per_encoding = *buf++;
877 per_width = get_DW_EH_PE_width (per_encoding,
878 ptr_size);
879 BFD_ASSERT (per_width != 0);
880 if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
881 buf = (contents
882 + ((buf - contents + per_width - 1)
883 & ~((bfd_size_type) per_width - 1)));
884 buf += per_width;
885 break;
886 default:
887 BFD_FAIL ();
888 }
889
890 BFD_ASSERT (*buf == sec_info->entry[i].fde_encoding);
891 *buf |= DW_EH_PE_pcrel;
892 }
893 }
894 else
895 {
896 /* FDE */
897 bfd_vma value = 0, address;
898 unsigned int fde_width;
899
900 buf = contents + sec_info->entry[i].offset;
901 /* Skip length. */
902 buf += 4;
903 bfd_put_32 (abfd,
904 sec_info->entry[i].new_offset + 4 - cie_offset, buf);
905 buf += 4;
906 fde_width = get_DW_EH_PE_width (sec_info->entry[i].fde_encoding,
907 ptr_size);
908 switch (fde_width)
909 {
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 ();
914 }
915 address = value;
916 switch (sec_info->entry[i].fde_encoding & 0xf0)
917 {
918 case DW_EH_PE_indirect:
919 case DW_EH_PE_textrel:
920 BFD_ASSERT (hdr_info == NULL);
921 break;
922 case DW_EH_PE_datarel:
923 {
924 asection *got = bfd_get_section_by_name (abfd, ".got");
925
926 BFD_ASSERT (got != NULL);
927 address += got->vma;
928 }
929 break;
930 case DW_EH_PE_pcrel:
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);
935 break;
936 }
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);
940 switch (fde_width)
941 {
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;
945 }
946
947 if (hdr_info)
948 {
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);
953 }
954 }
955
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;
960 }
961
962 BFD_ASSERT ((bfd_size_type) (p - contents) == sec->_cooked_size);
963
964 return bfd_set_section_contents (abfd, sec->output_section,
965 contents, (file_ptr) sec->output_offset,
966 sec->_cooked_size);
967}
968
969/* Helper function used to sort .eh_frame_hdr search table by increasing
970 VMA of FDE initial location. */
971
972static int
973vma_compare (a, b)
974 const PTR a;
975 const PTR b;
976{
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)
980 return 1;
981 if (p->initial_loc < q->initial_loc)
982 return -1;
983 return 0;
984}
985
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
988 .eh_frame sections.
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
992 .eh_frame section)
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) */
1007
1008boolean
1009_bfd_elf_write_section_eh_frame_hdr (abfd, sec)
1010 bfd *abfd;
1011 asection *sec;
1012{
1013 struct eh_frame_hdr_info *hdr_info;
1014 unsigned int ptr_size;
1015 bfd_byte *contents;
1016 asection *eh_frame_sec;
1017 bfd_size_type size;
1018
1019 ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
1020 == ELFCLASS64) ? 8 : 4;
1021
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)
1031 return false;
1032
1033 eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
1034 if (eh_frame_sec == NULL)
1035 return false;
1036
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)
1041 {
1042 contents[2] = DW_EH_PE_udata4; /* FDE count encoding */
1043 contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* search table enc */
1044 }
1045 else
1046 {
1047 contents[2] = DW_EH_PE_omit;
1048 contents[3] = DW_EH_PE_omit;
1049 }
1050 bfd_put_32 (abfd, eh_frame_sec->vma - sec->output_section->vma - 4,
1051 contents + 4);
1052 if (contents[2] != DW_EH_PE_omit)
1053 {
1054 unsigned int i;
1055
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),
1058 vma_compare);
1059 for (i = 0; i < hdr_info->fde_count; i++)
1060 {
1061 bfd_put_32 (abfd,
1062 hdr_info->array[i].initial_loc
1063 - sec->output_section->vma,
1064 contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
1065 bfd_put_32 (abfd,
1066 hdr_info->array[i].fde - sec->output_section->vma,
1067 contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
1068 }
1069 }
1070
1071 return bfd_set_section_contents (abfd, sec->output_section,
1072 contents, (file_ptr) sec->output_offset,
1073 sec->_cooked_size);
1074}
This page took 0.06308 seconds and 4 git commands to generate.