00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "bfd.h"
00025 #include "sysdep.h"
00026 #include "libbfd.h"
00027 #include "elf-bfd.h"
00028 #include "elf/dlx.h"
00029
00030 int set_dlx_skip_hi16_flag PARAMS ((int));
00031
00032 static bfd_boolean elf32_dlx_check_relocs
00033 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00034 const Elf_Internal_Rela *));
00035 static void elf32_dlx_info_to_howto
00036 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00037 static void elf32_dlx_info_to_howto_rel
00038 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00039 static bfd_reloc_status_type elf32_dlx_relocate16
00040 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00041 static bfd_reloc_status_type elf32_dlx_relocate26
00042 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00043 static reloc_howto_type *elf32_dlx_reloc_type_lookup
00044 PARAMS ((bfd *, bfd_reloc_code_real_type));
00045 static bfd_reloc_status_type _bfd_dlx_elf_hi16_reloc
00046 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00047 static reloc_howto_type * dlx_rtype_to_howto
00048 PARAMS ((unsigned int));
00049
00050
00051 #define USE_REL 1
00052
00053 #define bfd_elf32_bfd_reloc_type_lookup elf32_dlx_reloc_type_lookup
00054 #define elf_info_to_howto elf32_dlx_info_to_howto
00055 #define elf_info_to_howto_rel elf32_dlx_info_to_howto_rel
00056 #define elf_backend_check_relocs elf32_dlx_check_relocs
00057
00058 static reloc_howto_type dlx_elf_howto_table[]=
00059 {
00060
00061 HOWTO (R_DLX_NONE,
00062 0,
00063 0,
00064 0,
00065 FALSE,
00066 0,
00067 complain_overflow_dont,
00068 bfd_elf_generic_reloc,
00069 "R_DLX_NONE",
00070 FALSE,
00071 0,
00072 0,
00073 FALSE),
00074
00075
00076 HOWTO (R_DLX_RELOC_8,
00077 0,
00078 0,
00079 8,
00080 FALSE,
00081 0,
00082 complain_overflow_dont,
00083 bfd_elf_generic_reloc,
00084 "R_DLX_RELOC_8",
00085 TRUE,
00086 0xff,
00087 0xff,
00088 FALSE),
00089
00090
00091 HOWTO (R_DLX_RELOC_16,
00092 0,
00093 1,
00094 16,
00095 FALSE,
00096 0,
00097 complain_overflow_dont,
00098 bfd_elf_generic_reloc,
00099 "R_DLX_RELOC_16",
00100 TRUE,
00101 0xffff,
00102 0xffff,
00103 FALSE),
00104
00105
00106 HOWTO (R_DLX_RELOC_32,
00107 0,
00108 2,
00109 32,
00110 FALSE,
00111 0,
00112 complain_overflow_dont,
00113 bfd_elf_generic_reloc,
00114 "R_DLX_RELOC_32",
00115 TRUE,
00116 0xffffffff,
00117 0xffffffff,
00118 FALSE),
00119
00120
00121 HOWTO (R_DLX_GNU_VTINHERIT,
00122 0,
00123 2,
00124 0,
00125 FALSE,
00126 0,
00127 complain_overflow_dont,
00128 NULL,
00129 "R_DLX_GNU_VTINHERIT",
00130 FALSE,
00131 0,
00132 0,
00133 FALSE),
00134
00135
00136 HOWTO (R_DLX_GNU_VTENTRY,
00137 0,
00138 2,
00139 0,
00140 FALSE,
00141 0,
00142 complain_overflow_dont,
00143 _bfd_elf_rel_vtable_reloc_fn,
00144 "R_DLX_GNU_VTENTRY",
00145 FALSE,
00146 0,
00147 0,
00148 FALSE)
00149 };
00150
00151
00152 static reloc_howto_type elf_dlx_gnu_rel16_s2 =
00153 HOWTO (R_DLX_RELOC_16_PCREL,
00154 0,
00155 1,
00156 16,
00157 TRUE,
00158 0,
00159 complain_overflow_signed,
00160 elf32_dlx_relocate16,
00161 "R_DLX_RELOC_16_PCREL",
00162 TRUE,
00163 0xffff,
00164 0xffff,
00165 TRUE);
00166
00167
00168 static reloc_howto_type elf_dlx_gnu_rel26_s2 =
00169 HOWTO (R_DLX_RELOC_26_PCREL,
00170 0,
00171 2,
00172 26,
00173 TRUE,
00174 0,
00175 complain_overflow_dont,
00176 elf32_dlx_relocate26,
00177 "R_DLX_RELOC_26_PCREL",
00178 TRUE,
00179 0xffff,
00180 0xffff,
00181 TRUE);
00182
00183
00184 static reloc_howto_type elf_dlx_reloc_16_hi =
00185 HOWTO (R_DLX_RELOC_16_HI,
00186 16,
00187 2,
00188 32,
00189 FALSE,
00190 0,
00191 complain_overflow_dont,
00192 _bfd_dlx_elf_hi16_reloc,
00193 "R_DLX_RELOC_16_HI",
00194 TRUE,
00195 0xFFFF,
00196 0xffff,
00197 FALSE);
00198
00199
00200 static reloc_howto_type elf_dlx_reloc_16_lo =
00201 HOWTO (R_DLX_RELOC_16_LO,
00202 0,
00203 1,
00204 16,
00205 FALSE,
00206 0,
00207 complain_overflow_dont,
00208 bfd_elf_generic_reloc,
00209 "R_DLX_RELOC_16_LO",
00210 TRUE,
00211 0xffff,
00212 0xffff,
00213 FALSE);
00214
00215
00216
00217
00218
00219
00220
00221
00222 static int skip_dlx_elf_hi16_reloc = 0;
00223
00224 int
00225 set_dlx_skip_hi16_flag (flag)
00226 int flag;
00227 {
00228 skip_dlx_elf_hi16_reloc = flag;
00229 return flag;
00230 }
00231
00232 static bfd_reloc_status_type
00233 _bfd_dlx_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
00234 input_section, output_bfd, error_message)
00235 bfd *abfd;
00236 arelent *reloc_entry;
00237 asymbol *symbol;
00238 PTR data;
00239 asection *input_section;
00240 bfd *output_bfd;
00241 char **error_message;
00242 {
00243 bfd_reloc_status_type ret;
00244 bfd_vma relocation;
00245
00246
00247
00248
00249 if (skip_dlx_elf_hi16_reloc)
00250 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
00251 input_section, output_bfd, error_message);
00252
00253
00254
00255 if (output_bfd != (bfd *) NULL
00256 && (symbol->flags & BSF_SECTION_SYM) == 0
00257 && reloc_entry->addend == 0)
00258 {
00259 reloc_entry->address += input_section->output_offset;
00260 return bfd_reloc_ok;
00261 }
00262
00263 ret = bfd_reloc_ok;
00264
00265 if (bfd_is_und_section (symbol->section)
00266 && output_bfd == (bfd *) NULL)
00267 ret = bfd_reloc_undefined;
00268
00269 relocation = (bfd_is_com_section (symbol->section)) ? 0 : symbol->value;
00270 relocation += symbol->section->output_section->vma;
00271 relocation += symbol->section->output_offset;
00272 relocation += reloc_entry->addend;
00273 relocation += bfd_get_16 (abfd, (bfd_byte *)data + reloc_entry->address);
00274
00275 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00276 return bfd_reloc_outofrange;
00277
00278 bfd_put_16 (abfd, (short)((relocation >> 16) & 0xFFFF),
00279 (bfd_byte *)data + reloc_entry->address);
00280
00281 return ret;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 static bfd_reloc_status_type
00295 elf32_dlx_relocate16 (abfd, reloc_entry, symbol, data,
00296 input_section, output_bfd, error_message)
00297 bfd *abfd;
00298 arelent *reloc_entry;
00299 asymbol *symbol;
00300 PTR data;
00301 asection *input_section;
00302 bfd *output_bfd;
00303 char **error_message ATTRIBUTE_UNUSED;
00304 {
00305 unsigned long insn, vallo, allignment;
00306 int val;
00307
00308
00309
00310
00311
00312
00313 if (skip_dlx_elf_hi16_reloc)
00314 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
00315 input_section, output_bfd, error_message);
00316
00317
00318 if (bfd_is_und_section (symbol->section)
00319 && output_bfd == (bfd *) NULL)
00320 return bfd_reloc_undefined;
00321
00322
00323 if (strcmp (input_section->name, symbol->section->output_section->name) != 0)
00324 {
00325 fprintf (stderr,
00326 "BFD Link Error: branch (PC rel16) to section (%s) not supported\n",
00327 symbol->section->output_section->name);
00328 return bfd_reloc_undefined;
00329 }
00330
00331 insn = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address);
00332 allignment = 1 << (input_section->output_section->alignment_power - 1);
00333 vallo = insn & 0x0000FFFF;
00334
00335 if (vallo & 0x8000)
00336 vallo = ~(vallo | 0xFFFF0000) + 1;
00337
00338
00339 vallo += (((unsigned long)(input_section->output_section->vma +
00340 input_section->output_offset) +
00341 allignment) & ~allignment);
00342
00343
00344 val = (symbol->section->output_offset +
00345 symbol->section->output_section->vma +
00346 symbol->value) - vallo;
00347
00348 if (abs ((int) val) > 0x00007FFF)
00349 return bfd_reloc_outofrange;
00350
00351 insn = (insn & 0xFFFF0000) | (val & 0x0000FFFF);
00352
00353 bfd_put_32 (abfd, insn,
00354 (bfd_byte *) data + reloc_entry->address);
00355
00356 return bfd_reloc_ok;
00357 }
00358
00359 static bfd_reloc_status_type
00360 elf32_dlx_relocate26 (abfd, reloc_entry, symbol, data,
00361 input_section, output_bfd, error_message)
00362 bfd *abfd;
00363 arelent *reloc_entry;
00364 asymbol *symbol;
00365 PTR data;
00366 asection *input_section;
00367 bfd *output_bfd;
00368 char **error_message ATTRIBUTE_UNUSED;
00369 {
00370 unsigned long insn, vallo, allignment;
00371 int val;
00372
00373
00374
00375
00376
00377
00378 if (skip_dlx_elf_hi16_reloc)
00379 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
00380 input_section, output_bfd, error_message);
00381
00382
00383 if (bfd_is_und_section (symbol->section)
00384 && output_bfd == (bfd *) NULL)
00385 return bfd_reloc_undefined;
00386
00387
00388 if (strcmp (input_section->name, symbol->section->output_section->name) != 0)
00389 {
00390 fprintf (stderr,
00391 "BFD Link Error: jump (PC rel26) to section (%s) not supported\n",
00392 symbol->section->output_section->name);
00393 return bfd_reloc_undefined;
00394 }
00395
00396 insn = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address);
00397 allignment = 1 << (input_section->output_section->alignment_power - 1);
00398 vallo = insn & 0x03FFFFFF;
00399
00400 if (vallo & 0x03000000)
00401 vallo = ~(vallo | 0xFC000000) + 1;
00402
00403
00404 vallo += (((unsigned long) (input_section->output_section->vma +
00405 input_section->output_offset) +
00406 allignment) & ~allignment);
00407
00408
00409 val = (symbol->section->output_offset +
00410 symbol->section->output_section->vma + symbol->value)
00411 - vallo;
00412
00413 if (abs ((int) val) > 0x01FFFFFF)
00414 return bfd_reloc_outofrange;
00415
00416 insn = (insn & 0xFC000000) | (val & 0x03FFFFFF);
00417 bfd_put_32 (abfd, insn,
00418 (bfd_byte *) data + reloc_entry->address);
00419
00420 return bfd_reloc_ok;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 struct elf_reloc_map
00432 {
00433 bfd_reloc_code_real_type bfd_reloc_val;
00434 enum elf_dlx_reloc_type elf_reloc_val;
00435 };
00436
00437 static const struct elf_reloc_map dlx_reloc_map[] =
00438 {
00439 { BFD_RELOC_NONE, R_DLX_NONE },
00440 { BFD_RELOC_16, R_DLX_RELOC_16 },
00441 { BFD_RELOC_32, R_DLX_RELOC_32 },
00442 { BFD_RELOC_DLX_HI16_S, R_DLX_RELOC_16_HI },
00443 { BFD_RELOC_DLX_LO16, R_DLX_RELOC_16_LO },
00444 { BFD_RELOC_VTABLE_INHERIT, R_DLX_GNU_VTINHERIT },
00445 { BFD_RELOC_VTABLE_ENTRY, R_DLX_GNU_VTENTRY }
00446 };
00447
00448
00449
00450
00451
00452
00453 static bfd_boolean
00454 elf32_dlx_check_relocs (abfd, info, sec, relocs)
00455 bfd *abfd;
00456 struct bfd_link_info *info;
00457 asection *sec;
00458 const Elf_Internal_Rela *relocs;
00459 {
00460 Elf_Internal_Shdr *symtab_hdr;
00461 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
00462 const Elf_Internal_Rela *rel;
00463 const Elf_Internal_Rela *rel_end;
00464
00465 if (info->relocatable)
00466 return TRUE;
00467
00468 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00469 sym_hashes = elf_sym_hashes (abfd);
00470 sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
00471 if (!elf_bad_symtab (abfd))
00472 sym_hashes_end -= symtab_hdr->sh_info;
00473
00474 rel_end = relocs + sec->reloc_count;
00475 for (rel = relocs; rel < rel_end; rel++)
00476 {
00477 struct elf_link_hash_entry *h;
00478 unsigned long r_symndx;
00479
00480 r_symndx = ELF32_R_SYM (rel->r_info);
00481 if (r_symndx < symtab_hdr->sh_info)
00482 h = NULL;
00483 else
00484 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00485
00486 switch (ELF32_R_TYPE (rel->r_info))
00487 {
00488
00489
00490 case R_DLX_GNU_VTINHERIT:
00491 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00492 return FALSE;
00493 break;
00494
00495
00496
00497 case R_DLX_GNU_VTENTRY:
00498 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00499 return FALSE;
00500 break;
00501 }
00502 }
00503
00504 return TRUE;
00505 }
00506
00507
00508
00509 static reloc_howto_type *
00510 elf32_dlx_reloc_type_lookup (abfd, code)
00511 bfd *abfd ATTRIBUTE_UNUSED;
00512 bfd_reloc_code_real_type code;
00513 {
00514 unsigned int i;
00515
00516 for (i = 0; i < sizeof (dlx_reloc_map) / sizeof (struct elf_reloc_map); i++)
00517 if (dlx_reloc_map[i].bfd_reloc_val == code)
00518 return &dlx_elf_howto_table[(int) dlx_reloc_map[i].elf_reloc_val];
00519
00520 switch (code)
00521 {
00522 default:
00523 bfd_set_error (bfd_error_bad_value);
00524 return NULL;
00525 case BFD_RELOC_16_PCREL_S2:
00526 return &elf_dlx_gnu_rel16_s2;
00527 case BFD_RELOC_DLX_JMP26:
00528 return &elf_dlx_gnu_rel26_s2;
00529 case BFD_RELOC_HI16_S:
00530 return &elf_dlx_reloc_16_hi;
00531 case BFD_RELOC_LO16:
00532 return &elf_dlx_reloc_16_lo;
00533 }
00534 }
00535
00536 static reloc_howto_type *
00537 dlx_rtype_to_howto (r_type)
00538 unsigned int r_type;
00539 {
00540 switch (r_type)
00541 {
00542 case R_DLX_RELOC_16_PCREL:
00543 return & elf_dlx_gnu_rel16_s2;
00544 break;
00545 case R_DLX_RELOC_26_PCREL:
00546 return & elf_dlx_gnu_rel26_s2;
00547 break;
00548 case R_DLX_RELOC_16_HI:
00549 return & elf_dlx_reloc_16_hi;
00550 break;
00551 case R_DLX_RELOC_16_LO:
00552 return & elf_dlx_reloc_16_lo;
00553 break;
00554
00555 default:
00556 BFD_ASSERT (r_type < (unsigned int) R_DLX_max);
00557 return & dlx_elf_howto_table[r_type];
00558 break;
00559 }
00560 }
00561
00562 static void
00563 elf32_dlx_info_to_howto (abfd, cache_ptr, dst)
00564 bfd * abfd ATTRIBUTE_UNUSED;
00565 arelent * cache_ptr ATTRIBUTE_UNUSED;
00566 Elf_Internal_Rela * dst ATTRIBUTE_UNUSED;
00567 {
00568 abort ();
00569 }
00570
00571 static void
00572 elf32_dlx_info_to_howto_rel (abfd, cache_ptr, dst)
00573 bfd *abfd ATTRIBUTE_UNUSED;
00574 arelent *cache_ptr;
00575 Elf_Internal_Rela *dst;
00576 {
00577 unsigned int r_type;
00578
00579 r_type = ELF32_R_TYPE (dst->r_info);
00580 cache_ptr->howto = dlx_rtype_to_howto (r_type);
00581 return;
00582 }
00583
00584 #define TARGET_BIG_SYM bfd_elf32_dlx_big_vec
00585 #define TARGET_BIG_NAME "elf32-dlx"
00586 #define ELF_ARCH bfd_arch_dlx
00587 #define ELF_MACHINE_CODE EM_DLX
00588 #define ELF_MAXPAGESIZE 1
00589
00590 #include "elf32-target.h"