00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "bfd.h"
00026 #include "sysdep.h"
00027 #include "libbfd.h"
00028 #include "elf-bfd.h"
00029 #include "elf/dwarf2.h"
00030
00031 #define EH_FRAME_HDR_SIZE 8
00032
00033
00034
00035
00036 static inline bfd_boolean
00037 read_byte (bfd_byte **iter, bfd_byte *end, unsigned char *result)
00038 {
00039 if (*iter >= end)
00040 return FALSE;
00041 *result = *((*iter)++);
00042 return TRUE;
00043 }
00044
00045
00046
00047
00048 static inline bfd_boolean
00049 skip_bytes (bfd_byte **iter, bfd_byte *end, bfd_size_type length)
00050 {
00051 if ((bfd_size_type) (end - *iter) < length)
00052 {
00053 *iter = end;
00054 return FALSE;
00055 }
00056 *iter += length;
00057 return TRUE;
00058 }
00059
00060
00061
00062
00063 static bfd_boolean
00064 skip_leb128 (bfd_byte **iter, bfd_byte *end)
00065 {
00066 unsigned char byte;
00067 do
00068 if (!read_byte (iter, end, &byte))
00069 return FALSE;
00070 while (byte & 0x80);
00071 return TRUE;
00072 }
00073
00074
00075
00076
00077 static bfd_boolean
00078 read_uleb128 (bfd_byte **iter, bfd_byte *end, bfd_vma *value)
00079 {
00080 bfd_byte *start, *p;
00081
00082 start = *iter;
00083 if (!skip_leb128 (iter, end))
00084 return FALSE;
00085
00086 p = *iter;
00087 *value = *--p;
00088 while (p > start)
00089 *value = (*value << 7) | (*--p & 0x7f);
00090
00091 return TRUE;
00092 }
00093
00094
00095
00096 static bfd_boolean
00097 read_sleb128 (bfd_byte **iter, bfd_byte *end, bfd_signed_vma *value)
00098 {
00099 bfd_byte *start, *p;
00100
00101 start = *iter;
00102 if (!skip_leb128 (iter, end))
00103 return FALSE;
00104
00105 p = *iter;
00106 *value = ((*--p & 0x7f) ^ 0x40) - 0x40;
00107 while (p > start)
00108 *value = (*value << 7) | (*--p & 0x7f);
00109
00110 return TRUE;
00111 }
00112
00113
00114
00115 static
00116 int get_DW_EH_PE_width (int encoding, int ptr_size)
00117 {
00118
00119
00120 if ((encoding & 0x60) == 0x60)
00121 return 0;
00122
00123 switch (encoding & 7)
00124 {
00125 case DW_EH_PE_udata2: return 2;
00126 case DW_EH_PE_udata4: return 4;
00127 case DW_EH_PE_udata8: return 8;
00128 case DW_EH_PE_absptr: return ptr_size;
00129 default:
00130 break;
00131 }
00132
00133 return 0;
00134 }
00135
00136 #define get_DW_EH_PE_signed(encoding) (((encoding) & DW_EH_PE_signed) != 0)
00137
00138
00139
00140 static bfd_vma
00141 read_value (bfd *abfd, bfd_byte *buf, int width, int is_signed)
00142 {
00143 bfd_vma value;
00144
00145 switch (width)
00146 {
00147 case 2:
00148 if (is_signed)
00149 value = bfd_get_signed_16 (abfd, buf);
00150 else
00151 value = bfd_get_16 (abfd, buf);
00152 break;
00153 case 4:
00154 if (is_signed)
00155 value = bfd_get_signed_32 (abfd, buf);
00156 else
00157 value = bfd_get_32 (abfd, buf);
00158 break;
00159 case 8:
00160 if (is_signed)
00161 value = bfd_get_signed_64 (abfd, buf);
00162 else
00163 value = bfd_get_64 (abfd, buf);
00164 break;
00165 default:
00166 BFD_FAIL ();
00167 return 0;
00168 }
00169
00170 return value;
00171 }
00172
00173
00174
00175 static void
00176 write_value (bfd *abfd, bfd_byte *buf, bfd_vma value, int width)
00177 {
00178 switch (width)
00179 {
00180 case 2: bfd_put_16 (abfd, value, buf); break;
00181 case 4: bfd_put_32 (abfd, value, buf); break;
00182 case 8: bfd_put_64 (abfd, value, buf); break;
00183 default: BFD_FAIL ();
00184 }
00185 }
00186
00187
00188
00189 static
00190 int cie_compare (struct cie *c1, struct cie *c2)
00191 {
00192 if (c1->hdr.length == c2->hdr.length
00193 && c1->version == c2->version
00194 && strcmp (c1->augmentation, c2->augmentation) == 0
00195 && strcmp (c1->augmentation, "eh") != 0
00196 && c1->code_align == c2->code_align
00197 && c1->data_align == c2->data_align
00198 && c1->ra_column == c2->ra_column
00199 && c1->augmentation_size == c2->augmentation_size
00200 && c1->personality == c2->personality
00201 && c1->per_encoding == c2->per_encoding
00202 && c1->lsda_encoding == c2->lsda_encoding
00203 && c1->fde_encoding == c2->fde_encoding
00204 && c1->initial_insn_length == c2->initial_insn_length
00205 && memcmp (c1->initial_instructions,
00206 c2->initial_instructions,
00207 c1->initial_insn_length) == 0)
00208 return 0;
00209
00210 return 1;
00211 }
00212
00213
00214
00215
00216 static INLINE unsigned int
00217 extra_augmentation_string_bytes (struct eh_cie_fde *entry)
00218 {
00219 unsigned int size = 0;
00220 if (entry->cie)
00221 {
00222 if (entry->add_augmentation_size)
00223 size++;
00224 if (entry->add_fde_encoding)
00225 size++;
00226 }
00227 return size;
00228 }
00229
00230
00231
00232 static INLINE unsigned int
00233 extra_augmentation_data_bytes (struct eh_cie_fde *entry)
00234 {
00235 unsigned int size = 0;
00236 if (entry->cie)
00237 {
00238 if (entry->add_augmentation_size)
00239 size++;
00240 if (entry->add_fde_encoding)
00241 size++;
00242 }
00243 else
00244 {
00245 if (entry->cie_inf->add_augmentation_size)
00246 size++;
00247 }
00248 return size;
00249 }
00250
00251
00252
00253
00254 static unsigned int
00255 size_of_output_cie_fde (struct eh_cie_fde *entry, unsigned int alignment)
00256 {
00257 if (entry->removed)
00258 return 0;
00259 if (entry->size == 4)
00260 return 4;
00261 return (entry->size
00262 + extra_augmentation_string_bytes (entry)
00263 + extra_augmentation_data_bytes (entry)
00264 + alignment - 1) & -alignment;
00265 }
00266
00267
00268
00269
00270
00271 static bfd_boolean
00272 skip_cfa_op (bfd_byte **iter, bfd_byte *end, unsigned int encoded_ptr_width)
00273 {
00274 bfd_byte op;
00275 bfd_vma length;
00276
00277 if (!read_byte (iter, end, &op))
00278 return FALSE;
00279
00280 switch (op & 0x80 ? op & 0xc0 : op)
00281 {
00282 case DW_CFA_nop:
00283 case DW_CFA_advance_loc:
00284 case DW_CFA_restore:
00285
00286 return TRUE;
00287
00288 case DW_CFA_offset:
00289 case DW_CFA_restore_extended:
00290 case DW_CFA_undefined:
00291 case DW_CFA_same_value:
00292 case DW_CFA_def_cfa_register:
00293 case DW_CFA_def_cfa_offset:
00294 case DW_CFA_def_cfa_offset_sf:
00295 case DW_CFA_GNU_args_size:
00296
00297 return skip_leb128 (iter, end);
00298
00299 case DW_CFA_offset_extended:
00300 case DW_CFA_register:
00301 case DW_CFA_def_cfa:
00302 case DW_CFA_offset_extended_sf:
00303 case DW_CFA_GNU_negative_offset_extended:
00304 case DW_CFA_def_cfa_sf:
00305
00306 return (skip_leb128 (iter, end)
00307 && skip_leb128 (iter, end));
00308
00309 case DW_CFA_def_cfa_expression:
00310
00311 return (read_uleb128 (iter, end, &length)
00312 && skip_bytes (iter, end, length));
00313
00314 case DW_CFA_expression:
00315
00316 return (skip_leb128 (iter, end)
00317 && read_uleb128 (iter, end, &length)
00318 && skip_bytes (iter, end, length));
00319
00320 case DW_CFA_set_loc:
00321 return skip_bytes (iter, end, encoded_ptr_width);
00322
00323 case DW_CFA_advance_loc1:
00324 return skip_bytes (iter, end, 1);
00325
00326 case DW_CFA_advance_loc2:
00327 return skip_bytes (iter, end, 2);
00328
00329 case DW_CFA_advance_loc4:
00330 return skip_bytes (iter, end, 4);
00331
00332 case DW_CFA_MIPS_advance_loc8:
00333 return skip_bytes (iter, end, 8);
00334
00335 default:
00336 return FALSE;
00337 }
00338 }
00339
00340
00341
00342
00343
00344
00345 static bfd_byte *
00346 skip_non_nops (bfd_byte *buf, bfd_byte *end, unsigned int encoded_ptr_width)
00347 {
00348 bfd_byte *last;
00349
00350 last = buf;
00351 while (buf < end)
00352 if (*buf == DW_CFA_nop)
00353 buf++;
00354 else
00355 {
00356 if (!skip_cfa_op (&buf, end, encoded_ptr_width))
00357 return 0;
00358 last = buf;
00359 }
00360 return last;
00361 }
00362
00363
00364
00365
00366
00367
00368 bfd_boolean
00369 _bfd_elf_discard_section_eh_frame
00370 (bfd *abfd, struct bfd_link_info *info, asection *sec,
00371 bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
00372 struct elf_reloc_cookie *cookie)
00373 {
00374 #define REQUIRE(COND) \
00375 do \
00376 if (!(COND)) \
00377 goto free_no_table; \
00378 while (0)
00379
00380 bfd_byte *ehbuf = NULL, *buf;
00381 bfd_byte *last_cie, *last_fde;
00382 struct eh_cie_fde *ent, *last_cie_inf, *this_inf;
00383 struct cie_header hdr;
00384 struct cie cie;
00385 struct elf_link_hash_table *htab;
00386 struct eh_frame_hdr_info *hdr_info;
00387 struct eh_frame_sec_info *sec_info = NULL;
00388 unsigned int cie_usage_count, offset;
00389 unsigned int ptr_size;
00390
00391 if (sec->size == 0)
00392 {
00393
00394 return FALSE;
00395 }
00396
00397 if ((sec->output_section != NULL
00398 && bfd_is_abs_section (sec->output_section)))
00399 {
00400
00401
00402 return FALSE;
00403 }
00404
00405 htab = elf_hash_table (info);
00406 hdr_info = &htab->eh_info;
00407
00408
00409
00410 REQUIRE (bfd_malloc_and_get_section (abfd, sec, &ehbuf));
00411
00412 if (sec->size >= 4
00413 && bfd_get_32 (abfd, ehbuf) == 0
00414 && cookie->rel == cookie->relend)
00415 {
00416
00417 free (ehbuf);
00418 return FALSE;
00419 }
00420
00421
00422
00423 REQUIRE (sec->size == (unsigned int) sec->size);
00424
00425 ptr_size = (get_elf_backend_data (abfd)
00426 ->elf_backend_eh_frame_address_size (abfd, sec));
00427 REQUIRE (ptr_size != 0);
00428
00429 buf = ehbuf;
00430 last_cie = NULL;
00431 last_cie_inf = NULL;
00432 memset (&cie, 0, sizeof (cie));
00433 cie_usage_count = 0;
00434 sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)
00435 + 99 * sizeof (struct eh_cie_fde));
00436 REQUIRE (sec_info);
00437
00438 sec_info->alloced = 100;
00439
00440 #define ENSURE_NO_RELOCS(buf) \
00441 REQUIRE (!(cookie->rel < cookie->relend \
00442 && (cookie->rel->r_offset \
00443 < (bfd_size_type) ((buf) - ehbuf)) \
00444 && cookie->rel->r_info != 0))
00445
00446 #define SKIP_RELOCS(buf) \
00447 while (cookie->rel < cookie->relend \
00448 && (cookie->rel->r_offset \
00449 < (bfd_size_type) ((buf) - ehbuf))) \
00450 cookie->rel++
00451
00452 #define GET_RELOC(buf) \
00453 ((cookie->rel < cookie->relend \
00454 && (cookie->rel->r_offset \
00455 == (bfd_size_type) ((buf) - ehbuf))) \
00456 ? cookie->rel : NULL)
00457
00458 for (;;)
00459 {
00460 char *aug;
00461 bfd_byte *start, *end, *insns;
00462 bfd_size_type length;
00463
00464 if (sec_info->count == sec_info->alloced)
00465 {
00466 struct eh_cie_fde *old_entry = sec_info->entry;
00467 sec_info = bfd_realloc (sec_info,
00468 sizeof (struct eh_frame_sec_info)
00469 + ((sec_info->alloced + 99)
00470 * sizeof (struct eh_cie_fde)));
00471 REQUIRE (sec_info);
00472
00473 memset (&sec_info->entry[sec_info->alloced], 0,
00474 100 * sizeof (struct eh_cie_fde));
00475 sec_info->alloced += 100;
00476
00477
00478 if (last_cie_inf >= old_entry
00479 && last_cie_inf < old_entry + sec_info->count)
00480 last_cie_inf = sec_info->entry + (last_cie_inf - old_entry);
00481 }
00482
00483 this_inf = sec_info->entry + sec_info->count;
00484 last_fde = buf;
00485
00486
00487 if ((bfd_size_type) (buf - ehbuf) == sec->size)
00488 {
00489 hdr.length = 0;
00490 hdr.id = (unsigned int) -1;
00491 end = buf;
00492 }
00493 else
00494 {
00495
00496 REQUIRE (skip_bytes (&buf, ehbuf + sec->size, 4));
00497 hdr.length = bfd_get_32 (abfd, buf - 4);
00498
00499
00500 REQUIRE (hdr.length != 0xffffffff);
00501
00502
00503 REQUIRE ((bfd_size_type) (buf - ehbuf) + hdr.length <= sec->size);
00504 end = buf + hdr.length;
00505
00506 this_inf->offset = last_fde - ehbuf;
00507 this_inf->size = 4 + hdr.length;
00508
00509 if (hdr.length == 0)
00510 {
00511
00512
00513 REQUIRE ((bfd_size_type) (buf - ehbuf) == sec->size);
00514 ENSURE_NO_RELOCS (buf);
00515 sec_info->count++;
00516
00517
00518 hdr.id = (unsigned int) -1;
00519 }
00520 else
00521 {
00522 REQUIRE (skip_bytes (&buf, end, 4));
00523 hdr.id = bfd_get_32 (abfd, buf - 4);
00524 REQUIRE (hdr.id != (unsigned int) -1);
00525 }
00526 }
00527
00528 if (hdr.id == 0 || hdr.id == (unsigned int) -1)
00529 {
00530 unsigned int initial_insn_length;
00531
00532
00533 if (last_cie != NULL)
00534 {
00535
00536
00537
00538
00539 if ((!info->relocatable
00540 && hdr_info->last_cie_sec
00541 && (sec->output_section
00542 == hdr_info->last_cie_sec->output_section)
00543 && cie_compare (&cie, &hdr_info->last_cie) == 0)
00544 || cie_usage_count == 0)
00545 last_cie_inf->removed = 1;
00546 else
00547 {
00548 hdr_info->last_cie = cie;
00549 hdr_info->last_cie_sec = sec;
00550 last_cie_inf->make_relative = cie.make_relative;
00551 last_cie_inf->make_lsda_relative = cie.make_lsda_relative;
00552 last_cie_inf->per_encoding_relative
00553 = (cie.per_encoding & 0x70) == DW_EH_PE_pcrel;
00554 }
00555 }
00556
00557 if (hdr.id == (unsigned int) -1)
00558 break;
00559
00560 last_cie_inf = this_inf;
00561 this_inf->cie = 1;
00562
00563 cie_usage_count = 0;
00564 memset (&cie, 0, sizeof (cie));
00565 cie.hdr = hdr;
00566 REQUIRE (read_byte (&buf, end, &cie.version));
00567
00568
00569 REQUIRE (cie.version == 1 || cie.version == 3);
00570 REQUIRE (strlen ((char *) buf) < sizeof (cie.augmentation));
00571
00572 strcpy (cie.augmentation, (char *) buf);
00573 buf = (bfd_byte *) strchr ((char *) buf, '\0') + 1;
00574 ENSURE_NO_RELOCS (buf);
00575 if (buf[0] == 'e' && buf[1] == 'h')
00576 {
00577
00578
00579
00580
00581 REQUIRE (skip_bytes (&buf, end, ptr_size));
00582 SKIP_RELOCS (buf);
00583 }
00584 REQUIRE (read_uleb128 (&buf, end, &cie.code_align));
00585 REQUIRE (read_sleb128 (&buf, end, &cie.data_align));
00586 if (cie.version == 1)
00587 {
00588 REQUIRE (buf < end);
00589 cie.ra_column = *buf++;
00590 }
00591 else
00592 REQUIRE (read_uleb128 (&buf, end, &cie.ra_column));
00593 ENSURE_NO_RELOCS (buf);
00594 cie.lsda_encoding = DW_EH_PE_omit;
00595 cie.fde_encoding = DW_EH_PE_omit;
00596 cie.per_encoding = DW_EH_PE_omit;
00597 aug = cie.augmentation;
00598 if (aug[0] != 'e' || aug[1] != 'h')
00599 {
00600 if (*aug == 'z')
00601 {
00602 aug++;
00603 REQUIRE (read_uleb128 (&buf, end, &cie.augmentation_size));
00604 ENSURE_NO_RELOCS (buf);
00605 }
00606
00607 while (*aug != '\0')
00608 switch (*aug++)
00609 {
00610 case 'L':
00611 REQUIRE (read_byte (&buf, end, &cie.lsda_encoding));
00612 ENSURE_NO_RELOCS (buf);
00613 REQUIRE (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size));
00614 break;
00615 case 'R':
00616 REQUIRE (read_byte (&buf, end, &cie.fde_encoding));
00617 ENSURE_NO_RELOCS (buf);
00618 REQUIRE (get_DW_EH_PE_width (cie.fde_encoding, ptr_size));
00619 break;
00620 case 'P':
00621 {
00622 int per_width;
00623
00624 REQUIRE (read_byte (&buf, end, &cie.per_encoding));
00625 per_width = get_DW_EH_PE_width (cie.per_encoding,
00626 ptr_size);
00627 REQUIRE (per_width);
00628 if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
00629 {
00630 length = -(buf - ehbuf) & (per_width - 1);
00631 REQUIRE (skip_bytes (&buf, end, length));
00632 }
00633 ENSURE_NO_RELOCS (buf);
00634
00635
00636 if (GET_RELOC (buf) != NULL)
00637 {
00638 unsigned long r_symndx;
00639
00640 #ifdef BFD64
00641 if (ptr_size == 8)
00642 r_symndx = ELF64_R_SYM (cookie->rel->r_info);
00643 else
00644 #endif
00645 r_symndx = ELF32_R_SYM (cookie->rel->r_info);
00646 if (r_symndx >= cookie->locsymcount)
00647 {
00648 struct elf_link_hash_entry *h;
00649
00650 r_symndx -= cookie->extsymoff;
00651 h = cookie->sym_hashes[r_symndx];
00652
00653 while (h->root.type == bfd_link_hash_indirect
00654 || h->root.type == bfd_link_hash_warning)
00655 h = (struct elf_link_hash_entry *)
00656 h->root.u.i.link;
00657
00658 cie.personality = h;
00659 }
00660
00661 do
00662 cookie->rel++;
00663 while (GET_RELOC (buf) != NULL);
00664 }
00665 REQUIRE (skip_bytes (&buf, end, per_width));
00666 }
00667 break;
00668 default:
00669
00670 goto free_no_table;
00671 }
00672 }
00673
00674
00675
00676 if (info->shared
00677 && (get_elf_backend_data (abfd)
00678 ->elf_backend_can_make_relative_eh_frame
00679 (abfd, info, sec)))
00680 {
00681 if ((cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
00682 cie.make_relative = 1;
00683
00684
00685
00686 else if (cie.fde_encoding == DW_EH_PE_omit
00687 && (cie.per_encoding & 0xf0) != DW_EH_PE_aligned)
00688 {
00689 if (*cie.augmentation == 0)
00690 this_inf->add_augmentation_size = 1;
00691 this_inf->add_fde_encoding = 1;
00692 cie.make_relative = 1;
00693 }
00694 }
00695
00696 if (info->shared
00697 && (get_elf_backend_data (abfd)
00698 ->elf_backend_can_make_lsda_relative_eh_frame
00699 (abfd, info, sec))
00700 && (cie.lsda_encoding & 0xf0) == DW_EH_PE_absptr)
00701 cie.make_lsda_relative = 1;
00702
00703
00704
00705 if (cie.fde_encoding == DW_EH_PE_omit)
00706 cie.fde_encoding = DW_EH_PE_absptr;
00707
00708 initial_insn_length = end - buf;
00709 if (initial_insn_length <= 50)
00710 {
00711 cie.initial_insn_length = initial_insn_length;
00712 memcpy (cie.initial_instructions, buf, initial_insn_length);
00713 }
00714 insns = buf;
00715 buf += initial_insn_length;
00716 ENSURE_NO_RELOCS (buf);
00717 last_cie = last_fde;
00718 }
00719 else
00720 {
00721
00722 REQUIRE (last_cie);
00723 REQUIRE (hdr.id == (unsigned int) (buf - 4 - last_cie));
00724
00725 ENSURE_NO_RELOCS (buf);
00726 REQUIRE (GET_RELOC (buf));
00727
00728 if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
00729
00730
00731 this_inf->removed = 1;
00732 else
00733 {
00734 if (info->shared
00735 && (((cie.fde_encoding & 0xf0) == DW_EH_PE_absptr
00736 && cie.make_relative == 0)
00737 || (cie.fde_encoding & 0xf0) == DW_EH_PE_aligned))
00738 {
00739
00740
00741
00742
00743 hdr_info->table = FALSE;
00744 }
00745 cie_usage_count++;
00746 hdr_info->fde_count++;
00747 }
00748
00749 start = buf;
00750 length = get_DW_EH_PE_width (cie.fde_encoding, ptr_size);
00751 REQUIRE (skip_bytes (&buf, end, 2 * length));
00752
00753
00754 if (cie.augmentation[0] == 'z')
00755 REQUIRE (read_uleb128 (&buf, end, &length));
00756 else
00757 length = 0;
00758
00759
00760
00761
00762 if (cie.lsda_encoding != DW_EH_PE_omit)
00763 {
00764 this_inf->lsda_offset = buf - start;
00765
00766
00767 if (cie.augmentation[0] != 'z')
00768 length = end - buf;
00769 }
00770
00771
00772 REQUIRE (skip_bytes (&buf, end, length));
00773 insns = buf;
00774
00775 buf = last_fde + 4 + hdr.length;
00776 SKIP_RELOCS (buf);
00777 }
00778
00779
00780
00781
00782 length = get_DW_EH_PE_width (cie.fde_encoding, ptr_size);
00783 insns = skip_non_nops (insns, end, length);
00784 if (insns != 0)
00785 this_inf->size -= end - insns;
00786
00787 this_inf->fde_encoding = cie.fde_encoding;
00788 this_inf->lsda_encoding = cie.lsda_encoding;
00789 sec_info->count++;
00790 }
00791
00792 elf_section_data (sec)->sec_info = sec_info;
00793 sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
00794
00795
00796 offset = 0;
00797 last_cie_inf = hdr_info->last_cie_inf;
00798 for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
00799 if (!ent->removed)
00800 {
00801 if (ent->cie)
00802 last_cie_inf = ent;
00803 else
00804 ent->cie_inf = last_cie_inf;
00805 ent->new_offset = offset;
00806 offset += size_of_output_cie_fde (ent, ptr_size);
00807 }
00808 hdr_info->last_cie_inf = last_cie_inf;
00809
00810
00811 sec->rawsize = sec->size;
00812 sec->size = offset;
00813 if (sec->size == 0)
00814 sec->flags |= SEC_EXCLUDE;
00815
00816 free (ehbuf);
00817 return offset != sec->rawsize;
00818
00819 free_no_table:
00820 if (ehbuf)
00821 free (ehbuf);
00822 if (sec_info)
00823 free (sec_info);
00824 hdr_info->table = FALSE;
00825 hdr_info->last_cie.hdr.length = 0;
00826 return FALSE;
00827
00828 #undef REQUIRE
00829 }
00830
00831
00832
00833
00834
00835 bfd_boolean
00836 _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
00837 {
00838 struct elf_link_hash_table *htab;
00839 struct eh_frame_hdr_info *hdr_info;
00840 asection *sec;
00841
00842 htab = elf_hash_table (info);
00843 hdr_info = &htab->eh_info;
00844 sec = hdr_info->hdr_sec;
00845 if (sec == NULL)
00846 return FALSE;
00847
00848 sec->size = EH_FRAME_HDR_SIZE;
00849 if (hdr_info->table)
00850 sec->size += 4 + hdr_info->fde_count * 8;
00851
00852
00853 elf_tdata (abfd)->program_header_size = 0;
00854 elf_tdata (abfd)->eh_frame_hdr = sec;
00855 return TRUE;
00856 }
00857
00858
00859
00860
00861
00862
00863 bfd_boolean
00864 _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info)
00865 {
00866 asection *o;
00867 bfd *abfd;
00868 struct elf_link_hash_table *htab;
00869 struct eh_frame_hdr_info *hdr_info;
00870
00871 htab = elf_hash_table (info);
00872 hdr_info = &htab->eh_info;
00873 if (hdr_info->hdr_sec == NULL)
00874 return TRUE;
00875
00876 if (bfd_is_abs_section (hdr_info->hdr_sec->output_section))
00877 {
00878 hdr_info->hdr_sec = NULL;
00879 return TRUE;
00880 }
00881
00882 abfd = NULL;
00883 if (info->eh_frame_hdr)
00884 for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
00885 {
00886
00887
00888 o = bfd_get_section_by_name (abfd, ".eh_frame");
00889 if (o && o->size > 8 && !bfd_is_abs_section (o->output_section))
00890 break;
00891 }
00892
00893 if (abfd == NULL)
00894 {
00895 _bfd_strip_section_from_output (info, hdr_info->hdr_sec);
00896 hdr_info->hdr_sec = NULL;
00897 return TRUE;
00898 }
00899
00900 hdr_info->table = TRUE;
00901 return TRUE;
00902 }
00903
00904
00905
00906
00907
00908
00909 bfd_vma
00910 _bfd_elf_eh_frame_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
00911 struct bfd_link_info *info,
00912 asection *sec,
00913 bfd_vma offset)
00914 {
00915 struct eh_frame_sec_info *sec_info;
00916 struct elf_link_hash_table *htab;
00917 struct eh_frame_hdr_info *hdr_info;
00918 unsigned int lo, hi, mid;
00919
00920 if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
00921 return offset;
00922 sec_info = elf_section_data (sec)->sec_info;
00923
00924 if (offset >= sec->rawsize)
00925 return offset - sec->rawsize + sec->size;
00926
00927 htab = elf_hash_table (info);
00928 hdr_info = &htab->eh_info;
00929 if (hdr_info->offsets_adjusted)
00930 offset += sec->output_offset;
00931
00932 lo = 0;
00933 hi = sec_info->count;
00934 mid = 0;
00935 while (lo < hi)
00936 {
00937 mid = (lo + hi) / 2;
00938 if (offset < sec_info->entry[mid].offset)
00939 hi = mid;
00940 else if (offset
00941 >= sec_info->entry[mid].offset + sec_info->entry[mid].size)
00942 lo = mid + 1;
00943 else
00944 break;
00945 }
00946
00947 BFD_ASSERT (lo < hi);
00948
00949
00950 if (sec_info->entry[mid].removed)
00951 return (bfd_vma) -1;
00952
00953
00954
00955 if (!sec_info->entry[mid].cie
00956 && sec_info->entry[mid].cie_inf->make_relative
00957 && offset == sec_info->entry[mid].offset + 8)
00958 return (bfd_vma) -2;
00959
00960
00961
00962 if (!sec_info->entry[mid].cie
00963 && sec_info->entry[mid].cie_inf->make_lsda_relative
00964 && (offset == (sec_info->entry[mid].offset + 8
00965 + sec_info->entry[mid].lsda_offset))
00966 && (sec_info->entry[mid].cie_inf->need_lsda_relative
00967 || !hdr_info->offsets_adjusted))
00968 {
00969 sec_info->entry[mid].cie_inf->need_lsda_relative = 1;
00970 return (bfd_vma) -2;
00971 }
00972
00973 if (hdr_info->offsets_adjusted)
00974 offset -= sec->output_offset;
00975
00976 return (offset + sec_info->entry[mid].new_offset
00977 - sec_info->entry[mid].offset
00978 + extra_augmentation_string_bytes (sec_info->entry + mid)
00979 + extra_augmentation_data_bytes (sec_info->entry + mid));
00980 }
00981
00982
00983
00984
00985 bfd_boolean
00986 _bfd_elf_write_section_eh_frame (bfd *abfd,
00987 struct bfd_link_info *info,
00988 asection *sec,
00989 bfd_byte *contents)
00990 {
00991 struct eh_frame_sec_info *sec_info;
00992 struct elf_link_hash_table *htab;
00993 struct eh_frame_hdr_info *hdr_info;
00994 unsigned int ptr_size;
00995 struct eh_cie_fde *ent;
00996
00997 if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
00998 return bfd_set_section_contents (abfd, sec->output_section, contents,
00999 sec->output_offset, sec->size);
01000
01001 ptr_size = (get_elf_backend_data (abfd)
01002 ->elf_backend_eh_frame_address_size (abfd, sec));
01003 BFD_ASSERT (ptr_size != 0);
01004
01005 sec_info = elf_section_data (sec)->sec_info;
01006 htab = elf_hash_table (info);
01007 hdr_info = &htab->eh_info;
01008
01009
01010
01011
01012
01013
01014
01015 if (!hdr_info->offsets_adjusted)
01016 {
01017 bfd *ibfd;
01018 asection *eh;
01019 struct eh_frame_sec_info *eh_inf;
01020
01021 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
01022 {
01023 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
01024 || (ibfd->flags & DYNAMIC) != 0)
01025 continue;
01026
01027 eh = bfd_get_section_by_name (ibfd, ".eh_frame");
01028 if (eh == NULL || eh->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
01029 continue;
01030
01031 eh_inf = elf_section_data (eh)->sec_info;
01032 for (ent = eh_inf->entry; ent < eh_inf->entry + eh_inf->count; ++ent)
01033 {
01034 ent->offset += eh->output_offset;
01035 ent->new_offset += eh->output_offset;
01036 }
01037 }
01038 hdr_info->offsets_adjusted = TRUE;
01039 }
01040
01041 if (hdr_info->table && hdr_info->array == NULL)
01042 hdr_info->array
01043 = bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
01044 if (hdr_info->array == NULL)
01045 hdr_info = NULL;
01046
01047
01048
01049
01050
01051
01052 for (ent = sec_info->entry + sec_info->count; ent-- != sec_info->entry;)
01053 if (!ent->removed && ent->new_offset > ent->offset)
01054 memmove (contents + ent->new_offset - sec->output_offset,
01055 contents + ent->offset - sec->output_offset, ent->size);
01056
01057 for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
01058 if (!ent->removed && ent->new_offset < ent->offset)
01059 memmove (contents + ent->new_offset - sec->output_offset,
01060 contents + ent->offset - sec->output_offset, ent->size);
01061
01062 for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
01063 {
01064 unsigned char *buf, *end;
01065 unsigned int new_size;
01066
01067 if (ent->removed)
01068 continue;
01069
01070 if (ent->size == 4)
01071 {
01072
01073 BFD_ASSERT (ent == sec_info->entry + sec_info->count - 1);
01074 continue;
01075 }
01076
01077 buf = contents + ent->new_offset - sec->output_offset;
01078 end = buf + ent->size;
01079 new_size = size_of_output_cie_fde (ent, ptr_size);
01080
01081
01082 if (new_size != ent->size)
01083 {
01084 memset (end, 0, new_size - ent->size);
01085 bfd_put_32 (abfd, new_size - 4, buf);
01086 }
01087
01088 if (ent->cie)
01089 {
01090
01091 if (ent->make_relative
01092 || ent->need_lsda_relative
01093 || ent->per_encoding_relative)
01094 {
01095 char *aug;
01096 unsigned int action, extra_string, extra_data;
01097 unsigned int per_width, per_encoding;
01098
01099
01100
01101 action = ((ent->make_relative ? 1 : 0)
01102 | (ent->need_lsda_relative ? 2 : 0)
01103 | (ent->per_encoding_relative ? 4 : 0));
01104 extra_string = extra_augmentation_string_bytes (ent);
01105 extra_data = extra_augmentation_data_bytes (ent);
01106
01107
01108 buf += 9;
01109 aug = (char *) buf;
01110 buf += strlen (aug) + 1;
01111 skip_leb128 (&buf, end);
01112 skip_leb128 (&buf, end);
01113 skip_leb128 (&buf, end);
01114 if (*aug == 'z')
01115 {
01116
01117
01118 *buf++ += extra_data;
01119 aug++;
01120 }
01121
01122
01123 memmove (buf + extra_string + extra_data, buf, end - buf);
01124 memmove (aug + extra_string, aug, buf - (bfd_byte *) aug);
01125 buf += extra_string;
01126 end += extra_string + extra_data;
01127
01128 if (ent->add_augmentation_size)
01129 {
01130 *aug++ = 'z';
01131 *buf++ = extra_data - 1;
01132 }
01133 if (ent->add_fde_encoding)
01134 {
01135 BFD_ASSERT (action & 1);
01136 *aug++ = 'R';
01137 *buf++ = DW_EH_PE_pcrel;
01138 action &= ~1;
01139 }
01140
01141 while (action)
01142 switch (*aug++)
01143 {
01144 case 'L':
01145 if (action & 2)
01146 {
01147 BFD_ASSERT (*buf == ent->lsda_encoding);
01148 *buf |= DW_EH_PE_pcrel;
01149 action &= ~2;
01150 }
01151 buf++;
01152 break;
01153 case 'P':
01154 per_encoding = *buf++;
01155 per_width = get_DW_EH_PE_width (per_encoding, ptr_size);
01156 BFD_ASSERT (per_width != 0);
01157 BFD_ASSERT (((per_encoding & 0x70) == DW_EH_PE_pcrel)
01158 == ent->per_encoding_relative);
01159 if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
01160 buf = (contents
01161 + ((buf - contents + per_width - 1)
01162 & ~((bfd_size_type) per_width - 1)));
01163 if (action & 4)
01164 {
01165 bfd_vma val;
01166
01167 val = read_value (abfd, buf, per_width,
01168 get_DW_EH_PE_signed (per_encoding));
01169 val += ent->offset - ent->new_offset;
01170 val -= extra_string + extra_data;
01171 write_value (abfd, buf, val, per_width);
01172 action &= ~4;
01173 }
01174 buf += per_width;
01175 break;
01176 case 'R':
01177 if (action & 1)
01178 {
01179 BFD_ASSERT (*buf == ent->fde_encoding);
01180 *buf |= DW_EH_PE_pcrel;
01181 action &= ~1;
01182 }
01183 buf++;
01184 break;
01185 default:
01186 BFD_FAIL ();
01187 }
01188 }
01189 }
01190 else
01191 {
01192
01193 bfd_vma value, address;
01194 unsigned int width;
01195
01196
01197 buf += 4;
01198 value = ent->new_offset + 4 - ent->cie_inf->new_offset;
01199 bfd_put_32 (abfd, value, buf);
01200 buf += 4;
01201 width = get_DW_EH_PE_width (ent->fde_encoding, ptr_size);
01202 value = read_value (abfd, buf, width,
01203 get_DW_EH_PE_signed (ent->fde_encoding));
01204 address = value;
01205 if (value)
01206 {
01207 switch (ent->fde_encoding & 0xf0)
01208 {
01209 case DW_EH_PE_indirect:
01210 case DW_EH_PE_textrel:
01211 BFD_ASSERT (hdr_info == NULL);
01212 break;
01213 case DW_EH_PE_datarel:
01214 {
01215 asection *got = bfd_get_section_by_name (abfd, ".got");
01216
01217 BFD_ASSERT (got != NULL);
01218 address += got->vma;
01219 }
01220 break;
01221 case DW_EH_PE_pcrel:
01222 value += ent->offset - ent->new_offset;
01223 address += sec->output_section->vma + ent->offset + 8;
01224 break;
01225 }
01226 if (ent->cie_inf->make_relative)
01227 value -= sec->output_section->vma + ent->new_offset + 8;
01228 write_value (abfd, buf, value, width);
01229 }
01230
01231 if (hdr_info)
01232 {
01233 hdr_info->array[hdr_info->array_count].initial_loc = address;
01234 hdr_info->array[hdr_info->array_count++].fde
01235 = sec->output_section->vma + ent->new_offset;
01236 }
01237
01238 if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel
01239 || ent->cie_inf->need_lsda_relative)
01240 {
01241 buf += ent->lsda_offset;
01242 width = get_DW_EH_PE_width (ent->lsda_encoding, ptr_size);
01243 value = read_value (abfd, buf, width,
01244 get_DW_EH_PE_signed (ent->lsda_encoding));
01245 if (value)
01246 {
01247 if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel)
01248 value += ent->offset - ent->new_offset;
01249 else if (ent->cie_inf->need_lsda_relative)
01250 value -= (sec->output_section->vma + ent->new_offset + 8
01251 + ent->lsda_offset);
01252 write_value (abfd, buf, value, width);
01253 }
01254 }
01255 else if (ent->cie_inf->add_augmentation_size)
01256 {
01257
01258
01259 buf += width * 2;
01260 memmove (buf + 1, buf, end - buf);
01261 *buf = 0;
01262 }
01263 }
01264 }
01265
01266 {
01267 unsigned int alignment = 1 << sec->alignment_power;
01268 unsigned int pad = sec->size % alignment;
01269
01270
01271
01272 if (pad
01273 && ((sec->output_offset + sec->size + pad)
01274 <= sec->output_section->size))
01275 {
01276 bfd_byte *buf;
01277 unsigned int new_size;
01278
01279
01280 ent = sec_info->entry + sec_info->count;
01281 while (--ent != sec_info->entry)
01282 if (!ent->removed)
01283 break;
01284
01285
01286 if (ent->removed || ent->size < 4)
01287 abort ();
01288
01289 pad = alignment - pad;
01290 buf = contents + ent->new_offset - sec->output_offset;
01291 new_size = size_of_output_cie_fde (ent, ptr_size);
01292
01293
01294 memset (buf + new_size, 0, pad);
01295 bfd_put_32 (abfd, new_size + pad - 4, buf);
01296
01297 sec->size += pad;
01298 }
01299 }
01300
01301 return bfd_set_section_contents (abfd, sec->output_section,
01302 contents, (file_ptr) sec->output_offset,
01303 sec->size);
01304 }
01305
01306
01307
01308
01309 static int
01310 vma_compare (const void *a, const void *b)
01311 {
01312 const struct eh_frame_array_ent *p = a;
01313 const struct eh_frame_array_ent *q = b;
01314 if (p->initial_loc > q->initial_loc)
01315 return 1;
01316 if (p->initial_loc < q->initial_loc)
01317 return -1;
01318 return 0;
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343 bfd_boolean
01344 _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
01345 {
01346 struct elf_link_hash_table *htab;
01347 struct eh_frame_hdr_info *hdr_info;
01348 asection *sec;
01349 bfd_byte *contents;
01350 asection *eh_frame_sec;
01351 bfd_size_type size;
01352 bfd_boolean retval;
01353 bfd_vma encoded_eh_frame;
01354
01355 htab = elf_hash_table (info);
01356 hdr_info = &htab->eh_info;
01357 sec = hdr_info->hdr_sec;
01358 if (sec == NULL)
01359 return TRUE;
01360
01361 size = EH_FRAME_HDR_SIZE;
01362 if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
01363 size += 4 + hdr_info->fde_count * 8;
01364 contents = bfd_malloc (size);
01365 if (contents == NULL)
01366 return FALSE;
01367
01368 eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
01369 if (eh_frame_sec == NULL)
01370 {
01371 free (contents);
01372 return FALSE;
01373 }
01374
01375 memset (contents, 0, EH_FRAME_HDR_SIZE);
01376 contents[0] = 1;
01377 contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address
01378 (abfd, info, eh_frame_sec, 0, sec, 4,
01379 &encoded_eh_frame);
01380
01381 if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
01382 {
01383 contents[2] = DW_EH_PE_udata4;
01384 contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
01385 }
01386 else
01387 {
01388 contents[2] = DW_EH_PE_omit;
01389 contents[3] = DW_EH_PE_omit;
01390 }
01391 bfd_put_32 (abfd, encoded_eh_frame, contents + 4);
01392
01393 if (contents[2] != DW_EH_PE_omit)
01394 {
01395 unsigned int i;
01396
01397 bfd_put_32 (abfd, hdr_info->fde_count, contents + EH_FRAME_HDR_SIZE);
01398 qsort (hdr_info->array, hdr_info->fde_count, sizeof (*hdr_info->array),
01399 vma_compare);
01400 for (i = 0; i < hdr_info->fde_count; i++)
01401 {
01402 bfd_put_32 (abfd,
01403 hdr_info->array[i].initial_loc
01404 - sec->output_section->vma,
01405 contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
01406 bfd_put_32 (abfd,
01407 hdr_info->array[i].fde - sec->output_section->vma,
01408 contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
01409 }
01410 }
01411
01412 retval = bfd_set_section_contents (abfd, sec->output_section,
01413 contents, (file_ptr) sec->output_offset,
01414 sec->size);
01415 free (contents);
01416 return retval;
01417 }
01418
01419
01420
01421 unsigned int
01422 _bfd_elf_eh_frame_address_size (bfd *abfd, asection *sec ATTRIBUTE_UNUSED)
01423 {
01424 return elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64 ? 8 : 4;
01425 }
01426
01427
01428
01429
01430 bfd_boolean
01431 _bfd_elf_can_make_relative (bfd *input_bfd ATTRIBUTE_UNUSED,
01432 struct bfd_link_info *info ATTRIBUTE_UNUSED,
01433 asection *eh_frame_section ATTRIBUTE_UNUSED)
01434 {
01435 return TRUE;
01436 }
01437
01438
01439
01440
01441 bfd_byte
01442 _bfd_elf_encode_eh_address (bfd *abfd ATTRIBUTE_UNUSED,
01443 struct bfd_link_info *info ATTRIBUTE_UNUSED,
01444 asection *osec, bfd_vma offset,
01445 asection *loc_sec, bfd_vma loc_offset,
01446 bfd_vma *encoded)
01447 {
01448 *encoded = osec->vma + offset -
01449 (loc_sec->output_section->vma + loc_sec->output_offset + loc_offset);
01450 return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
01451 }