00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef USE_REL
00021 #define USE_REL 0
00022 #endif
00023
00024 typedef unsigned long int insn32;
00025 typedef unsigned short int insn16;
00026
00027 static bfd_boolean elf32_arm_set_private_flags
00028 PARAMS ((bfd *, flagword));
00029 static bfd_boolean elf32_arm_copy_private_bfd_data
00030 PARAMS ((bfd *, bfd *));
00031 static bfd_boolean elf32_arm_merge_private_bfd_data
00032 PARAMS ((bfd *, bfd *));
00033 static bfd_boolean elf32_arm_print_private_bfd_data
00034 PARAMS ((bfd *, PTR));
00035 static int elf32_arm_get_symbol_type
00036 PARAMS (( Elf_Internal_Sym *, int));
00037 static struct bfd_link_hash_table *elf32_arm_link_hash_table_create
00038 PARAMS ((bfd *));
00039 static bfd_reloc_status_type elf32_arm_final_link_relocate
00040 PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *,
00041 Elf_Internal_Rela *, bfd_vma, struct bfd_link_info *, asection *,
00042 const char *, int, struct elf_link_hash_entry *));
00043 static insn32 insert_thumb_branch
00044 PARAMS ((insn32, int));
00045 static struct elf_link_hash_entry *find_thumb_glue
00046 PARAMS ((struct bfd_link_info *, const char *, bfd *));
00047 static struct elf_link_hash_entry *find_arm_glue
00048 PARAMS ((struct bfd_link_info *, const char *, bfd *));
00049 static void elf32_arm_post_process_headers
00050 PARAMS ((bfd *, struct bfd_link_info *));
00051 static int elf32_arm_to_thumb_stub
00052 PARAMS ((struct bfd_link_info *, const char *, bfd *, bfd *, asection *,
00053 bfd_byte *, asection *, bfd_vma, bfd_signed_vma, bfd_vma));
00054 static int elf32_thumb_to_arm_stub
00055 PARAMS ((struct bfd_link_info *, const char *, bfd *, bfd *, asection *,
00056 bfd_byte *, asection *, bfd_vma, bfd_signed_vma, bfd_vma));
00057 static bfd_boolean elf32_arm_relocate_section
00058 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00059 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00060 static asection * elf32_arm_gc_mark_hook
00061 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
00062 struct elf_link_hash_entry *, Elf_Internal_Sym *));
00063 static bfd_boolean elf32_arm_gc_sweep_hook
00064 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00065 const Elf_Internal_Rela *));
00066 static bfd_boolean elf32_arm_check_relocs
00067 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00068 const Elf_Internal_Rela *));
00069 static bfd_boolean elf32_arm_find_nearest_line
00070 PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **,
00071 const char **, unsigned int *));
00072 static bfd_boolean elf32_arm_adjust_dynamic_symbol
00073 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
00074 static bfd_boolean elf32_arm_size_dynamic_sections
00075 PARAMS ((bfd *, struct bfd_link_info *));
00076 static bfd_boolean elf32_arm_finish_dynamic_symbol
00077 PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
00078 Elf_Internal_Sym *));
00079 static bfd_boolean elf32_arm_finish_dynamic_sections
00080 PARAMS ((bfd *, struct bfd_link_info *));
00081 static struct bfd_hash_entry * elf32_arm_link_hash_newfunc
00082 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
00083 #if USE_REL
00084 static void arm_add_to_rel
00085 PARAMS ((bfd *, bfd_byte *, reloc_howto_type *, bfd_signed_vma));
00086 #endif
00087 static bfd_boolean allocate_dynrelocs
00088 PARAMS ((struct elf_link_hash_entry *h, PTR inf));
00089 static bfd_boolean create_got_section
00090 PARAMS ((bfd * dynobj, struct bfd_link_info * info));
00091 static bfd_boolean elf32_arm_create_dynamic_sections
00092 PARAMS ((bfd * dynobj, struct bfd_link_info * info));
00093 static enum elf_reloc_type_class elf32_arm_reloc_type_class
00094 PARAMS ((const Elf_Internal_Rela *));
00095 static bfd_boolean elf32_arm_object_p
00096 PARAMS ((bfd *));
00097
00098 #ifndef ELFARM_NABI_C_INCLUDED
00099 static void record_arm_to_thumb_glue
00100 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
00101 static void record_thumb_to_arm_glue
00102 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
00103 bfd_boolean bfd_elf32_arm_allocate_interworking_sections
00104 PARAMS ((struct bfd_link_info *));
00105 bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
00106 PARAMS ((bfd *, struct bfd_link_info *));
00107 bfd_boolean bfd_elf32_arm_process_before_allocation
00108 PARAMS ((bfd *, struct bfd_link_info *, int));
00109 #endif
00110
00111
00112 #define INTERWORK_FLAG(abfd) (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK)
00113
00114
00115
00116
00117
00118 #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
00119 #define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"
00120
00121 #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
00122 #define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"
00123
00124
00125
00126 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
00127
00128 #ifdef FOUR_WORD_PLT
00129
00130
00131
00132 #define PLT_HEADER_SIZE 16
00133
00134
00135 #define PLT_ENTRY_SIZE 16
00136
00137
00138
00139
00140
00141 static const bfd_vma elf32_arm_plt0_entry [PLT_HEADER_SIZE / 4] =
00142 {
00143 0xe52de004,
00144 0xe59fe010,
00145 0xe08fe00e,
00146 0xe5bef008,
00147 };
00148
00149
00150
00151 static const bfd_vma elf32_arm_plt_entry [PLT_ENTRY_SIZE / 4] =
00152 {
00153 0xe28fc600,
00154 0xe28cca00,
00155 0xe5bcf000,
00156 0x00000000,
00157 };
00158
00159 #else
00160
00161
00162
00163 #define PLT_HEADER_SIZE 20
00164
00165
00166 #define PLT_ENTRY_SIZE 12
00167
00168
00169
00170
00171
00172 static const bfd_vma elf32_arm_plt0_entry [PLT_HEADER_SIZE / 4] =
00173 {
00174 0xe52de004,
00175 0xe59fe004,
00176 0xe08fe00e,
00177 0xe5bef008,
00178 0x00000000,
00179 };
00180
00181
00182
00183 static const bfd_vma elf32_arm_plt_entry [PLT_ENTRY_SIZE / 4] =
00184 {
00185 0xe28fc600,
00186 0xe28cca00,
00187 0xe5bcf000,
00188 };
00189
00190 #endif
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 struct elf32_arm_relocs_copied
00201 {
00202
00203 struct elf32_arm_relocs_copied * next;
00204
00205 asection * section;
00206
00207 bfd_size_type count;
00208 };
00209
00210
00211 struct elf32_arm_link_hash_entry
00212 {
00213 struct elf_link_hash_entry root;
00214
00215
00216 struct elf32_arm_relocs_copied * relocs_copied;
00217 };
00218
00219
00220 #define elf32_arm_link_hash_traverse(table, func, info) \
00221 (elf_link_hash_traverse \
00222 (&(table)->root, \
00223 (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
00224 (info)))
00225
00226
00227 #define elf32_arm_hash_table(info) \
00228 ((struct elf32_arm_link_hash_table *) ((info)->hash))
00229
00230
00231 struct elf32_arm_link_hash_table
00232 {
00233
00234 struct elf_link_hash_table root;
00235
00236
00237 bfd_size_type thumb_glue_size;
00238
00239
00240 bfd_size_type arm_glue_size;
00241
00242
00243 bfd * bfd_of_glue_owner;
00244
00245
00246
00247 int no_pipeline_knowledge;
00248
00249
00250 asection *sgot;
00251 asection *sgotplt;
00252 asection *srelgot;
00253 asection *splt;
00254 asection *srelplt;
00255 asection *sdynbss;
00256 asection *srelbss;
00257
00258
00259 struct sym_sec_cache sym_sec;
00260 };
00261
00262
00263
00264 static struct bfd_hash_entry *
00265 elf32_arm_link_hash_newfunc (entry, table, string)
00266 struct bfd_hash_entry * entry;
00267 struct bfd_hash_table * table;
00268 const char * string;
00269 {
00270 struct elf32_arm_link_hash_entry * ret =
00271 (struct elf32_arm_link_hash_entry *) entry;
00272
00273
00274
00275 if (ret == (struct elf32_arm_link_hash_entry *) NULL)
00276 ret = ((struct elf32_arm_link_hash_entry *)
00277 bfd_hash_allocate (table,
00278 sizeof (struct elf32_arm_link_hash_entry)));
00279 if (ret == (struct elf32_arm_link_hash_entry *) NULL)
00280 return (struct bfd_hash_entry *) ret;
00281
00282
00283 ret = ((struct elf32_arm_link_hash_entry *)
00284 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
00285 table, string));
00286 if (ret != (struct elf32_arm_link_hash_entry *) NULL)
00287 ret->relocs_copied = NULL;
00288
00289 return (struct bfd_hash_entry *) ret;
00290 }
00291
00292
00293
00294
00295 static bfd_boolean
00296 create_got_section (dynobj, info)
00297 bfd *dynobj;
00298 struct bfd_link_info *info;
00299 {
00300 struct elf32_arm_link_hash_table *htab;
00301
00302 if (! _bfd_elf_create_got_section (dynobj, info))
00303 return FALSE;
00304
00305 htab = elf32_arm_hash_table (info);
00306 htab->sgot = bfd_get_section_by_name (dynobj, ".got");
00307 htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
00308 if (!htab->sgot || !htab->sgotplt)
00309 abort ();
00310
00311 htab->srelgot = bfd_make_section (dynobj, ".rel.got");
00312 if (htab->srelgot == NULL
00313 || ! bfd_set_section_flags (dynobj, htab->srelgot,
00314 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
00315 | SEC_IN_MEMORY | SEC_LINKER_CREATED
00316 | SEC_READONLY))
00317 || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
00318 return FALSE;
00319 return TRUE;
00320 }
00321
00322
00323
00324
00325
00326 static bfd_boolean
00327 elf32_arm_create_dynamic_sections (dynobj, info)
00328 bfd *dynobj;
00329 struct bfd_link_info *info;
00330 {
00331 struct elf32_arm_link_hash_table *htab;
00332
00333 htab = elf32_arm_hash_table (info);
00334 if (!htab->sgot && !create_got_section (dynobj, info))
00335 return FALSE;
00336
00337 if (!_bfd_elf_create_dynamic_sections (dynobj, info))
00338 return FALSE;
00339
00340 htab->splt = bfd_get_section_by_name (dynobj, ".plt");
00341 htab->srelplt = bfd_get_section_by_name (dynobj, ".rel.plt");
00342 htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
00343 if (!info->shared)
00344 htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss");
00345
00346 if (!htab->splt || !htab->srelplt || !htab->sdynbss
00347 || (!info->shared && !htab->srelbss))
00348 abort ();
00349
00350 return TRUE;
00351 }
00352
00353
00354
00355 static void
00356 elf32_arm_copy_indirect_symbol (const struct elf_backend_data *bed,
00357 struct elf_link_hash_entry *dir,
00358 struct elf_link_hash_entry *ind)
00359 {
00360 struct elf32_arm_link_hash_entry *edir, *eind;
00361
00362 edir = (struct elf32_arm_link_hash_entry *) dir;
00363 eind = (struct elf32_arm_link_hash_entry *) ind;
00364
00365 if (eind->relocs_copied != NULL)
00366 {
00367 if (edir->relocs_copied != NULL)
00368 {
00369 struct elf32_arm_relocs_copied **pp;
00370 struct elf32_arm_relocs_copied *p;
00371
00372 if (ind->root.type == bfd_link_hash_indirect)
00373 abort ();
00374
00375
00376
00377 for (pp = &eind->relocs_copied; (p = *pp) != NULL; )
00378 {
00379 struct elf32_arm_relocs_copied *q;
00380
00381 for (q = edir->relocs_copied; q != NULL; q = q->next)
00382 if (q->section == p->section)
00383 {
00384 q->count += p->count;
00385 *pp = p->next;
00386 break;
00387 }
00388 if (q == NULL)
00389 pp = &p->next;
00390 }
00391 *pp = edir->relocs_copied;
00392 }
00393
00394 edir->relocs_copied = eind->relocs_copied;
00395 eind->relocs_copied = NULL;
00396 }
00397
00398 _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
00399 }
00400
00401
00402
00403 static struct bfd_link_hash_table *
00404 elf32_arm_link_hash_table_create (abfd)
00405 bfd *abfd;
00406 {
00407 struct elf32_arm_link_hash_table *ret;
00408 bfd_size_type amt = sizeof (struct elf32_arm_link_hash_table);
00409
00410 ret = (struct elf32_arm_link_hash_table *) bfd_malloc (amt);
00411 if (ret == (struct elf32_arm_link_hash_table *) NULL)
00412 return NULL;
00413
00414 if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
00415 elf32_arm_link_hash_newfunc))
00416 {
00417 free (ret);
00418 return NULL;
00419 }
00420
00421 ret->sgot = NULL;
00422 ret->sgotplt = NULL;
00423 ret->srelgot = NULL;
00424 ret->splt = NULL;
00425 ret->srelplt = NULL;
00426 ret->sdynbss = NULL;
00427 ret->srelbss = NULL;
00428 ret->thumb_glue_size = 0;
00429 ret->arm_glue_size = 0;
00430 ret->bfd_of_glue_owner = NULL;
00431 ret->no_pipeline_knowledge = 0;
00432 ret->sym_sec.abfd = NULL;
00433
00434 return &ret->root.root;
00435 }
00436
00437
00438
00439 static struct elf_link_hash_entry *
00440 find_thumb_glue (link_info, name, input_bfd)
00441 struct bfd_link_info *link_info;
00442 const char *name;
00443 bfd *input_bfd;
00444 {
00445 char *tmp_name;
00446 struct elf_link_hash_entry *hash;
00447 struct elf32_arm_link_hash_table *hash_table;
00448
00449
00450 hash_table = elf32_arm_hash_table (link_info);
00451
00452 tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
00453 + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1);
00454
00455 BFD_ASSERT (tmp_name);
00456
00457 sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
00458
00459 hash = elf_link_hash_lookup
00460 (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE);
00461
00462 if (hash == NULL)
00463
00464 (*_bfd_error_handler) (_("%s: unable to find THUMB glue '%s' for `%s'"),
00465 bfd_archive_filename (input_bfd), tmp_name, name);
00466
00467 free (tmp_name);
00468
00469 return hash;
00470 }
00471
00472
00473
00474 static struct elf_link_hash_entry *
00475 find_arm_glue (link_info, name, input_bfd)
00476 struct bfd_link_info *link_info;
00477 const char *name;
00478 bfd *input_bfd;
00479 {
00480 char *tmp_name;
00481 struct elf_link_hash_entry *myh;
00482 struct elf32_arm_link_hash_table *hash_table;
00483
00484
00485 hash_table = elf32_arm_hash_table (link_info);
00486
00487 tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
00488 + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1);
00489
00490 BFD_ASSERT (tmp_name);
00491
00492 sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
00493
00494 myh = elf_link_hash_lookup
00495 (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE);
00496
00497 if (myh == NULL)
00498
00499 (*_bfd_error_handler) (_("%s: unable to find ARM glue '%s' for `%s'"),
00500 bfd_archive_filename (input_bfd), tmp_name, name);
00501
00502 free (tmp_name);
00503
00504 return myh;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 #define ARM2THUMB_GLUE_SIZE 12
00517 static const insn32 a2t1_ldr_insn = 0xe59fc000;
00518 static const insn32 a2t2_bx_r12_insn = 0xe12fff1c;
00519 static const insn32 a2t3_func_addr_insn = 0x00000001;
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 #define THUMB2ARM_GLUE_SIZE 8
00538 static const insn16 t2a1_bx_pc_insn = 0x4778;
00539 static const insn16 t2a2_noop_insn = 0x46c0;
00540 static const insn32 t2a3_b_insn = 0xea000000;
00541
00542 #ifndef ELFARM_NABI_C_INCLUDED
00543 bfd_boolean
00544 bfd_elf32_arm_allocate_interworking_sections (info)
00545 struct bfd_link_info * info;
00546 {
00547 asection * s;
00548 bfd_byte * foo;
00549 struct elf32_arm_link_hash_table * globals;
00550
00551 globals = elf32_arm_hash_table (info);
00552
00553 BFD_ASSERT (globals != NULL);
00554
00555 if (globals->arm_glue_size != 0)
00556 {
00557 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
00558
00559 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
00560 ARM2THUMB_GLUE_SECTION_NAME);
00561
00562 BFD_ASSERT (s != NULL);
00563
00564 foo = (bfd_byte *) bfd_alloc (globals->bfd_of_glue_owner,
00565 globals->arm_glue_size);
00566
00567 s->_raw_size = s->_cooked_size = globals->arm_glue_size;
00568 s->contents = foo;
00569 }
00570
00571 if (globals->thumb_glue_size != 0)
00572 {
00573 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
00574
00575 s = bfd_get_section_by_name
00576 (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
00577
00578 BFD_ASSERT (s != NULL);
00579
00580 foo = (bfd_byte *) bfd_alloc (globals->bfd_of_glue_owner,
00581 globals->thumb_glue_size);
00582
00583 s->_raw_size = s->_cooked_size = globals->thumb_glue_size;
00584 s->contents = foo;
00585 }
00586
00587 return TRUE;
00588 }
00589
00590 static void
00591 record_arm_to_thumb_glue (link_info, h)
00592 struct bfd_link_info * link_info;
00593 struct elf_link_hash_entry * h;
00594 {
00595 const char * name = h->root.root.string;
00596 asection * s;
00597 char * tmp_name;
00598 struct elf_link_hash_entry * myh;
00599 struct bfd_link_hash_entry * bh;
00600 struct elf32_arm_link_hash_table * globals;
00601 bfd_vma val;
00602
00603 globals = elf32_arm_hash_table (link_info);
00604
00605 BFD_ASSERT (globals != NULL);
00606 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
00607
00608 s = bfd_get_section_by_name
00609 (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
00610
00611 BFD_ASSERT (s != NULL);
00612
00613 tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
00614 + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1);
00615
00616 BFD_ASSERT (tmp_name);
00617
00618 sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
00619
00620 myh = elf_link_hash_lookup
00621 (&(globals)->root, tmp_name, FALSE, FALSE, TRUE);
00622
00623 if (myh != NULL)
00624 {
00625
00626 free (tmp_name);
00627 return;
00628 }
00629
00630
00631
00632
00633 bh = NULL;
00634 val = globals->arm_glue_size + 1;
00635 _bfd_generic_link_add_one_symbol (link_info, globals->bfd_of_glue_owner,
00636 tmp_name, BSF_GLOBAL, s, val,
00637 NULL, TRUE, FALSE, &bh);
00638
00639 free (tmp_name);
00640
00641 globals->arm_glue_size += ARM2THUMB_GLUE_SIZE;
00642
00643 return;
00644 }
00645
00646 static void
00647 record_thumb_to_arm_glue (link_info, h)
00648 struct bfd_link_info *link_info;
00649 struct elf_link_hash_entry *h;
00650 {
00651 const char *name = h->root.root.string;
00652 asection *s;
00653 char *tmp_name;
00654 struct elf_link_hash_entry *myh;
00655 struct bfd_link_hash_entry *bh;
00656 struct elf32_arm_link_hash_table *hash_table;
00657 char bind;
00658 bfd_vma val;
00659
00660 hash_table = elf32_arm_hash_table (link_info);
00661
00662 BFD_ASSERT (hash_table != NULL);
00663 BFD_ASSERT (hash_table->bfd_of_glue_owner != NULL);
00664
00665 s = bfd_get_section_by_name
00666 (hash_table->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
00667
00668 BFD_ASSERT (s != NULL);
00669
00670 tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
00671 + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1);
00672
00673 BFD_ASSERT (tmp_name);
00674
00675 sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
00676
00677 myh = elf_link_hash_lookup
00678 (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE);
00679
00680 if (myh != NULL)
00681 {
00682
00683 free (tmp_name);
00684 return;
00685 }
00686
00687 bh = NULL;
00688 val = hash_table->thumb_glue_size + 1;
00689 _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner,
00690 tmp_name, BSF_GLOBAL, s, val,
00691 NULL, TRUE, FALSE, &bh);
00692
00693
00694 myh = (struct elf_link_hash_entry *) bh;
00695 bind = ELF_ST_BIND (myh->type);
00696 myh->type = ELF_ST_INFO (bind, STT_ARM_TFUNC);
00697
00698 free (tmp_name);
00699
00700 #define CHANGE_TO_ARM "__%s_change_to_arm"
00701 #define BACK_FROM_ARM "__%s_back_from_arm"
00702
00703
00704 tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
00705 + strlen (CHANGE_TO_ARM) + 1);
00706
00707 BFD_ASSERT (tmp_name);
00708
00709 sprintf (tmp_name, CHANGE_TO_ARM, name);
00710
00711 bh = NULL;
00712 val = hash_table->thumb_glue_size + 4,
00713 _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner,
00714 tmp_name, BSF_LOCAL, s, val,
00715 NULL, TRUE, FALSE, &bh);
00716
00717 free (tmp_name);
00718
00719 hash_table->thumb_glue_size += THUMB2ARM_GLUE_SIZE;
00720
00721 return;
00722 }
00723
00724
00725
00726
00727 bfd_boolean
00728 bfd_elf32_arm_add_glue_sections_to_bfd (abfd, info)
00729 bfd *abfd;
00730 struct bfd_link_info *info;
00731 {
00732 flagword flags;
00733 asection *sec;
00734
00735
00736
00737 if (info->relocatable)
00738 return TRUE;
00739
00740 sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
00741
00742 if (sec == NULL)
00743 {
00744
00745
00746
00747 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;
00748
00749 sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME);
00750
00751 if (sec == NULL
00752 || !bfd_set_section_flags (abfd, sec, flags)
00753 || !bfd_set_section_alignment (abfd, sec, 2))
00754 return FALSE;
00755
00756
00757
00758 sec->gc_mark = 1;
00759 }
00760
00761 sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);
00762
00763 if (sec == NULL)
00764 {
00765 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;
00766
00767 sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME);
00768
00769 if (sec == NULL
00770 || !bfd_set_section_flags (abfd, sec, flags)
00771 || !bfd_set_section_alignment (abfd, sec, 2))
00772 return FALSE;
00773
00774 sec->gc_mark = 1;
00775 }
00776
00777 return TRUE;
00778 }
00779
00780
00781
00782
00783
00784 bfd_boolean
00785 bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
00786 bfd *abfd;
00787 struct bfd_link_info *info;
00788 {
00789 struct elf32_arm_link_hash_table *globals;
00790
00791
00792
00793 if (info->relocatable)
00794 return TRUE;
00795
00796 globals = elf32_arm_hash_table (info);
00797
00798 BFD_ASSERT (globals != NULL);
00799
00800 if (globals->bfd_of_glue_owner != NULL)
00801 return TRUE;
00802
00803
00804 globals->bfd_of_glue_owner = abfd;
00805
00806 return TRUE;
00807 }
00808
00809 bfd_boolean
00810 bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
00811 bfd *abfd;
00812 struct bfd_link_info *link_info;
00813 int no_pipeline_knowledge;
00814 {
00815 Elf_Internal_Shdr *symtab_hdr;
00816 Elf_Internal_Rela *internal_relocs = NULL;
00817 Elf_Internal_Rela *irel, *irelend;
00818 bfd_byte *contents = NULL;
00819
00820 asection *sec;
00821 struct elf32_arm_link_hash_table *globals;
00822
00823
00824
00825 if (link_info->relocatable)
00826 return TRUE;
00827
00828
00829
00830 globals = elf32_arm_hash_table (link_info);
00831
00832 BFD_ASSERT (globals != NULL);
00833 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
00834
00835 globals->no_pipeline_knowledge = no_pipeline_knowledge;
00836
00837
00838 sec = abfd->sections;
00839
00840 if (sec == NULL)
00841 return TRUE;
00842
00843 for (; sec != NULL; sec = sec->next)
00844 {
00845 if (sec->reloc_count == 0)
00846 continue;
00847
00848 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00849
00850
00851 internal_relocs
00852 = _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL,
00853 (Elf_Internal_Rela *) NULL, FALSE);
00854
00855 if (internal_relocs == NULL)
00856 goto error_return;
00857
00858 irelend = internal_relocs + sec->reloc_count;
00859 for (irel = internal_relocs; irel < irelend; irel++)
00860 {
00861 long r_type;
00862 unsigned long r_index;
00863
00864 struct elf_link_hash_entry *h;
00865
00866 r_type = ELF32_R_TYPE (irel->r_info);
00867 r_index = ELF32_R_SYM (irel->r_info);
00868
00869
00870 if ( r_type != R_ARM_PC24
00871 && r_type != R_ARM_THM_PC22)
00872 continue;
00873
00874
00875 if (contents == NULL)
00876 {
00877
00878 if (elf_section_data (sec)->this_hdr.contents != NULL)
00879 contents = elf_section_data (sec)->this_hdr.contents;
00880 else
00881 {
00882
00883 contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
00884 if (contents == NULL)
00885 goto error_return;
00886
00887 if (!bfd_get_section_contents (abfd, sec, contents,
00888 (file_ptr) 0, sec->_raw_size))
00889 goto error_return;
00890 }
00891 }
00892
00893
00894 h = NULL;
00895
00896
00897 if (r_index < symtab_hdr->sh_info)
00898 continue;
00899
00900
00901 r_index -= symtab_hdr->sh_info;
00902 h = (struct elf_link_hash_entry *)
00903 elf_sym_hashes (abfd)[r_index];
00904
00905
00906
00907 if (h == NULL)
00908 continue;
00909
00910 switch (r_type)
00911 {
00912 case R_ARM_PC24:
00913
00914
00915
00916 if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC)
00917 record_arm_to_thumb_glue (link_info, h);
00918 break;
00919
00920 case R_ARM_THM_PC22:
00921
00922
00923
00924 if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC)
00925 record_thumb_to_arm_glue (link_info, h);
00926 break;
00927
00928 default:
00929 break;
00930 }
00931 }
00932
00933 if (contents != NULL
00934 && elf_section_data (sec)->this_hdr.contents != contents)
00935 free (contents);
00936 contents = NULL;
00937
00938 if (internal_relocs != NULL
00939 && elf_section_data (sec)->relocs != internal_relocs)
00940 free (internal_relocs);
00941 internal_relocs = NULL;
00942 }
00943
00944 return TRUE;
00945
00946 error_return:
00947 if (contents != NULL
00948 && elf_section_data (sec)->this_hdr.contents != contents)
00949 free (contents);
00950 if (internal_relocs != NULL
00951 && elf_section_data (sec)->relocs != internal_relocs)
00952 free (internal_relocs);
00953
00954 return FALSE;
00955 }
00956 #endif
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 #define LOW_HI_ORDER 0xF800F000
00987 #define HI_LOW_ORDER 0xF000F800
00988
00989 static insn32
00990 insert_thumb_branch (br_insn, rel_off)
00991 insn32 br_insn;
00992 int rel_off;
00993 {
00994 unsigned int low_bits;
00995 unsigned int high_bits;
00996
00997 BFD_ASSERT ((rel_off & 1) != 1);
00998
00999 rel_off >>= 1;
01000 low_bits = rel_off & 0x000007FF;
01001 high_bits = (rel_off >> 11) & 0x000007FF;
01002
01003 if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)
01004 br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
01005 else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER)
01006 br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;
01007 else
01008
01009 abort ();
01010
01011 return br_insn;
01012 }
01013
01014
01015
01016 static int
01017 elf32_thumb_to_arm_stub (info, name, input_bfd, output_bfd, input_section,
01018 hit_data, sym_sec, offset, addend, val)
01019 struct bfd_link_info * info;
01020 const char * name;
01021 bfd * input_bfd;
01022 bfd * output_bfd;
01023 asection * input_section;
01024 bfd_byte * hit_data;
01025 asection * sym_sec;
01026 bfd_vma offset;
01027 bfd_signed_vma addend;
01028 bfd_vma val;
01029 {
01030 asection * s = 0;
01031 bfd_vma my_offset;
01032 unsigned long int tmp;
01033 long int ret_offset;
01034 struct elf_link_hash_entry * myh;
01035 struct elf32_arm_link_hash_table * globals;
01036
01037 myh = find_thumb_glue (info, name, input_bfd);
01038 if (myh == NULL)
01039 return FALSE;
01040
01041 globals = elf32_arm_hash_table (info);
01042
01043 BFD_ASSERT (globals != NULL);
01044 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01045
01046 my_offset = myh->root.u.def.value;
01047
01048 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
01049 THUMB2ARM_GLUE_SECTION_NAME);
01050
01051 BFD_ASSERT (s != NULL);
01052 BFD_ASSERT (s->contents != NULL);
01053 BFD_ASSERT (s->output_section != NULL);
01054
01055 if ((my_offset & 0x01) == 0x01)
01056 {
01057 if (sym_sec != NULL
01058 && sym_sec->owner != NULL
01059 && !INTERWORK_FLAG (sym_sec->owner))
01060 {
01061 (*_bfd_error_handler)
01062 (_("%s(%s): warning: interworking not enabled."),
01063 bfd_archive_filename (sym_sec->owner), name);
01064 (*_bfd_error_handler)
01065 (_(" first occurrence: %s: thumb call to arm"),
01066 bfd_archive_filename (input_bfd));
01067
01068 return FALSE;
01069 }
01070
01071 --my_offset;
01072 myh->root.u.def.value = my_offset;
01073
01074 bfd_put_16 (output_bfd, (bfd_vma) t2a1_bx_pc_insn,
01075 s->contents + my_offset);
01076
01077 bfd_put_16 (output_bfd, (bfd_vma) t2a2_noop_insn,
01078 s->contents + my_offset + 2);
01079
01080 ret_offset =
01081
01082 ((bfd_signed_vma) val)
01083 - ((bfd_signed_vma)
01084
01085 (s->output_offset
01086
01087 + my_offset
01088
01089 + s->output_section->vma)
01090
01091 + 4
01092
01093 + 8);
01094
01095 bfd_put_32 (output_bfd,
01096 (bfd_vma) t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF),
01097 s->contents + my_offset + 4);
01098 }
01099
01100 BFD_ASSERT (my_offset <= globals->thumb_glue_size);
01101
01102
01103 ret_offset =
01104
01105 (s->output_section->vma + s->output_offset + my_offset)
01106
01107 - (input_section->output_section->vma + input_section->output_offset + offset)
01108
01109 - addend
01110
01111 - 8;
01112
01113 tmp = bfd_get_32 (input_bfd, hit_data
01114 - input_section->vma);
01115
01116 bfd_put_32 (output_bfd,
01117 (bfd_vma) insert_thumb_branch (tmp, ret_offset),
01118 hit_data - input_section->vma);
01119
01120 return TRUE;
01121 }
01122
01123
01124
01125 static int
01126 elf32_arm_to_thumb_stub (info, name, input_bfd, output_bfd, input_section,
01127 hit_data, sym_sec, offset, addend, val)
01128 struct bfd_link_info * info;
01129 const char * name;
01130 bfd * input_bfd;
01131 bfd * output_bfd;
01132 asection * input_section;
01133 bfd_byte * hit_data;
01134 asection * sym_sec;
01135 bfd_vma offset;
01136 bfd_signed_vma addend;
01137 bfd_vma val;
01138 {
01139 unsigned long int tmp;
01140 bfd_vma my_offset;
01141 asection * s;
01142 long int ret_offset;
01143 struct elf_link_hash_entry * myh;
01144 struct elf32_arm_link_hash_table * globals;
01145
01146 myh = find_arm_glue (info, name, input_bfd);
01147 if (myh == NULL)
01148 return FALSE;
01149
01150 globals = elf32_arm_hash_table (info);
01151
01152 BFD_ASSERT (globals != NULL);
01153 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01154
01155 my_offset = myh->root.u.def.value;
01156 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
01157 ARM2THUMB_GLUE_SECTION_NAME);
01158 BFD_ASSERT (s != NULL);
01159 BFD_ASSERT (s->contents != NULL);
01160 BFD_ASSERT (s->output_section != NULL);
01161
01162 if ((my_offset & 0x01) == 0x01)
01163 {
01164 if (sym_sec != NULL
01165 && sym_sec->owner != NULL
01166 && !INTERWORK_FLAG (sym_sec->owner))
01167 {
01168 (*_bfd_error_handler)
01169 (_("%s(%s): warning: interworking not enabled."),
01170 bfd_archive_filename (sym_sec->owner), name);
01171 (*_bfd_error_handler)
01172 (_(" first occurrence: %s: arm call to thumb"),
01173 bfd_archive_filename (input_bfd));
01174 }
01175
01176 --my_offset;
01177 myh->root.u.def.value = my_offset;
01178
01179 bfd_put_32 (output_bfd, (bfd_vma) a2t1_ldr_insn,
01180 s->contents + my_offset);
01181
01182 bfd_put_32 (output_bfd, (bfd_vma) a2t2_bx_r12_insn,
01183 s->contents + my_offset + 4);
01184
01185
01186 bfd_put_32 (output_bfd, val | a2t3_func_addr_insn,
01187 s->contents + my_offset + 8);
01188 }
01189
01190 BFD_ASSERT (my_offset <= globals->arm_glue_size);
01191
01192 tmp = bfd_get_32 (input_bfd, hit_data);
01193 tmp = tmp & 0xFF000000;
01194
01195
01196 ret_offset = (s->output_offset
01197 + my_offset
01198 + s->output_section->vma
01199 - (input_section->output_offset
01200 + input_section->output_section->vma
01201 + offset + addend)
01202 - 8);
01203
01204 tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);
01205
01206 bfd_put_32 (output_bfd, (bfd_vma) tmp, hit_data - input_section->vma);
01207
01208 return TRUE;
01209 }
01210
01211
01212
01213
01214
01215
01216 #define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
01217 ((DYN) \
01218 && ((SHARED) \
01219 || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
01220 && ((H)->dynindx != -1 \
01221 || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
01222
01223
01224
01225 static bfd_reloc_status_type
01226 elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
01227 input_section, contents, rel, value,
01228 info, sym_sec, sym_name, sym_flags, h)
01229 reloc_howto_type * howto;
01230 bfd * input_bfd;
01231 bfd * output_bfd;
01232 asection * input_section;
01233 bfd_byte * contents;
01234 Elf_Internal_Rela * rel;
01235 bfd_vma value;
01236 struct bfd_link_info * info;
01237 asection * sym_sec;
01238 const char * sym_name;
01239 int sym_flags;
01240 struct elf_link_hash_entry * h;
01241 {
01242 unsigned long r_type = howto->type;
01243 unsigned long r_symndx;
01244 bfd_byte * hit_data = contents + rel->r_offset;
01245 bfd * dynobj = NULL;
01246 Elf_Internal_Shdr * symtab_hdr;
01247 struct elf_link_hash_entry ** sym_hashes;
01248 bfd_vma * local_got_offsets;
01249 asection * sgot = NULL;
01250 asection * splt = NULL;
01251 asection * sreloc = NULL;
01252 bfd_vma addend;
01253 bfd_signed_vma signed_addend;
01254 struct elf32_arm_link_hash_table * globals;
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 if (bfd_get_start_address (output_bfd) != 0)
01266 elf_elfheader (output_bfd)->e_flags |= EF_ARM_HASENTRY;
01267
01268 globals = elf32_arm_hash_table (info);
01269
01270 dynobj = elf_hash_table (info)->dynobj;
01271 if (dynobj)
01272 {
01273 sgot = bfd_get_section_by_name (dynobj, ".got");
01274 splt = bfd_get_section_by_name (dynobj, ".plt");
01275 }
01276 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
01277 sym_hashes = elf_sym_hashes (input_bfd);
01278 local_got_offsets = elf_local_got_offsets (input_bfd);
01279 r_symndx = ELF32_R_SYM (rel->r_info);
01280
01281 #if USE_REL
01282 addend = bfd_get_32 (input_bfd, hit_data) & howto->src_mask;
01283
01284 if (addend & ((howto->src_mask + 1) >> 1))
01285 {
01286 signed_addend = -1;
01287 signed_addend &= ~ howto->src_mask;
01288 signed_addend |= addend;
01289 }
01290 else
01291 signed_addend = addend;
01292 #else
01293 addend = signed_addend = rel->r_addend;
01294 #endif
01295
01296 switch (r_type)
01297 {
01298 case R_ARM_NONE:
01299 return bfd_reloc_ok;
01300
01301 case R_ARM_PC24:
01302 case R_ARM_ABS32:
01303 case R_ARM_REL32:
01304 #ifndef OLD_ARM_ABI
01305 case R_ARM_XPC25:
01306 #endif
01307 case R_ARM_PLT32:
01308
01309
01310
01311 if (r_symndx == 0)
01312 return bfd_reloc_ok;
01313
01314
01315
01316
01317
01318 if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32)
01319 && h != NULL
01320 && splt != NULL
01321 && h->plt.offset != (bfd_vma) -1)
01322 {
01323
01324
01325
01326 BFD_ASSERT (!SYMBOL_CALLS_LOCAL (info, h));
01327
01328 value = (splt->output_section->vma
01329 + splt->output_offset
01330 + h->plt.offset);
01331 return _bfd_final_link_relocate (howto, input_bfd, input_section,
01332 contents, rel->r_offset, value,
01333 (bfd_vma) 0);
01334 }
01335
01336
01337
01338 if (info->shared
01339 && (input_section->flags & SEC_ALLOC)
01340 && (h == NULL
01341 || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
01342 || h->root.type != bfd_link_hash_undefweak)
01343 && r_type != R_ARM_PC24
01344 && r_type != R_ARM_PLT32)
01345 {
01346 Elf_Internal_Rela outrel;
01347 bfd_byte *loc;
01348 bfd_boolean skip, relocate;
01349
01350 if (sreloc == NULL)
01351 {
01352 const char * name;
01353
01354 name = (bfd_elf_string_from_elf_section
01355 (input_bfd,
01356 elf_elfheader (input_bfd)->e_shstrndx,
01357 elf_section_data (input_section)->rel_hdr.sh_name));
01358 if (name == NULL)
01359 return bfd_reloc_notsupported;
01360
01361 BFD_ASSERT (strncmp (name, ".rel", 4) == 0
01362 && strcmp (bfd_get_section_name (input_bfd,
01363 input_section),
01364 name + 4) == 0);
01365
01366 sreloc = bfd_get_section_by_name (dynobj, name);
01367 BFD_ASSERT (sreloc != NULL);
01368 }
01369
01370 skip = FALSE;
01371 relocate = FALSE;
01372
01373 outrel.r_offset =
01374 _bfd_elf_section_offset (output_bfd, info, input_section,
01375 rel->r_offset);
01376 if (outrel.r_offset == (bfd_vma) -1)
01377 skip = TRUE;
01378 else if (outrel.r_offset == (bfd_vma) -2)
01379 skip = TRUE, relocate = TRUE;
01380 outrel.r_offset += (input_section->output_section->vma
01381 + input_section->output_offset);
01382
01383 if (skip)
01384 memset (&outrel, 0, sizeof outrel);
01385 else if (h != NULL
01386 && h->dynindx != -1
01387 && (!info->shared
01388 || !info->symbolic
01389 || (h->elf_link_hash_flags
01390 & ELF_LINK_HASH_DEF_REGULAR) == 0))
01391 outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
01392 else
01393 {
01394
01395 relocate = TRUE;
01396 outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
01397 }
01398
01399 loc = sreloc->contents;
01400 loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
01401 bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
01402
01403
01404
01405
01406 if (! relocate)
01407 return bfd_reloc_ok;
01408
01409 return _bfd_final_link_relocate (howto, input_bfd, input_section,
01410 contents, rel->r_offset, value,
01411 (bfd_vma) 0);
01412 }
01413 else switch (r_type)
01414 {
01415 #ifndef OLD_ARM_ABI
01416 case R_ARM_XPC25:
01417 #endif
01418 case R_ARM_PC24:
01419 case R_ARM_PLT32:
01420 #ifndef OLD_ARM_ABI
01421 if (r_type == R_ARM_XPC25)
01422 {
01423
01424
01425
01426 if (sym_flags != STT_ARM_TFUNC)
01427 (*_bfd_error_handler) (_("\
01428 %s: Warning: Arm BLX instruction targets Arm function '%s'."),
01429 bfd_archive_filename (input_bfd),
01430 h ? h->root.root.string : "(local)");
01431 }
01432 else
01433 #endif
01434 {
01435
01436 if (sym_flags == STT_ARM_TFUNC)
01437 {
01438 elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
01439 input_section, hit_data, sym_sec, rel->r_offset,
01440 signed_addend, value);
01441 return bfd_reloc_ok;
01442 }
01443 }
01444
01445 if ( strcmp (bfd_get_target (input_bfd), "elf32-littlearm-oabi") == 0
01446 || strcmp (bfd_get_target (input_bfd), "elf32-bigarm-oabi") == 0)
01447 {
01448
01449
01450 value -= (input_section->output_section->vma
01451 + input_section->output_offset);
01452 value -= rel->r_offset;
01453 value += addend;
01454
01455 if (! globals->no_pipeline_knowledge)
01456 value -= 8;
01457 }
01458 else
01459 {
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478 value -= (input_section->output_section->vma
01479 + input_section->output_offset);
01480 value -= rel->r_offset;
01481 value += (signed_addend << howto->size);
01482
01483
01484
01485
01486
01487
01488 if (! globals->no_pipeline_knowledge)
01489 {
01490 Elf_Internal_Ehdr * i_ehdrp;
01491
01492 i_ehdrp = elf_elfheader (input_bfd);
01493
01494 if (i_ehdrp->e_ident[EI_OSABI] == 0)
01495 value -= 8;
01496 }
01497 }
01498
01499 signed_addend = value;
01500 signed_addend >>= howto->rightshift;
01501
01502
01503
01504
01505
01506 if (! h || h->root.type != bfd_link_hash_undefweak)
01507 {
01508
01509 if ( signed_addend > ((bfd_signed_vma) (howto->dst_mask >> 1))
01510 || signed_addend < - ((bfd_signed_vma) ((howto->dst_mask + 1) >> 1)))
01511 return bfd_reloc_overflow;
01512 }
01513
01514 #ifndef OLD_ARM_ABI
01515
01516 if (r_type == R_ARM_XPC25 && ((value & 2) == 2))
01517 value = (signed_addend & howto->dst_mask)
01518 | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask))
01519 | (1 << 24);
01520 else
01521 #endif
01522 value = (signed_addend & howto->dst_mask)
01523 | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));
01524 break;
01525
01526 case R_ARM_ABS32:
01527 value += addend;
01528 if (sym_flags == STT_ARM_TFUNC)
01529 value |= 1;
01530 break;
01531
01532 case R_ARM_REL32:
01533 value -= (input_section->output_section->vma
01534 + input_section->output_offset + rel->r_offset);
01535 value += addend;
01536 break;
01537 }
01538
01539 bfd_put_32 (input_bfd, value, hit_data);
01540 return bfd_reloc_ok;
01541
01542 case R_ARM_ABS8:
01543 value += addend;
01544 if ((long) value > 0x7f || (long) value < -0x80)
01545 return bfd_reloc_overflow;
01546
01547 bfd_put_8 (input_bfd, value, hit_data);
01548 return bfd_reloc_ok;
01549
01550 case R_ARM_ABS16:
01551 value += addend;
01552
01553 if ((long) value > 0x7fff || (long) value < -0x8000)
01554 return bfd_reloc_overflow;
01555
01556 bfd_put_16 (input_bfd, value, hit_data);
01557 return bfd_reloc_ok;
01558
01559 case R_ARM_ABS12:
01560
01561
01562 value += addend;
01563
01564 if ((long) value > 0x7ff || (long) value < -0x800)
01565 return bfd_reloc_overflow;
01566
01567 value |= (bfd_get_32 (input_bfd, hit_data) & 0xfffff000);
01568 bfd_put_32 (input_bfd, value, hit_data);
01569 return bfd_reloc_ok;
01570
01571 case R_ARM_THM_ABS5:
01572
01573 #if USE_REL
01574
01575 addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
01576
01577 addend >>= howto->rightshift;
01578 #endif
01579 value += addend;
01580
01581
01582 if ((long) value > 0x1f || (long) value < -0x10)
01583 return bfd_reloc_overflow;
01584
01585
01586 value |= bfd_get_16 (input_bfd, hit_data) & 0xf83f;
01587 bfd_put_16 (input_bfd, value, hit_data);
01588 return bfd_reloc_ok;
01589
01590 #ifndef OLD_ARM_ABI
01591 case R_ARM_THM_XPC22:
01592 #endif
01593 case R_ARM_THM_PC22:
01594
01595 {
01596 bfd_vma relocation;
01597 bfd_boolean overflow = FALSE;
01598 bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
01599 bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
01600 bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift;
01601 bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
01602 bfd_vma check;
01603 bfd_signed_vma signed_check;
01604
01605 #if USE_REL
01606
01607
01608 {
01609 bfd_vma upper = upper_insn & 0x7ff;
01610 bfd_vma lower = lower_insn & 0x7ff;
01611 upper = (upper ^ 0x400) - 0x400;
01612 addend = (upper << 12) | (lower << 1);
01613 signed_addend = addend;
01614 }
01615 #endif
01616 #ifndef OLD_ARM_ABI
01617 if (r_type == R_ARM_THM_XPC22)
01618 {
01619
01620
01621
01622 if (sym_flags == STT_ARM_TFUNC)
01623 (*_bfd_error_handler) (_("\
01624 %s: Warning: Thumb BLX instruction targets thumb function '%s'."),
01625 bfd_archive_filename (input_bfd),
01626 h ? h->root.root.string : "(local)");
01627 }
01628 else
01629 #endif
01630 {
01631
01632
01633
01634 if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION)
01635 {
01636 if (elf32_thumb_to_arm_stub
01637 (info, sym_name, input_bfd, output_bfd, input_section,
01638 hit_data, sym_sec, rel->r_offset, signed_addend, value))
01639 return bfd_reloc_ok;
01640 else
01641 return bfd_reloc_dangerous;
01642 }
01643 }
01644
01645 relocation = value + signed_addend;
01646
01647 relocation -= (input_section->output_section->vma
01648 + input_section->output_offset
01649 + rel->r_offset);
01650
01651 if (! globals->no_pipeline_knowledge)
01652 {
01653 Elf_Internal_Ehdr * i_ehdrp;
01654
01655 i_ehdrp = elf_elfheader (input_bfd);
01656
01657
01658
01659
01660
01661
01662 if ( strcmp (bfd_get_target (input_bfd), "elf32-littlearm-oabi") == 0
01663 || strcmp (bfd_get_target (input_bfd), "elf32-bigarm-oabi") == 0
01664 || i_ehdrp->e_ident[EI_OSABI] == 0)
01665 relocation += 4;
01666 }
01667
01668 check = relocation >> howto->rightshift;
01669
01670
01671
01672 if ((bfd_signed_vma) relocation >= 0)
01673 signed_check = check;
01674 else
01675 signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);
01676
01677
01678 if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
01679 overflow = TRUE;
01680
01681 #ifndef OLD_ARM_ABI
01682 if (r_type == R_ARM_THM_XPC22
01683 && ((lower_insn & 0x1800) == 0x0800))
01684
01685
01686
01687
01688 relocation = (relocation + 2) & ~ 3;
01689 #endif
01690
01691 upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff);
01692 lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff);
01693
01694
01695 bfd_put_16 (input_bfd, upper_insn, hit_data);
01696 bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
01697
01698 return (overflow ? bfd_reloc_overflow : bfd_reloc_ok);
01699 }
01700 break;
01701
01702 case R_ARM_THM_PC11:
01703
01704 {
01705 bfd_signed_vma relocation;
01706 bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
01707 bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
01708 bfd_signed_vma signed_check;
01709
01710 #if USE_REL
01711
01712 addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
01713 if (addend & ((howto->src_mask + 1) >> 1))
01714 {
01715 signed_addend = -1;
01716 signed_addend &= ~ howto->src_mask;
01717 signed_addend |= addend;
01718 }
01719 else
01720 signed_addend = addend;
01721
01722
01723
01724 signed_addend <<= howto->rightshift;
01725 #endif
01726 relocation = value + signed_addend;
01727
01728 relocation -= (input_section->output_section->vma
01729 + input_section->output_offset
01730 + rel->r_offset);
01731
01732 relocation >>= howto->rightshift;
01733 signed_check = relocation;
01734 relocation &= howto->dst_mask;
01735 relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask));
01736
01737 bfd_put_16 (input_bfd, relocation, hit_data);
01738
01739
01740 if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
01741 return bfd_reloc_overflow;
01742
01743 return bfd_reloc_ok;
01744 }
01745
01746 case R_ARM_GNU_VTINHERIT:
01747 case R_ARM_GNU_VTENTRY:
01748 return bfd_reloc_ok;
01749
01750 case R_ARM_COPY:
01751 return bfd_reloc_notsupported;
01752
01753 case R_ARM_GLOB_DAT:
01754 return bfd_reloc_notsupported;
01755
01756 case R_ARM_JUMP_SLOT:
01757 return bfd_reloc_notsupported;
01758
01759 case R_ARM_RELATIVE:
01760 return bfd_reloc_notsupported;
01761
01762 case R_ARM_GOTOFF:
01763
01764
01765
01766 BFD_ASSERT (sgot != NULL);
01767 if (sgot == NULL)
01768 return bfd_reloc_notsupported;
01769
01770
01771
01772
01773 if (sym_flags == STT_ARM_TFUNC)
01774 value += 1;
01775
01776
01777
01778
01779
01780
01781 value -= sgot->output_section->vma;
01782 return _bfd_final_link_relocate (howto, input_bfd, input_section,
01783 contents, rel->r_offset, value,
01784 (bfd_vma) 0);
01785
01786 case R_ARM_GOTPC:
01787
01788 BFD_ASSERT (sgot != NULL);
01789
01790 if (sgot == NULL)
01791 return bfd_reloc_notsupported;
01792
01793 value = sgot->output_section->vma;
01794 return _bfd_final_link_relocate (howto, input_bfd, input_section,
01795 contents, rel->r_offset, value,
01796 (bfd_vma) 0);
01797
01798 case R_ARM_GOT32:
01799
01800
01801 if (sgot == NULL)
01802 return bfd_reloc_notsupported;
01803
01804 if (h != NULL)
01805 {
01806 bfd_vma off;
01807 bfd_boolean dyn;
01808
01809 off = h->got.offset;
01810 BFD_ASSERT (off != (bfd_vma) -1);
01811 dyn = globals->root.dynamic_sections_created;
01812
01813 if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
01814 || (info->shared
01815 && SYMBOL_REFERENCES_LOCAL (info, h))
01816 || (ELF_ST_VISIBILITY (h->other)
01817 && h->root.type == bfd_link_hash_undefweak))
01818 {
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 if ((off & 1) != 0)
01829 off &= ~1;
01830 else
01831 {
01832
01833
01834
01835
01836 if (sym_flags == STT_ARM_TFUNC)
01837 value |= 1;
01838
01839 bfd_put_32 (output_bfd, value, sgot->contents + off);
01840 h->got.offset |= 1;
01841 }
01842 }
01843
01844 value = sgot->output_offset + off;
01845 }
01846 else
01847 {
01848 bfd_vma off;
01849
01850 BFD_ASSERT (local_got_offsets != NULL &&
01851 local_got_offsets[r_symndx] != (bfd_vma) -1);
01852
01853 off = local_got_offsets[r_symndx];
01854
01855
01856
01857
01858 if ((off & 1) != 0)
01859 off &= ~1;
01860 else
01861 {
01862 bfd_put_32 (output_bfd, value, sgot->contents + off);
01863
01864 if (info->shared)
01865 {
01866 asection * srelgot;
01867 Elf_Internal_Rela outrel;
01868 bfd_byte *loc;
01869
01870 srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
01871 BFD_ASSERT (srelgot != NULL);
01872
01873 outrel.r_offset = (sgot->output_section->vma
01874 + sgot->output_offset
01875 + off);
01876 outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
01877 loc = srelgot->contents;
01878 loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
01879 bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
01880 }
01881
01882 local_got_offsets[r_symndx] |= 1;
01883 }
01884
01885 value = sgot->output_offset + off;
01886 }
01887
01888 return _bfd_final_link_relocate (howto, input_bfd, input_section,
01889 contents, rel->r_offset, value,
01890 (bfd_vma) 0);
01891
01892 case R_ARM_SBREL32:
01893 return bfd_reloc_notsupported;
01894
01895 case R_ARM_AMP_VCALL9:
01896 return bfd_reloc_notsupported;
01897
01898 case R_ARM_RSBREL32:
01899 return bfd_reloc_notsupported;
01900
01901 case R_ARM_THM_RPC22:
01902 return bfd_reloc_notsupported;
01903
01904 case R_ARM_RREL32:
01905 return bfd_reloc_notsupported;
01906
01907 case R_ARM_RABS32:
01908 return bfd_reloc_notsupported;
01909
01910 case R_ARM_RPC24:
01911 return bfd_reloc_notsupported;
01912
01913 case R_ARM_RBASE:
01914 return bfd_reloc_notsupported;
01915
01916 default:
01917 return bfd_reloc_notsupported;
01918 }
01919 }
01920
01921 #if USE_REL
01922
01923 static void
01924 arm_add_to_rel (abfd, address, howto, increment)
01925 bfd * abfd;
01926 bfd_byte * address;
01927 reloc_howto_type * howto;
01928 bfd_signed_vma increment;
01929 {
01930 bfd_signed_vma addend;
01931
01932 if (howto->type == R_ARM_THM_PC22)
01933 {
01934 int upper_insn, lower_insn;
01935 int upper, lower;
01936
01937 upper_insn = bfd_get_16 (abfd, address);
01938 lower_insn = bfd_get_16 (abfd, address + 2);
01939 upper = upper_insn & 0x7ff;
01940 lower = lower_insn & 0x7ff;
01941
01942 addend = (upper << 12) | (lower << 1);
01943 addend += increment;
01944 addend >>= 1;
01945
01946 upper_insn = (upper_insn & 0xf800) | ((addend >> 11) & 0x7ff);
01947 lower_insn = (lower_insn & 0xf800) | (addend & 0x7ff);
01948
01949 bfd_put_16 (abfd, (bfd_vma) upper_insn, address);
01950 bfd_put_16 (abfd, (bfd_vma) lower_insn, address + 2);
01951 }
01952 else
01953 {
01954 bfd_vma contents;
01955
01956 contents = bfd_get_32 (abfd, address);
01957
01958
01959 addend = contents & howto->src_mask;
01960 if (addend & ((howto->src_mask + 1) >> 1))
01961 {
01962 bfd_signed_vma mask;
01963
01964 mask = -1;
01965 mask &= ~ howto->src_mask;
01966 addend |= mask;
01967 }
01968
01969
01970 switch (howto->type)
01971 {
01972 default:
01973 addend += increment;
01974 break;
01975
01976 case R_ARM_PC24:
01977 addend <<= howto->size;
01978 addend += increment;
01979
01980
01981
01982
01983 addend >>= howto->rightshift;
01984 break;
01985 }
01986
01987 contents = (contents & ~ howto->dst_mask) | (addend & howto->dst_mask);
01988
01989 bfd_put_32 (abfd, contents, address);
01990 }
01991 }
01992 #endif
01993
01994
01995 static bfd_boolean
01996 elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
01997 contents, relocs, local_syms, local_sections)
01998 bfd *output_bfd;
01999 struct bfd_link_info *info;
02000 bfd *input_bfd;
02001 asection *input_section;
02002 bfd_byte *contents;
02003 Elf_Internal_Rela *relocs;
02004 Elf_Internal_Sym *local_syms;
02005 asection **local_sections;
02006 {
02007 Elf_Internal_Shdr *symtab_hdr;
02008 struct elf_link_hash_entry **sym_hashes;
02009 Elf_Internal_Rela *rel;
02010 Elf_Internal_Rela *relend;
02011 const char *name;
02012
02013 #if !USE_REL
02014 if (info->relocatable)
02015 return TRUE;
02016 #endif
02017
02018 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
02019 sym_hashes = elf_sym_hashes (input_bfd);
02020
02021 rel = relocs;
02022 relend = relocs + input_section->reloc_count;
02023 for (; rel < relend; rel++)
02024 {
02025 int r_type;
02026 reloc_howto_type * howto;
02027 unsigned long r_symndx;
02028 Elf_Internal_Sym * sym;
02029 asection * sec;
02030 struct elf_link_hash_entry * h;
02031 bfd_vma relocation;
02032 bfd_reloc_status_type r;
02033 arelent bfd_reloc;
02034
02035 r_symndx = ELF32_R_SYM (rel->r_info);
02036 r_type = ELF32_R_TYPE (rel->r_info);
02037
02038 if ( r_type == R_ARM_GNU_VTENTRY
02039 || r_type == R_ARM_GNU_VTINHERIT)
02040 continue;
02041
02042 elf32_arm_info_to_howto (input_bfd, & bfd_reloc, rel);
02043 howto = bfd_reloc.howto;
02044
02045 #if USE_REL
02046 if (info->relocatable)
02047 {
02048
02049
02050
02051
02052 if (r_symndx < symtab_hdr->sh_info)
02053 {
02054 sym = local_syms + r_symndx;
02055 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
02056 {
02057 sec = local_sections[r_symndx];
02058 arm_add_to_rel (input_bfd, contents + rel->r_offset,
02059 howto,
02060 (bfd_signed_vma) (sec->output_offset
02061 + sym->st_value));
02062 }
02063 }
02064
02065 continue;
02066 }
02067 #endif
02068
02069
02070 h = NULL;
02071 sym = NULL;
02072 sec = NULL;
02073
02074 if (r_symndx < symtab_hdr->sh_info)
02075 {
02076 sym = local_syms + r_symndx;
02077 sec = local_sections[r_symndx];
02078 #if USE_REL
02079 relocation = (sec->output_section->vma
02080 + sec->output_offset
02081 + sym->st_value);
02082 if ((sec->flags & SEC_MERGE)
02083 && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
02084 {
02085 asection *msec;
02086 bfd_vma addend, value;
02087
02088 if (howto->rightshift)
02089 {
02090 (*_bfd_error_handler)
02091 (_("%s(%s+0x%lx): %s relocation against SEC_MERGE section"),
02092 bfd_archive_filename (input_bfd),
02093 bfd_get_section_name (input_bfd, input_section),
02094 (long) rel->r_offset, howto->name);
02095 return FALSE;
02096 }
02097
02098 value = bfd_get_32 (input_bfd, contents + rel->r_offset);
02099
02100
02101 addend = value & howto->src_mask;
02102 if (addend & ((howto->src_mask + 1) >> 1))
02103 {
02104 bfd_signed_vma mask;
02105
02106 mask = -1;
02107 mask &= ~ howto->src_mask;
02108 addend |= mask;
02109 }
02110 msec = sec;
02111 addend =
02112 _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend)
02113 - relocation;
02114 addend += msec->output_section->vma + msec->output_offset;
02115 value = (value & ~ howto->dst_mask) | (addend & howto->dst_mask);
02116 bfd_put_32 (input_bfd, value, contents + rel->r_offset);
02117 }
02118 #else
02119 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
02120 #endif
02121 }
02122 else
02123 {
02124 bfd_boolean warned;
02125 bfd_boolean unresolved_reloc;
02126
02127 RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx,
02128 symtab_hdr, relocation,
02129 sec, unresolved_reloc, info,
02130 warned);
02131
02132 if (unresolved_reloc || relocation != 0)
02133 {
02134
02135
02136
02137 switch (r_type)
02138 {
02139 case R_ARM_PC24:
02140 case R_ARM_ABS32:
02141 case R_ARM_THM_PC22:
02142 if (info->shared
02143 && (
02144 (!info->symbolic && h->dynindx != -1)
02145 || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
02146 )
02147 && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
02148 && ((input_section->flags & SEC_ALLOC) != 0
02149
02150
02151
02152
02153 || ((input_section->flags & SEC_DEBUGGING) != 0
02154 && (h->elf_link_hash_flags
02155 & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
02156 )
02157 relocation = 0;
02158 break;
02159
02160 case R_ARM_GOTPC:
02161 relocation = 0;
02162 break;
02163
02164 case R_ARM_GOT32:
02165 if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL
02166 (elf_hash_table (info)->dynamic_sections_created,
02167 info->shared, h))
02168 && (!info->shared
02169 || (!info->symbolic && h->dynindx != -1)
02170 || (h->elf_link_hash_flags
02171 & ELF_LINK_HASH_DEF_REGULAR) == 0))
02172 relocation = 0;
02173 break;
02174
02175 case R_ARM_PLT32:
02176 if (h->plt.offset != (bfd_vma)-1)
02177 relocation = 0;
02178 break;
02179
02180 default:
02181 if (unresolved_reloc)
02182 _bfd_error_handler
02183 (_("%s: warning: unresolvable relocation %d against symbol `%s' from %s section"),
02184 bfd_archive_filename (input_bfd),
02185 r_type,
02186 h->root.root.string,
02187 bfd_get_section_name (input_bfd, input_section));
02188 break;
02189 }
02190 }
02191 }
02192
02193 if (h != NULL)
02194 name = h->root.root.string;
02195 else
02196 {
02197 name = (bfd_elf_string_from_elf_section
02198 (input_bfd, symtab_hdr->sh_link, sym->st_name));
02199 if (name == NULL || *name == '\0')
02200 name = bfd_section_name (input_bfd, sec);
02201 }
02202
02203 r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
02204 input_section, contents, rel,
02205 relocation, info, sec, name,
02206 (h ? ELF_ST_TYPE (h->type) :
02207 ELF_ST_TYPE (sym->st_info)), h);
02208
02209 if (r != bfd_reloc_ok)
02210 {
02211 const char * msg = (const char *) 0;
02212
02213 switch (r)
02214 {
02215 case bfd_reloc_overflow:
02216
02217
02218
02219 if ((! h ||
02220 h->root.type != bfd_link_hash_undefined)
02221 && (!((*info->callbacks->reloc_overflow)
02222 (info, name, howto->name, (bfd_vma) 0,
02223 input_bfd, input_section, rel->r_offset))))
02224 return FALSE;
02225 break;
02226
02227 case bfd_reloc_undefined:
02228 if (!((*info->callbacks->undefined_symbol)
02229 (info, name, input_bfd, input_section,
02230 rel->r_offset, TRUE)))
02231 return FALSE;
02232 break;
02233
02234 case bfd_reloc_outofrange:
02235 msg = _("internal error: out of range error");
02236 goto common_error;
02237
02238 case bfd_reloc_notsupported:
02239 msg = _("internal error: unsupported relocation error");
02240 goto common_error;
02241
02242 case bfd_reloc_dangerous:
02243 msg = _("internal error: dangerous error");
02244 goto common_error;
02245
02246 default:
02247 msg = _("internal error: unknown error");
02248
02249
02250 common_error:
02251 if (!((*info->callbacks->warning)
02252 (info, msg, name, input_bfd, input_section,
02253 rel->r_offset)))
02254 return FALSE;
02255 break;
02256 }
02257 }
02258 }
02259
02260 return TRUE;
02261 }
02262
02263
02264
02265 static bfd_boolean
02266 elf32_arm_object_p (abfd)
02267 bfd *abfd;
02268 {
02269 unsigned int mach;
02270
02271 mach = bfd_arm_get_mach_from_notes (abfd, ARM_NOTE_SECTION);
02272
02273 if (mach != bfd_mach_arm_unknown)
02274 bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach);
02275
02276 else if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT)
02277 bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312);
02278
02279 else
02280 bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach);
02281
02282 return TRUE;
02283 }
02284
02285
02286 static bfd_boolean
02287 elf32_arm_set_private_flags (abfd, flags)
02288 bfd *abfd;
02289 flagword flags;
02290 {
02291 if (elf_flags_init (abfd)
02292 && elf_elfheader (abfd)->e_flags != flags)
02293 {
02294 if (EF_ARM_EABI_VERSION (flags) == EF_ARM_EABI_UNKNOWN)
02295 {
02296 if (flags & EF_ARM_INTERWORK)
02297 (*_bfd_error_handler) (_("\
02298 Warning: Not setting interworking flag of %s since it has already been specified as non-interworking"),
02299 bfd_archive_filename (abfd));
02300 else
02301 _bfd_error_handler (_("\
02302 Warning: Clearing the interworking flag of %s due to outside request"),
02303 bfd_archive_filename (abfd));
02304 }
02305 }
02306 else
02307 {
02308 elf_elfheader (abfd)->e_flags = flags;
02309 elf_flags_init (abfd) = TRUE;
02310 }
02311
02312 return TRUE;
02313 }
02314
02315
02316
02317 static bfd_boolean
02318 elf32_arm_copy_private_bfd_data (ibfd, obfd)
02319 bfd *ibfd;
02320 bfd *obfd;
02321 {
02322 flagword in_flags;
02323 flagword out_flags;
02324
02325 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
02326 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
02327 return TRUE;
02328
02329 in_flags = elf_elfheader (ibfd)->e_flags;
02330 out_flags = elf_elfheader (obfd)->e_flags;
02331
02332 if (elf_flags_init (obfd)
02333 && EF_ARM_EABI_VERSION (out_flags) == EF_ARM_EABI_UNKNOWN
02334 && in_flags != out_flags)
02335 {
02336
02337 if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
02338 return FALSE;
02339
02340
02341 if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT))
02342 return FALSE;
02343
02344
02345
02346 if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK))
02347 {
02348 if (out_flags & EF_ARM_INTERWORK)
02349 _bfd_error_handler (_("\
02350 Warning: Clearing the interworking flag of %s because non-interworking code in %s has been linked with it"),
02351 bfd_get_filename (obfd),
02352 bfd_archive_filename (ibfd));
02353
02354 in_flags &= ~EF_ARM_INTERWORK;
02355 }
02356
02357
02358 if ((in_flags & EF_ARM_PIC) != (out_flags & EF_ARM_PIC))
02359 in_flags &= ~EF_ARM_PIC;
02360 }
02361
02362 elf_elfheader (obfd)->e_flags = in_flags;
02363 elf_flags_init (obfd) = TRUE;
02364
02365 return TRUE;
02366 }
02367
02368
02369
02370
02371 static bfd_boolean
02372 elf32_arm_merge_private_bfd_data (ibfd, obfd)
02373 bfd * ibfd;
02374 bfd * obfd;
02375 {
02376 flagword out_flags;
02377 flagword in_flags;
02378 bfd_boolean flags_compatible = TRUE;
02379 asection *sec;
02380
02381
02382 if (! _bfd_generic_verify_endian_match (ibfd, obfd))
02383 return FALSE;
02384
02385 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
02386 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
02387 return TRUE;
02388
02389
02390
02391
02392
02393
02394
02395 in_flags = elf_elfheader (ibfd)->e_flags;
02396 out_flags = elf_elfheader (obfd)->e_flags;
02397
02398 if (!elf_flags_init (obfd))
02399 {
02400
02401
02402
02403
02404
02405
02406 if (bfd_get_arch_info (ibfd)->the_default
02407 && elf_elfheader (ibfd)->e_flags == 0)
02408 return TRUE;
02409
02410 elf_flags_init (obfd) = TRUE;
02411 elf_elfheader (obfd)->e_flags = in_flags;
02412
02413 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
02414 && bfd_get_arch_info (obfd)->the_default)
02415 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
02416
02417 return TRUE;
02418 }
02419
02420
02421
02422 if (! bfd_arm_merge_machines (ibfd, obfd))
02423 return FALSE;
02424
02425
02426 if (in_flags == out_flags)
02427 return TRUE;
02428
02429
02430
02431
02432
02433
02434
02435 if (!(ibfd->flags & DYNAMIC))
02436 {
02437 bfd_boolean null_input_bfd = TRUE;
02438
02439 for (sec = ibfd->sections; sec != NULL; sec = sec->next)
02440 {
02441
02442 if (strcmp (sec->name, ".glue_7")
02443 && strcmp (sec->name, ".glue_7t"))
02444 {
02445 null_input_bfd = FALSE;
02446 break;
02447 }
02448 }
02449 if (null_input_bfd)
02450 return TRUE;
02451 }
02452
02453
02454 if (EF_ARM_EABI_VERSION (in_flags) != EF_ARM_EABI_VERSION (out_flags))
02455 {
02456 _bfd_error_handler (_("\
02457 ERROR: %s is compiled for EABI version %d, whereas %s is compiled for version %d"),
02458 bfd_archive_filename (ibfd),
02459 (in_flags & EF_ARM_EABIMASK) >> 24,
02460 bfd_get_filename (obfd),
02461 (out_flags & EF_ARM_EABIMASK) >> 24);
02462 return FALSE;
02463 }
02464
02465
02466 if (EF_ARM_EABI_VERSION (in_flags) == EF_ARM_EABI_UNKNOWN)
02467 {
02468 if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
02469 {
02470 _bfd_error_handler (_("\
02471 ERROR: %s is compiled for APCS-%d, whereas target %s uses APCS-%d"),
02472 bfd_archive_filename (ibfd),
02473 in_flags & EF_ARM_APCS_26 ? 26 : 32,
02474 bfd_get_filename (obfd),
02475 out_flags & EF_ARM_APCS_26 ? 26 : 32);
02476 flags_compatible = FALSE;
02477 }
02478
02479 if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT))
02480 {
02481 if (in_flags & EF_ARM_APCS_FLOAT)
02482 _bfd_error_handler (_("\
02483 ERROR: %s passes floats in float registers, whereas %s passes them in integer registers"),
02484 bfd_archive_filename (ibfd),
02485 bfd_get_filename (obfd));
02486 else
02487 _bfd_error_handler (_("\
02488 ERROR: %s passes floats in integer registers, whereas %s passes them in float registers"),
02489 bfd_archive_filename (ibfd),
02490 bfd_get_filename (obfd));
02491
02492 flags_compatible = FALSE;
02493 }
02494
02495 if ((in_flags & EF_ARM_VFP_FLOAT) != (out_flags & EF_ARM_VFP_FLOAT))
02496 {
02497 if (in_flags & EF_ARM_VFP_FLOAT)
02498 _bfd_error_handler (_("\
02499 ERROR: %s uses VFP instructions, whereas %s does not"),
02500 bfd_archive_filename (ibfd),
02501 bfd_get_filename (obfd));
02502 else
02503 _bfd_error_handler (_("\
02504 ERROR: %s uses FPA instructions, whereas %s does not"),
02505 bfd_archive_filename (ibfd),
02506 bfd_get_filename (obfd));
02507
02508 flags_compatible = FALSE;
02509 }
02510
02511 if ((in_flags & EF_ARM_MAVERICK_FLOAT) != (out_flags & EF_ARM_MAVERICK_FLOAT))
02512 {
02513 if (in_flags & EF_ARM_MAVERICK_FLOAT)
02514 _bfd_error_handler (_("\
02515 ERROR: %s uses Maverick instructions, whereas %s does not"),
02516 bfd_archive_filename (ibfd),
02517 bfd_get_filename (obfd));
02518 else
02519 _bfd_error_handler (_("\
02520 ERROR: %s does not use Maverick instructions, whereas %s does"),
02521 bfd_archive_filename (ibfd),
02522 bfd_get_filename (obfd));
02523
02524 flags_compatible = FALSE;
02525 }
02526
02527 #ifdef EF_ARM_SOFT_FLOAT
02528 if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT))
02529 {
02530
02531
02532
02533
02534
02535 if ((in_flags & EF_ARM_APCS_FLOAT) != 0
02536 || (in_flags & EF_ARM_VFP_FLOAT) == 0)
02537 {
02538 if (in_flags & EF_ARM_SOFT_FLOAT)
02539 _bfd_error_handler (_("\
02540 ERROR: %s uses software FP, whereas %s uses hardware FP"),
02541 bfd_archive_filename (ibfd),
02542 bfd_get_filename (obfd));
02543 else
02544 _bfd_error_handler (_("\
02545 ERROR: %s uses hardware FP, whereas %s uses software FP"),
02546 bfd_archive_filename (ibfd),
02547 bfd_get_filename (obfd));
02548
02549 flags_compatible = FALSE;
02550 }
02551 }
02552 #endif
02553
02554
02555 if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK))
02556 {
02557 if (in_flags & EF_ARM_INTERWORK)
02558 {
02559 _bfd_error_handler (_("\
02560 Warning: %s supports interworking, whereas %s does not"),
02561 bfd_archive_filename (ibfd),
02562 bfd_get_filename (obfd));
02563 }
02564 else
02565 {
02566 _bfd_error_handler (_("\
02567 Warning: %s does not support interworking, whereas %s does"),
02568 bfd_archive_filename (ibfd),
02569 bfd_get_filename (obfd));
02570 }
02571 }
02572 }
02573
02574 return flags_compatible;
02575 }
02576
02577
02578
02579 static bfd_boolean
02580 elf32_arm_print_private_bfd_data (abfd, ptr)
02581 bfd *abfd;
02582 PTR ptr;
02583 {
02584 FILE * file = (FILE *) ptr;
02585 unsigned long flags;
02586
02587 BFD_ASSERT (abfd != NULL && ptr != NULL);
02588
02589
02590 _bfd_elf_print_private_bfd_data (abfd, ptr);
02591
02592 flags = elf_elfheader (abfd)->e_flags;
02593
02594
02595
02596
02597 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
02598
02599 switch (EF_ARM_EABI_VERSION (flags))
02600 {
02601 case EF_ARM_EABI_UNKNOWN:
02602
02603
02604
02605 if (flags & EF_ARM_INTERWORK)
02606 fprintf (file, _(" [interworking enabled]"));
02607
02608 if (flags & EF_ARM_APCS_26)
02609 fprintf (file, " [APCS-26]");
02610 else
02611 fprintf (file, " [APCS-32]");
02612
02613 if (flags & EF_ARM_VFP_FLOAT)
02614 fprintf (file, _(" [VFP float format]"));
02615 else if (flags & EF_ARM_MAVERICK_FLOAT)
02616 fprintf (file, _(" [Maverick float format]"));
02617 else
02618 fprintf (file, _(" [FPA float format]"));
02619
02620 if (flags & EF_ARM_APCS_FLOAT)
02621 fprintf (file, _(" [floats passed in float registers]"));
02622
02623 if (flags & EF_ARM_PIC)
02624 fprintf (file, _(" [position independent]"));
02625
02626 if (flags & EF_ARM_NEW_ABI)
02627 fprintf (file, _(" [new ABI]"));
02628
02629 if (flags & EF_ARM_OLD_ABI)
02630 fprintf (file, _(" [old ABI]"));
02631
02632 if (flags & EF_ARM_SOFT_FLOAT)
02633 fprintf (file, _(" [software FP]"));
02634
02635 flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT
02636 | EF_ARM_PIC | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI
02637 | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT
02638 | EF_ARM_MAVERICK_FLOAT);
02639 break;
02640
02641 case EF_ARM_EABI_VER1:
02642 fprintf (file, _(" [Version1 EABI]"));
02643
02644 if (flags & EF_ARM_SYMSARESORTED)
02645 fprintf (file, _(" [sorted symbol table]"));
02646 else
02647 fprintf (file, _(" [unsorted symbol table]"));
02648
02649 flags &= ~ EF_ARM_SYMSARESORTED;
02650 break;
02651
02652 case EF_ARM_EABI_VER2:
02653 fprintf (file, _(" [Version2 EABI]"));
02654
02655 if (flags & EF_ARM_SYMSARESORTED)
02656 fprintf (file, _(" [sorted symbol table]"));
02657 else
02658 fprintf (file, _(" [unsorted symbol table]"));
02659
02660 if (flags & EF_ARM_DYNSYMSUSESEGIDX)
02661 fprintf (file, _(" [dynamic symbols use segment index]"));
02662
02663 if (flags & EF_ARM_MAPSYMSFIRST)
02664 fprintf (file, _(" [mapping symbols precede others]"));
02665
02666 flags &= ~(EF_ARM_SYMSARESORTED | EF_ARM_DYNSYMSUSESEGIDX
02667 | EF_ARM_MAPSYMSFIRST);
02668 break;
02669
02670 default:
02671 fprintf (file, _(" <EABI version unrecognised>"));
02672 break;
02673 }
02674
02675 flags &= ~ EF_ARM_EABIMASK;
02676
02677 if (flags & EF_ARM_RELEXEC)
02678 fprintf (file, _(" [relocatable executable]"));
02679
02680 if (flags & EF_ARM_HASENTRY)
02681 fprintf (file, _(" [has entry point]"));
02682
02683 flags &= ~ (EF_ARM_RELEXEC | EF_ARM_HASENTRY);
02684
02685 if (flags)
02686 fprintf (file, _("<Unrecognised flag bits set>"));
02687
02688 fputc ('\n', file);
02689
02690 return TRUE;
02691 }
02692
02693 static int
02694 elf32_arm_get_symbol_type (elf_sym, type)
02695 Elf_Internal_Sym * elf_sym;
02696 int type;
02697 {
02698 switch (ELF_ST_TYPE (elf_sym->st_info))
02699 {
02700 case STT_ARM_TFUNC:
02701 return ELF_ST_TYPE (elf_sym->st_info);
02702
02703 case STT_ARM_16BIT:
02704
02705
02706
02707
02708 if (type != STT_OBJECT)
02709 return ELF_ST_TYPE (elf_sym->st_info);
02710 break;
02711
02712 default:
02713 break;
02714 }
02715
02716 return type;
02717 }
02718
02719 static asection *
02720 elf32_arm_gc_mark_hook (sec, info, rel, h, sym)
02721 asection *sec;
02722 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02723 Elf_Internal_Rela *rel;
02724 struct elf_link_hash_entry *h;
02725 Elf_Internal_Sym *sym;
02726 {
02727 if (h != NULL)
02728 {
02729 switch (ELF32_R_TYPE (rel->r_info))
02730 {
02731 case R_ARM_GNU_VTINHERIT:
02732 case R_ARM_GNU_VTENTRY:
02733 break;
02734
02735 default:
02736 switch (h->root.type)
02737 {
02738 case bfd_link_hash_defined:
02739 case bfd_link_hash_defweak:
02740 return h->root.u.def.section;
02741
02742 case bfd_link_hash_common:
02743 return h->root.u.c.p->section;
02744
02745 default:
02746 break;
02747 }
02748 }
02749 }
02750 else
02751 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
02752
02753 return NULL;
02754 }
02755
02756
02757
02758 static bfd_boolean
02759 elf32_arm_gc_sweep_hook (abfd, info, sec, relocs)
02760 bfd *abfd ATTRIBUTE_UNUSED;
02761 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02762 asection *sec ATTRIBUTE_UNUSED;
02763 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
02764 {
02765 Elf_Internal_Shdr *symtab_hdr;
02766 struct elf_link_hash_entry **sym_hashes;
02767 bfd_signed_vma *local_got_refcounts;
02768 const Elf_Internal_Rela *rel, *relend;
02769 unsigned long r_symndx;
02770 struct elf_link_hash_entry *h;
02771
02772 elf_section_data (sec)->local_dynrel = NULL;
02773
02774 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
02775 sym_hashes = elf_sym_hashes (abfd);
02776 local_got_refcounts = elf_local_got_refcounts (abfd);
02777
02778 relend = relocs + sec->reloc_count;
02779 for (rel = relocs; rel < relend; rel++)
02780 switch (ELF32_R_TYPE (rel->r_info))
02781 {
02782 case R_ARM_GOT32:
02783 r_symndx = ELF32_R_SYM (rel->r_info);
02784 if (r_symndx >= symtab_hdr->sh_info)
02785 {
02786 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
02787 if (h->got.refcount > 0)
02788 h->got.refcount -= 1;
02789 }
02790 else if (local_got_refcounts != NULL)
02791 {
02792 if (local_got_refcounts[r_symndx] > 0)
02793 local_got_refcounts[r_symndx] -= 1;
02794 }
02795 break;
02796
02797 case R_ARM_ABS32:
02798 case R_ARM_REL32:
02799 case R_ARM_PC24:
02800 case R_ARM_PLT32:
02801 r_symndx = ELF32_R_SYM (rel->r_info);
02802 if (r_symndx >= symtab_hdr->sh_info)
02803 {
02804 struct elf32_arm_link_hash_entry *eh;
02805 struct elf32_arm_relocs_copied **pp;
02806 struct elf32_arm_relocs_copied *p;
02807
02808 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
02809
02810 if (h->plt.refcount > 0)
02811 h->plt.refcount -= 1;
02812
02813 if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
02814 || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32)
02815 {
02816 eh = (struct elf32_arm_link_hash_entry *) h;
02817
02818 for (pp = &eh->relocs_copied; (p = *pp) != NULL;
02819 pp = &p->next)
02820 if (p->section == sec)
02821 {
02822 p->count -= 1;
02823 if (p->count == 0)
02824 *pp = p->next;
02825 break;
02826 }
02827 }
02828 }
02829 break;
02830
02831 default:
02832 break;
02833 }
02834
02835 return TRUE;
02836 }
02837
02838
02839
02840 static bfd_boolean
02841 elf32_arm_check_relocs (abfd, info, sec, relocs)
02842 bfd *abfd;
02843 struct bfd_link_info *info;
02844 asection *sec;
02845 const Elf_Internal_Rela *relocs;
02846 {
02847 Elf_Internal_Shdr *symtab_hdr;
02848 struct elf_link_hash_entry **sym_hashes;
02849 struct elf_link_hash_entry **sym_hashes_end;
02850 const Elf_Internal_Rela *rel;
02851 const Elf_Internal_Rela *rel_end;
02852 bfd *dynobj;
02853 asection *sreloc;
02854 bfd_vma *local_got_offsets;
02855 struct elf32_arm_link_hash_table *htab;
02856
02857 if (info->relocatable)
02858 return TRUE;
02859
02860 htab = elf32_arm_hash_table (info);
02861 sreloc = NULL;
02862
02863 dynobj = elf_hash_table (info)->dynobj;
02864 local_got_offsets = elf_local_got_offsets (abfd);
02865
02866 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
02867 sym_hashes = elf_sym_hashes (abfd);
02868 sym_hashes_end = sym_hashes
02869 + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
02870
02871 if (!elf_bad_symtab (abfd))
02872 sym_hashes_end -= symtab_hdr->sh_info;
02873
02874 rel_end = relocs + sec->reloc_count;
02875 for (rel = relocs; rel < rel_end; rel++)
02876 {
02877 struct elf_link_hash_entry *h;
02878 unsigned long r_symndx;
02879
02880 r_symndx = ELF32_R_SYM (rel->r_info);
02881 if (r_symndx < symtab_hdr->sh_info)
02882 h = NULL;
02883 else
02884 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
02885
02886 switch (ELF32_R_TYPE (rel->r_info))
02887 {
02888 case R_ARM_GOT32:
02889
02890 if (h != NULL)
02891 {
02892 h->got.refcount++;
02893 }
02894 else
02895 {
02896 bfd_signed_vma *local_got_refcounts;
02897
02898
02899 local_got_refcounts = elf_local_got_refcounts (abfd);
02900 if (local_got_refcounts == NULL)
02901 {
02902 bfd_size_type size;
02903
02904 size = symtab_hdr->sh_info;
02905 size *= (sizeof (bfd_signed_vma) + sizeof(char));
02906 local_got_refcounts = ((bfd_signed_vma *)
02907 bfd_zalloc (abfd, size));
02908 if (local_got_refcounts == NULL)
02909 return FALSE;
02910 elf_local_got_refcounts (abfd) = local_got_refcounts;
02911 }
02912 local_got_refcounts[r_symndx] += 1;
02913 }
02914 break;
02915
02916 case R_ARM_GOTOFF:
02917 case R_ARM_GOTPC:
02918 if (htab->sgot == NULL)
02919 {
02920 if (htab->root.dynobj == NULL)
02921 htab->root.dynobj = abfd;
02922 if (!create_got_section (htab->root.dynobj, info))
02923 return FALSE;
02924 }
02925 break;
02926
02927 case R_ARM_ABS32:
02928 case R_ARM_REL32:
02929 case R_ARM_PC24:
02930 case R_ARM_PLT32:
02931 if (h != NULL)
02932 {
02933
02934
02935
02936
02937
02938
02939 if (!info->shared)
02940 h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
02941
02942
02943
02944
02945
02946 if (ELF32_R_TYPE (rel->r_info) == R_ARM_PC24
02947 || ELF32_R_TYPE (rel->r_info) == R_ARM_PLT32)
02948 h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
02949
02950
02951
02952 h->plt.refcount += 1;
02953 }
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967 if (info->shared
02968 && (sec->flags & SEC_ALLOC) != 0
02969 && ((ELF32_R_TYPE (rel->r_info) != R_ARM_PC24
02970 && ELF32_R_TYPE (rel->r_info) != R_ARM_PLT32)
02971 || (h != NULL
02972 && (! info->symbolic
02973 || (h->elf_link_hash_flags
02974 & ELF_LINK_HASH_DEF_REGULAR) == 0))))
02975 {
02976 struct elf32_arm_relocs_copied *p, **head;
02977
02978
02979
02980
02981 if (sreloc == NULL)
02982 {
02983 const char * name;
02984
02985 name = (bfd_elf_string_from_elf_section
02986 (abfd,
02987 elf_elfheader (abfd)->e_shstrndx,
02988 elf_section_data (sec)->rel_hdr.sh_name));
02989 if (name == NULL)
02990 return FALSE;
02991
02992 BFD_ASSERT (strncmp (name, ".rel", 4) == 0
02993 && strcmp (bfd_get_section_name (abfd, sec),
02994 name + 4) == 0);
02995
02996 sreloc = bfd_get_section_by_name (dynobj, name);
02997 if (sreloc == NULL)
02998 {
02999 flagword flags;
03000
03001 sreloc = bfd_make_section (dynobj, name);
03002 flags = (SEC_HAS_CONTENTS | SEC_READONLY
03003 | SEC_IN_MEMORY | SEC_LINKER_CREATED);
03004 if ((sec->flags & SEC_ALLOC) != 0)
03005 flags |= SEC_ALLOC | SEC_LOAD;
03006 if (sreloc == NULL
03007 || ! bfd_set_section_flags (dynobj, sreloc, flags)
03008 || ! bfd_set_section_alignment (dynobj, sreloc, 2))
03009 return FALSE;
03010 }
03011
03012 elf_section_data (sec)->sreloc = sreloc;
03013 }
03014
03015
03016
03017 if (h != NULL)
03018 {
03019 head = &((struct elf32_arm_link_hash_entry *) h)->relocs_copied;
03020 }
03021 else
03022 {
03023
03024
03025
03026
03027 asection *s;
03028 s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
03029 sec, r_symndx);
03030 if (s == NULL)
03031 return FALSE;
03032
03033 head = ((struct elf32_arm_relocs_copied **)
03034 &elf_section_data (s)->local_dynrel);
03035 }
03036
03037 p = *head;
03038 if (p == NULL || p->section != sec)
03039 {
03040 bfd_size_type amt = sizeof *p;
03041 p = bfd_alloc (htab->root.dynobj, amt);
03042 if (p == NULL)
03043 return FALSE;
03044 p->next = *head;
03045 *head = p;
03046 p->section = sec;
03047 p->count = 0;
03048 }
03049
03050 if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
03051 || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32)
03052 p->count += 1;
03053 }
03054 break;
03055
03056
03057
03058 case R_ARM_GNU_VTINHERIT:
03059 if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
03060 return FALSE;
03061 break;
03062
03063
03064
03065 case R_ARM_GNU_VTENTRY:
03066 if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
03067 return FALSE;
03068 break;
03069 }
03070 }
03071
03072 return TRUE;
03073 }
03074
03075
03076
03077
03078
03079 static bfd_boolean
03080 elf32_arm_find_nearest_line
03081 (abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr)
03082 bfd *abfd;
03083 asection *section;
03084 asymbol **symbols;
03085 bfd_vma offset;
03086 const char **filename_ptr;
03087 const char **functionname_ptr;
03088 unsigned int *line_ptr;
03089 {
03090 bfd_boolean found;
03091 const char *filename;
03092 asymbol *func;
03093 bfd_vma low_func;
03094 asymbol **p;
03095
03096 if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
03097 filename_ptr, functionname_ptr,
03098 line_ptr, 0,
03099 &elf_tdata (abfd)->dwarf2_find_line_info))
03100 return TRUE;
03101
03102 if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
03103 &found, filename_ptr,
03104 functionname_ptr, line_ptr,
03105 &elf_tdata (abfd)->line_info))
03106 return FALSE;
03107
03108 if (found)
03109 return TRUE;
03110
03111 if (symbols == NULL)
03112 return FALSE;
03113
03114 filename = NULL;
03115 func = NULL;
03116 low_func = 0;
03117
03118 for (p = symbols; *p != NULL; p++)
03119 {
03120 elf_symbol_type *q;
03121
03122 q = (elf_symbol_type *) *p;
03123
03124 if (bfd_get_section (&q->symbol) != section)
03125 continue;
03126
03127 switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
03128 {
03129 default:
03130 break;
03131 case STT_FILE:
03132 filename = bfd_asymbol_name (&q->symbol);
03133 break;
03134 case STT_NOTYPE:
03135 case STT_FUNC:
03136 case STT_ARM_TFUNC:
03137 if (q->symbol.section == section
03138 && q->symbol.value >= low_func
03139 && q->symbol.value <= offset)
03140 {
03141 func = (asymbol *) q;
03142 low_func = q->symbol.value;
03143 }
03144 break;
03145 }
03146 }
03147
03148 if (func == NULL)
03149 return FALSE;
03150
03151 *filename_ptr = filename;
03152 *functionname_ptr = bfd_asymbol_name (func);
03153 *line_ptr = 0;
03154
03155 return TRUE;
03156 }
03157
03158
03159
03160
03161
03162
03163
03164 static bfd_boolean
03165 elf32_arm_adjust_dynamic_symbol (info, h)
03166 struct bfd_link_info * info;
03167 struct elf_link_hash_entry * h;
03168 {
03169 bfd * dynobj;
03170 asection * s;
03171 unsigned int power_of_two;
03172
03173 dynobj = elf_hash_table (info)->dynobj;
03174
03175
03176 BFD_ASSERT (dynobj != NULL
03177 && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
03178 || h->weakdef != NULL
03179 || ((h->elf_link_hash_flags
03180 & ELF_LINK_HASH_DEF_DYNAMIC) != 0
03181 && (h->elf_link_hash_flags
03182 & ELF_LINK_HASH_REF_REGULAR) != 0
03183 && (h->elf_link_hash_flags
03184 & ELF_LINK_HASH_DEF_REGULAR) == 0)));
03185
03186
03187
03188
03189 if (h->type == STT_FUNC
03190 || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
03191 {
03192 if (h->plt.refcount <= 0
03193 || SYMBOL_CALLS_LOCAL (info, h)
03194 || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
03195 && h->root.type == bfd_link_hash_undefweak))
03196 {
03197
03198
03199
03200
03201
03202 h->plt.offset = (bfd_vma) -1;
03203 h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
03204 }
03205
03206 return TRUE;
03207 }
03208 else
03209
03210
03211
03212
03213
03214 h->plt.offset = (bfd_vma) -1;
03215
03216
03217
03218
03219 if (h->weakdef != NULL)
03220 {
03221 BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
03222 || h->weakdef->root.type == bfd_link_hash_defweak);
03223 h->root.u.def.section = h->weakdef->root.u.def.section;
03224 h->root.u.def.value = h->weakdef->root.u.def.value;
03225 return TRUE;
03226 }
03227
03228
03229
03230
03231
03232
03233
03234
03235 if (info->shared)
03236 return TRUE;
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247 s = bfd_get_section_by_name (dynobj, ".dynbss");
03248 BFD_ASSERT (s != NULL);
03249
03250
03251
03252
03253
03254 if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
03255 {
03256 asection *srel;
03257
03258 srel = bfd_get_section_by_name (dynobj, ".rel.bss");
03259 BFD_ASSERT (srel != NULL);
03260 srel->_raw_size += sizeof (Elf32_External_Rel);
03261 h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
03262 }
03263
03264
03265
03266 power_of_two = bfd_log2 (h->size);
03267 if (power_of_two > 3)
03268 power_of_two = 3;
03269
03270
03271 s->_raw_size = BFD_ALIGN (s->_raw_size,
03272 (bfd_size_type) (1 << power_of_two));
03273 if (power_of_two > bfd_get_section_alignment (dynobj, s))
03274 {
03275 if (! bfd_set_section_alignment (dynobj, s, power_of_two))
03276 return FALSE;
03277 }
03278
03279
03280 h->root.u.def.section = s;
03281 h->root.u.def.value = s->_raw_size;
03282
03283
03284 s->_raw_size += h->size;
03285
03286 return TRUE;
03287 }
03288
03289
03290
03291
03292 static bfd_boolean
03293 allocate_dynrelocs (h, inf)
03294 struct elf_link_hash_entry *h;
03295 PTR inf;
03296 {
03297 struct bfd_link_info *info;
03298 struct elf32_arm_link_hash_table *htab;
03299 struct elf32_arm_link_hash_entry *eh;
03300 struct elf32_arm_relocs_copied *p;
03301
03302 if (h->root.type == bfd_link_hash_indirect)
03303 return TRUE;
03304
03305 if (h->root.type == bfd_link_hash_warning)
03306
03307
03308
03309 h = (struct elf_link_hash_entry *) h->root.u.i.link;
03310
03311 info = (struct bfd_link_info *) inf;
03312 htab = elf32_arm_hash_table (info);
03313
03314 if (htab->root.dynamic_sections_created
03315 && h->plt.refcount > 0)
03316 {
03317
03318
03319 if (h->dynindx == -1
03320 && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
03321 {
03322 if (! bfd_elf32_link_record_dynamic_symbol (info, h))
03323 return FALSE;
03324 }
03325
03326 if (info->shared
03327 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
03328 {
03329 asection *s = htab->splt;
03330
03331
03332
03333 if (s->_raw_size == 0)
03334 s->_raw_size += PLT_HEADER_SIZE;
03335
03336 h->plt.offset = s->_raw_size;
03337
03338
03339
03340
03341
03342
03343 if (! info->shared
03344 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
03345 {
03346 h->root.u.def.section = s;
03347 h->root.u.def.value = h->plt.offset;
03348 }
03349
03350
03351 s->_raw_size += PLT_ENTRY_SIZE;
03352
03353
03354
03355 htab->sgotplt->_raw_size += 4;
03356
03357
03358 htab->srelplt->_raw_size += sizeof (Elf32_External_Rel);
03359 }
03360 else
03361 {
03362 h->plt.offset = (bfd_vma) -1;
03363 h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
03364 }
03365 }
03366 else
03367 {
03368 h->plt.offset = (bfd_vma) -1;
03369 h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
03370 }
03371
03372 if (h->got.refcount > 0)
03373 {
03374 asection *s;
03375 bfd_boolean dyn;
03376
03377
03378
03379 if (h->dynindx == -1
03380 && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
03381 {
03382 if (! bfd_elf32_link_record_dynamic_symbol (info, h))
03383 return FALSE;
03384 }
03385
03386 s = htab->sgot;
03387 h->got.offset = s->_raw_size;
03388 s->_raw_size += 4;
03389 dyn = htab->root.dynamic_sections_created;
03390 if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
03391 || h->root.type != bfd_link_hash_undefweak)
03392 && (info->shared
03393 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
03394 htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
03395 }
03396 else
03397 h->got.offset = (bfd_vma) -1;
03398
03399 eh = (struct elf32_arm_link_hash_entry *) h;
03400 if (eh->relocs_copied == NULL)
03401 return TRUE;
03402
03403
03404
03405
03406
03407
03408
03409 if (info->shared)
03410 {
03411
03412
03413 if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
03414 && h->root.type == bfd_link_hash_undefweak)
03415 eh->relocs_copied = NULL;
03416 }
03417 else
03418 {
03419
03420
03421
03422
03423 if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
03424 && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
03425 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
03426 || (htab->root.dynamic_sections_created
03427 && (h->root.type == bfd_link_hash_undefweak
03428 || h->root.type == bfd_link_hash_undefined))))
03429 {
03430
03431
03432 if (h->dynindx == -1
03433 && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
03434 {
03435 if (! bfd_elf32_link_record_dynamic_symbol (info, h))
03436 return FALSE;
03437 }
03438
03439
03440
03441 if (h->dynindx != -1)
03442 goto keep;
03443 }
03444
03445 eh->relocs_copied = NULL;
03446
03447 keep: ;
03448 }
03449
03450
03451 for (p = eh->relocs_copied; p != NULL; p = p->next)
03452 {
03453 asection *sreloc = elf_section_data (p->section)->sreloc;
03454 sreloc->_raw_size += p->count * sizeof (Elf32_External_Rel);
03455 }
03456
03457 return TRUE;
03458 }
03459
03460
03461
03462 static bfd_boolean
03463 elf32_arm_size_dynamic_sections (output_bfd, info)
03464 bfd * output_bfd ATTRIBUTE_UNUSED;
03465 struct bfd_link_info * info;
03466 {
03467 bfd * dynobj;
03468 asection * s;
03469 bfd_boolean plt;
03470 bfd_boolean relocs;
03471 bfd *ibfd;
03472 struct elf32_arm_link_hash_table *htab;
03473
03474 htab = elf32_arm_hash_table (info);
03475 dynobj = elf_hash_table (info)->dynobj;
03476 BFD_ASSERT (dynobj != NULL);
03477
03478 if (elf_hash_table (info)->dynamic_sections_created)
03479 {
03480
03481 if (info->executable)
03482 {
03483 s = bfd_get_section_by_name (dynobj, ".interp");
03484 BFD_ASSERT (s != NULL);
03485 s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
03486 s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
03487 }
03488 }
03489
03490
03491
03492 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
03493 {
03494 bfd_signed_vma *local_got;
03495 bfd_signed_vma *end_local_got;
03496 char *local_tls_type;
03497 bfd_size_type locsymcount;
03498 Elf_Internal_Shdr *symtab_hdr;
03499 asection *srel;
03500
03501 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
03502 continue;
03503
03504 for (s = ibfd->sections; s != NULL; s = s->next)
03505 {
03506 struct elf32_arm_relocs_copied *p;
03507
03508 for (p = *((struct elf32_arm_relocs_copied **)
03509 &elf_section_data (s)->local_dynrel);
03510 p != NULL;
03511 p = p->next)
03512 {
03513 if (!bfd_is_abs_section (p->section)
03514 && bfd_is_abs_section (p->section->output_section))
03515 {
03516
03517
03518
03519
03520 }
03521 else if (p->count != 0)
03522 {
03523 srel = elf_section_data (p->section)->sreloc;
03524 srel->_raw_size += p->count * sizeof (Elf32_External_Rel);
03525 if ((p->section->output_section->flags & SEC_READONLY) != 0)
03526 info->flags |= DF_TEXTREL;
03527 }
03528 }
03529 }
03530
03531 local_got = elf_local_got_refcounts (ibfd);
03532 if (!local_got)
03533 continue;
03534
03535 symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
03536 locsymcount = symtab_hdr->sh_info;
03537 end_local_got = local_got + locsymcount;
03538 s = htab->sgot;
03539 srel = htab->srelgot;
03540 for (; local_got < end_local_got; ++local_got, ++local_tls_type)
03541 {
03542 if (*local_got > 0)
03543 {
03544 *local_got = s->_raw_size;
03545 s->_raw_size += 4;
03546 if (info->shared)
03547 srel->_raw_size += sizeof (Elf32_External_Rel);
03548 }
03549 else
03550 *local_got = (bfd_vma) -1;
03551 }
03552 }
03553
03554
03555
03556 elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
03557
03558
03559
03560
03561 plt = FALSE;
03562 relocs = FALSE;
03563 for (s = dynobj->sections; s != NULL; s = s->next)
03564 {
03565 const char * name;
03566 bfd_boolean strip;
03567
03568 if ((s->flags & SEC_LINKER_CREATED) == 0)
03569 continue;
03570
03571
03572
03573 name = bfd_get_section_name (dynobj, s);
03574
03575 strip = FALSE;
03576
03577 if (strcmp (name, ".plt") == 0)
03578 {
03579 if (s->_raw_size == 0)
03580 {
03581
03582
03583 strip = TRUE;
03584 }
03585 else
03586 {
03587
03588 plt = TRUE;
03589 }
03590 }
03591 else if (strncmp (name, ".rel", 4) == 0)
03592 {
03593 if (s->_raw_size == 0)
03594 {
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604 strip = TRUE;
03605 }
03606 else
03607 {
03608
03609
03610 if (strcmp (name, ".rel.plt") != 0)
03611 relocs = TRUE;
03612
03613
03614
03615 s->reloc_count = 0;
03616 }
03617 }
03618 else if (strncmp (name, ".got", 4) != 0)
03619 {
03620
03621 continue;
03622 }
03623
03624 if (strip)
03625 {
03626 _bfd_strip_section_from_output (info, s);
03627 continue;
03628 }
03629
03630
03631 s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
03632 if (s->contents == NULL && s->_raw_size != 0)
03633 return FALSE;
03634 }
03635
03636 if (elf_hash_table (info)->dynamic_sections_created)
03637 {
03638
03639
03640
03641
03642
03643 #define add_dynamic_entry(TAG, VAL) \
03644 bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
03645
03646 if (!info->shared)
03647 {
03648 if (!add_dynamic_entry (DT_DEBUG, 0))
03649 return FALSE;
03650 }
03651
03652 if (plt)
03653 {
03654 if ( !add_dynamic_entry (DT_PLTGOT, 0)
03655 || !add_dynamic_entry (DT_PLTRELSZ, 0)
03656 || !add_dynamic_entry (DT_PLTREL, DT_REL)
03657 || !add_dynamic_entry (DT_JMPREL, 0))
03658 return FALSE;
03659 }
03660
03661 if (relocs)
03662 {
03663 if ( !add_dynamic_entry (DT_REL, 0)
03664 || !add_dynamic_entry (DT_RELSZ, 0)
03665 || !add_dynamic_entry (DT_RELENT, sizeof (Elf32_External_Rel)))
03666 return FALSE;
03667 }
03668
03669 if ((info->flags & DF_TEXTREL) != 0)
03670 {
03671 if (!add_dynamic_entry (DT_TEXTREL, 0))
03672 return FALSE;
03673 info->flags |= DF_TEXTREL;
03674 }
03675 }
03676 #undef add_synamic_entry
03677
03678 return TRUE;
03679 }
03680
03681
03682
03683
03684 static bfd_boolean
03685 elf32_arm_finish_dynamic_symbol (output_bfd, info, h, sym)
03686 bfd * output_bfd;
03687 struct bfd_link_info * info;
03688 struct elf_link_hash_entry * h;
03689 Elf_Internal_Sym * sym;
03690 {
03691 bfd * dynobj;
03692
03693 dynobj = elf_hash_table (info)->dynobj;
03694
03695 if (h->plt.offset != (bfd_vma) -1)
03696 {
03697 asection * splt;
03698 asection * sgot;
03699 asection * srel;
03700 bfd_vma plt_index;
03701 bfd_vma got_offset;
03702 Elf_Internal_Rela rel;
03703 bfd_byte *loc;
03704 bfd_vma got_displacement;
03705
03706
03707
03708
03709 BFD_ASSERT (h->dynindx != -1);
03710
03711 splt = bfd_get_section_by_name (dynobj, ".plt");
03712 sgot = bfd_get_section_by_name (dynobj, ".got.plt");
03713 srel = bfd_get_section_by_name (dynobj, ".rel.plt");
03714 BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
03715
03716
03717
03718
03719
03720 plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
03721
03722
03723
03724
03725 got_offset = (plt_index + 3) * 4;
03726
03727
03728
03729 got_displacement = (sgot->output_section->vma
03730 + sgot->output_offset
03731 + got_offset
03732 - splt->output_section->vma
03733 - splt->output_offset
03734 - h->plt.offset
03735 - 8);
03736
03737 BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
03738
03739
03740 bfd_put_32 (output_bfd, elf32_arm_plt_entry[0] | ((got_displacement & 0x0ff00000) >> 20),
03741 splt->contents + h->plt.offset + 0);
03742 bfd_put_32 (output_bfd, elf32_arm_plt_entry[1] | ((got_displacement & 0x000ff000) >> 12),
03743 splt->contents + h->plt.offset + 4);
03744 bfd_put_32 (output_bfd, elf32_arm_plt_entry[2] | (got_displacement & 0x00000fff),
03745 splt->contents + h->plt.offset + 8);
03746 #ifdef FOUR_WORD_PLT
03747 bfd_put_32 (output_bfd, elf32_arm_plt_entry[3],
03748 splt->contents + h->plt.offset + 12);
03749 #endif
03750
03751
03752 bfd_put_32 (output_bfd,
03753 (splt->output_section->vma
03754 + splt->output_offset),
03755 sgot->contents + got_offset);
03756
03757
03758 rel.r_offset = (sgot->output_section->vma
03759 + sgot->output_offset
03760 + got_offset);
03761 rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_JUMP_SLOT);
03762 loc = srel->contents + plt_index * sizeof (Elf32_External_Rel);
03763 bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
03764
03765 if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
03766 {
03767
03768
03769 sym->st_shndx = SHN_UNDEF;
03770
03771
03772
03773
03774 if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
03775 == 0)
03776 sym->st_value = 0;
03777 }
03778 }
03779
03780 if (h->got.offset != (bfd_vma) -1)
03781 {
03782 asection * sgot;
03783 asection * srel;
03784 Elf_Internal_Rela rel;
03785 bfd_byte *loc;
03786
03787
03788
03789 sgot = bfd_get_section_by_name (dynobj, ".got");
03790 srel = bfd_get_section_by_name (dynobj, ".rel.got");
03791 BFD_ASSERT (sgot != NULL && srel != NULL);
03792
03793 rel.r_offset = (sgot->output_section->vma
03794 + sgot->output_offset
03795 + (h->got.offset &~ (bfd_vma) 1));
03796
03797
03798
03799
03800
03801
03802 if (info->shared
03803 && SYMBOL_REFERENCES_LOCAL (info, h))
03804 {
03805 BFD_ASSERT((h->got.offset & 1) != 0);
03806 rel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
03807 }
03808 else
03809 {
03810 BFD_ASSERT((h->got.offset & 1) == 0);
03811 bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
03812 rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT);
03813 }
03814
03815 loc = srel->contents + srel->reloc_count++ * sizeof (Elf32_External_Rel);
03816 bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
03817 }
03818
03819 if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
03820 {
03821 asection * s;
03822 Elf_Internal_Rela rel;
03823 bfd_byte *loc;
03824
03825
03826 BFD_ASSERT (h->dynindx != -1
03827 && (h->root.type == bfd_link_hash_defined
03828 || h->root.type == bfd_link_hash_defweak));
03829
03830 s = bfd_get_section_by_name (h->root.u.def.section->owner,
03831 ".rel.bss");
03832 BFD_ASSERT (s != NULL);
03833
03834 rel.r_offset = (h->root.u.def.value
03835 + h->root.u.def.section->output_section->vma
03836 + h->root.u.def.section->output_offset);
03837 rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_COPY);
03838 loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rel);
03839 bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
03840 }
03841
03842
03843 if (strcmp (h->root.root.string, "_DYNAMIC") == 0
03844 || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
03845 sym->st_shndx = SHN_ABS;
03846
03847 return TRUE;
03848 }
03849
03850
03851
03852 static bfd_boolean
03853 elf32_arm_finish_dynamic_sections (output_bfd, info)
03854 bfd * output_bfd;
03855 struct bfd_link_info * info;
03856 {
03857 bfd * dynobj;
03858 asection * sgot;
03859 asection * sdyn;
03860
03861 dynobj = elf_hash_table (info)->dynobj;
03862
03863 sgot = bfd_get_section_by_name (dynobj, ".got.plt");
03864 BFD_ASSERT (sgot != NULL);
03865 sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
03866
03867 if (elf_hash_table (info)->dynamic_sections_created)
03868 {
03869 asection *splt;
03870 Elf32_External_Dyn *dyncon, *dynconend;
03871
03872 splt = bfd_get_section_by_name (dynobj, ".plt");
03873 BFD_ASSERT (splt != NULL && sdyn != NULL);
03874
03875 dyncon = (Elf32_External_Dyn *) sdyn->contents;
03876 dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
03877
03878 for (; dyncon < dynconend; dyncon++)
03879 {
03880 Elf_Internal_Dyn dyn;
03881 const char * name;
03882 asection * s;
03883
03884 bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
03885
03886 switch (dyn.d_tag)
03887 {
03888 default:
03889 break;
03890
03891 case DT_PLTGOT:
03892 name = ".got";
03893 goto get_vma;
03894 case DT_JMPREL:
03895 name = ".rel.plt";
03896 get_vma:
03897 s = bfd_get_section_by_name (output_bfd, name);
03898 BFD_ASSERT (s != NULL);
03899 dyn.d_un.d_ptr = s->vma;
03900 bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
03901 break;
03902
03903 case DT_PLTRELSZ:
03904 s = bfd_get_section_by_name (output_bfd, ".rel.plt");
03905 BFD_ASSERT (s != NULL);
03906 if (s->_cooked_size != 0)
03907 dyn.d_un.d_val = s->_cooked_size;
03908 else
03909 dyn.d_un.d_val = s->_raw_size;
03910 bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
03911 break;
03912
03913 case DT_RELSZ:
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923 s = bfd_get_section_by_name (output_bfd, ".rel.plt");
03924 if (s != NULL)
03925 {
03926 if (s->_cooked_size != 0)
03927 dyn.d_un.d_val -= s->_cooked_size;
03928 else
03929 dyn.d_un.d_val -= s->_raw_size;
03930 }
03931 bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
03932 break;
03933
03934
03935
03936 case DT_INIT:
03937 name = info->init_function;
03938 goto get_sym;
03939 case DT_FINI:
03940 name = info->fini_function;
03941 get_sym:
03942
03943
03944 if (dyn.d_un.d_val != 0)
03945 {
03946 struct elf_link_hash_entry * eh;
03947
03948 eh = elf_link_hash_lookup (elf_hash_table (info), name,
03949 FALSE, FALSE, TRUE);
03950 if (eh != (struct elf_link_hash_entry *) NULL
03951 && ELF_ST_TYPE (eh->type) == STT_ARM_TFUNC)
03952 {
03953 dyn.d_un.d_val |= 1;
03954 bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
03955 }
03956 }
03957 break;
03958 }
03959 }
03960
03961
03962 if (splt->_raw_size > 0)
03963 {
03964 bfd_vma got_displacement;
03965
03966
03967 got_displacement = (sgot->output_section->vma
03968 + sgot->output_offset
03969 - splt->output_section->vma
03970 - splt->output_offset
03971 - 16);
03972
03973 bfd_put_32 (output_bfd, elf32_arm_plt0_entry[0], splt->contents + 0);
03974 bfd_put_32 (output_bfd, elf32_arm_plt0_entry[1], splt->contents + 4);
03975 bfd_put_32 (output_bfd, elf32_arm_plt0_entry[2], splt->contents + 8);
03976 bfd_put_32 (output_bfd, elf32_arm_plt0_entry[3], splt->contents + 12);
03977 #ifdef FOUR_WORD_PLT
03978
03979
03980 bfd_put_32 (output_bfd, got_displacement, splt->contents + 28);
03981 #else
03982 bfd_put_32 (output_bfd, got_displacement, splt->contents + 16);
03983 #endif
03984 }
03985
03986
03987
03988 elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
03989 }
03990
03991
03992 if (sgot->_raw_size > 0)
03993 {
03994 if (sdyn == NULL)
03995 bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
03996 else
03997 bfd_put_32 (output_bfd,
03998 sdyn->output_section->vma + sdyn->output_offset,
03999 sgot->contents);
04000 bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4);
04001 bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8);
04002 }
04003
04004 elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
04005
04006 return TRUE;
04007 }
04008
04009 static void
04010 elf32_arm_post_process_headers (abfd, link_info)
04011 bfd * abfd;
04012 struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
04013 {
04014 Elf_Internal_Ehdr * i_ehdrp;
04015
04016 i_ehdrp = elf_elfheader (abfd);
04017
04018 i_ehdrp->e_ident[EI_OSABI] = ARM_ELF_OS_ABI_VERSION;
04019 i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION;
04020 }
04021
04022 static enum elf_reloc_type_class
04023 elf32_arm_reloc_type_class (rela)
04024 const Elf_Internal_Rela *rela;
04025 {
04026 switch ((int) ELF32_R_TYPE (rela->r_info))
04027 {
04028 case R_ARM_RELATIVE:
04029 return reloc_class_relative;
04030 case R_ARM_JUMP_SLOT:
04031 return reloc_class_plt;
04032 case R_ARM_COPY:
04033 return reloc_class_copy;
04034 default:
04035 return reloc_class_normal;
04036 }
04037 }
04038
04039 static bfd_boolean elf32_arm_section_flags PARAMS ((flagword *, Elf_Internal_Shdr *));
04040 static void elf32_arm_final_write_processing PARAMS ((bfd *, bfd_boolean));
04041
04042
04043
04044 static bfd_boolean
04045 elf32_arm_section_flags (flags, hdr)
04046 flagword *flags;
04047 Elf_Internal_Shdr *hdr;
04048 {
04049 if (hdr->sh_type == SHT_NOTE)
04050 *flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_CONTENTS;
04051
04052 return TRUE;
04053 }
04054
04055 void
04056 elf32_arm_final_write_processing (abfd, linker)
04057 bfd *abfd;
04058 bfd_boolean linker ATTRIBUTE_UNUSED;
04059 {
04060 bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
04061 }
04062
04063 #define ELF_ARCH bfd_arch_arm
04064 #define ELF_MACHINE_CODE EM_ARM
04065 #ifdef __QNXTARGET__
04066 #define ELF_MAXPAGESIZE 0x1000
04067 #else
04068 #define ELF_MAXPAGESIZE 0x8000
04069 #endif
04070
04071 #define bfd_elf32_bfd_copy_private_bfd_data elf32_arm_copy_private_bfd_data
04072 #define bfd_elf32_bfd_merge_private_bfd_data elf32_arm_merge_private_bfd_data
04073 #define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags
04074 #define bfd_elf32_bfd_print_private_bfd_data elf32_arm_print_private_bfd_data
04075 #define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
04076 #define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
04077 #define bfd_elf32_find_nearest_line elf32_arm_find_nearest_line
04078
04079 #define elf_backend_get_symbol_type elf32_arm_get_symbol_type
04080 #define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook
04081 #define elf_backend_gc_sweep_hook elf32_arm_gc_sweep_hook
04082 #define elf_backend_check_relocs elf32_arm_check_relocs
04083 #define elf_backend_relocate_section elf32_arm_relocate_section
04084 #define elf_backend_adjust_dynamic_symbol elf32_arm_adjust_dynamic_symbol
04085 #define elf_backend_create_dynamic_sections elf32_arm_create_dynamic_sections
04086 #define elf_backend_finish_dynamic_symbol elf32_arm_finish_dynamic_symbol
04087 #define elf_backend_finish_dynamic_sections elf32_arm_finish_dynamic_sections
04088 #define elf_backend_size_dynamic_sections elf32_arm_size_dynamic_sections
04089 #define elf_backend_post_process_headers elf32_arm_post_process_headers
04090 #define elf_backend_reloc_type_class elf32_arm_reloc_type_class
04091 #define elf_backend_object_p elf32_arm_object_p
04092 #define elf_backend_section_flags elf32_arm_section_flags
04093 #define elf_backend_final_write_processing elf32_arm_final_write_processing
04094 #define elf_backend_copy_indirect_symbol elf32_arm_copy_indirect_symbol
04095
04096 #define elf_backend_can_refcount 1
04097 #define elf_backend_can_gc_sections 1
04098 #define elf_backend_plt_readonly 1
04099 #define elf_backend_want_got_plt 1
04100 #define elf_backend_want_plt_sym 0
04101 #if !USE_REL
04102 #define elf_backend_rela_normal 1
04103 #endif
04104
04105 #define elf_backend_got_header_size 12
04106
04107 #include "elf32-target.h"
04108