1/* BFD back-end for oasys objects. 2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, 3 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4 Written by Steve Chamberlain of Cygnus Support, <sac@cygnus.com>. 5 6 This file is part of BFD, the Binary File Descriptor library. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 21 22#define UNDERSCORE_HACK 1 23#include "bfd.h" 24#include "sysdep.h" 25#include "safe-ctype.h" 26#include "libbfd.h" 27#include "oasys.h" 28#include "liboasys.h" 29 30/* Read in all the section data and relocation stuff too. */ 31 32static bfd_boolean 33oasys_read_record (bfd *abfd, oasys_record_union_type *record) 34{ 35 bfd_size_type amt = sizeof (record->header); 36 37 if (bfd_bread ((void *) record, amt, abfd) != amt) 38 return FALSE; 39 40 amt = record->header.length - sizeof (record->header); 41 if ((long) amt <= 0) 42 return TRUE; 43 if (bfd_bread ((void *) ((char *) record + sizeof (record->header)), amt, abfd) 44 != amt) 45 return FALSE; 46 return TRUE; 47} 48 49static size_t 50oasys_string_length (oasys_record_union_type *record) 51{ 52 return record->header.length 53 - ((char *) record->symbol.name - (char *) record); 54} 55 56/* Slurp the symbol table by reading in all the records at the start file 57 till we get to the first section record. 58 59 We'll sort the symbolss into two lists, defined and undefined. The 60 undefined symbols will be placed into the table according to their 61 refno. 62 63 We do this by placing all undefined symbols at the front of the table 64 moving in, and the defined symbols at the end of the table moving back. */ 65 66static bfd_boolean 67oasys_slurp_symbol_table (bfd *const abfd) 68{ 69 oasys_record_union_type record; 70 oasys_data_type *data = OASYS_DATA (abfd); 71 bfd_boolean loop = TRUE; 72 asymbol *dest_defined; 73 asymbol *dest; 74 char *string_ptr; 75 bfd_size_type amt; 76 77 if (data->symbols != NULL) 78 return TRUE; 79 80 /* Buy enough memory for all the symbols and all the names. */ 81 amt = abfd->symcount; 82 amt *= sizeof (asymbol); 83 data->symbols = bfd_alloc (abfd, amt); 84 85 amt = data->symbol_string_length; 86#ifdef UNDERSCORE_HACK 87 /* Buy 1 more char for each symbol to keep the underscore in. */ 88 amt += abfd->symcount; 89#endif 90 data->strings = bfd_alloc (abfd, amt); 91 92 if (!data->symbols || !data->strings) 93 return FALSE; 94 95 dest_defined = data->symbols + abfd->symcount - 1; 96 97 string_ptr = data->strings; 98 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 99 return FALSE; 100 while (loop) 101 { 102 if (! oasys_read_record (abfd, &record)) 103 return FALSE; 104 105 switch (record.header.type) 106 { 107 case oasys_record_is_header_enum: 108 break; 109 case oasys_record_is_local_enum: 110 case oasys_record_is_symbol_enum: 111 { 112 int flag = record.header.type == (int) oasys_record_is_local_enum ? 113 (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT); 114 115 size_t length = oasys_string_length (&record); 116 switch (record.symbol.relb & RELOCATION_TYPE_BITS) 117 { 118 case RELOCATION_TYPE_ABS: 119 dest = dest_defined--; 120 dest->section = bfd_abs_section_ptr; 121 dest->flags = 0; 122 123 break; 124 case RELOCATION_TYPE_REL: 125 dest = dest_defined--; 126 dest->section = 127 OASYS_DATA (abfd)->sections[record.symbol.relb & 128 RELOCATION_SECT_BITS]; 129 if (record.header.type == (int) oasys_record_is_local_enum) 130 { 131 dest->flags = BSF_LOCAL; 132 if (dest->section == (asection *) (~0)) 133 { 134 /* It seems that sometimes internal symbols are tied up, but 135 still get output, even though there is no 136 section */ 137 dest->section = 0; 138 } 139 } 140 else 141 dest->flags = flag; 142 break; 143 case RELOCATION_TYPE_UND: 144 dest = data->symbols + H_GET_16 (abfd, record.symbol.refno); 145 dest->section = bfd_und_section_ptr; 146 break; 147 case RELOCATION_TYPE_COM: 148 dest = dest_defined--; 149 dest->name = string_ptr; 150 dest->the_bfd = abfd; 151 dest->section = bfd_com_section_ptr; 152 break; 153 default: 154 dest = dest_defined--; 155 BFD_ASSERT (FALSE); 156 break; 157 } 158 dest->name = string_ptr; 159 dest->the_bfd = abfd; 160 dest->udata.p = NULL; 161 dest->value = H_GET_32 (abfd, record.symbol.value); 162 163#ifdef UNDERSCORE_HACK 164 if (record.symbol.name[0] != '_') 165 { 166 string_ptr[0] = '_'; 167 string_ptr++; 168 } 169#endif 170 memcpy (string_ptr, record.symbol.name, length); 171 172 string_ptr[length] = 0; 173 string_ptr += length + 1; 174 } 175 break; 176 default: 177 loop = FALSE; 178 } 179 } 180 return TRUE; 181} 182 183static long 184oasys_get_symtab_upper_bound (bfd *const abfd) 185{ 186 if (! oasys_slurp_symbol_table (abfd)) 187 return -1; 188 189 return (abfd->symcount + 1) * (sizeof (oasys_symbol_type *)); 190} 191 192extern const bfd_target oasys_vec; 193 194static long 195oasys_canonicalize_symtab (bfd *abfd, asymbol **location) 196{ 197 asymbol *symbase; 198 unsigned int counter; 199 200 if (! oasys_slurp_symbol_table (abfd)) 201 return -1; 202 203 symbase = OASYS_DATA (abfd)->symbols; 204 for (counter = 0; counter < abfd->symcount; counter++) 205 *(location++) = symbase++; 206 207 *location = 0; 208 return abfd->symcount; 209} 210 211/* Archive stuff. */ 212 213static const bfd_target * 214oasys_archive_p (bfd *abfd) 215{ 216 oasys_archive_header_type header; 217 oasys_extarchive_header_type header_ext; 218 unsigned int i; 219 file_ptr filepos; 220 bfd_size_type amt; 221 222 amt = sizeof (header_ext); 223 if (bfd_seek (abfd, (file_ptr) 0, 0) != 0 224 || bfd_bread ((void *) &header_ext, amt, abfd) != amt) 225 { 226 if (bfd_get_error () != bfd_error_system_call) 227 bfd_set_error (bfd_error_wrong_format); 228 return NULL; 229 } 230 231 header.version = H_GET_32 (abfd, header_ext.version); 232 header.mod_count = H_GET_32 (abfd, header_ext.mod_count); 233 header.mod_tbl_offset = H_GET_32 (abfd, header_ext.mod_tbl_offset); 234 header.sym_tbl_size = H_GET_32 (abfd, header_ext.sym_tbl_size); 235 header.sym_count = H_GET_32 (abfd, header_ext.sym_count); 236 header.sym_tbl_offset = H_GET_32 (abfd, header_ext.sym_tbl_offset); 237 header.xref_count = H_GET_32 (abfd, header_ext.xref_count); 238 header.xref_lst_offset = H_GET_32 (abfd, header_ext.xref_lst_offset); 239 240 /* There isn't a magic number in an Oasys archive, so the best we 241 can do to verify reasonableness is to make sure that the values in 242 the header are too weird. */ 243 244 if (header.version > 10000 245 || header.mod_count > 10000 246 || header.sym_count > 100000 247 || header.xref_count > 100000) 248 return NULL; 249 250 /* That all worked, let's buy the space for the header and read in 251 the headers. */ 252 { 253 oasys_ar_data_type *ar; 254 oasys_module_info_type *module; 255 oasys_module_table_type record; 256 257 amt = sizeof (oasys_ar_data_type); 258 ar = bfd_alloc (abfd, amt); 259 260 amt = header.mod_count; 261 amt *= sizeof (oasys_module_info_type); 262 module = bfd_alloc (abfd, amt); 263 264 if (!ar || !module) 265 return NULL; 266 267 abfd->tdata.oasys_ar_data = ar; 268 ar->module = module; 269 ar->module_count = header.mod_count; 270 271 filepos = header.mod_tbl_offset; 272 for (i = 0; i < header.mod_count; i++) 273 { 274 if (bfd_seek (abfd, filepos, SEEK_SET) != 0) 275 return NULL; 276 277 /* There are two ways of specifying the archive header. */ 278 { 279 oasys_extmodule_table_type_b_type record_ext; 280 281 amt = sizeof (record_ext); 282 if (bfd_bread ((void *) &record_ext, amt, abfd) != amt) 283 return NULL; 284 285 record.mod_size = H_GET_32 (abfd, record_ext.mod_size); 286 record.file_offset = H_GET_32 (abfd, record_ext.file_offset); 287 288 record.dep_count = H_GET_32 (abfd, record_ext.dep_count); 289 record.depee_count = H_GET_32 (abfd, record_ext.depee_count); 290 record.sect_count = H_GET_32 (abfd, record_ext.sect_count); 291 record.module_name_size = H_GET_32 (abfd, 292 record_ext.mod_name_length); 293 294 amt = record.module_name_size; 295 module[i].name = bfd_alloc (abfd, amt + 1); 296 if (!module[i].name) 297 return NULL; 298 if (bfd_bread ((void *) module[i].name, amt, abfd) != amt) 299 return NULL; 300 module[i].name[record.module_name_size] = 0; 301 filepos += (sizeof (record_ext) 302 + record.dep_count * 4 303 + record.module_name_size + 1); 304 } 305 306 module[i].size = record.mod_size; 307 module[i].pos = record.file_offset; 308 module[i].abfd = 0; 309 } 310 } 311 return abfd->xvec; 312} 313 314static bfd_boolean 315oasys_mkobject (bfd *abfd) 316{ 317 bfd_size_type amt = sizeof (oasys_data_type); 318 319 abfd->tdata.oasys_obj_data = bfd_alloc (abfd, amt); 320 321 return abfd->tdata.oasys_obj_data != NULL; 322} 323 324/* The howto table is build using the top two bits of a reloc byte to 325 index into it. The bits are PCREL,WORD/LONG. */ 326 327static reloc_howto_type howto_table[] = 328{ 329 330 HOWTO (0, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE), 331 HOWTO (0, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs32", TRUE, 0xffffffff, 0xffffffff, FALSE), 332 HOWTO (0, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, FALSE), 333 HOWTO (0, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0, "pcrel32", TRUE, 0xffffffff, 0xffffffff, FALSE) 334}; 335 336/* Read in all the section data and relocation stuff too. */ 337 338static bfd_boolean 339oasys_slurp_section_data (bfd *const abfd) 340{ 341 oasys_record_union_type record; 342 oasys_data_type *data = OASYS_DATA (abfd); 343 bfd_boolean loop = TRUE; 344 oasys_per_section_type *per; 345 asection *s; 346 bfd_size_type amt; 347 348 /* See if the data has been slurped already. */ 349 for (s = abfd->sections; s != NULL; s = s->next) 350 { 351 per = oasys_per_section (s); 352 if (per->initialized) 353 return TRUE; 354 } 355 356 if (data->first_data_record == 0) 357 return TRUE; 358 359 if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0) 360 return FALSE; 361 362 while (loop) 363 { 364 if (! oasys_read_record (abfd, &record)) 365 return FALSE; 366 367 switch (record.header.type) 368 { 369 case oasys_record_is_header_enum: 370 break; 371 case oasys_record_is_data_enum: 372 { 373 bfd_byte *src = record.data.data; 374 bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length; 375 bfd_byte *dst_ptr; 376 bfd_byte *dst_base_ptr; 377 unsigned int relbit; 378 unsigned int count; 379 asection *section = 380 data->sections[record.data.relb & RELOCATION_SECT_BITS]; 381 bfd_vma dst_offset; 382 383 per = oasys_per_section (section); 384 385 if (! per->initialized) 386 { 387 arelent **relpp; 388 389 per->data = bfd_zalloc (abfd, section->size); 390 if (!per->data) 391 return FALSE; 392 relpp = §ion->relocation; 393 per->reloc_tail_ptr = (oasys_reloc_type **) relpp; 394 per->had_vma = FALSE; 395 per->initialized = TRUE; 396 section->reloc_count = 0; 397 section->flags = SEC_ALLOC; 398 } 399 400 dst_offset = H_GET_32 (abfd, record.data.addr); 401 if (! per->had_vma) 402 { 403 /* Take the first vma we see as the base. */ 404 section->vma = dst_offset; 405 per->had_vma = TRUE; 406 } 407 408 dst_offset -= section->vma; 409 410 dst_base_ptr = oasys_per_section (section)->data; 411 dst_ptr = oasys_per_section (section)->data + 412 dst_offset; 413 414 if (src < end_src) 415 section->flags |= SEC_LOAD | SEC_HAS_CONTENTS; 416 417 while (src < end_src) 418 { 419 unsigned char mod_byte = *src++; 420 size_t gap = end_src - src; 421 422 count = 8; 423 if (mod_byte == 0 && gap >= 8) 424 { 425 dst_ptr[0] = src[0]; 426 dst_ptr[1] = src[1]; 427 dst_ptr[2] = src[2]; 428 dst_ptr[3] = src[3]; 429 dst_ptr[4] = src[4]; 430 dst_ptr[5] = src[5]; 431 dst_ptr[6] = src[6]; 432 dst_ptr[7] = src[7]; 433 dst_ptr += 8; 434 src += 8; 435 } 436 else 437 { 438 for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1) 439 { 440 if (relbit & mod_byte) 441 { 442 unsigned char reloc = *src; 443 /* This item needs to be relocated. */ 444 switch (reloc & RELOCATION_TYPE_BITS) 445 { 446 case RELOCATION_TYPE_ABS: 447 break; 448 449 case RELOCATION_TYPE_REL: 450 { 451 /* Relocate the item relative to the section. */ 452 oasys_reloc_type *r; 453 454 amt = sizeof (oasys_reloc_type); 455 r = bfd_alloc (abfd, amt); 456 if (!r) 457 return FALSE; 458 *(per->reloc_tail_ptr) = r; 459 per->reloc_tail_ptr = &r->next; 460 r->next = NULL; 461 /* Reference to undefined symbol. */ 462 src++; 463 /* There is no symbol. */ 464 r->symbol = 0; 465 /* Work out the howto. */ 466 abort (); 467 r->relent.address = dst_ptr - dst_base_ptr; 468 r->relent.howto = &howto_table[reloc >> 6]; 469 r->relent.sym_ptr_ptr = NULL; 470 section->reloc_count++; 471 472 /* Fake up the data to look like 473 it's got the -ve pc in it, this 474 makes it much easier to convert 475 into other formats. This is done 476 by hitting the addend. */ 477 if (r->relent.howto->pc_relative) 478 r->relent.addend -= dst_ptr - dst_base_ptr; 479 } 480 break; 481 482 case RELOCATION_TYPE_UND: 483 { 484 oasys_reloc_type *r; 485 486 amt = sizeof (oasys_reloc_type); 487 r = bfd_alloc (abfd, amt); 488 if (!r) 489 return FALSE; 490 *(per->reloc_tail_ptr) = r; 491 per->reloc_tail_ptr = &r->next; 492 r->next = NULL; 493 /* Reference to undefined symbol. */ 494 src++; 495 /* Get symbol number. */ 496 r->symbol = (src[0] << 8) | src[1]; 497 /* Work out the howto. */ 498 abort (); 499 500 r->relent.addend = 0; 501 r->relent.address = dst_ptr - dst_base_ptr; 502 r->relent.howto = &howto_table[reloc >> 6]; 503 r->relent.sym_ptr_ptr = NULL; 504 section->reloc_count++; 505 506 src += 2; 507 /* Fake up the data to look like 508 it's got the -ve pc in it, this 509 makes it much easier to convert 510 into other formats. This is done 511 by hitting the addend. */ 512 if (r->relent.howto->pc_relative) 513 r->relent.addend -= dst_ptr - dst_base_ptr; 514 } 515 break; 516 case RELOCATION_TYPE_COM: 517 BFD_FAIL (); 518 } 519 } 520 *dst_ptr++ = *src++; 521 } 522 } 523 } 524 } 525 break; 526 case oasys_record_is_local_enum: 527 case oasys_record_is_symbol_enum: 528 case oasys_record_is_section_enum: 529 break; 530 default: 531 loop = FALSE; 532 } 533 } 534 535 return TRUE; 536 537} 538 539#define MAX_SECS 16 540 541static const bfd_target * 542oasys_object_p (bfd *abfd) 543{ 544 oasys_data_type *oasys; 545 oasys_data_type *save = OASYS_DATA (abfd); 546 bfd_boolean loop = TRUE; 547 bfd_boolean had_usefull = FALSE; 548 549 abfd->tdata.oasys_obj_data = 0; 550 oasys_mkobject (abfd); 551 oasys = OASYS_DATA (abfd); 552 memset ((void *) oasys->sections, 0xff, sizeof (oasys->sections)); 553 554 /* Point to the start of the file. */ 555 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 556 goto fail; 557 oasys->symbol_string_length = 0; 558 559 /* Inspect the records, but only keep the section info - 560 remember the size of the symbols. */ 561 oasys->first_data_record = 0; 562 while (loop) 563 { 564 oasys_record_union_type record; 565 if (! oasys_read_record (abfd, &record)) 566 goto fail; 567 if ((size_t) record.header.length < (size_t) sizeof (record.header)) 568 goto fail; 569 570 switch ((oasys_record_enum_type) (record.header.type)) 571 { 572 case oasys_record_is_header_enum: 573 had_usefull = TRUE; 574 break; 575 case oasys_record_is_symbol_enum: 576 case oasys_record_is_local_enum: 577 /* Count symbols and remember their size for a future malloc. */ 578 abfd->symcount++; 579 oasys->symbol_string_length += 1 + oasys_string_length (&record); 580 had_usefull = TRUE; 581 break; 582 case oasys_record_is_section_enum: 583 { 584 asection *s; 585 char *buffer; 586 unsigned int section_number; 587 588 if (record.section.header.length != sizeof (record.section)) 589 goto fail; 590 591 buffer = bfd_alloc (abfd, (bfd_size_type) 3); 592 if (!buffer) 593 goto fail; 594 section_number = record.section.relb & RELOCATION_SECT_BITS; 595 sprintf (buffer, "%u", section_number); 596 s = bfd_make_section (abfd, buffer); 597 oasys->sections[section_number] = s; 598 switch (record.section.relb & RELOCATION_TYPE_BITS) 599 { 600 case RELOCATION_TYPE_ABS: 601 case RELOCATION_TYPE_REL: 602 break; 603 case RELOCATION_TYPE_UND: 604 case RELOCATION_TYPE_COM: 605 BFD_FAIL (); 606 } 607 608 s->size = H_GET_32 (abfd, record.section.value); 609 s->vma = H_GET_32 (abfd, record.section.vma); 610 s->flags = 0; 611 had_usefull = TRUE; 612 } 613 break; 614 case oasys_record_is_data_enum: 615 oasys->first_data_record = bfd_tell (abfd) - record.header.length; 616 case oasys_record_is_debug_enum: 617 case oasys_record_is_module_enum: 618 case oasys_record_is_named_section_enum: 619 case oasys_record_is_end_enum: 620 if (! had_usefull) 621 goto fail; 622 loop = FALSE; 623 break; 624 default: 625 goto fail; 626 } 627 } 628 oasys->symbols = NULL; 629 630 /* Oasys support several architectures, but I can't see a simple way 631 to discover which one is in a particular file - we'll guess. */ 632 bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0); 633 if (abfd->symcount != 0) 634 abfd->flags |= HAS_SYMS; 635 636 /* We don't know if a section has data until we've read it. */ 637 oasys_slurp_section_data (abfd); 638 639 return abfd->xvec; 640 641fail: 642 (void) bfd_release (abfd, oasys); 643 abfd->tdata.oasys_obj_data = save; 644 return NULL; 645} 646 647 648static void 649oasys_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED, 650 asymbol *symbol, 651 symbol_info *ret) 652{ 653 bfd_symbol_info (symbol, ret); 654 655 if (!symbol->section) 656 ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A'; 657} 658 659static void 660oasys_print_symbol (bfd *abfd, void * afile, asymbol *symbol, bfd_print_symbol_type how) 661{ 662 FILE *file = (FILE *) afile; 663 664 switch (how) 665 { 666 case bfd_print_symbol_name: 667 case bfd_print_symbol_more: 668 fprintf (file, "%s", symbol->name); 669 break; 670 case bfd_print_symbol_all: 671 { 672 const char *section_name = symbol->section == NULL ? 673 (const char *) "*abs" : symbol->section->name; 674 675 bfd_print_symbol_vandf (abfd, (void *) file, symbol); 676 677 fprintf (file, " %-5s %s", 678 section_name, 679 symbol->name); 680 } 681 break; 682 } 683} 684 685static bfd_boolean 686oasys_new_section_hook (bfd *abfd, asection *newsect) 687{ 688 if (!newsect->used_by_bfd) 689 { 690 newsect->used_by_bfd 691 = bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type)); 692 if (!newsect->used_by_bfd) 693 return FALSE; 694 } 695 oasys_per_section (newsect)->data = NULL; 696 oasys_per_section (newsect)->section = newsect; 697 oasys_per_section (newsect)->offset = 0; 698 oasys_per_section (newsect)->initialized = FALSE; 699 newsect->alignment_power = 1; 700 701 /* Turn the section string into an index. */ 702 sscanf (newsect->name, "%u", &newsect->target_index); 703 704 return _bfd_generic_new_section_hook (abfd, newsect); 705} 706 707 708static long 709oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect) 710{ 711 if (! oasys_slurp_section_data (abfd)) 712 return -1; 713 return (asect->reloc_count + 1) * sizeof (arelent *); 714} 715 716static bfd_boolean 717oasys_get_section_contents (bfd *abfd, 718 sec_ptr section, 719 void * location, 720 file_ptr offset, 721 bfd_size_type count) 722{ 723 oasys_per_section_type *p = oasys_per_section (section); 724 725 oasys_slurp_section_data (abfd); 726 727 if (! p->initialized) 728 (void) memset (location, 0, (size_t) count); 729 else 730 (void) memcpy (location, (void *) (p->data + offset), (size_t) count); 731 732 return TRUE; 733} 734 735static long 736oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED, 737 sec_ptr section, 738 arelent **relptr, 739 asymbol **symbols ATTRIBUTE_UNUSED) 740{ 741 unsigned int reloc_count = 0; 742 oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation); 743 744 if (src != NULL) 745 abort (); 746 747 *relptr = NULL; 748 return section->reloc_count = reloc_count; 749} 750 751 752/* Writing. */ 753 754/* Calculate the checksum and write one record. */ 755 756static bfd_boolean 757oasys_write_record (bfd *abfd, 758 oasys_record_enum_type type, 759 oasys_record_union_type *record, 760 size_t size) 761{ 762 int checksum; 763 size_t i; 764 unsigned char *ptr; 765 766 record->header.length = size; 767 record->header.type = (int) type; 768 record->header.check_sum = 0; 769 record->header.fill = 0; 770 ptr = (unsigned char *) &record->pad[0]; 771 checksum = 0; 772 for (i = 0; i < size; i++) 773 checksum += *ptr++; 774 record->header.check_sum = 0xff & (-checksum); 775 if (bfd_bwrite ((void *) record, (bfd_size_type) size, abfd) != size) 776 return FALSE; 777 return TRUE; 778} 779 780 781/* Write out all the symbols. */ 782 783static bfd_boolean 784oasys_write_syms (bfd *abfd) 785{ 786 unsigned int count; 787 asymbol **generic = bfd_get_outsymbols (abfd); 788 unsigned int index = 0; 789 790 for (count = 0; count < bfd_get_symcount (abfd); count++) 791 { 792 oasys_symbol_record_type symbol; 793 asymbol *const g = generic[count]; 794 const char *src = g->name; 795 char *dst = symbol.name; 796 unsigned int l = 0; 797 798 if (bfd_is_com_section (g->section)) 799 { 800 symbol.relb = RELOCATION_TYPE_COM; 801 H_PUT_16 (abfd, index, symbol.refno); 802 index++; 803 } 804 else if (bfd_is_abs_section (g->section)) 805 { 806 symbol.relb = RELOCATION_TYPE_ABS; 807 H_PUT_16 (abfd, 0, symbol.refno); 808 } 809 else if (bfd_is_und_section (g->section)) 810 { 811 symbol.relb = RELOCATION_TYPE_UND; 812 H_PUT_16 (abfd, index, symbol.refno); 813 /* Overload the value field with the output index number */ 814 index++; 815 } 816 else if (g->flags & BSF_DEBUGGING) 817 /* Throw it away. */ 818 continue; 819 else 820 { 821 if (g->section == NULL) 822 /* Sometime, the oasys tools give out a symbol with illegal 823 bits in it, we'll output it in the same broken way. */ 824 symbol.relb = RELOCATION_TYPE_REL | 0; 825 else 826 symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index; 827 828 H_PUT_16 (abfd, 0, symbol.refno); 829 } 830 831#ifdef UNDERSCORE_HACK 832 if (src[l] == '_') 833 dst[l++] = '.'; 834#endif 835 while (src[l]) 836 { 837 dst[l] = src[l]; 838 l++; 839 } 840 841 H_PUT_32 (abfd, g->value, symbol.value); 842 843 if (g->flags & BSF_LOCAL) 844 { 845 if (! oasys_write_record (abfd, 846 oasys_record_is_local_enum, 847 (oasys_record_union_type *) & symbol, 848 offsetof (oasys_symbol_record_type, 849 name[0]) + l)) 850 return FALSE; 851 } 852 else 853 { 854 if (! oasys_write_record (abfd, 855 oasys_record_is_symbol_enum, 856 (oasys_record_union_type *) & symbol, 857 offsetof (oasys_symbol_record_type, 858 name[0]) + l)) 859 return FALSE; 860 } 861 g->value = index - 1; 862 } 863 864 return TRUE; 865} 866 867/* Write a section header for each section. */ 868 869static bfd_boolean 870oasys_write_sections (bfd *abfd) 871{ 872 asection *s; 873 static oasys_section_record_type out; 874 875 for (s = abfd->sections; s != NULL; s = s->next) 876 { 877 if (!ISDIGIT (s->name[0])) 878 { 879 (*_bfd_error_handler) 880 (_("%s: can not represent section `%s' in oasys"), 881 bfd_get_filename (abfd), s->name); 882 bfd_set_error (bfd_error_nonrepresentable_section); 883 return FALSE; 884 } 885 out.relb = RELOCATION_TYPE_REL | s->target_index; 886 H_PUT_32 (abfd, s->size, out.value); 887 H_PUT_32 (abfd, s->vma, out.vma); 888 889 if (! oasys_write_record (abfd, 890 oasys_record_is_section_enum, 891 (oasys_record_union_type *) & out, 892 sizeof (out))) 893 return FALSE; 894 } 895 return TRUE; 896} 897 898static bfd_boolean 899oasys_write_header (bfd *abfd) 900{ 901 /* Create and write the header. */ 902 oasys_header_record_type r; 903 size_t length = strlen (abfd->filename); 904 905 if (length > (size_t) sizeof (r.module_name)) 906 length = sizeof (r.module_name); 907 908 (void) memcpy (r.module_name, abfd->filename, length); 909 (void) memset (r.module_name + length, ' ', sizeof (r.module_name) - length); 910 911 r.version_number = OASYS_VERSION_NUMBER; 912 r.rev_number = OASYS_REV_NUMBER; 913 914 return oasys_write_record (abfd, oasys_record_is_header_enum, 915 (oasys_record_union_type *) & r, 916 offsetof (oasys_header_record_type, 917 description[0])); 918} 919 920static bfd_boolean 921oasys_write_end (bfd *abfd) 922{ 923 oasys_end_record_type end; 924 unsigned char null = 0; 925 926 end.relb = RELOCATION_TYPE_ABS; 927 H_PUT_32 (abfd, abfd->start_address, end.entry); 928 H_PUT_16 (abfd, 0, end.fill); 929 end.zero = 0; 930 if (! oasys_write_record (abfd, 931 oasys_record_is_end_enum, 932 (oasys_record_union_type *) & end, 933 sizeof (end))) 934 return FALSE; 935 936 return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1; 937} 938 939static int 940comp (const void * ap, const void * bp) 941{ 942 arelent *a = *((arelent **) ap); 943 arelent *b = *((arelent **) bp); 944 945 return a->address - b->address; 946} 947 948static bfd_boolean 949oasys_write_data (bfd *abfd) 950{ 951 asection *s; 952 953 for (s = abfd->sections; s != NULL; s = s->next) 954 { 955 if (s->flags & SEC_LOAD) 956 { 957 bfd_byte *raw_data = oasys_per_section (s)->data; 958 oasys_data_record_type processed_data; 959 bfd_size_type current_byte_index = 0; 960 unsigned int relocs_to_go = s->reloc_count; 961 arelent **p = s->orelocation; 962 963 if (s->reloc_count != 0) 964 /* Sort the reloc records so it's easy to insert the relocs into the 965 data. */ 966 qsort (s->orelocation, s->reloc_count, sizeof (arelent **), comp); 967 968 current_byte_index = 0; 969 processed_data.relb = s->target_index | RELOCATION_TYPE_REL; 970 971 while (current_byte_index < s->size) 972 { 973 /* Scan forwards by eight bytes or however much is left and see if 974 there are any relocations going on. */ 975 bfd_byte *mod = &processed_data.data[0]; 976 bfd_byte *dst = &processed_data.data[1]; 977 978 unsigned int i = 0; 979 *mod = 0; 980 981 H_PUT_32 (abfd, s->vma + current_byte_index, 982 processed_data.addr); 983 984 /* Don't start a relocation unless you're sure you can finish it 985 within the same data record. The worst case relocation is a 986 4-byte relocatable value which is split across two modification 987 bytes (1 relocation byte + 2 symbol reference bytes + 2 data + 988 1 modification byte + 2 data = 8 bytes total). That's where 989 the magic number 8 comes from. */ 990 while (current_byte_index < s->size && dst <= 991 & processed_data.data[sizeof (processed_data.data) - 8]) 992 { 993 if (relocs_to_go != 0) 994 { 995 arelent *r = *p; 996 997 /* There is a relocation, is it for this byte ? */ 998 if (r->address == current_byte_index) 999 abort (); 1000 } 1001 1002 /* If this is coming from an unloadable section then copy 1003 zeros. */ 1004 if (raw_data == NULL) 1005 *dst++ = 0; 1006 else 1007 *dst++ = *raw_data++; 1008 1009 if (++i >= 8) 1010 { 1011 i = 0; 1012 mod = dst++; 1013 *mod = 0; 1014 } 1015 current_byte_index++; 1016 } 1017 1018 /* Don't write a useless null modification byte. */ 1019 if (dst == mod + 1) 1020 --dst; 1021 1022 if (! (oasys_write_record 1023 (abfd, oasys_record_is_data_enum, 1024 ((oasys_record_union_type *) &processed_data), 1025 (size_t) (dst - (bfd_byte *) &processed_data)))) 1026 return FALSE; 1027 } 1028 } 1029 } 1030 1031 return TRUE; 1032} 1033 1034static bfd_boolean 1035oasys_write_object_contents (bfd *abfd) 1036{ 1037 if (! oasys_write_header (abfd)) 1038 return FALSE; 1039 if (! oasys_write_syms (abfd)) 1040 return FALSE; 1041 if (! oasys_write_sections (abfd)) 1042 return FALSE; 1043 if (! oasys_write_data (abfd)) 1044 return FALSE; 1045 if (! oasys_write_end (abfd)) 1046 return FALSE; 1047 return TRUE; 1048} 1049 1050/* Set section contents is complicated with OASYS since the format is 1051 not a byte image, but a record stream. */ 1052 1053static bfd_boolean 1054oasys_set_section_contents (bfd *abfd, 1055 sec_ptr section, 1056 const void * location, 1057 file_ptr offset, 1058 bfd_size_type count) 1059{ 1060 if (count != 0) 1061 { 1062 if (oasys_per_section (section)->data == NULL) 1063 { 1064 oasys_per_section (section)->data = bfd_alloc (abfd, section->size); 1065 if (!oasys_per_section (section)->data) 1066 return FALSE; 1067 } 1068 (void) memcpy ((void *) (oasys_per_section (section)->data + offset), 1069 location, (size_t) count); 1070 } 1071 return TRUE; 1072} 1073 1074 1075 1076/* Native-level interface to symbols. */ 1077 1078/* We read the symbols into a buffer, which is discarded when this 1079 function exits. We read the strings into a buffer large enough to 1080 hold them all plus all the cached symbol entries. */ 1081 1082static asymbol * 1083oasys_make_empty_symbol (bfd *abfd) 1084{ 1085 bfd_size_type amt = sizeof (oasys_symbol_type); 1086 oasys_symbol_type *new = bfd_zalloc (abfd, amt); 1087 1088 if (!new) 1089 return NULL; 1090 new->symbol.the_bfd = abfd; 1091 return &new->symbol; 1092} 1093 1094/* User should have checked the file flags; perhaps we should return 1095 BFD_NO_MORE_SYMBOLS if there are none? */ 1096 1097static bfd * 1098oasys_openr_next_archived_file (bfd *arch, bfd *prev) 1099{ 1100 oasys_ar_data_type *ar = OASYS_AR_DATA (arch); 1101 oasys_module_info_type *p; 1102 1103 /* Take the next one from the arch state, or reset. */ 1104 if (prev == NULL) 1105 /* Reset the index - the first two entries are bogus. */ 1106 ar->module_index = 0; 1107 1108 p = ar->module + ar->module_index; 1109 ar->module_index++; 1110 1111 if (ar->module_index <= ar->module_count) 1112 { 1113 if (p->abfd == NULL) 1114 { 1115 p->abfd = _bfd_create_empty_archive_element_shell (arch); 1116 p->abfd->origin = p->pos; 1117 p->abfd->filename = p->name; 1118 1119 /* Fixup a pointer to this element for the member. */ 1120 p->abfd->arelt_data = (void *) p; 1121 } 1122 return p->abfd; 1123 } 1124 1125 bfd_set_error (bfd_error_no_more_archived_files); 1126 return NULL; 1127} 1128 1129static bfd_boolean 1130oasys_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED, 1131 asection *section ATTRIBUTE_UNUSED, 1132 asymbol **symbols ATTRIBUTE_UNUSED, 1133 bfd_vma offset ATTRIBUTE_UNUSED, 1134 const char **filename_ptr ATTRIBUTE_UNUSED, 1135 const char **functionname_ptr ATTRIBUTE_UNUSED, 1136 unsigned int *line_ptr ATTRIBUTE_UNUSED) 1137{ 1138 return FALSE; 1139} 1140 1141static bfd_boolean 1142oasys_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED, 1143 const char **filename_ptr ATTRIBUTE_UNUSED, 1144 const char **functionname_ptr ATTRIBUTE_UNUSED, 1145 unsigned int *line_ptr ATTRIBUTE_UNUSED) 1146{ 1147 return FALSE; 1148} 1149 1150static int 1151oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf) 1152{ 1153 oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data; 1154 1155 if (mod == NULL) 1156 { 1157 bfd_set_error (bfd_error_invalid_operation); 1158 return -1; 1159 } 1160 1161 buf->st_size = mod->size; 1162 buf->st_mode = 0666; 1163 return 0; 1164} 1165 1166static int 1167oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, 1168 struct bfd_link_info *info ATTRIBUTE_UNUSED) 1169{ 1170 return 0; 1171} 1172 1173#define oasys_close_and_cleanup _bfd_generic_close_and_cleanup 1174#define oasys_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 1175#define oasys_slurp_armap bfd_true 1176#define oasys_slurp_extended_name_table bfd_true 1177#define oasys_construct_extended_name_table ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_true) 1178#define oasys_truncate_arname bfd_dont_truncate_arname 1179#define oasys_write_armap ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) bfd_true) 1180#define oasys_read_ar_hdr bfd_nullvoidptr 1181#define oasys_get_elt_at_index _bfd_generic_get_elt_at_index 1182#define oasys_update_armap_timestamp bfd_true 1183#define oasys_bfd_is_local_label_name bfd_generic_is_local_label_name 1184#define oasys_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) 1185#define oasys_get_lineno _bfd_nosymbols_get_lineno 1186#define oasys_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 1187#define oasys_read_minisymbols _bfd_generic_read_minisymbols 1188#define oasys_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 1189#define oasys_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup 1190#define oasys_set_arch_mach bfd_default_set_arch_mach 1191#define oasys_get_section_contents_in_window _bfd_generic_get_section_contents_in_window 1192#define oasys_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents 1193#define oasys_bfd_relax_section bfd_generic_relax_section 1194#define oasys_bfd_gc_sections bfd_generic_gc_sections 1195#define oasys_bfd_merge_sections bfd_generic_merge_sections 1196#define oasys_bfd_is_group_section bfd_generic_is_group_section 1197#define oasys_bfd_discard_group bfd_generic_discard_group 1198#define oasys_section_already_linked _bfd_generic_section_already_linked 1199#define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 1200#define oasys_bfd_link_hash_table_free _bfd_generic_link_hash_table_free 1201#define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols 1202#define oasys_bfd_link_just_syms _bfd_generic_link_just_syms 1203#define oasys_bfd_final_link _bfd_generic_final_link 1204#define oasys_bfd_link_split_section _bfd_generic_link_split_section 1205 1206const bfd_target oasys_vec = 1207{ 1208 "oasys", /* Name. */ 1209 bfd_target_oasys_flavour, 1210 BFD_ENDIAN_BIG, /* Target byte order. */ 1211 BFD_ENDIAN_BIG, /* Target headers byte order. */ 1212 (HAS_RELOC | EXEC_P | /* Object flags. */ 1213 HAS_LINENO | HAS_DEBUG | 1214 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 1215 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS 1216 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */ 1217 0, /* Leading underscore. */ 1218 ' ', /* AR_pad_char. */ 1219 16, /* AR_max_namelen. */ 1220 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1221 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1222 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ 1223 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1224 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1225 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */ 1226 1227 {_bfd_dummy_target, 1228 oasys_object_p, /* bfd_check_format. */ 1229 oasys_archive_p, 1230 _bfd_dummy_target, 1231 }, 1232 { /* bfd_set_format. */ 1233 bfd_false, 1234 oasys_mkobject, 1235 _bfd_generic_mkarchive, 1236 bfd_false 1237 }, 1238 { /* bfd_write_contents. */ 1239 bfd_false, 1240 oasys_write_object_contents, 1241 _bfd_write_archive_contents, 1242 bfd_false, 1243 }, 1244 1245 BFD_JUMP_TABLE_GENERIC (oasys), 1246 BFD_JUMP_TABLE_COPY (_bfd_generic), 1247 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1248 BFD_JUMP_TABLE_ARCHIVE (oasys), 1249 BFD_JUMP_TABLE_SYMBOLS (oasys), 1250 BFD_JUMP_TABLE_RELOCS (oasys), 1251 BFD_JUMP_TABLE_WRITE (oasys), 1252 BFD_JUMP_TABLE_LINK (oasys), 1253 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1254 1255 NULL, 1256 1257 NULL 1258}; 1259