home *** CD-ROM | disk | FTP | other *** search
- /* BFD back-end for Commodore-Amiga AmigaDOS binaries.
- Copyright (C) 1990-1994 Free Software Foundation, Inc.
- Contributed by Leonard Norrgard. Partially based on the bout
- and ieee BFD backends and Markus Wild's tool hunk2gcc.
-
- This file is part of BFD, the Binary File Descriptor library.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* TODO:
-
- - writing of object files
-
- - .chipdata, .chipbss
-
- - fix fixme:s
-
- BFD:
- - add flag to say if the format allows multiple sections with the
- same name. Fix bfd_get_section_by_name() and bfd_make_section()
- accordingly.
-
- - dumpobj.c: the disassembler: use relocation record data to find symbolic
- names of addresses, when available. Needs new routine where one can
- specify the source section of the symbol to be printed as well as some
- rewrite of the disassemble functions.
-
- */
-
- #include "bfd.h"
- #include "sysdep.h"
- #include "libbfd.h"
- #include "libamiga.h"
-
- #define GL(x) bfd_get_32 (abfd, (bfd_byte *) (x))
-
- #define DEBUG_AMIGA 0
-
- static boolean amiga_digest_file ();
- static boolean amiga_mkobject ();
-
- reloc_howto_type howto_hunk_reloc8 =
- {
- HUNK_RELOC8, /* type */
- 0, /* rightshift */
- 0, /* size */
- 0, /* bitsize */
- true, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- 0, /* special_function */
- "reloc8", /* textual name */
- false, /* partial_inplace? */
- 0x000000ff, /* src_mask */
- 0x000000ff, /* dst_mask */
- true /* pcrel_offset */
- };
-
- reloc_howto_type howto_hunk_reloc16 =
- {HUNK_RELOC16,0,0,0,true,0,complain_overflow_bitfield,0,"reloc16",false,0x0000ffff,0x0000ffff,true};
-
- reloc_howto_type howto_hunk_reloc32 =
- {HUNK_RELOC32,0,0,0,true,0,complain_overflow_bitfield,0,"reloc32",false,0xffffffff,0xffffffff,true};
-
- reloc_howto_type howto_hunk_drel8 =
- {HUNK_DREL8,0,0,0,false,0,complain_overflow_bitfield,0,"drel8",false,0x000000ff,0x000000ff,true};
-
- reloc_howto_type howto_hunk_drel16 =
- {HUNK_DREL16,0,0,0,false,0,complain_overflow_bitfield,0,"drel16",false,0x0000ffff,0x0000ffff,true};
-
- reloc_howto_type howto_hunk_drel32 =
- {HUNK_DREL32,0,0,0,false,0,complain_overflow_bitfield,0,"drel32",false,0xffffffff,0xffffffff,true};
-
- reloc_howto_type *amiga_howto_array[2][3] =
- {
- { &howto_hunk_reloc8, &howto_hunk_reloc16, &howto_hunk_reloc32 },
- { &howto_hunk_drel8, &howto_hunk_drel16, &howto_hunk_drel32 }
- };
-
- static bfd_target *
- amiga_object_p (abfd)
- bfd *abfd;
- {
- char buf[8];
- unsigned int x;
- struct stat stat_buffer;
-
- /* An Amiga object file must be at least 8 bytes long. */
- if (bfd_read ((PTR) buf, 1, 8, abfd) != 8)
- {
- bfd_error = wrong_format;
- return 0;
- }
-
- /* Does it look like an Amiga object file? */
- x = GL(buf);
- if ((x != HUNK_UNIT) && (x != HUNK_HEADER))
- {
- /* Not an Amiga file. */
- bfd_error = wrong_format;
- return 0;
- }
-
- /* So far it seems to be an Amiga file. Now slurp it
- in and examine it closer. */
- if (-1 == fstat (fileno ((FILE *) abfd->iostream), &stat_buffer))
- {
- bfd_error = system_call_error;
- return 0;
- }
-
- /* Can't fail and return (but must be declared boolean to suit
- other bfd requirements). */
- (void) amiga_mkobject (abfd);
-
- AMIGA_DATA(abfd)->symbol_tail_ptr = &AMIGA_DATA(abfd)->external_symbols;
-
- AMIGA_DATA(abfd)->first_byte = (unsigned long *) bfd_alloc (abfd, stat_buffer.st_size);
- bfd_seek (abfd, 0, SEEK_SET);
- bfd_read (AMIGA_DATA(abfd)->first_byte, 1, stat_buffer.st_size, abfd);
- AMIGA_DATA(abfd)->file_pointer = AMIGA_DATA(abfd)->first_byte;
- AMIGA_DATA(abfd)->file_end = (unsigned long *)((unsigned char *)AMIGA_DATA(abfd)->first_byte + stat_buffer.st_size);
-
- if (!amiga_digest_file (abfd))
- {
- /* Something went wrong. */
- return (struct bfd_target *) 0;
- }
-
- /* Set default architecture to m68k:68020. */
- abfd->arch_info = bfd_scan_arch ("m68k:68020");
-
- return abfd->xvec;
- }
-
- /* Skip over the hunk length longword + the number of longwords given there. */
- #define next_hunk(abfd) \
- { AMIGA_DATA(abfd)->file_pointer += 1 + GL(AMIGA_DATA(abfd)->file_pointer); }
-
- static asection *
- amiga_get_section_by_hunk_number (abfd, hunk_number)
- bfd *abfd;
- unsigned int hunk_number;
- {
- /* A cache, so we don't have to search the entire list every time. */
- static asection *last_reference;
- asection *p;
-
- if (last_reference)
- if (last_reference->target_index == hunk_number)
- return last_reference;
- for (p = abfd->sections; p != NULL; p = p->next)
- if (p->target_index == hunk_number)
- {
- last_reference = p;
- return p;
- }
- BFD_FAIL();
- return (asection *) 0;
- }
-
- /* Remember about a symbol found at the current file position.
- Return number of longwords to advance the file_pointer with. */
- static unsigned long
- amiga_add_symbol (abfd, hunk_number)
- bfd *abfd;
- unsigned int hunk_number;
- {
- int length;
-
- amiga_symbol_type *symbol = bfd_alloc (abfd, sizeof (amiga_symbol_type));
-
- if (symbol)
- {
- amiga_data_type *amiga_data = AMIGA_DATA(abfd);
- unsigned long *file_pointer = amiga_data->file_pointer;
- unsigned char type = GL(file_pointer) >> 24;
-
- ++abfd->symcount;
- *amiga_data->symbol_tail_ptr = symbol;
- amiga_data->symbol_tail_ptr = &symbol->next;
-
- symbol->symbol.the_bfd = abfd;
-
- /* The symbol name is not necessarily nul-terminated in the file.
- So, we move it to start on the length word and put a NUL at the
- end of it all. This way, we avoid allocating separate memory for
- the symbol name, while assuring that the name is nul-terminated. */
-
- length = (GL(file_pointer) & 0xffffff) << 2;
- strncpy ((char *) file_pointer, (char *) (file_pointer + 1), length);
- *(((char *)file_pointer) + length) = '\0';
-
- symbol->symbol.name = (char *)file_pointer;
- symbol->symbol.udata = (PTR) NULL;
- symbol->symbol.flags = ((type == EXT_DEF) || (type == EXT_ABS))
- ? BSF_GLOBAL : BSF_NO_FLAGS;
- symbol->symbol.value = ((type == EXT_DEF) || (type == EXT_ABS))
- ? (symvalue) GL(file_pointer + 1 + (length>>2)) : 0;
- symbol->symbol.section = amiga_get_section_by_hunk_number (abfd, hunk_number);
- symbol->hunk_number = hunk_number;
- symbol->type = type;
- symbol->next = 0;
- }
- return length >> 2;
- }
-
- static void
- amiga_add_reloc (abfd, section, offset, symbol_number, howto, target_hunk)
- bfd *abfd;
- asection *section;
- bfd_size_type offset;
- int symbol_number;
- reloc_howto_type *howto;
- unsigned int target_hunk;
- {
- amiga_reloc_type *reloc;
-
- reloc = (amiga_reloc_type *) bfd_alloc (abfd, sizeof (amiga_reloc_type));
- reloc->next = 0;
-
- abfd -> flags |= HAS_RELOC;
- section -> flags |= SEC_RELOC;
- ++section->reloc_count;
- if (amiga_per_section(section)->reloc_tail_ptr)
- amiga_per_section(section)->reloc_tail_ptr->next = reloc;
- else
- section->relocation = (struct reloc_cache_entry *) reloc;
- amiga_per_section(section)->reloc_tail_ptr = reloc;
- amiga_per_section(section)->reloc_tail_ptr->next = (amiga_reloc_type *) 0;
- reloc->relent.address = offset;
- reloc->relent.addend = 0;
- reloc->relent.howto = howto;
- reloc->symbol_number = symbol_number;
- reloc->target_hunk = target_hunk;
- }
-
- /* BFD doesn't currently allow multiple sections with the same
- name, so we try a little harder to get a unique name. */
- asection *
- amiga_make_unique_section (abfd, name)
- bfd *abfd;
- CONST char *name;
- {
- asection *section;
-
- section = bfd_make_section (abfd, name);
- if (!section)
- {
- int i = 1;
- char *new_name;
-
- new_name = bfd_alloc (abfd, strlen(name) + 3);
-
- /* We try to come up with an original name (since BFD
- currently requires all sections to have different names). */
- while (!section && (i<=99))
- {
- sprintf (new_name, "%s_%u", name, i);
- section = bfd_make_section (abfd, new_name);
- }
-
- if (!section)
- {
- /* Complain about the given name. */
- bfd_error = bad_value;
- return 0;
- }
- }
- return section;
- }
-
- static boolean
- amiga_digest_file (abfd)
- bfd *abfd;
- {
- int is_chip;
- int units = 0;
- int hunk_number;
- char *current_name = 0;
- asection *current_section;
- amiga_data_type *amiga_data = AMIGA_DATA(abfd);
- int hunk_type;
-
- /* Hunk numbers starts with 0, but we pre-increment the hunk_number when
- we assign a new one, so this really makes the first hunk number 0. */
- hunk_number = -1;
-
- while (units < 2)
- {
- hunk_type = HUNK_VALUE(GL(amiga_data->file_pointer++));
- #if DEBUG_AMIGA
- printf ("Processing %s hunk...",
- hunk_type == HUNK_UNIT ? "HUNK_UNIT" :
- hunk_type == HUNK_NAME ? "HUNK_NAME" :
- hunk_type == HUNK_DEBUG ? "HUNK_DEBUG" :
- hunk_type == HUNK_OVERLAY ? "HUNK_OVERLAY" :
- hunk_type == HUNK_BREAK ? "HUNK_BREAK" :
- hunk_type == HUNK_HEADER ? "HUNK_HEADER" :
- hunk_type == HUNK_CODE ? "HUNK_CODE" :
- hunk_type == HUNK_DATA ? "HUNK_DATA" :
- hunk_type == HUNK_BSS ? "HUNK_BSS" :
- hunk_type == HUNK_RELOC8 ? "HUNK_RELOC8" :
- hunk_type == HUNK_RELOC16 ? "HUNK_RELOC16" :
- hunk_type == HUNK_RELOC32 ? "HUNK_RELOC32" :
- hunk_type == HUNK_DREL8 ? "HUNK_DREL8" :
- hunk_type == HUNK_DREL16 ? "HUNK_DREL16" :
- hunk_type == HUNK_DREL32 ? "HUNK_DREL32" :
- hunk_type == HUNK_SYMBOL ? "HUNK_SYMBOL" :
- hunk_type == HUNK_EXT ? "HUNK_EXT" :
- hunk_type == HUNK_END ? "HUNK_END" :
- hunk_type == HUNK_LIB ? "HUNK_LIB" :
- hunk_type == HUNK_INDEX ? "HUNK_INDEX" :
- "*unknown*");
- #endif
- switch (hunk_type)
- {
- case HUNK_UNIT:
- current_name =
- (GL(amiga_data->file_pointer) == 0)
- ? "" : (char *)(amiga_data->file_pointer + 1);
-
- /* Allow only one program unit per bfd. */
- if (units++)
- break;
-
- /* We always initialize hunk_number to -1, as desribed above. */
- hunk_number = -1;
-
- next_hunk (abfd);
- break;
-
- case HUNK_NAME:
- {
- int length = GL(amiga_data->file_pointer) << 2;
-
- /* Change the name to a nul-terminated string. */
- strncpy ((char *)amiga_data->file_pointer, (char *)(amiga_data->file_pointer + 1), length);
- *(((char *) amiga_data->file_pointer) + length) = '\0';
- current_name = (char *) amiga_data->file_pointer;
-
- /* Can't use next_hunk() here, as we wrote over the hunk length
- that next_hunk() looks at. */
- amiga_data->file_pointer += 1 + (length>>2);
- }
- break;
-
- case HUNK_DEBUG:
- /* The format for the HUNK_DEBUG, as produced by Amiga GNU C:
-
- longwords:
-
- |---------------|
- | HUNK_DEBUG | 0x3f1, Amigados imposed
- |---------------|
- | N | Size of this hunk in longwords
- |---------------|
- | AMIGA_ZMAGIC | 0413, same as BSD unix ZMAGIC
- |---------------|
- | symtabsize | size of the symbol table in bytes
- |---------------|
- | stringtabsize | size of the string table in bytes
- |---------------|
- | symtab data | symbol table in a.out format,
- : : size is symtabsize.
- : .....:
- |..........| |
- | stringtab | string table in a.out format,
- : data : size is stringtabsize.
- : : (can start on byte boundary,
- |---------------| and can be padded at the end).
-
- /* Same as BSD unix ZMAGIC, but I don't want to include
- any BSD files here. */
-
- #define AMIGA_ZMAGIC 0413
-
- /* Identifier for the GNU C format for HUNK_DEBUG on the Amiga. */
- if (GL(amiga_data->file_pointer + 1) == AMIGA_ZMAGIC)
- {
- amiga_data->symtab_size = GL(amiga_data->file_pointer + 2);
- amiga_data->stringtab_size = GL(amiga_data->file_pointer + 3);
- adata(abfd).sym_filepos =
- (file_ptr) ((char *)(amiga_data->file_pointer + 4) - (char *)amiga_data->first_byte);
- adata(abfd).str_filepos = adata(abfd).sym_filepos
- + amiga_data->symtab_size;
- }
- else
- fprintf (stderr, "unknown debug hunk type\n");
- next_hunk (abfd);
- break;
-
- case HUNK_OVERLAY:
- /* Poor man's virtual memory. Not yet supported. */
- /* fixme */
- fprintf (stderr, "Warning: HUNK_OVERLAY encountered, ignoring.\n");
- next_hunk (abfd);
- break;
-
- case HUNK_BREAK:
- /* HUNK_BREAK indicates the end of an overlay node. This
- hunk consists of a single longword, HUNK_BREAK. As we
- do not yet support overlays, we ignore thins hunk for now. */
- /* fixme */
- fprintf(stderr, "Warning: HUNK_BREAK encountered, ignoring.\n");
- next_hunk (abfd);
- break;
-
- case HUNK_HEADER:
- /* This is the header of a load file.
-
- Skip resident library names (never used, it's
- an obsolete feature of the file format). fixme: verify that! */
- while (GL(amiga_data->file_pointer))
- next_hunk (abfd);
-
- /* Skip null-word, table_size, F & L, and size-table. */
- amiga_data->file_pointer += 4 + GL(amiga_data->file_pointer + 1) - GL(amiga_data->file_pointer + 2);
- break;
-
- case HUNK_CODE:
- is_chip = HUNK_ATTRIBUTE (GL(amiga_data->file_pointer - 1)) == HUNK_ATTR_CHIP;
- if (is_chip)
- fprintf (stderr, "Warning: CHIP code hunks are not supported, ignoring CHIP attribute\n");
-
- current_section = amiga_make_unique_section (abfd, (current_name && current_name[0]) ? current_name : ".text");
- if (current_section == 0)
- {
- /* Fatal error. */
- return false;
- }
- current_section->filepos = (char *) (amiga_data->file_pointer + 1) - (char *)amiga_data->first_byte;
- current_section->_raw_size = GL(amiga_data->file_pointer) << 2;
- current_section->target_index = ++hunk_number;
- bfd_set_section_flags (abfd, current_section, SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
-
- next_hunk (abfd);
- break;
-
- case HUNK_DATA:
- current_section = amiga_make_unique_section (abfd, (current_name && current_name[0]) ? current_name : ".data");
- if (current_section == 0)
- {
- /* Fatal error. */
- return false;
- }
- current_section->filepos = (char *) (amiga_data->file_pointer + 1) - (char *)amiga_data->first_byte;
- current_section->_raw_size = GL(amiga_data->file_pointer) << 2;
- current_section->target_index = ++hunk_number;
- bfd_set_section_flags (abfd, current_section, SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS);
- next_hunk (abfd);
- break;
-
- case HUNK_BSS:
- current_section = amiga_make_unique_section (abfd, (current_name && current_name[0]) ? current_name : ".bss");
- if (current_section == 0)
- {
- /* Fatal error. */
- return false;
- }
- current_section->filepos = (file_ptr) -1;
- current_section->_raw_size = GL(amiga_data->file_pointer) << 2;
- current_section->target_index = ++hunk_number;
- bfd_set_section_flags (abfd, current_section, SEC_ALLOC);
- ++ amiga_data->file_pointer;
- break;
-
- case HUNK_RELOC8:
- case HUNK_RELOC16:
- case HUNK_RELOC32:
- case HUNK_DREL8:
- case HUNK_DREL16:
- case HUNK_DREL32:
- {
- int size, base_relative;
- reloc_howto_type *howto;
-
- base_relative = GL(&amiga_data->file_pointer[-1]) >= HUNK_DREL32;
- size = (base_relative ? HUNK_DREL8 : HUNK_RELOC8) - GL(&amiga_data->file_pointer[-1]);
- howto = amiga_howto_array[base_relative][size];
-
- while (GL(amiga_data->file_pointer))
- {
- long to_reloc = GL(amiga_data->file_pointer + 1);
- long n = GL(amiga_data->file_pointer);
- long i = 1;
-
- while (i++ < n)
- amiga_add_reloc (abfd, current_section,
- GL(amiga_data->file_pointer + i + 1),
- -1, howto, to_reloc);
- amiga_data->file_pointer += GL(amiga_data->file_pointer) + 2;
- }
- ++amiga_data->file_pointer;
- }
- break;
-
- case HUNK_SYMBOL:
- /* "You use this block to attach a symbol table to a hunk so that
- you can use a symbolic debugger on the code. The linker passes
- symbol table blocks through attached to the hunk and, if the hunks
- are coagulated, coagulates the symbol tables. The loader does not
- load symbol table blocks into memory; when this is required,
- the debugger is expected to read the load file."
- -- The AmigaDOS Manual, 3rd ed.
-
- GNU C on the Amiga passes all needed debug information in the
- debug hunk (HUNK_DEBUG). Thus we do not depend on HUNK_SYMBOL
- for the GNU debugger GDB to get symbol information and can safely
- ignore this hunk.
- If, however, someone would like to add full support for
- HUNK_SYMBOL to be able to use some debugger that doesn't
- understand the GNU C debug hunk, please go ahead.
- As of this writing, the BarFly debugger written by
- Ralph "laire" Schmidt is starting to understand the GNU C debug
- hunk. As the GNU version of the debug hunk is publically
- documented, unlike for example the format used by SAS Insitute
- on the Amiga, I hope other debugger writers will follow his
- example. -- vinsci@nic.funet.fi */
-
- /* The formats of the HUNK_SYMBOL and HUNK_EXT hunks are exactly
- the same, except the type byte of anything in the HUNK_SYMBOL
- is always zero. Thus we ignore the symbol hunk by ignoring
- all EXT_SYMB's below and can thus reuse the code. */
-
- /* Fall through */
-
- case HUNK_EXT:
-
- while (GL(amiga_data->file_pointer))
- {
- int num, size, base_relative;
- unsigned char type;
- reloc_howto_type *howto;
-
- /* Make sure we don't set this flag for HUNK_SYMBOL hunks. */
- if (hunk_type == HUNK_EXT)
- abfd -> flags |= HAS_SYMS;
-
- switch (type = (GL(amiga_data->file_pointer) >> 24))
- {
- case EXT_SYMB: /* This is a symbol from HUNK_SYMBOL, which we
- ignore. See long description above. */
- num = GL(amiga_data->file_pointer) & 0xffffff;
- amiga_data->file_pointer += 2 + num;
- break;
-
- case EXT_DEF: /* Relocatable definition. */
- case EXT_ABS: /* Absolute definition. */
- /* case EXT_RES: obsolete; Resident library definition. */
-
- num = amiga_add_symbol (abfd, hunk_number);
- amiga_data->file_pointer += 2 + num;
- break;
-
- case EXT_COMMON: /* 32 bit reference to COMMON block. */
- {
- int i = 0;
-
- num = amiga_add_symbol (abfd, hunk_number);
- amiga_data->file_pointer += 2 + num;
-
- num = GL(amiga_data->file_pointer);
- while (i++ < num)
- amiga_add_reloc
- (abfd, current_section, GL(amiga_data->file_pointer + i),
- amiga_data->a.n_symbols, &howto_hunk_drel32, -1);
- next_hunk (abfd);
- }
- break;
-
- case EXT_REF8: /* 8 bit reference to symbol. */
- case EXT_REF16: /* 16 bit reference to symbol. */
- case EXT_REF32: /* 32 bit reference to symbol. */
- case EXT_DEXT8: /* 8 bit data relative reference. */
- case EXT_DEXT16: /* 16 bit data relative reference. */
- case EXT_DEXT32: /* 32 bit data relative reference. */
- size = GL(amiga_data->file_pointer) >> 24;
- base_relative = size >= EXT_DEXT32;
- switch (size)
- {
- case EXT_REF32:
- case EXT_DEXT32:
- size = 2;
- break;
- case EXT_REF16:
- case EXT_DEXT16:
- size = 1;
- break;
- default:
- size = 0;
- }
- howto = amiga_howto_array[base_relative][size];
-
- num = amiga_add_symbol (abfd, hunk_number);
-
- amiga_data->file_pointer += 1 + num;
- {
- int i = 0;
-
- num = GL(amiga_data->file_pointer);
- while (i++ < num)
- amiga_add_reloc (abfd, current_section,
- GL(amiga_data->file_pointer + i),
- amiga_data->a.n_symbols, howto, -1);
- }
- next_hunk (abfd);
- break;
-
- default:
- fprintf (stderr, "Unknown symbol type %d, don't know how to handle.\n", type);
- /* Fatal error. */
- return false;
- }
- }
- ++ amiga_data->file_pointer;
- break;
-
- case HUNK_END:
- break;
-
- case HUNK_LIB:
- case HUNK_INDEX:
- fprintf (stderr, "Can not handle HUNK_LIB and HUNK_INDEX hunks.\nConvert the library to ALINK (join) format.\n");
- break;
-
- default:
- fprintf (stderr, "Unknown hunk type $%x, unit offset = $%x.\n",
- GL(amiga_data->file_pointer -1),
- ((amiga_data->file_pointer - 1) - amiga_data->first_byte) * 4);
- /* Fatal error. */
- return false;
- }
-
- #if DEBUG_AMIGA
- printf ("...hunk processed.\n");
- #endif
- if (amiga_data->file_pointer >= amiga_data->file_end)
- break;
- }
-
- /* OK. */
- return true;
- }
-
- static boolean
- amiga_mkobject (abfd)
- bfd *abfd;
- {
- struct amiga_data_struct *rawptr;
-
- rawptr = (struct amiga_data_struct *) bfd_zalloc (abfd, sizeof (struct amiga_data_struct));
- abfd->tdata.amiga_data = rawptr;
-
- return true;
- }
-
- static boolean
- amiga_write_object_contents (abfd)
- bfd *abfd;
- {
- /* fixme */
- return true;
- }
-
- static boolean
- amiga_get_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- sec_ptr section;
- PTR location;
- file_ptr offset;
- bfd_size_type count;
- {
- memmove ((void *) location,
- (void *) (((int) AMIGA_DATA(abfd)->first_byte)
- + (int) section->filepos
- + (int) offset),
- count);
- return true;
- }
-
- boolean
- amiga_new_section_hook (abfd, newsect)
- bfd *abfd;
- asection *newsect;
- {
- newsect->used_by_bfd = (PTR) bfd_alloc (abfd, sizeof (amiga_per_section_type));
- newsect->alignment_power = 2;
- amiga_per_section(newsect)->reloc_tail_ptr = (amiga_reloc_type *) 0;
- return true;
- }
-
- void
- amiga_slurp_symbol_table (abfd)
- bfd *abfd;
- {
- /* fixme: currently we always load the symbols at check_format time,
- so we don't do it here. When the amiga backend someday doesn't
- keep more info than needed in memory, this will have to be fixed. */
- }
-
- unsigned int
- amiga_get_symtab_upper_bound (abfd)
- bfd *abfd;
- {
- amiga_slurp_symbol_table (abfd);
- return (abfd->symcount != 0) ?
- (abfd->symcount+1) * (sizeof (amiga_symbol_type *)) : 0;
- }
-
- unsigned int
- amiga_get_symtab (abfd, location)
- bfd *abfd;
- asymbol **location;
- {
- amiga_symbol_type *symp;
-
- if (abfd->symcount)
- {
- int i = 0;
-
- amiga_slurp_symbol_table (abfd);
-
- for (symp = AMIGA_DATA(abfd)->external_symbols;
- symp != (amiga_symbol_type *) NULL;
- symp = symp->next)
- {
- location[i++] = &symp->symbol;
- }
- for (symp = AMIGA_DATA(abfd)->external_references;
- symp != (amiga_symbol_type *) NULL;
- symp = symp->next)
- {
- location[i++] = &symp->symbol;
- }
- }
- return abfd->symcount;
- }
-
- asymbol *
- amiga_make_empty_symbol (abfd)
- bfd *abfd;
- {
- amiga_symbol_type *new =
- (amiga_symbol_type *) bfd_zalloc (abfd, sizeof (amiga_symbol_type));
- new->symbol.the_bfd = abfd;
- return &new->symbol;
- }
-
- void
- amiga_get_symbol_info (ignore_abfd, symbol, ret)
- bfd *ignore_abfd;
- asymbol *symbol;
- symbol_info *ret;
- {
- bfd_symbol_info (symbol, ret);
- if (symbol->name[0] == ' ')
- ret->name = "* empty table entry ";
- if (!symbol->section)
- ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
- }
-
- void
- amiga_print_symbol (ignore_abfd, afile, symbol, how)
- bfd *ignore_abfd;
- PTR afile;
- asymbol *symbol;
- bfd_print_symbol_type how;
- {
- FILE *file = (FILE *)afile;
-
- switch (how) {
- case bfd_print_symbol_name:
- fprintf(file, "%s", symbol->name);
- break;
- case bfd_print_symbol_more:
- /* fixme: adapt for amiga */
- BFD_FAIL();
- break;
- case bfd_print_symbol_all:
- {
- CONST char *section_name = (symbol->section == (asection *)NULL)
- ? (CONST char *)"*abs" : symbol->section->name;
- if (symbol->name[0] == ' ')
- {
- fprintf(file, "* empty table entry ");
- }
- else
- {
- bfd_print_symbol_vandf ((PTR)file, symbol);
-
- fprintf(file," %-5s %04x %02x %s",
- section_name,
- amiga_symbol(symbol)->hunk_number, /* ->desc */
- (unsigned) 0, /* ->other */
- /* type */
- symbol->name); /* ->name */
- }
- }
- break;
- }
- }
-
- static unsigned int
- amiga_get_reloc_upper_bound (abfd, asect)
- bfd *abfd;
- sec_ptr asect;
- {
- if (bfd_get_format (abfd) != bfd_object)
- {
- bfd_error = invalid_operation;
- return 0;
- }
- return sizeof (arelent *) * (asect->reloc_count + 1);
- }
-
- unsigned int
- amiga_canonicalize_reloc (abfd, section, relptr, symbols)
- bfd *abfd;
- sec_ptr section;
- arelent **relptr;
- asymbol **symbols;
- {
- amiga_reloc_type *src = (amiga_reloc_type *) section->relocation;
- int i = 0;
-
- while (src != (amiga_reloc_type *) 0)
- {
- if (src->symbol_number == -1)
- src->relent.sym_ptr_ptr =
- &(amiga_get_section_by_hunk_number(abfd,src->target_hunk))->symbol;
- else
- src->relent.sym_ptr_ptr = symbols + i++;
- *relptr++ = &src->relent;
- src = src->next;
- }
- *relptr = (arelent *) 0;
-
- return section->reloc_count;
- }
-
- static boolean
- amiga_set_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- sec_ptr section;
- unsigned char *location;
- file_ptr offset;
- int count;
- {
- /* fixme */
- return true;
- }
-
- static boolean
- amiga_set_arch_mach (abfd, arch, machine)
- bfd *abfd;
- enum bfd_architecture arch;
- unsigned long machine;
- {
- bfd_default_set_arch_mach(abfd, arch, machine);
-
- if (arch == bfd_arch_m68k)
- {
- switch (machine)
- {
- case 68000:
- case 68008:
- case 68010:
- case 68020:
- case 68030:
- case 68040:
- case 68070:
- case 0:
- return true;
- default:
- return false;
- }
- }
- return false;
- }
-
- static int
- DEFUN(amiga_sizeof_headers,(ignore_abfd, ignore),
- bfd *ignore_abfd AND
- boolean ignore)
- {
- /* The amiga hunk format doesn't have headers. */
- return 0;
- }
-
- /* Provided a BFD, a section and an offset into the section, calculate
- and return the name of the source file and the line nearest to the
- wanted location. */
- boolean
- amiga_find_nearest_line(abfd, section, symbols, offset, filename_ptr,
- functionname_ptr, line_ptr)
- bfd *abfd;
- asection *section;
- asymbol **symbols;
- bfd_vma offset;
- char **filename_ptr;
- char **functionname_ptr;
- int *line_ptr;
- {
- /* fixme (see aoutx.h, for example) */
- return false;
- }
-
- static const struct reloc_howto_struct *
- amiga_bfd_reloc_type_lookup (abfd, code)
- bfd *abfd;
- bfd_reloc_code_real_type code;
- {
- switch (code)
- {
- case BFD_RELOC_8_PCREL: return &howto_hunk_reloc8;
- case BFD_RELOC_16_PCREL: return &howto_hunk_reloc16;
- case BFD_RELOC_32_PCREL: return &howto_hunk_reloc32;
- case BFD_RELOC_8: return &howto_hunk_drel8;
- case BFD_RELOC_16: return &howto_hunk_drel16;
- case BFD_RELOC_32: return &howto_hunk_drel32;
- default: return 0;
- }
- }
-
-
- /* We don't have core files. */
- #define amiga_core_file_failing_command _bfd_dummy_core_file_failing_command
- #define amiga_core_file_failing_signal _bfd_dummy_core_file_failing_signal
- #define amiga_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
-
- /* We use BSD-Unix generic archive files (fixme: test that this actually works). */
- #define amiga_openr_next_archived_file bfd_generic_openr_next_archived_file
- #define amiga_generic_stat_arch_elt bfd_generic_stat_arch_elt
- #define amiga_slurp_armap bfd_slurp_bsd_armap
- #define amiga_slurp_extended_name_table bfd_true
- #define amiga_write_armap bsd_write_armap
- #define amiga_truncate_arname bfd_bsd_truncate_arname
-
- #define amiga_bfd_debug_info_start bfd_void
- #define amiga_bfd_debug_info_end bfd_void
- #define amiga_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
-
- /* fixme: (when everything else has been done) a tailor-made
- amiga_get_relocated_section_contents would probably be faster
- than the generic routine. */
- #define amiga_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
- #define amiga_bfd_relax_section bfd_generic_relax_section
- #define amiga_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
- #define amiga_close_and_cleanup bfd_generic_close_and_cleanup
- #define amiga_bfd_make_debug_symbol \
- ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
- #define amiga_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
- #define amiga_bfd_link_add_symbols _bfd_generic_link_add_symbols
- #define amiga_bfd_final_link _bfd_generic_final_link
-
- #if defined (amiga)
- /* So that the JUMP_TABLE() macro below can work. */
- #undef amiga
- #endif
-
- bfd_target amiga_vec =
- {
- "amiga", /* name */
- bfd_target_amiga_flavour,
- true, /* data byte order is little */
- true, /* header byte order is little */
- HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT, /* object flags */
- SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC, /* section flags */
- '_', /* symbol leading char */
- ' ', /* ar_pad_char */
- 31, /* ar_max_namelen */
- 2, /* minimum align */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32,
- bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
- bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32,
- bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
- {
- /* bfd_check_format */
- _bfd_dummy_target,
- amiga_object_p,
- bfd_generic_archive_p,
- _bfd_dummy_target
- },
- {
- /* bfd_set_format */
- bfd_false,
- amiga_mkobject,
- _bfd_generic_mkarchive,
- bfd_false
- },
- {
- /* bfd_write_contents */
- bfd_false,
- amiga_write_object_contents,
- _bfd_write_archive_contents,
- bfd_false
- },
- JUMP_TABLE(amiga),
- (PTR) 0
- #if 0
- /* fixme: no longer in use? */
- /* How applications can find out about amiga relocation types (see
- documentation on reloc types). */
- amiga_reloc_type_lookup
- #endif
- };
-