* elf-bfd.h (enum elf_link_info_type): New.
[deliverable/binutils-gdb.git] / bfd / elf-eh-frame.c
1 /* .eh_frame section optimization.
2 Copyright 2001 Free Software Foundation, Inc.
3 Written by Jakub Jelinek <jakub@redhat.com>.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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.
11
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.
16
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. */
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
29 struct cie_header
30 {
31 unsigned int length;
32 unsigned int id;
33 };
34
35 struct 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
53 struct 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
65 struct eh_frame_sec_info
66 {
67 unsigned int count;
68 unsigned int alloced;
69 struct eh_cie_fde entry[1];
70 };
71
72 struct eh_frame_array_ent
73 {
74 bfd_vma initial_loc;
75 bfd_vma fde;
76 };
77
78 struct 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;
89 };
90
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
96 PARAMS ((int, int));
97 static int cie_compare
98 PARAMS ((struct cie *, struct cie *));
99 static int vma_compare
100 PARAMS ((const PTR a, const PTR b));
101
102 /* Helper function for reading uleb128 encoded data. */
103
104 static bfd_vma
105 read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
106 bfd *abfd ATTRIBUTE_UNUSED;
107 char *buf;
108 unsigned int *bytes_read_ptr;
109 {
110 bfd_vma result;
111 unsigned int num_read;
112 int shift;
113 unsigned char byte;
114
115 result = 0;
116 shift = 0;
117 num_read = 0;
118 do
119 {
120 byte = bfd_get_8 (abfd, (bfd_byte *) buf);
121 buf ++;
122 num_read ++;
123 result |= (((bfd_vma) byte & 0x7f) << shift);
124 shift += 7;
125 }
126 while (byte & 0x80);
127 * bytes_read_ptr = num_read;
128 return result;
129 }
130
131 /* Helper function for reading sleb128 encoded data. */
132
133 static bfd_signed_vma
134 read_signed_leb128 (abfd, buf, bytes_read_ptr)
135 bfd *abfd ATTRIBUTE_UNUSED;
136 char *buf;
137 unsigned int * bytes_read_ptr;
138 {
139 bfd_vma result;
140 int shift;
141 int num_read;
142 unsigned char byte;
143
144 result = 0;
145 shift = 0;
146 num_read = 0;
147 do
148 {
149 byte = bfd_get_8 (abfd, (bfd_byte *) buf);
150 buf ++;
151 num_read ++;
152 result |= (((bfd_vma) byte & 0x7f) << shift);
153 shift += 7;
154 }
155 while (byte & 0x80);
156 if (byte & 0x40)
157 result |= (((bfd_vma) -1) << (shift - 7)) << 7;
158 * bytes_read_ptr = num_read;
159 return result;
160 }
161
162 #define read_uleb128(VAR, BUF) \
163 do \
164 { \
165 (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp); \
166 (BUF) += leb128_tmp; \
167 } \
168 while (0)
169
170 #define read_sleb128(VAR, BUF) \
171 do \
172 { \
173 (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp); \
174 (BUF) += leb128_tmp; \
175 } \
176 while (0)
177
178 /* Return 0 if either encoding is variable width, or not yet known to bfd. */
179
180 static
181 int get_DW_EH_PE_width (encoding, ptr_size)
182 int encoding, ptr_size;
183 {
184 /* DW_EH_PE_ values of 0x60 and 0x70 weren't defined at the time .eh_frame
185 was added to bfd. */
186 if ((encoding & 0x60) == 0x60)
187 return 0;
188
189 switch (encoding & 7)
190 {
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;
195 default:
196 break;
197 }
198
199 return 0;
200 }
201
202 /* Return zero if C1 and C2 CIEs can be merged. */
203
204 static
205 int cie_compare (c1, c2)
206 struct cie *c1, *c2;
207 {
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)
225 return 0;
226
227 return 1;
228 }
229
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
233 deleted. */
234
235 boolean
236 _bfd_elf_discard_section_eh_frame (abfd, info, sec, ehdrsec,
237 reloc_symbol_deleted_p, cookie)
238 bfd *abfd;
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;
243 {
244 bfd_byte *ehbuf = NULL, *buf;
245 bfd_byte *last_cie, *last_fde;
246 struct cie_header hdr;
247 struct cie cie;
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;
255
256 if (sec->_raw_size == 0)
257 {
258 /* This file does not contain .eh_frame information. */
259 return false;
260 }
261
262 if ((sec->output_section != NULL
263 && bfd_is_abs_section (sec->output_section)))
264 {
265 /* At least one of the sections is being discarded from the
266 link, so we should just ignore them. */
267 return false;
268 }
269
270 /* Read the frame unwind information from abfd. */
271
272 ehbuf = (bfd_byte *) bfd_malloc (sec->_raw_size);
273 if (ehbuf == NULL
274 || ! bfd_get_section_contents (abfd, sec, ehbuf, (bfd_vma) 0,
275 sec->_raw_size))
276 {
277 if (elf_section_data (ehdrsec)->sec_info_type
278 != ELF_INFO_TYPE_EH_FRAME_HDR)
279 {
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;
284 }
285 return false;
286 }
287
288 if (sec->_raw_size >= 4
289 && bfd_get_32 (abfd, ehbuf) == 0
290 && cookie->rel == cookie->relend)
291 {
292 /* Empty .eh_frame section. */
293 free (ehbuf);
294 return false;
295 }
296
297 if (elf_section_data (ehdrsec)->sec_info_type
298 != ELF_INFO_TYPE_EH_FRAME_HDR)
299 {
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;
306 }
307 else
308 hdr_info = (struct eh_frame_hdr_info *)
309 elf_section_data (ehdrsec)->sec_info;
310
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)
314 return false;
315
316 ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
317 == ELFCLASS64) ? 8 : 4;
318 buf = ehbuf;
319 last_cie = NULL;
320 last_cie_ndx = 0;
321 memset (&cie, 0, sizeof (cie));
322 cie_usage_count = 0;
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)
328 goto free_no_table;
329 sec_info->alloced = 100;
330
331 #define ENSURE_NO_RELOCS(buf) \
332 if (cookie->rel < cookie->relend \
333 && (cookie->rel->r_offset \
334 < (bfd_size_type) ((buf) - ehbuf))) \
335 goto free_no_table
336
337 #define SKIP_RELOCS(buf) \
338 while (cookie->rel < cookie->relend \
339 && (cookie->rel->r_offset \
340 < (bfd_size_type) ((buf) - ehbuf))) \
341 cookie->rel++
342
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)
348
349 for (;;)
350 {
351 unsigned char *aug;
352
353 if (sec_info->count == sec_info->alloced)
354 {
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)
360 goto free_no_table;
361
362 memset (&sec_info->entry[sec_info->alloced], 0,
363 100 * sizeof (struct eh_cie_fde));
364 sec_info->alloced += 100;
365 }
366
367 last_fde = buf;
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;
372 else
373 {
374 if ((bfd_size_type) (buf + 4 - ehbuf) > sec->_raw_size)
375 /* No space for CIE/FDE header length. */
376 goto free_no_table;
377
378 hdr.length = bfd_get_32 (abfd, buf);
379 if (hdr.length == 0xffffffff)
380 /* 64-bit .eh_frame is not supported. */
381 goto free_no_table;
382 buf += 4;
383 if ((buf - ehbuf) + hdr.length > sec->_raw_size)
384 /* CIE/FDE not contained fully in this .eh_frame input section. */
385 goto free_no_table;
386
387 sec_info->entry[sec_info->count].offset = last_fde - ehbuf;
388 sec_info->entry[sec_info->count].size = 4 + hdr.length;
389
390 if (hdr.length == 0)
391 {
392 /* CIE with length 0 must be only the last in the section. */
393 if ((bfd_size_type) (buf - ehbuf) < sec->_raw_size)
394 goto free_no_table;
395 ENSURE_NO_RELOCS (buf);
396 sec_info->count++;
397 /* Now just finish last encountered CIE processing and break
398 the loop. */
399 hdr.id = (unsigned int) -1;
400 }
401 else
402 {
403 hdr.id = bfd_get_32 (abfd, buf);
404 buf += 4;
405 if (hdr.id == (unsigned int) -1)
406 goto free_no_table;
407 }
408 }
409
410 if (hdr.id == 0 || hdr.id == (unsigned int) -1)
411 {
412 unsigned int initial_insn_length;
413
414 /* CIE */
415 if (last_cie != NULL)
416 {
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
420 that. */
421 if (cie_compare (&cie, &hdr_info->last_cie) == 0
422 || cie_usage_count == 0)
423 {
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;
429 }
430 else
431 {
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
436 = cie.make_relative;
437 }
438 }
439
440 if (hdr.id == (unsigned int) -1)
441 break;
442
443 last_cie_ndx = sec_info->count;
444 sec_info->entry[sec_info->count].cie = 1;
445
446 cie_usage_count = 0;
447 memset (&cie, 0, sizeof (cie));
448 cie.hdr = hdr;
449 cie.version = *buf++;
450
451 /* Cannot handle unknown versions. */
452 if (cie.version != 1)
453 goto free_no_table;
454 if (strlen (buf) > sizeof (cie.augmentation) - 1)
455 goto free_no_table;
456
457 strcpy (cie.augmentation, buf);
458 buf = strchr (buf, '\0') + 1;
459 ENSURE_NO_RELOCS (buf);
460 if (buf[0] == 'e' && buf[1] == 'h')
461 {
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.
465 Just skip it. */
466 buf += ptr_size;
467 SKIP_RELOCS (buf);
468 }
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')
478 {
479 if (*aug == 'z')
480 {
481 aug++;
482 read_uleb128 (cie.augmentation_size, buf);
483 ENSURE_NO_RELOCS (buf);
484 }
485
486 while (*aug != '\0')
487 switch (*aug++)
488 {
489 case 'L':
490 cie.lsda_encoding = *buf++;
491 ENSURE_NO_RELOCS (buf);
492 if (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size) == 0)
493 goto free_no_table;
494 break;
495 case 'R':
496 cie.fde_encoding = *buf++;
497 ENSURE_NO_RELOCS (buf);
498 if (get_DW_EH_PE_width (cie.fde_encoding, ptr_size) == 0)
499 goto free_no_table;
500 break;
501 case 'P':
502 {
503 int per_width;
504
505 cie.per_encoding = *buf++;
506 per_width = get_DW_EH_PE_width (cie.per_encoding,
507 ptr_size);
508 if (per_width == 0)
509 goto free_no_table;
510 if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
511 buf = (ehbuf
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
517 a global symbol. */
518 if (rel != NULL)
519 {
520 unsigned long r_symndx;
521
522 #ifdef BFD64
523 if (ptr_size == 8)
524 r_symndx = ELF64_R_SYM (cookie->rel->r_info);
525 else
526 #endif
527 r_symndx = ELF32_R_SYM (cookie->rel->r_info);
528 if (r_symndx >= cookie->locsymcount)
529 {
530 struct elf_link_hash_entry *h;
531
532 r_symndx -= cookie->extsymoff;
533 h = cookie->sym_hashes[r_symndx];
534
535 while (h->root.type == bfd_link_hash_indirect
536 || h->root.type == bfd_link_hash_warning)
537 h = (struct elf_link_hash_entry *)
538 h->root.u.i.link;
539
540 cie.personality = h;
541 }
542 cookie->rel++;
543 }
544 buf += per_width;
545 }
546 break;
547 default:
548 /* Unrecognized augmentation. Better bail out. */
549 goto free_no_table;
550 }
551 }
552
553 /* For shared libraries, try to get rid of as many RELATIVE relocs
554 as possible.
555 FIXME: For this to work, ELF backends need to perform the
556 relocation if omitting dynamic relocs, not skip it. */
557 if (0
558 && info->shared
559 && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
560 cie.make_relative = 1;
561
562 /* If FDE encoding was not specified, it defaults to
563 DW_EH_absptr. */
564 if (cie.fde_encoding == DW_EH_PE_omit)
565 cie.fde_encoding = DW_EH_PE_absptr;
566
567 initial_insn_length = cie.hdr.length - (buf - last_fde - 4);
568 if (initial_insn_length <= 50)
569 {
570 cie.initial_insn_length = initial_insn_length;
571 memcpy (cie.initial_instructions, buf, initial_insn_length);
572 }
573 buf += initial_insn_length;
574 ENSURE_NO_RELOCS (buf);
575 last_cie = last_fde;
576 }
577 else
578 {
579 /* Ensure this FDE uses the last CIE encountered. */
580 if (last_cie == NULL
581 || hdr.id != (unsigned int) (buf - 4 - last_cie))
582 goto free_no_table;
583
584 ENSURE_NO_RELOCS (buf);
585 rel = GET_RELOC (buf);
586 if (rel == NULL)
587 /* This should not happen. */
588 goto free_no_table;
589 if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
590 {
591 cookie->rel = rel;
592 /* This is a FDE against discarded section, it should
593 be deleted. */
594 new_size -= hdr.length + 4;
595 sec_info->entry[sec_info->count].removed = 1;
596 }
597 else
598 {
599 cie_usage_count++;
600 hdr_info->fde_count++;
601 }
602 cookie->rel = rel;
603 buf = last_fde + 4 + hdr.length;
604 SKIP_RELOCS (buf);
605 }
606
607 sec_info->entry[sec_info->count].fde_encoding = cie.fde_encoding;
608 sec_info->count++;
609 }
610
611 elf_section_data (sec)->sec_info = sec_info;
612 elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
613
614 /* Ok, now we can assign new offsets. */
615 offset = 0;
616 last_cie_ndx = 0;
617 for (i = 0; i < sec_info->count; i++)
618 {
619 if (! sec_info->entry[i].removed)
620 {
621 sec_info->entry[i].new_offset = offset;
622 offset += sec_info->entry[i].size;
623 if (sec_info->entry[i].cie)
624 {
625 last_cie_ndx = i;
626 make_relative = sec_info->entry[i].make_relative;
627 }
628 else
629 sec_info->entry[i].make_relative = make_relative;
630 }
631 else if (sec_info->entry[i].cie && sec_info->entry[i].sec == sec)
632 {
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;
638 }
639 }
640 if (hdr_info->last_cie_sec == sec)
641 {
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;
645 }
646
647 /* Shrink the sec as needed. */
648
649 sec->_cooked_size = new_size;
650 if (sec->_cooked_size == 0)
651 sec->flags |= SEC_EXCLUDE;
652
653 return new_size != sec->_raw_size;
654
655 free_no_table:
656 if (sec_info)
657 free (sec_info);
658 hdr_info->table = false;
659 hdr_info->last_cie.hdr.length = 0;
660 return false;
661 }
662
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. */
666
667 boolean
668 _bfd_elf_discard_section_eh_frame_hdr (abfd, info, sec)
669 bfd *abfd;
670 struct bfd_link_info *info;
671 asection *sec;
672 {
673 struct eh_frame_hdr_info *hdr_info;
674 unsigned int ptr_size;
675
676 ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
677 == ELFCLASS64) ? 8 : 4;
678
679 if ((elf_section_data (sec)->sec_info_type
680 != ELF_INFO_TYPE_EH_FRAME_HDR)
681 || ! info->eh_frame_hdr)
682 {
683 _bfd_strip_section_from_output (info, sec);
684 return false;
685 }
686
687 hdr_info = (struct eh_frame_hdr_info *)
688 elf_section_data (sec)->sec_info;
689 sec->_cooked_size = EH_FRAME_HDR_SIZE;
690 if (hdr_info->table)
691 sec->_cooked_size += 4 + hdr_info->fde_count * 8;
692
693 /* Request program headers to be recalculated. */
694 elf_tdata (abfd)->program_header_size = 0;
695 elf_tdata (abfd)->eh_frame_hdr = true;
696 return true;
697 }
698
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. */
703
704 bfd_vma
705 _bfd_elf_eh_frame_section_offset (output_bfd, sec, offset)
706 bfd *output_bfd ATTRIBUTE_UNUSED;
707 asection *sec;
708 bfd_vma offset;
709 {
710 struct eh_frame_sec_info *sec_info;
711 unsigned int lo, hi, mid;
712
713 if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
714 return offset;
715 sec_info = (struct eh_frame_sec_info *)
716 elf_section_data (sec)->sec_info;
717
718 if (offset >= sec->_raw_size)
719 return offset - (sec->_cooked_size - sec->_raw_size);
720
721 lo = 0;
722 hi = sec_info->count;
723 mid = 0;
724 while (lo < hi)
725 {
726 mid = (lo + hi) / 2;
727 if (offset < sec_info->entry[mid].offset)
728 hi = mid;
729 else if (offset
730 >= sec_info->entry[mid].offset + sec_info->entry[mid].size)
731 lo = mid + 1;
732 else
733 break;
734 }
735
736 BFD_ASSERT (lo < hi);
737
738 /* FDE or CIE was removed. */
739 if (sec_info->entry[mid].removed)
740 return (bfd_vma) -1;
741
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)
747 return (bfd_vma) -1;
748
749 return (offset
750 + (sec_info->entry[mid].new_offset - sec_info->entry[mid].offset));
751 }
752
753 /* Write out .eh_frame section. This is called with the relocated
754 contents. */
755
756 boolean
757 _bfd_elf_write_section_eh_frame (abfd, sec, ehdrsec, contents)
758 bfd *abfd;
759 asection *sec, *ehdrsec;
760 bfd_byte *contents;
761 {
762 struct eh_frame_sec_info *sec_info;
763 struct eh_frame_hdr_info *hdr_info;
764 unsigned int i;
765 bfd_byte *p, *buf;
766 unsigned int leb128_tmp;
767 unsigned int cie_offset = 0;
768 unsigned int ptr_size;
769
770 ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
771 == ELFCLASS64) ? 8 : 4;
772
773 if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
774 return bfd_set_section_contents (abfd, sec->output_section,
775 contents,
776 (file_ptr) sec->output_offset,
777 sec->_raw_size);
778 sec_info = (struct eh_frame_sec_info *)
779 elf_section_data (sec)->sec_info;
780 hdr_info = NULL;
781 if (ehdrsec
782 && (elf_section_data (ehdrsec)->sec_info_type
783 == ELF_INFO_TYPE_EH_FRAME_HDR))
784 {
785 hdr_info = (struct eh_frame_hdr_info *)
786 elf_section_data (ehdrsec)->sec_info;
787 if (hdr_info->table && hdr_info->array == NULL)
788 hdr_info->array
789 = bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
790 if (hdr_info->array == NULL)
791 hdr_info = NULL;
792 }
793
794 p = contents;
795 for (i = 0; i < sec_info->count; ++i)
796 {
797 if (sec_info->entry[i].removed)
798 {
799 if (sec_info->entry[i].cie)
800 {
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);
806 }
807 continue;
808 }
809 if (sec_info->entry[i].cie)
810 {
811 /* CIE */
812 cie_offset = sec_info->entry[i].new_offset;
813 if (sec_info->entry[i].make_relative)
814 {
815 unsigned char *aug;
816 unsigned int dummy, per_width, per_encoding;
817
818 /* Need to find 'R' augmentation's argument and modify
819 DW_EH_PE_* value. */
820 buf = contents + sec_info->entry[i].offset;
821 /* Skip length, id and version. */
822 buf += 9;
823 aug = buf;
824 buf = strchr (buf, '\0') + 1;
825 read_uleb128 (dummy, buf);
826 read_sleb128 (dummy, buf);
827 read_uleb128 (dummy, buf);
828 if (*aug == 'z')
829 {
830 read_uleb128 (dummy, buf);
831 aug++;
832 }
833
834 while (*aug != 'R')
835 switch (*aug++)
836 {
837 case 'L':
838 buf++;
839 break;
840 case 'P':
841 per_encoding = *buf++;
842 per_width = get_DW_EH_PE_width (per_encoding,
843 ptr_size);
844 BFD_ASSERT (per_width != 0);
845 if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
846 buf = (contents
847 + ((buf - contents + per_width - 1)
848 & ~((bfd_size_type) per_width - 1)));
849 buf += per_width;
850 break;
851 default:
852 BFD_FAIL ();
853 }
854
855 BFD_ASSERT (*buf == sec_info->entry[i].fde_encoding);
856 *buf |= DW_EH_PE_pcrel;
857 }
858 }
859 else
860 {
861 /* FDE */
862 bfd_vma value = 0, address;
863 unsigned int fde_width;
864
865 buf = contents + sec_info->entry[i].offset;
866 /* Skip length. */
867 buf += 4;
868 bfd_put_32 (abfd,
869 sec_info->entry[i].new_offset + 4 - cie_offset, buf);
870 buf += 4;
871 fde_width = get_DW_EH_PE_width (sec_info->entry[i].fde_encoding,
872 ptr_size);
873 switch (fde_width)
874 {
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 ();
879 }
880 address = value;
881 switch (sec_info->entry[i].fde_encoding & 0xf0)
882 {
883 case DW_EH_PE_indirect:
884 case DW_EH_PE_textrel:
885 BFD_ASSERT (hdr_info == NULL);
886 break;
887 case DW_EH_PE_datarel:
888 {
889 asection *got = bfd_get_section_by_name (abfd, ".got");
890
891 BFD_ASSERT (got != NULL);
892 address += got->vma;
893 }
894 break;
895 case DW_EH_PE_pcrel:
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);
900 break;
901 }
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);
905 switch (fde_width)
906 {
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;
910 }
911
912 if (hdr_info)
913 {
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);
918 }
919 }
920
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;
925 }
926
927 BFD_ASSERT ((bfd_size_type) (p - contents) == sec->_cooked_size);
928
929 return bfd_set_section_contents (abfd, sec->output_section,
930 contents, (file_ptr) sec->output_offset,
931 sec->_cooked_size);
932 }
933
934 /* Helper function used to sort .eh_frame_hdr search table by increasing
935 VMA of FDE initial location. */
936
937 static int
938 vma_compare (a, b)
939 const PTR a;
940 const PTR b;
941 {
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)
945 return 1;
946 if (p->initial_loc < q->initial_loc)
947 return -1;
948 return 0;
949 }
950
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
953 .eh_frame sections.
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
957 .eh_frame section)
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) */
972
973 boolean
974 _bfd_elf_write_section_eh_frame_hdr (abfd, sec)
975 bfd *abfd;
976 asection *sec;
977 {
978 struct eh_frame_hdr_info *hdr_info;
979 unsigned int ptr_size;
980 bfd_byte *contents;
981 asection *eh_frame_sec;
982 bfd_size_type size;
983
984 ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
985 == ELFCLASS64) ? 8 : 4;
986
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)
996 return false;
997
998 eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
999 if (eh_frame_sec == NULL)
1000 return false;
1001
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)
1006 {
1007 contents[2] = DW_EH_PE_udata4; /* FDE count encoding */
1008 contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* search table enc */
1009 }
1010 else
1011 {
1012 contents[2] = DW_EH_PE_omit;
1013 contents[3] = DW_EH_PE_omit;
1014 }
1015 bfd_put_32 (abfd, eh_frame_sec->vma - sec->output_section->vma - 4,
1016 contents + 4);
1017 if (contents[2] != DW_EH_PE_omit)
1018 {
1019 unsigned int i;
1020
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),
1023 vma_compare);
1024 for (i = 0; i < hdr_info->fde_count; i++)
1025 {
1026 bfd_put_32 (abfd,
1027 hdr_info->array[i].initial_loc
1028 - sec->output_section->vma,
1029 contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
1030 bfd_put_32 (abfd,
1031 hdr_info->array[i].fde - sec->output_section->vma,
1032 contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
1033 }
1034 }
1035
1036 return bfd_set_section_contents (abfd, sec->output_section,
1037 contents, (file_ptr) sec->output_offset,
1038 sec->_cooked_size);
1039 }
This page took 0.059714 seconds and 5 git commands to generate.