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 #include "bfd.h"
00027 #include "sysdep.h"
00028
00029
00030
00031
00032
00033
00034 #define NAME(x,y) CONCAT3 (aoutarm,_32_,y)
00035
00036 #define N_TXTADDR(x) \
00037 ((N_MAGIC (x) == NMAGIC) \
00038 ? (bfd_vma) 0x8000 \
00039 : ((N_MAGIC (x) != ZMAGIC) \
00040 ? (bfd_vma) 0 \
00041 : ((N_SHARED_LIB (x)) \
00042 ? ((x).a_entry & ~(bfd_vma) (TARGET_PAGE_SIZE - 1)) \
00043 : (bfd_vma) TEXT_START_ADDR)))
00044
00045 #define TEXT_START_ADDR 0x8000
00046 #define TARGET_PAGE_SIZE 0x8000
00047 #define SEGMENT_SIZE TARGET_PAGE_SIZE
00048 #define DEFAULT_ARCH bfd_arch_arm
00049
00050 #define MY(OP) CONCAT2 (aoutarm_,OP)
00051 #define N_BADMAG(x) ((((x).a_info & ~007200) != ZMAGIC) && \
00052 (((x).a_info & ~006000) != OMAGIC) && \
00053 ((x).a_info != NMAGIC))
00054 #define N_MAGIC(x) ((x).a_info & ~07200)
00055
00056 #define MY_bfd_reloc_type_lookup aoutarm_bfd_reloc_type_lookup
00057
00058 #include "libaout.h"
00059 #include "aout/aout64.h"
00060
00061 static bfd_boolean MY(write_object_contents)
00062 PARAMS ((bfd *));
00063 static bfd_reloc_status_type MY(fix_pcrel_26_done)
00064 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00065 static bfd_reloc_status_type MY(fix_pcrel_26)
00066 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00067 static void MY(swap_std_reloc_in)
00068 PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
00069 bfd_size_type));
00070 reloc_howto_type *MY(bfd_reloc_type_lookup)
00071 PARAMS ((bfd *, bfd_reloc_code_real_type));
00072 reloc_howto_type * MY(reloc_howto)
00073 PARAMS ((bfd *, struct reloc_std_external *, int *, int *, int *));
00074 void MY(put_reloc)
00075 PARAMS ((bfd *, int, int, bfd_vma, reloc_howto_type *,
00076 struct reloc_std_external *));
00077 void MY(relocatable_reloc)
00078 PARAMS ((reloc_howto_type *, bfd *, struct reloc_std_external *, bfd_vma *,
00079 bfd_vma));
00080 void MY(swap_std_reloc_out)
00081 PARAMS ((bfd *, arelent *, struct reloc_std_external *));
00082
00083 reloc_howto_type MY(howto_table)[] =
00084 {
00085
00086
00087 HOWTO (0, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "8", TRUE,
00088 0x000000ff, 0x000000ff, FALSE),
00089 HOWTO (1, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 0, "16", TRUE,
00090 0x0000ffff, 0x0000ffff, FALSE),
00091 HOWTO (2, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "32", TRUE,
00092 0xffffffff, 0xffffffff, FALSE),
00093 HOWTO (3, 2, 2, 26, TRUE, 0, complain_overflow_signed, MY(fix_pcrel_26),
00094 "ARM26", TRUE, 0x00ffffff, 0x00ffffff, TRUE),
00095 HOWTO (4, 0, 0, 8, TRUE, 0, complain_overflow_signed, 0, "DISP8", TRUE,
00096 0x000000ff, 0x000000ff, TRUE),
00097 HOWTO (5, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "DISP16", TRUE,
00098 0x0000ffff, 0x0000ffff, TRUE),
00099 HOWTO (6, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0, "DISP32", TRUE,
00100 0xffffffff, 0xffffffff, TRUE),
00101 HOWTO (7, 2, 2, 26, FALSE, 0, complain_overflow_signed,
00102 MY(fix_pcrel_26_done), "ARM26D", TRUE, 0x0, 0x0,
00103 FALSE),
00104 EMPTY_HOWTO (-1),
00105 HOWTO (9, 0, -1, 16, FALSE, 0, complain_overflow_bitfield, 0, "NEG16", TRUE,
00106 0x0000ffff, 0x0000ffff, FALSE),
00107 HOWTO (10, 0, -2, 32, FALSE, 0, complain_overflow_bitfield, 0, "NEG32", TRUE,
00108 0xffffffff, 0xffffffff, FALSE)
00109 };
00110
00111 #define RELOC_ARM_BITS_NEG_BIG ((unsigned int) 0x08)
00112 #define RELOC_ARM_BITS_NEG_LITTLE ((unsigned int) 0x10)
00113
00114 reloc_howto_type *
00115 MY(reloc_howto) (abfd, rel, r_index, r_extern, r_pcrel)
00116 bfd *abfd;
00117 struct reloc_std_external *rel;
00118 int *r_index;
00119 int *r_extern;
00120 int *r_pcrel;
00121 {
00122 unsigned int r_length;
00123 unsigned int r_pcrel_done;
00124 unsigned int r_neg;
00125 int index;
00126
00127 *r_pcrel = 0;
00128 if (bfd_header_big_endian (abfd))
00129 {
00130 *r_index = ((rel->r_index[0] << 16)
00131 | (rel->r_index[1] << 8)
00132 | rel->r_index[2]);
00133 *r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
00134 r_pcrel_done = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
00135 r_neg = (0 != (rel->r_type[0] & RELOC_ARM_BITS_NEG_BIG));
00136 r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
00137 >> RELOC_STD_BITS_LENGTH_SH_BIG);
00138 }
00139 else
00140 {
00141 *r_index = ((rel->r_index[2] << 16)
00142 | (rel->r_index[1] << 8)
00143 | rel->r_index[0]);
00144 *r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
00145 r_pcrel_done = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
00146 r_neg = (0 != (rel->r_type[0] & RELOC_ARM_BITS_NEG_LITTLE));
00147 r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
00148 >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
00149 }
00150 index = r_length + 4 * r_pcrel_done + 8 * r_neg;
00151 if (index == 3)
00152 *r_pcrel = 1;
00153
00154 return MY(howto_table) + index;
00155 }
00156
00157 #define MY_reloc_howto(BFD, REL, IN, EX, PC) \
00158 MY(reloc_howto) (BFD, REL, &IN, &EX, &PC)
00159
00160 void
00161 MY(put_reloc) (abfd, r_extern, r_index, value, howto, reloc)
00162 bfd *abfd;
00163 int r_extern;
00164 int r_index;
00165 bfd_vma value;
00166 reloc_howto_type *howto;
00167 struct reloc_std_external *reloc;
00168 {
00169 unsigned int r_length;
00170 int r_pcrel;
00171 int r_neg;
00172
00173 PUT_WORD (abfd, value, reloc->r_address);
00174
00175 r_length = howto->size;
00176
00177
00178 if (howto->type == 3 || howto->type == 7)
00179 r_length = 3;
00180
00181 r_pcrel = howto->type & 4;
00182 r_neg = howto->type & 8;
00183
00184 if (bfd_header_big_endian (abfd))
00185 {
00186 reloc->r_index[0] = r_index >> 16;
00187 reloc->r_index[1] = r_index >> 8;
00188 reloc->r_index[2] = r_index;
00189 reloc->r_type[0] =
00190 ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
00191 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
00192 | (r_neg ? RELOC_ARM_BITS_NEG_BIG : 0)
00193 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
00194 }
00195 else
00196 {
00197 reloc->r_index[2] = r_index >> 16;
00198 reloc->r_index[1] = r_index >> 8;
00199 reloc->r_index[0] = r_index;
00200 reloc->r_type[0] =
00201 ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
00202 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
00203 | (r_neg ? RELOC_ARM_BITS_NEG_LITTLE : 0)
00204 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
00205 }
00206 }
00207
00208 #define MY_put_reloc(BFD, EXT, IDX, VAL, HOWTO, RELOC) \
00209 MY(put_reloc) (BFD, EXT, IDX, VAL, HOWTO, RELOC)
00210
00211 void
00212 MY(relocatable_reloc) (howto, abfd, reloc, amount, r_addr)
00213 reloc_howto_type *howto;
00214 bfd *abfd;
00215 struct reloc_std_external *reloc;
00216 bfd_vma *amount;
00217 bfd_vma r_addr;
00218 {
00219 if (howto->type == 3)
00220 {
00221 if (reloc->r_type[0]
00222 & (bfd_header_big_endian (abfd)
00223 ? RELOC_STD_BITS_EXTERN_BIG : RELOC_STD_BITS_EXTERN_LITTLE))
00224 {
00225
00226 *amount = 0;
00227 }
00228 else
00229 {
00230 *amount -= r_addr;
00231
00232
00233 if (bfd_header_big_endian (abfd))
00234 reloc->r_type[0] |= RELOC_STD_BITS_PCREL_BIG;
00235 else
00236 reloc->r_type[0] |= RELOC_STD_BITS_PCREL_LITTLE;
00237 }
00238 }
00239 else if (howto->type == 7)
00240 *amount = 0;
00241 }
00242
00243 #define MY_relocatable_reloc(HOW, BFD, REL, AMOUNT, ADDR) \
00244 MY(relocatable_reloc) (HOW, BFD, REL, &(AMOUNT), ADDR)
00245
00246 static bfd_reloc_status_type
00247 MY(fix_pcrel_26_done) (abfd, reloc_entry, symbol, data, input_section,
00248 output_bfd, error_message)
00249 bfd *abfd ATTRIBUTE_UNUSED;
00250 arelent *reloc_entry ATTRIBUTE_UNUSED;
00251 asymbol *symbol ATTRIBUTE_UNUSED;
00252 PTR data ATTRIBUTE_UNUSED;
00253 asection *input_section ATTRIBUTE_UNUSED;
00254 bfd *output_bfd ATTRIBUTE_UNUSED;
00255 char **error_message ATTRIBUTE_UNUSED;
00256 {
00257
00258 return bfd_reloc_ok;
00259 }
00260
00261 static bfd_reloc_status_type
00262 MY(fix_pcrel_26) (abfd, reloc_entry, symbol, data, input_section,
00263 output_bfd, error_message)
00264 bfd *abfd;
00265 arelent *reloc_entry;
00266 asymbol *symbol;
00267 PTR data;
00268 asection *input_section;
00269 bfd *output_bfd;
00270 char **error_message ATTRIBUTE_UNUSED;
00271 {
00272 bfd_vma relocation;
00273 bfd_size_type addr = reloc_entry->address;
00274 bfd_vma target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
00275 bfd_reloc_status_type flag = bfd_reloc_ok;
00276
00277
00278 if (symbol->section == &bfd_und_section
00279 && (symbol->flags & BSF_WEAK) == 0)
00280 return output_bfd ? bfd_reloc_ok : bfd_reloc_undefined;
00281
00282
00283
00284 if (symbol->section->name != input_section->name
00285 && output_bfd != (bfd *)NULL)
00286 return bfd_reloc_ok;
00287
00288 relocation = (target & 0x00ffffff) << 2;
00289 relocation = (relocation ^ 0x02000000) - 0x02000000;
00290 relocation += symbol->value;
00291 relocation += symbol->section->output_section->vma;
00292 relocation += symbol->section->output_offset;
00293 relocation += reloc_entry->addend;
00294 relocation -= input_section->output_section->vma;
00295 relocation -= input_section->output_offset;
00296 relocation -= addr;
00297 if (relocation & 3)
00298 return bfd_reloc_overflow;
00299
00300
00301 if (relocation & 0x02000000)
00302 {
00303 if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
00304 flag = bfd_reloc_overflow;
00305 }
00306 else if (relocation & ~ (bfd_vma) 0x03ffffff)
00307 flag = bfd_reloc_overflow;
00308
00309 target &= ~ (bfd_vma) 0x00ffffff;
00310 target |= (relocation >> 2) & 0x00ffffff;
00311 bfd_put_32 (abfd, target, (bfd_byte *) data + addr);
00312
00313
00314
00315 reloc_entry->howto = &MY(howto_table)[7];
00316
00317 return flag;
00318 }
00319
00320 reloc_howto_type *
00321 MY(bfd_reloc_type_lookup) (abfd,code)
00322 bfd *abfd;
00323 bfd_reloc_code_real_type code;
00324 {
00325 #define ASTD(i,j) case i: return &MY(howto_table)[j]
00326 if (code == BFD_RELOC_CTOR)
00327 switch (bfd_get_arch_info (abfd)->bits_per_address)
00328 {
00329 case 32:
00330 code = BFD_RELOC_32;
00331 break;
00332 default:
00333 return (const struct reloc_howto_struct *) 0;
00334 }
00335
00336 switch (code)
00337 {
00338 ASTD (BFD_RELOC_16, 1);
00339 ASTD (BFD_RELOC_32, 2);
00340 ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
00341 ASTD (BFD_RELOC_8_PCREL, 4);
00342 ASTD (BFD_RELOC_16_PCREL, 5);
00343 ASTD (BFD_RELOC_32_PCREL, 6);
00344 default:
00345 return (const struct reloc_howto_struct *) 0;
00346 }
00347 }
00348
00349 #define MY_swap_std_reloc_in MY(swap_std_reloc_in)
00350 #define MY_swap_std_reloc_out MY(swap_std_reloc_out)
00351 #define MY_get_section_contents _bfd_generic_get_section_contents
00352
00353
00354
00355
00356 #include "aoutx.h"
00357
00358 static void
00359 MY_swap_std_reloc_in (abfd, bytes, cache_ptr, symbols, symcount)
00360 bfd *abfd;
00361 struct reloc_std_external *bytes;
00362 arelent *cache_ptr;
00363 asymbol **symbols;
00364 bfd_size_type symcount ATTRIBUTE_UNUSED;
00365 {
00366 int r_index;
00367 int r_extern;
00368 int r_pcrel;
00369 struct aoutdata *su = &(abfd->tdata.aout_data->a);
00370
00371 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
00372
00373 cache_ptr->howto = MY_reloc_howto (abfd, bytes, r_index, r_extern, r_pcrel);
00374
00375 MOVE_ADDRESS (0);
00376 }
00377
00378 void
00379 MY_swap_std_reloc_out (abfd, g, natptr)
00380 bfd *abfd;
00381 arelent *g;
00382 struct reloc_std_external *natptr;
00383 {
00384 int r_index;
00385 asymbol *sym = *(g->sym_ptr_ptr);
00386 int r_extern;
00387 int r_length;
00388 int r_pcrel;
00389 int r_neg = 0;
00390 asection *output_section = sym->section->output_section;
00391
00392 PUT_WORD(abfd, g->address, natptr->r_address);
00393
00394 r_length = g->howto->size ;
00395 if (r_length < 0)
00396 {
00397 r_length = -r_length;
00398 r_neg = 1;
00399 }
00400
00401 r_pcrel = (int) g->howto->pc_relative;
00402
00403
00404
00405
00406
00407 if (g->howto->type == 3)
00408 {
00409 r_length = 3;
00410 r_pcrel = 0;
00411 }
00412 else if (g->howto->type == 7)
00413 {
00414 r_length = 3;
00415 r_pcrel = 1;
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 if (bfd_is_com_section (output_section)
00429 || output_section == &bfd_abs_section
00430 || output_section == &bfd_und_section)
00431 {
00432 if (bfd_abs_section.symbol == sym)
00433 {
00434
00435
00436 r_index = 0;
00437 r_extern = 0;
00438 }
00439 else
00440 {
00441
00442 r_extern = 1;
00443 r_index = (*(g->sym_ptr_ptr))->KEEPIT;
00444 }
00445 }
00446 else
00447 {
00448
00449 r_extern = 0;
00450 r_index = output_section->target_index;
00451 }
00452
00453
00454 if (bfd_header_big_endian (abfd))
00455 {
00456 natptr->r_index[0] = r_index >> 16;
00457 natptr->r_index[1] = r_index >> 8;
00458 natptr->r_index[2] = r_index;
00459 natptr->r_type[0] =
00460 ( (r_extern ? RELOC_STD_BITS_EXTERN_BIG: 0)
00461 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG: 0)
00462 | (r_neg ? RELOC_ARM_BITS_NEG_BIG: 0)
00463 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
00464 }
00465 else
00466 {
00467 natptr->r_index[2] = r_index >> 16;
00468 natptr->r_index[1] = r_index >> 8;
00469 natptr->r_index[0] = r_index;
00470 natptr->r_type[0] =
00471 ( (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE: 0)
00472 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE: 0)
00473 | (r_neg ? RELOC_ARM_BITS_NEG_LITTLE: 0)
00474 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
00475 }
00476 }
00477
00478 #define MY_BFD_TARGET
00479
00480 #include "aout-target.h"
00481
00482 extern const bfd_target aout_arm_big_vec;
00483
00484 const bfd_target aout_arm_little_vec =
00485 {
00486 "a.out-arm-little",
00487 bfd_target_aout_flavour,
00488 BFD_ENDIAN_LITTLE,
00489 BFD_ENDIAN_LITTLE,
00490 (HAS_RELOC | EXEC_P |
00491 HAS_LINENO | HAS_DEBUG |
00492 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
00493 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
00494 MY_symbol_leading_char,
00495 AR_PAD_CHAR,
00496 15,
00497 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00498 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00499 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
00500 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00501 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00502 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
00503 {_bfd_dummy_target, MY_object_p,
00504 bfd_generic_archive_p, MY_core_file_p},
00505 {bfd_false, MY_mkobject,
00506 _bfd_generic_mkarchive, bfd_false},
00507 {bfd_false, MY_write_object_contents,
00508 _bfd_write_archive_contents, bfd_false},
00509
00510 BFD_JUMP_TABLE_GENERIC (MY),
00511 BFD_JUMP_TABLE_COPY (MY),
00512 BFD_JUMP_TABLE_CORE (MY),
00513 BFD_JUMP_TABLE_ARCHIVE (MY),
00514 BFD_JUMP_TABLE_SYMBOLS (MY),
00515 BFD_JUMP_TABLE_RELOCS (MY),
00516 BFD_JUMP_TABLE_WRITE (MY),
00517 BFD_JUMP_TABLE_LINK (MY),
00518 BFD_JUMP_TABLE_DYNAMIC (MY),
00519
00520 & aout_arm_big_vec,
00521
00522 (PTR) MY_backend_data,
00523 };
00524
00525 const bfd_target aout_arm_big_vec =
00526 {
00527 "a.out-arm-big",
00528 bfd_target_aout_flavour,
00529 BFD_ENDIAN_BIG,
00530 BFD_ENDIAN_BIG,
00531 (HAS_RELOC | EXEC_P |
00532 HAS_LINENO | HAS_DEBUG |
00533 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
00534 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
00535 MY_symbol_leading_char,
00536 AR_PAD_CHAR,
00537 15,
00538 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00539 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00540 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
00541 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00542 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00543 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
00544 {_bfd_dummy_target, MY_object_p,
00545 bfd_generic_archive_p, MY_core_file_p},
00546 {bfd_false, MY_mkobject,
00547 _bfd_generic_mkarchive, bfd_false},
00548 {bfd_false, MY_write_object_contents,
00549 _bfd_write_archive_contents, bfd_false},
00550
00551 BFD_JUMP_TABLE_GENERIC (MY),
00552 BFD_JUMP_TABLE_COPY (MY),
00553 BFD_JUMP_TABLE_CORE (MY),
00554 BFD_JUMP_TABLE_ARCHIVE (MY),
00555 BFD_JUMP_TABLE_SYMBOLS (MY),
00556 BFD_JUMP_TABLE_RELOCS (MY),
00557 BFD_JUMP_TABLE_WRITE (MY),
00558 BFD_JUMP_TABLE_LINK (MY),
00559 BFD_JUMP_TABLE_DYNAMIC (MY),
00560
00561 & aout_arm_little_vec,
00562
00563 (PTR) MY_backend_data,
00564 };