00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "bfd.h"
00028 #include "sysdep.h"
00029 #include "libbfd.h"
00030 #include "coff/m68k.h"
00031 #include "coff/internal.h"
00032 #include "libcoff.h"
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
00056
00057 #ifndef COFF_PAGE_SIZE
00058
00059 #define COFF_PAGE_SIZE 0x2000
00060 #endif
00061
00062 #ifndef COFF_COMMON_ADDEND
00063 #define RELOC_SPECIAL_FN 0
00064 #else
00065 static bfd_reloc_status_type m68kcoff_common_addend_special_fn
00066 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00067 static reloc_howto_type *m68kcoff_common_addend_rtype_to_howto
00068 PARAMS ((bfd *, asection *, struct internal_reloc *,
00069 struct coff_link_hash_entry *, struct internal_syment *,
00070 bfd_vma *));
00071 #define RELOC_SPECIAL_FN m68kcoff_common_addend_special_fn
00072 #endif
00073
00074 static bfd_boolean m68k_coff_is_local_label_name
00075 PARAMS ((bfd *, const char *));
00076
00077
00078
00079
00080
00081 static bfd_boolean
00082 m68k_coff_is_local_label_name (abfd, name)
00083 bfd *abfd;
00084 const char *name;
00085 {
00086 if (name[0] == 'L' && name[1] == '%')
00087 return TRUE;
00088
00089 return _bfd_coff_is_local_label_name (abfd, name);
00090 }
00091
00092 #ifndef STATIC_RELOCS
00093
00094 #define m68kcoff_howto_table _bfd_m68kcoff_howto_table
00095 #define m68k_rtype2howto _bfd_m68kcoff_rtype2howto
00096 #define m68k_howto2rtype _bfd_m68kcoff_howto2rtype
00097 #define m68k_reloc_type_lookup _bfd_m68kcoff_reloc_type_lookup
00098 #endif
00099
00100 #ifdef ONLY_DECLARE_RELOCS
00101 extern reloc_howto_type m68kcoff_howto_table[];
00102 #else
00103 #ifdef STATIC_RELOCS
00104 static
00105 #endif
00106 reloc_howto_type m68kcoff_howto_table[] =
00107 {
00108 HOWTO (R_RELBYTE, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "8", TRUE, 0x000000ff,0x000000ff, FALSE),
00109 HOWTO (R_RELWORD, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
00110 HOWTO (R_RELLONG, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "32", TRUE, 0xffffffff,0xffffffff, FALSE),
00111 HOWTO (R_PCRBYTE, 0, 0, 8, TRUE, 0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP8", TRUE, 0x000000ff,0x000000ff, FALSE),
00112 HOWTO (R_PCRWORD, 0, 1, 16, TRUE, 0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
00113 HOWTO (R_PCRLONG, 0, 2, 32, TRUE, 0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP32", TRUE, 0xffffffff,0xffffffff, FALSE),
00114 HOWTO (R_RELLONG_NEG, 0, -2, 32, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "-32", TRUE, 0xffffffff,0xffffffff, FALSE),
00115 };
00116 #endif
00117
00118 #ifndef BADMAG
00119 #define BADMAG(x) M68KBADMAG(x)
00120 #endif
00121 #define M68 1
00122
00123
00124
00125 #ifdef ONLY_DECLARE_RELOCS
00126 extern void m68k_rtype2howto PARAMS ((arelent *internal, int relocentry));
00127 extern int m68k_howto2rtype PARAMS ((reloc_howto_type *));
00128 extern reloc_howto_type *m68k_reloc_type_lookup
00129 PARAMS ((bfd *, bfd_reloc_code_real_type));
00130 #else
00131
00132 #ifdef STATIC_RELOCS
00133 #define STAT_REL static
00134 #else
00135 #define STAT_REL
00136 #endif
00137
00138 STAT_REL reloc_howto_type * m68k_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
00139 STAT_REL int m68k_howto2rtype PARAMS ((reloc_howto_type *));
00140 STAT_REL void m68k_rtype2howto PARAMS ((arelent *, int));
00141
00142
00143 STAT_REL void
00144 m68k_rtype2howto(internal, relocentry)
00145 arelent *internal;
00146 int relocentry;
00147 {
00148 switch (relocentry)
00149 {
00150 case R_RELBYTE: internal->howto = m68kcoff_howto_table + 0; break;
00151 case R_RELWORD: internal->howto = m68kcoff_howto_table + 1; break;
00152 case R_RELLONG: internal->howto = m68kcoff_howto_table + 2; break;
00153 case R_PCRBYTE: internal->howto = m68kcoff_howto_table + 3; break;
00154 case R_PCRWORD: internal->howto = m68kcoff_howto_table + 4; break;
00155 case R_PCRLONG: internal->howto = m68kcoff_howto_table + 5; break;
00156 case R_RELLONG_NEG: internal->howto = m68kcoff_howto_table + 6; break;
00157 }
00158 }
00159
00160 STAT_REL int
00161 m68k_howto2rtype (internal)
00162 reloc_howto_type *internal;
00163 {
00164 if (internal->pc_relative)
00165 {
00166 switch (internal->bitsize)
00167 {
00168 case 32: return R_PCRLONG;
00169 case 16: return R_PCRWORD;
00170 case 8: return R_PCRBYTE;
00171 }
00172 }
00173 else
00174 {
00175 switch (internal->bitsize)
00176 {
00177 case 32: return R_RELLONG;
00178 case 16: return R_RELWORD;
00179 case 8: return R_RELBYTE;
00180 }
00181 }
00182 return R_RELLONG;
00183 }
00184
00185 STAT_REL reloc_howto_type *
00186 m68k_reloc_type_lookup (abfd, code)
00187 bfd *abfd ATTRIBUTE_UNUSED;
00188 bfd_reloc_code_real_type code;
00189 {
00190 switch (code)
00191 {
00192 default: return NULL;
00193 case BFD_RELOC_8: return m68kcoff_howto_table + 0;
00194 case BFD_RELOC_16: return m68kcoff_howto_table + 1;
00195 case BFD_RELOC_CTOR:
00196 case BFD_RELOC_32: return m68kcoff_howto_table + 2;
00197 case BFD_RELOC_8_PCREL: return m68kcoff_howto_table + 3;
00198 case BFD_RELOC_16_PCREL: return m68kcoff_howto_table + 4;
00199 case BFD_RELOC_32_PCREL: return m68kcoff_howto_table + 5;
00200
00201 }
00202
00203 }
00204
00205 #endif
00206
00207 #define RTYPE2HOWTO(internal, relocentry) \
00208 m68k_rtype2howto(internal, (relocentry)->r_type)
00209
00210 #define SELECT_RELOC(external, internal) \
00211 external.r_type = m68k_howto2rtype (internal)
00212
00213 #define coff_bfd_reloc_type_lookup m68k_reloc_type_lookup
00214
00215 #ifndef COFF_COMMON_ADDEND
00216 #ifndef coff_rtype_to_howto
00217
00218 #define coff_rtype_to_howto m68kcoff_rtype_to_howto
00219
00220 static reloc_howto_type *m68kcoff_rtype_to_howto
00221 PARAMS ((bfd *, asection *, struct internal_reloc *,
00222 struct coff_link_hash_entry *, struct internal_syment *,
00223 bfd_vma *));
00224
00225 static reloc_howto_type *
00226 m68kcoff_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00227 bfd *abfd ATTRIBUTE_UNUSED;
00228 asection *sec;
00229 struct internal_reloc *rel;
00230 struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
00231 struct internal_syment *sym ATTRIBUTE_UNUSED;
00232 bfd_vma *addendp;
00233 {
00234 arelent relent;
00235 reloc_howto_type *howto;
00236
00237 RTYPE2HOWTO (&relent, rel);
00238
00239 howto = relent.howto;
00240
00241 if (howto->pc_relative)
00242 *addendp += sec->vma;
00243
00244 return howto;
00245 }
00246
00247 #endif
00248 #endif
00249
00250 #ifdef COFF_COMMON_ADDEND
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 static bfd_reloc_status_type
00263 m68kcoff_common_addend_special_fn (abfd, reloc_entry, symbol, data,
00264 input_section, output_bfd, error_message)
00265 bfd *abfd;
00266 arelent *reloc_entry;
00267 asymbol *symbol;
00268 PTR data;
00269 asection *input_section ATTRIBUTE_UNUSED;
00270 bfd *output_bfd;
00271 char **error_message ATTRIBUTE_UNUSED;
00272 {
00273 symvalue diff;
00274
00275 if (output_bfd == (bfd *) NULL)
00276 return bfd_reloc_continue;
00277
00278 if (bfd_is_com_section (symbol->section))
00279 {
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 diff = symbol->value + reloc_entry->addend;
00292 }
00293 else
00294 {
00295
00296
00297
00298
00299 diff = reloc_entry->addend;
00300 }
00301
00302 #define DOIT(x) \
00303 x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
00304
00305 if (diff != 0)
00306 {
00307 reloc_howto_type *howto = reloc_entry->howto;
00308 unsigned char *addr = (unsigned char *) data + reloc_entry->address;
00309
00310 switch (howto->size)
00311 {
00312 case 0:
00313 {
00314 char x = bfd_get_8 (abfd, addr);
00315 DOIT (x);
00316 bfd_put_8 (abfd, x, addr);
00317 }
00318 break;
00319
00320 case 1:
00321 {
00322 short x = bfd_get_16 (abfd, addr);
00323 DOIT (x);
00324 bfd_put_16 (abfd, (bfd_vma) x, addr);
00325 }
00326 break;
00327
00328 case 2:
00329 {
00330 long x = bfd_get_32 (abfd, addr);
00331 DOIT (x);
00332 bfd_put_32 (abfd, (bfd_vma) x, addr);
00333 }
00334 break;
00335
00336 default:
00337 abort ();
00338 }
00339 }
00340
00341
00342 return bfd_reloc_continue;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
00359 { \
00360 coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
00361 if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
00362 coffsym = (obj_symbols (abfd) \
00363 + (cache_ptr->sym_ptr_ptr - symbols)); \
00364 else if (ptr) \
00365 coffsym = coff_symbol_from (abfd, ptr); \
00366 if (coffsym != (coff_symbol_type *) NULL \
00367 && coffsym->native->u.syment.n_scnum == 0) \
00368 cache_ptr->addend = - coffsym->native->u.syment.n_value; \
00369 else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
00370 && ptr->section != (asection *) NULL) \
00371 cache_ptr->addend = - (ptr->section->vma + ptr->value); \
00372 else \
00373 cache_ptr->addend = 0; \
00374 if (ptr && (reloc.r_type == R_PCRBYTE \
00375 || reloc.r_type == R_PCRWORD \
00376 || reloc.r_type == R_PCRLONG)) \
00377 cache_ptr->addend += asect->vma; \
00378 }
00379
00380 #ifndef coff_rtype_to_howto
00381
00382
00383
00384
00385 static reloc_howto_type *
00386 m68kcoff_common_addend_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00387 bfd *abfd ATTRIBUTE_UNUSED;
00388 asection *sec;
00389 struct internal_reloc *rel;
00390 struct coff_link_hash_entry *h;
00391 struct internal_syment *sym;
00392 bfd_vma *addendp;
00393 {
00394 arelent relent;
00395 reloc_howto_type *howto;
00396
00397 RTYPE2HOWTO (&relent, rel);
00398
00399 howto = relent.howto;
00400
00401 if (howto->pc_relative)
00402 *addendp += sec->vma;
00403
00404 if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
00405 {
00406
00407
00408
00409
00410
00411 BFD_ASSERT (h != NULL);
00412 *addendp -= sym->n_value;
00413 }
00414
00415
00416
00417
00418 if (h != NULL && h->root.type == bfd_link_hash_common)
00419 *addendp += h->root.u.c.size;
00420
00421 return howto;
00422 }
00423
00424 #define coff_rtype_to_howto m68kcoff_common_addend_rtype_to_howto
00425
00426 #endif
00427
00428 #endif
00429
00430 #if !defined ONLY_DECLARE_RELOCS && ! defined STATIC_RELOCS
00431
00432
00433
00434
00435
00436
00437
00438 bfd_boolean
00439 bfd_m68k_coff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
00440 bfd *abfd;
00441 struct bfd_link_info *info;
00442 asection *datasec;
00443 asection *relsec;
00444 char **errmsg;
00445 {
00446 char *extsyms;
00447 bfd_size_type symesz;
00448 struct internal_reloc *irel, *irelend;
00449 bfd_byte *p;
00450 bfd_size_type amt;
00451
00452 BFD_ASSERT (! info->relocatable);
00453
00454 *errmsg = NULL;
00455
00456 if (datasec->reloc_count == 0)
00457 return TRUE;
00458
00459 extsyms = obj_coff_external_syms (abfd);
00460 symesz = bfd_coff_symesz (abfd);
00461
00462 irel = _bfd_coff_read_internal_relocs (abfd, datasec, TRUE, NULL, FALSE,
00463 NULL);
00464 irelend = irel + datasec->reloc_count;
00465
00466 amt = (bfd_size_type) datasec->reloc_count * 12;
00467 relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
00468 if (relsec->contents == NULL)
00469 return FALSE;
00470
00471 p = relsec->contents;
00472
00473 for (; irel < irelend; irel++, p += 12)
00474 {
00475 asection *targetsec;
00476
00477
00478
00479
00480
00481
00482
00483
00484 if (irel->r_type != R_RELLONG)
00485 {
00486 *errmsg = _("unsupported reloc type");
00487 bfd_set_error (bfd_error_bad_value);
00488 return FALSE;
00489 }
00490
00491 if (irel->r_symndx == -1)
00492 targetsec = bfd_abs_section_ptr;
00493 else
00494 {
00495 struct coff_link_hash_entry *h;
00496
00497 h = obj_coff_sym_hashes (abfd)[irel->r_symndx];
00498 if (h == NULL)
00499 {
00500 struct internal_syment isym;
00501
00502 bfd_coff_swap_sym_in (abfd, extsyms + symesz * irel->r_symndx,
00503 &isym);
00504 targetsec = coff_section_from_bfd_index (abfd, isym.n_scnum);
00505 }
00506 else if (h->root.type == bfd_link_hash_defined
00507 || h->root.type == bfd_link_hash_defweak)
00508 targetsec = h->root.u.def.section;
00509 else
00510 targetsec = NULL;
00511 }
00512
00513 bfd_put_32 (abfd,
00514 (irel->r_vaddr - datasec->vma + datasec->output_offset), p);
00515 memset (p + 4, 0, 8);
00516 if (targetsec != NULL)
00517 strncpy ((char *) p + 4, targetsec->output_section->name, 8);
00518 }
00519
00520 return TRUE;
00521 }
00522 #endif
00523
00524 #define coff_bfd_is_local_label_name m68k_coff_is_local_label_name
00525
00526 #define coff_relocate_section _bfd_coff_generic_relocate_section
00527
00528 #include "coffcode.h"
00529
00530 #ifndef TARGET_SYM
00531 #define TARGET_SYM m68kcoff_vec
00532 #endif
00533
00534 #ifndef TARGET_NAME
00535 #define TARGET_NAME "coff-m68k"
00536 #endif
00537
00538 #ifdef NAMES_HAVE_UNDERSCORE
00539 CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE)
00540 #else
00541 CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, 0, NULL, COFF_SWAP_TABLE)
00542 #endif