diff -urN binutils-2.12.90.0.1-orig/bfd/coff-tiarm.c binutils-2.12.90.0.1/bfd/coff-tiarm.c --- binutils-2.12.90.0.1-orig/bfd/coff-tiarm.c Thu Jan 1 01:00:00 1970 +++ binutils-2.12.90.0.1/bfd/coff-tiarm.c Tue Mar 2 16:18:15 2004 @@ -0,0 +1,336 @@ +/* BFD back-end for TI ARM coff binaries. + Peter Maydell 2004-02-26, based on tic54x.c which is: + + Copyright 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Timothy Wall (twall@cygnus.com) + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#include "bfdlink.h" +#include "coff/tiarm.h" +#include "coff/internal.h" +#include "libcoff.h" + +/* TI COFF allows >8 char section names (name goes into symbol table + * and section name field becomes an offset to it); they're slightly + * different to the existing PE style long name support. + */ +#define COFF_LONG_SECTION_NAMES +#define COFF_TI_LONG_SECTION_NAMES + +#undef F_LSYMS +#define F_LSYMS F_LSYMS_TICOFF + +static void tiarm_reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *)); +static bfd_reloc_status_type tiarm_relocation PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static boolean tiarm_set_section_contents PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type)); +static reloc_howto_type * coff_tiarm_rtype_to_howto PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *)); +static boolean tiarm_set_arch_mach PARAMS ((bfd *, enum bfd_architecture, unsigned long)); +static reloc_howto_type * tiarm_coff_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); +static void tiarm_lookup_howto PARAMS ((arelent *, struct internal_reloc *)); +static boolean ticoff_bfd_is_local_label_name PARAMS ((bfd *, const char *)); + + +/* Set the architecture appropriately. Allow unknown architectures + (e.g. binary). */ + +static boolean +tiarm_set_arch_mach (abfd, arch, machine) + bfd *abfd; + enum bfd_architecture arch; + unsigned long machine; +{ + if (arch == bfd_arch_unknown) + arch = bfd_arch_arm; + + else if (arch != bfd_arch_arm) + return false; + + return bfd_default_set_arch_mach (abfd, arch, machine); +} + +static bfd_reloc_status_type +tiarm_relocation (abfd, reloc_entry, symbol, data, input_section, + output_bfd, error_message) + bfd *abfd ATTRIBUTE_UNUSED; + arelent *reloc_entry; + asymbol *symbol ATTRIBUTE_UNUSED; + PTR data ATTRIBUTE_UNUSED; + asection *input_section; + bfd *output_bfd; + char **error_message ATTRIBUTE_UNUSED; +{ + if (output_bfd != (bfd *) NULL) + { + /* This is a partial relocation, and we want to apply the + relocation to the reloc entry rather than the raw data. + Modify the reloc inplace to reflect what we now know. */ + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + return bfd_reloc_continue; +} + +reloc_howto_type tiarm_howto_table[] = + { + /* type,rightshift,size (0=byte, 1=short, 2=long), + bit size, pc_relative, bitpos, dont complain_on_overflow, + special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */ + + /* NORMAL BANK */ + /* 23 bit PC relative reference to a symbol's address in halfwords (ie div by 2) */ + HOWTO (R_PCR23H,0,2,23,true,0,complain_overflow_dont, + tiarm_relocation,"PCR23H",false,0x007FFFFF,0x007FFFFF,false), + + /* 24 bit PC relative reference to a symbol's address in words (ie div by 4) */ + HOWTO (R_PCR24W,0,2,24,false,0,complain_overflow_dont, + tiarm_relocation,"ARM26",false,0x00FFFFFF,0x00FFFFFF,false), + + /* 32-bit relocation exclusively for stabs */ + HOWTO (R_RELLONG,0,2,32,false,0,complain_overflow_dont, + tiarm_relocation,"STAB",false,0xFFFFFFFF,0xFFFFFFFF,false), + + /* ABSOLUTE BANK */ + /* 23 bit PC relative reference to a symbol's address in halfwords (ie div by 2) */ + HOWTO (R_PCR23H,0,2,23,true,0,complain_overflow_dont, + tiarm_relocation,"APCR23H",false,0x007FFFFF,0x007FFFFF,false), + + /* 24 bit PC relative reference to a symbol's address in words (ie div by 4) */ + HOWTO (R_PCR24W,0,2,24,false,0,complain_overflow_dont, + tiarm_relocation,"APCR24W",false,0x00FFFFFF,0x00FFFFFF,false), + + /* 32-bit relocation exclusively for stabs */ + HOWTO (R_RELLONG,0,2,32,false,0,complain_overflow_dont, + tiarm_relocation,"STAB",false,0xFFFFFFFF,0xFFFFFFFF,false), + }; + +#define coff_bfd_reloc_type_lookup tiarm_coff_reloc_type_lookup + +/* For the case statement use the code values used tc_gen_reloc (defined in + bfd/reloc.c) to map to the howto table entries. */ + +reloc_howto_type * +tiarm_coff_reloc_type_lookup (abfd, code) + bfd *abfd ATTRIBUTE_UNUSED; + bfd_reloc_code_real_type code; +{ + fprintf(stderr, "tiarm_coff_reloc_type_lookup: code %d\n", code); + switch (code) + { + case BFD_RELOC_ARM_PCREL_BLX: /* this is a bit of a guess -- PMM*/ + return &tiarm_howto_table[0]; + case BFD_RELOC_ARM_PCREL_BRANCH: + return &tiarm_howto_table[1]; + case BFD_RELOC_32: + return &tiarm_howto_table[2]; + default: + return (reloc_howto_type *) NULL; + } +} + +/* Code to turn a r_type into a howto ptr, uses the above howto table. + Called after some initial checking by the tiarm_rtype_to_howto fn below. */ + +static void +tiarm_lookup_howto (internal, dst) + arelent *internal; + struct internal_reloc *dst; +{ + unsigned i; + int bank = (dst->r_symndx == -1) ? HOWTO_BANK : 0; + + for (i = 0; i < sizeof tiarm_howto_table/sizeof tiarm_howto_table[0]; i++) + { + if (tiarm_howto_table[i].type == dst->r_type) + { + internal->howto = tiarm_howto_table + i + bank; + return; + } + } + + (*_bfd_error_handler) (_("Unrecognized reloc type 0x%x"), + (unsigned int) dst->r_type); + abort (); +} + +#define RELOC_PROCESSING(RELENT,RELOC,SYMS,ABFD,SECT)\ + tiarm_reloc_processing(RELENT,RELOC,SYMS,ABFD,SECT) + +#define coff_rtype_to_howto coff_tiarm_rtype_to_howto + +static reloc_howto_type * +coff_tiarm_rtype_to_howto (abfd, sec, rel, h, sym, addendp) + bfd *abfd ATTRIBUTE_UNUSED; + asection *sec; + struct internal_reloc *rel; + struct coff_link_hash_entry *h ATTRIBUTE_UNUSED; + struct internal_syment *sym ATTRIBUTE_UNUSED; + bfd_vma *addendp; +{ + arelent genrel; + + if (rel->r_symndx == -1 && addendp != NULL) + { + /* This is a TI "internal relocation", which means that the relocation + amount is the amount by which the current section is being relocated + in the output section. */ + *addendp = (sec->output_section->vma + sec->output_offset) - sec->vma; + } + + tiarm_lookup_howto (&genrel, rel); + + return genrel.howto; +} + +/* Replace the stock _bfd_coff_is_local_label_name to recognize TI COFF local + labels. */ + +static boolean +ticoff_bfd_is_local_label_name (abfd, name) + bfd *abfd ATTRIBUTE_UNUSED; + const char *name; +{ + if (TICOFF_LOCAL_LABEL_P(name)) + return true; + return false; +} + +#define coff_bfd_is_local_label_name ticoff_bfd_is_local_label_name + +/* Customize coffcode.h; the default coff_ functions are set up to use COFF2; + coff_bad_format_hook uses BADMAG, so set that for COFF2. The COFF1 + and COFF0 vectors use custom _bad_format_hook procs instead of setting + BADMAG. */ +#define BADMAG(x) COFF2_BADMAG(x) +#include "coffcode.h" + +static boolean +tiarm_set_section_contents (abfd, section, location, offset, bytes_to_do) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type bytes_to_do; +{ + return coff_set_section_contents (abfd, section, location, + offset, bytes_to_do); +} + +static void +tiarm_reloc_processing (relent, reloc, symbols, abfd, section) + arelent *relent; + struct internal_reloc *reloc; + asymbol **symbols; + bfd *abfd; + asection *section; +{ + asymbol *ptr; + + relent->address = reloc->r_vaddr; + + if (reloc->r_symndx != -1) + { + if (reloc->r_symndx < 0 || reloc->r_symndx >= obj_conv_table_size (abfd)) + { + (*_bfd_error_handler) + (_("%s: warning: illegal symbol index %ld in relocs"), + bfd_archive_filename (abfd), reloc->r_symndx); + relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + ptr = NULL; + } + else + { + relent->sym_ptr_ptr = (symbols + + obj_convert (abfd)[reloc->r_symndx]); + ptr = *(relent->sym_ptr_ptr); + } + } + else + { + relent->sym_ptr_ptr = section->symbol_ptr_ptr; + ptr = *(relent->sym_ptr_ptr); + } + + /* The symbols definitions that we have read in have been + relocated as if their sections started at 0. But the offsets + refering to the symbols in the raw data have not been + modified, so we have to have a negative addend to compensate. + + Note that symbols which used to be common must be left alone. */ + + /* Calculate any reloc addend by looking at the symbol. */ + CALC_ADDEND (abfd, ptr, *reloc, relent); + + relent->address -= section->vma; + /* !! relent->section = (asection *) NULL;*/ + + /* Fill in the relent->howto field from reloc->r_type. */ + tiarm_lookup_howto (relent, reloc); +} + + +/* TI COFF v2, ARM CPU */ +const bfd_target tiarm_coff_vec = + { + /* NB that coff_set_flags() looks at the 5th character in this name string + * to decide what COFF version to output, so it *must* be 0/1/2! -- PMM + */ + "coff2ti-arm", /* name */ + bfd_target_coff_flavour, + BFD_ENDIAN_LITTLE, /* data byte order is little */ + BFD_ENDIAN_LITTLE, /* header byte order is little */ + + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT ), + + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + '_', /* leading symbol underscore */ + '/', /* ar_pad_char */ + 15, /* ar_max_namelen */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ + + {_bfd_dummy_target, coff_object_p, /* bfd_check_format */ + bfd_generic_archive_p, _bfd_dummy_target}, + {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */ + bfd_false}, + {bfd_false, coff_write_object_contents, /* bfd_write_contents */ + _bfd_write_archive_contents, bfd_false}, + + BFD_JUMP_TABLE_GENERIC (coff), + BFD_JUMP_TABLE_COPY (coff), + BFD_JUMP_TABLE_CORE (_bfd_nocore), + BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), + BFD_JUMP_TABLE_SYMBOLS (coff), + BFD_JUMP_TABLE_RELOCS (coff), + BFD_JUMP_TABLE_WRITE (tiarm), + BFD_JUMP_TABLE_LINK (coff), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + + NULL, + + COFF_SWAP_TABLE + }; diff -urN binutils-2.12.90.0.1-orig/bfd/coffcode.h binutils-2.12.90.0.1/bfd/coffcode.h --- binutils-2.12.90.0.1-orig/bfd/coffcode.h Wed Mar 17 14:29:42 2004 +++ binutils-2.12.90.0.1/bfd/coffcode.h Mon Mar 1 17:13:22 2004 @@ -3416,7 +3416,15 @@ if (len > SCNNMLEN) { memset (section.s_name, 0, SCNNMLEN); +#ifdef COFF_TI_LONG_SECTION_NAMES + /* TI do this slightly differently, with 4 leading NULs and + * then the offset as an int rather than a string. + * FIXME-PMM endianity issues here? + */ + H_PUT_32(abfd, string_size, section.s_name + 4); +#else sprintf (section.s_name, "/%lu", (unsigned long) string_size); +#endif string_size += len + 1; long_section_names = true; } diff -urN binutils-2.12.90.0.1-orig/bfd/coffgen.c binutils-2.12.90.0.1/bfd/coffgen.c --- binutils-2.12.90.0.1-orig/bfd/coffgen.c Wed Mar 17 14:29:43 2004 +++ binutils-2.12.90.0.1/bfd/coffgen.c Mon Mar 1 17:15:03 2004 @@ -88,25 +88,42 @@ name = NULL; /* Handle long section names as in PE. */ - if (bfd_coff_long_section_names (abfd) - && hdr->s_name[0] == '/') + if (bfd_coff_long_section_names (abfd)) { - char buf[SCNNMLEN]; - long strindex; - char *p; - const char *strings; + long strindex = -1; + + if (hdr->s_name[0] == '/') + { + char buf[SCNNMLEN]; + char *p; + + memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1); + buf[SCNNMLEN - 1] = '\0'; + strindex = strtol (buf, &p, 10); + if (*p != '\0') + strindex = -1; + } + else if (hdr->s_name[0] == '\0') + { + /* TI style long section names: the first 4 bytes of the section + * header are 0, followed by an offset into the string table. + * FIXME-PMM is this the right way to read the data regardless + * of endianity? + */ + long nulls = H_GET_32(abfd, hdr->s_name); + if (nulls == 0) + strindex = H_GET_32(abfd, hdr->s_name + 4); + } - memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1); - buf[SCNNMLEN - 1] = '\0'; - strindex = strtol (buf, &p, 10); - if (*p == '\0' && strindex >= 0) + if (strindex >= 0) { + const char *strings; strings = _bfd_coff_read_string_table (abfd); if (strings == NULL) return false; /* FIXME: For extra safety, we should make sure that - strindex does not run us past the end, but right now we - don't know the length of the string table. */ + strindex does not run us past the end, but right now we + don't know the length of the string table. */ strings += strindex; name = bfd_alloc (abfd, (bfd_size_type) strlen (strings) + 1); if (name == NULL) @@ -114,7 +131,7 @@ strcpy (name, strings); } } - + if (name == NULL) { /* Assorted wastage to null-terminate the name, thanks AT&T! */ diff -urN binutils-2.12.90.0.1-orig/bfd/targets.c binutils-2.12.90.0.1/bfd/targets.c --- binutils-2.12.90.0.1-orig/bfd/targets.c Wed Mar 17 14:29:43 2004 +++ binutils-2.12.90.0.1/bfd/targets.c Thu Feb 26 12:45:02 2004 @@ -645,6 +645,7 @@ extern const bfd_target sparclynx_coff_vec; extern const bfd_target sparcnetbsd_vec; extern const bfd_target sunos_big_vec; +extern const bfd_target tiarm_coff_vec; extern const bfd_target tic30_aout_vec; extern const bfd_target tic30_coff_vec; extern const bfd_target tic54x_coff0_beh_vec; @@ -945,6 +946,7 @@ &sparclynx_coff_vec, &sparcnetbsd_vec, &sunos_big_vec, + &tiarm_coff_vec, &tic30_aout_vec, &tic30_coff_vec, &tic54x_coff0_beh_vec, diff -urN binutils-2.12.90.0.1-orig/include/coff/tiarm.h binutils-2.12.90.0.1/include/coff/tiarm.h --- binutils-2.12.90.0.1-orig/include/coff/tiarm.h Thu Jan 1 01:00:00 1970 +++ binutils-2.12.90.0.1/include/coff/tiarm.h Fri Feb 27 12:27:46 2004 @@ -0,0 +1,37 @@ +/* TI COFF information for Texas Instruments style COFF file, ARM CPU + This file customizes the settings in coff/ti.h. + Peter Maydell 2004-02-26 + + Copyright 2001 Free Software Foundation, Inc. + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef COFF_TIARM_H +#define COFF_TIARM_H + +#define TIARM_TARGET_ID 0x97 +#define TI_TARGET_ID TIARM_TARGET_ID +#define OCTETS_PER_BYTE_POWER 1 /* octets per byte, as a power of two */ +#define HOWTO_BANK 3 /* add to howto to get absolute/sect-relative version */ +#define TICOFF_TARGET_ARCH bfd_arch_arm +#define TICOFF_DEFAULT_MAGIC TICOFF2MAGIC + +/* Relocation types, as per CodeComposer documentation */ +#define R_PCR23H 0x16 /* 23 bit PC-relative reference to a symbol's addr in halfwords */ +#define R_PCR24W 0x17 /* 24 bit PC-relative reference to a symbol's addr in words */ + +#include "coff/ti.h" + +#endif /* COFF_TIC54X_H */