Back to index

cell-binutils  2.17cvs20070401
ti.h
Go to the documentation of this file.
00001 /* COFF information for TI COFF support.  Definitions in this file should be
00002    customized in a target-specific file, and then this file included (see
00003    tic54x.h for an example).
00004    
00005    Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016    
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 #ifndef COFF_TI_H
00021 #define COFF_TI_H
00022 
00023 /* Note "coff/external.h is not used because TI adds extra fields to the structures.  */
00024 
00025 /********************** FILE HEADER **********************/
00026 
00027 struct external_filehdr
00028   {
00029     char f_magic[2]; /* magic number                    */
00030     char f_nscns[2]; /* number of sections              */
00031     char f_timdat[4];       /* time & date stamp        */
00032     char f_symptr[4];       /* file pointer to symtab   */
00033     char f_nsyms[4]; /* number of symtab entries */
00034     char f_opthdr[2];       /* sizeof(optional hdr)            */
00035     char f_flags[2]; /* flags                    */
00036     char f_target_id[2];    /* magic no. (TI COFF-specific) */
00037   };
00038 
00039 /* COFF0 has magic number in f_magic, and omits f_target_id from the file
00040    header; for later versions, f_magic is 0xC1 for COFF1 and 0xC2 for COFF2
00041    and the target-specific magic number is found in f_target_id */ 
00042 
00043 #define TICOFF0MAGIC    TI_TARGET_ID
00044 #define TICOFF1MAGIC    0x00C1
00045 #define TICOFF2MAGIC    0x00C2
00046 #define TICOFF_AOUT_MAGIC    0x0108 /* magic number in optional header */
00047 #define TICOFF          1 /* customize coffcode.h */
00048 
00049 /* The target_id field changes depending on the particular CPU target */
00050 /* for COFF0, the target id appeared in f_magic, where COFFX magic is now */
00051 #ifndef TI_TARGET_ID
00052 #error "TI_TARGET_ID needs to be defined for your CPU"
00053 #endif
00054 
00055 /* Which bfd_arch to use... */
00056 #ifndef TICOFF_TARGET_ARCH
00057 #error "TICOFF_TARGET_ARCH needs to be defined for your CPU"
00058 #endif
00059 
00060 #ifndef TICOFF_TARGET_MACHINE_GET
00061 #define TICOFF_TARGET_MACHINE_GET(FLAGS) 0
00062 #endif
00063 
00064 #ifndef TICOFF_TARGET_MACHINE_SET
00065 #define TICOFF_TARGET_MACHINE_SET(FLAGSP, MACHINE)
00066 #endif
00067 
00068 /* Default to COFF2 for file output */
00069 #ifndef TICOFF_DEFAULT_MAGIC
00070 #define TICOFF_DEFAULT_MAGIC TICOFF2MAGIC
00071 #endif
00072 
00073 /* This value is made available in the rare case where a bfd is unavailable */
00074 #ifndef OCTETS_PER_BYTE_POWER
00075 #error "OCTETS_PER_BYTE_POWER not defined for this CPU"
00076 #else
00077 #define OCTETS_PER_BYTE (1<<OCTETS_PER_BYTE_POWER)
00078 #endif
00079 
00080 /* default alignment is on a byte (not octet!) boundary */
00081 #ifndef COFF_DEFAULT_SECTION_ALIGNMENT_POWER
00082 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
00083 #endif
00084 
00085 /* TI COFF encodes the section alignment in the section header flags */
00086 #define COFF_ALIGN_IN_SECTION_HEADER 1
00087 #define COFF_ALIGN_IN_S_FLAGS 1
00088 /* requires a power-of-two argument */
00089 #define COFF_ENCODE_ALIGNMENT(S,X) ((S).s_flags |= (((unsigned)(X)&0xF)<<8))
00090 /* result is a power of two */
00091 #define COFF_DECODE_ALIGNMENT(X) (((X)>>8)&0xF)
00092 
00093 #define COFF0_P(ABFD) (bfd_coff_filhsz(ABFD) == FILHSZ_V0)
00094 #define COFF2_P(ABFD) (bfd_coff_scnhsz(ABFD) != SCNHSZ_V01)
00095 
00096 #define COFF0_BADMAG(x) ((x).f_magic != TICOFF0MAGIC)
00097 #define COFF1_BADMAG(x) ((x).f_magic != TICOFF1MAGIC || (x).f_target_id != TI_TARGET_ID)
00098 #define COFF2_BADMAG(x) ((x).f_magic != TICOFF2MAGIC || (x).f_target_id != TI_TARGET_ID)
00099 
00100 /* we need to read/write an extra field in the coff file header */
00101 #ifndef COFF_ADJUST_FILEHDR_IN_POST
00102 #define COFF_ADJUST_FILEHDR_IN_POST(abfd, src, dst) \
00103   do                                                           \
00104     {                                                          \
00105       ((struct internal_filehdr *)(dst))->f_target_id =               \
00106        H_GET_16 (abfd, ((FILHDR *)(src))->f_target_id);        \
00107     }                                                          \
00108   while (0)
00109 #endif
00110 
00111 #ifndef COFF_ADJUST_FILEHDR_OUT_POST
00112 #define COFF_ADJUST_FILEHDR_OUT_POST(abfd, src, dst) \
00113   do                                                           \
00114     {                                                          \
00115       H_PUT_16 (abfd, ((struct internal_filehdr *)(src))->f_target_id,       \
00116               ((FILHDR *)(dst))->f_target_id);                        \
00117     }                                                          \
00118   while (0)
00119 #endif
00120 
00121 #define       FILHDR struct external_filehdr
00122 #define       FILHSZ 22
00123 #define FILHSZ_V0 20                /* COFF0 omits target_id field */
00124 
00125 /* File header flags */
00126 #define       F_RELFLG      (0x0001)
00127 #define       F_EXEC        (0x0002)
00128 #define       F_LNNO        (0x0004)
00129 #define F_VERS          (0x0010) /* TMS320C4x code */
00130 /* F_LSYMS needs to be redefined in your source file */
00131 #define       F_LSYMS_TICOFF       (0x0010) /* normal COFF is 0x8 */
00132 
00133 #define F_10            0x00    /* file built for TMS320C1x devices */
00134 #define F_20            0x10    /* file built for TMS320C2x devices */
00135 #define F_25            0x20    /* file built for TMS320C2x/C5x devices */
00136 #define F_LENDIAN       0x0100  /* 16 bits/word, LSB first */
00137 #define F_SYMMERGE      0x1000  /* duplicate symbols were removed */
00138 
00139 /********************** OPTIONAL HEADER **********************/
00140 
00141 
00142 typedef struct 
00143 {
00144   char        magic[2];            /* type of file (0x108)            */
00145   char vstamp[2];           /* version stamp                   */
00146   char tsize[4];            /* text size in bytes, padded to FW bdry*/
00147   char dsize[4];            /* initialized data "  "           */
00148   char bsize[4];            /* uninitialized data "   "        */
00149   char entry[4];            /* entry pt.                       */
00150   char        text_start[4];              /* base of text used for this file */
00151   char        data_start[4];              /* base of data used for this file */
00152 }
00153 AOUTHDR;
00154 
00155 
00156 #define AOUTHDRSZ 28
00157 #define AOUTSZ 28
00158 
00159 
00160 /********************** SECTION HEADER **********************/
00161 /* COFF0, COFF1 */
00162 struct external_scnhdr_v01 {
00163        char          s_name[8];    /* section name                    */
00164        char          s_paddr[4];   /* physical address, aliased s_nlib */
00165        char          s_vaddr[4];   /* virtual address          */
00166        char          s_size[4];    /* section size (in WORDS)      */
00167        char          s_scnptr[4];  /* file ptr to raw data for section */
00168        char          s_relptr[4];  /* file ptr to relocation   */
00169        char          s_lnnoptr[4]; /* file ptr to line numbers */
00170        char          s_nreloc[2];  /* number of relocation entries    */
00171        char          s_nlnno[2];   /* number of line number entries*/
00172        char          s_flags[2];   /* flags                    */
00173         char            s_reserved[1];  /* reserved                     */ 
00174         char            s_page[1];      /* section page number (LOAD)   */
00175 };
00176 
00177 /* COFF2 */
00178 struct external_scnhdr {
00179        char          s_name[8];    /* section name                    */
00180        char          s_paddr[4];   /* physical address, aliased s_nlib */
00181        char          s_vaddr[4];   /* virtual address          */
00182        char          s_size[4];    /* section size (in WORDS)      */
00183        char          s_scnptr[4];  /* file ptr to raw data for section */
00184        char          s_relptr[4];  /* file ptr to relocation   */
00185        char          s_lnnoptr[4]; /* file ptr to line numbers */
00186        char          s_nreloc[4];  /* number of relocation entries    */
00187        char          s_nlnno[4];   /* number of line number entries*/
00188        char          s_flags[4];   /* flags                    */
00189         char            s_reserved[2];  /* reserved                     */ 
00190         char            s_page[2];      /* section page number (LOAD)   */
00191 };
00192 
00193 /*
00194  * Special section flags
00195  */
00196 
00197 /* TI COFF defines these flags; 
00198    STYP_CLINK: the section should be excluded from the final
00199    linker output if there are no references found to any symbol in the section
00200    STYP_BLOCK: the section should be blocked, i.e. if the section would cross
00201    a page boundary, it is started at a page boundary instead.
00202    TI COFF puts the section alignment power of two in the section flags
00203    e.g. 2**N is alignment, flags |= (N & 0xF) << 8
00204 */ 
00205 #define STYP_CLINK      (0x4000)
00206 #define STYP_BLOCK      (0x1000)
00207 #define STYP_ALIGN      (0x0F00) /* TI COFF stores section alignment here */
00208 
00209 #define       SCNHDR_V01 struct external_scnhdr_v01
00210 #define SCNHDR struct external_scnhdr
00211 #define       SCNHSZ_V01 40                  /* for v0 and v1 */
00212 #define SCNHSZ 48
00213 
00214 /* COFF2 changes the offsets and sizes of these fields 
00215    Assume we're dealing with the COFF2 scnhdr structure, and adjust
00216    accordingly 
00217  */
00218 #define GET_SCNHDR_NRELOC(ABFD, LOC) \
00219   (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, LOC))
00220 #define PUT_SCNHDR_NRELOC(ABFD, VAL, LOC) \
00221   (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, LOC))
00222 #define GET_SCNHDR_NLNNO(ABFD, LOC) \
00223   (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 2))
00224 #define PUT_SCNHDR_NLNNO(ABFD, VAL, LOC) \
00225   (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 2))
00226 #define GET_SCNHDR_FLAGS(ABFD, LOC) \
00227   (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 4))
00228 #define PUT_SCNHDR_FLAGS(ABFD, VAL, LOC) \
00229   (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 4))
00230 #define GET_SCNHDR_PAGE(ABFD, LOC) \
00231   (COFF2_P (ABFD) ? H_GET_16 (ABFD, LOC) : (unsigned) H_GET_8 (ABFD, (LOC) - 7))
00232 /* on output, make sure that the "reserved" field is zero */
00233 #define PUT_SCNHDR_PAGE(ABFD, VAL, LOC) \
00234   (COFF2_P (ABFD) \
00235    ? H_PUT_16 (ABFD, VAL, LOC) \
00236    : H_PUT_8 (ABFD, VAL, (LOC) - 7), H_PUT_8 (ABFD, 0, (LOC) - 8))
00237 
00238 /* TI COFF stores section size as number of bytes (address units, not octets),
00239    so adjust to be number of octets, which is what BFD expects */ 
00240 #define GET_SCNHDR_SIZE(ABFD, SZP) \
00241   (H_GET_32 (ABFD, SZP) * bfd_octets_per_byte (ABFD))
00242 #define PUT_SCNHDR_SIZE(ABFD, SZ, SZP) \
00243   H_PUT_32 (ABFD, (SZ) / bfd_octets_per_byte (ABFD), SZP)
00244 
00245 #define COFF_ADJUST_SCNHDR_IN_POST(ABFD, EXT, INT) \
00246   do                                                           \
00247     {                                                          \
00248       ((struct internal_scnhdr *)(INT))->s_page =                     \
00249        GET_SCNHDR_PAGE (ABFD, ((SCNHDR *)(EXT))->s_page);             \
00250     }                                                          \
00251    while (0)
00252 
00253 /* The line number and reloc overflow checking in coff_swap_scnhdr_out in
00254    coffswap.h doesn't use PUT_X for s_nlnno and s_nreloc.
00255    Due to different sized v0/v1/v2 section headers, we have to re-write these
00256    fields.
00257  */
00258 #define COFF_ADJUST_SCNHDR_OUT_POST(ABFD, INT, EXT) \
00259   do                                                              \
00260     {                                                             \
00261       PUT_SCNHDR_NLNNO (ABFD, ((struct internal_scnhdr *)(INT))->s_nlnno,  \
00262                      ((SCNHDR *)(EXT))->s_nlnno);                        \
00263       PUT_SCNHDR_NRELOC (ABFD, ((struct internal_scnhdr *)(INT))->s_nreloc,\
00264                       ((SCNHDR *)(EXT))->s_nreloc);                      \
00265       PUT_SCNHDR_FLAGS (ABFD, ((struct internal_scnhdr *)(INT))->s_flags,  \
00266                      ((SCNHDR *)(EXT))->s_flags);                        \
00267       PUT_SCNHDR_PAGE (ABFD, ((struct internal_scnhdr *)(INT))->s_page,    \
00268                      ((SCNHDR *)(EXT))->s_page);                  \
00269     }                                                             \
00270    while (0)
00271 
00272 /*
00273  * names of "special" sections
00274  */
00275 #define _TEXT ".text"
00276 #define _DATA ".data"
00277 #define _BSS  ".bss"
00278 #define _CINIT  ".cinit"            /* initialized C data */
00279 #define _SCONST  ".const"           /* constants */
00280 #define _SWITCH ".switch"           /* switch tables */
00281 #define _STACK  ".stack"            /* C stack */
00282 #define _SYSMEM ".sysmem"           /* used for malloc et al. syscalls */
00283 
00284 /********************** LINE NUMBERS **********************/
00285 
00286 /* 1 line number entry for every "breakpointable" source line in a section.
00287  * Line numbers are grouped on a per function basis; first entry in a function
00288  * grouping will have l_lnno = 0 and in place of physical address will be the
00289  * symbol table index of the function name.
00290  */
00291 struct external_lineno {
00292   union {
00293     char l_symndx[4];       /* function name symbol index, iff l_lnno == 0*/
00294     char l_paddr[4]; /* (physical) address of line number      */
00295   } l_addr;
00296   char l_lnno[2];    /* line number              */
00297 };
00298 
00299 #define       LINENO struct external_lineno
00300 #define       LINESZ 6
00301 
00302 
00303 /********************** SYMBOLS **********************/
00304 
00305 /* NOTE: this is what a local label looks like in assembly source; what it
00306    looks like in COFF output is undefined */
00307 #define TICOFF_LOCAL_LABEL_P(NAME) \
00308 ((NAME[0] == '$' && NAME[1] >= '0' && NAME[1] <= '9' && NAME[2] == '\0') \
00309  || NAME[strlen(NAME)-1] == '?')
00310 
00311 #define E_SYMNMLEN   8      /* # characters in a symbol name   */
00312 #define E_FILNMLEN   14     /* # characters in a file name            */
00313 #define E_DIMNUM     4      /* # array dimensions in auxiliary entry */
00314 
00315 struct external_syment 
00316 {
00317   union {
00318     char e_name[E_SYMNMLEN];
00319     struct {
00320       char e_zeroes[4];
00321       char e_offset[4];
00322     } e;
00323   } e;
00324   char e_value[4];
00325   char e_scnum[2];
00326   char e_type[2];
00327   char e_sclass[1];
00328   char e_numaux[1];
00329 };
00330 
00331 
00332 #define N_BTMASK     (017)
00333 #define N_TMASK             (060)
00334 #define N_BTSHFT     (4)
00335 #define N_TSHIFT     (2)
00336   
00337 
00338 union external_auxent {
00339   struct {
00340        char x_tagndx[4];    /* str, un, or enum tag indx */
00341        union {
00342          struct {
00343               char  x_lnno[2]; /* declaration line number */
00344               char  x_size[2]; /* str/union/array size */
00345          } x_lnsz;
00346          char x_fsize[4];   /* size of function */
00347        } x_misc;
00348        union {
00349          struct {           /* if ISFCN, tag, or .bb */
00350               char x_lnnoptr[4];   /* ptr to fcn line # */
00351               char x_endndx[4];    /* entry ndx past block end */
00352          } x_fcn;
00353          struct {           /* if ISARY, up to 4 dimen. */
00354               char x_dimen[E_DIMNUM][2];
00355          } x_ary;
00356        } x_fcnary;
00357        char x_tvndx[2];            /* tv index */
00358   } x_sym;
00359   
00360   union {
00361        char x_fname[E_FILNMLEN];
00362        struct {
00363          char x_zeroes[4];
00364          char x_offset[4];
00365        } x_n;
00366   } x_file;
00367   
00368   struct {
00369        char x_scnlen[4];                  /* section length */
00370        char x_nreloc[2];    /* # relocation entries */
00371        char x_nlinno[2];    /* # line numbers */
00372   } x_scn;
00373   
00374   struct {
00375        char x_tvfill[4];    /* tv fill value */
00376        char x_tvlen[2];     /* length of .tv */
00377        char x_tvran[2][2];  /* tv range */
00378   } x_tv;            /* info about .tv section (in auxent of symbol .tv)) */
00379   
00380 
00381 };
00382 
00383 #define       SYMENT struct external_syment
00384 #define       SYMESZ 18     
00385 #define       AUXENT union external_auxent
00386 #define       AUXESZ 18
00387 
00388 /* section lengths are in target bytes (not host bytes) */
00389 #define GET_SCN_SCNLEN(ABFD, EXT) \
00390   (H_GET_32 (ABFD, (EXT)->x_scn.x_scnlen) * bfd_octets_per_byte (ABFD))
00391 #define PUT_SCN_SCNLEN(ABFD, INT, EXT) \
00392   H_PUT_32 (ABFD, (INT) / bfd_octets_per_byte (ABFD), (EXT)->x_scn.x_scnlen)
00393 
00394 /* lnsz size is in bits in COFF file, in bytes in BFD */
00395 #define GET_LNSZ_SIZE(abfd, ext) \
00396  (H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size) / (class != C_FIELD ? 8 : 1))
00397 
00398 #define PUT_LNSZ_SIZE(abfd, in, ext) \
00399   H_PUT_16 (abfd, ((class != C_FIELD) ? (in) * 8 : (in)), \
00400           ext->x_sym.x_misc.x_lnsz.x_size)
00401  
00402 /* TI COFF stores offsets for MOS and MOU in bits; BFD expects bytes 
00403    Also put the load page flag of the section into the symbol value if it's an
00404    address.  */
00405 #ifndef NEEDS_PAGE
00406 #define NEEDS_PAGE(X) 0
00407 #define PAGE_MASK 0
00408 #endif
00409 #define COFF_ADJUST_SYM_IN_POST(ABFD, EXT, INT) \
00410   do                                                           \
00411     {                                                          \
00412       struct internal_syment *dst = (struct internal_syment *)(INT);  \
00413       if (dst->n_sclass == C_MOS || dst->n_sclass == C_MOU)           \
00414        dst->n_value /= 8;                                      \
00415       else if (NEEDS_PAGE (dst->n_sclass)) {                            \
00416         asection *scn = coff_section_from_bfd_index (abfd, dst->n_scnum); \
00417         dst->n_value |= (scn->lma & PAGE_MASK);                         \
00418       }                                                               \
00419     }                                                          \
00420    while (0)
00421 
00422 #define COFF_ADJUST_SYM_OUT_POST(ABFD, INT, EXT) \
00423   do                                                           \
00424     {                                                          \
00425        struct internal_syment *src = (struct internal_syment *)(INT); \
00426        SYMENT *dst = (SYMENT *)(EXT);                                 \
00427        if (src->n_sclass == C_MOU || src->n_sclass == C_MOS)          \
00428         H_PUT_32 (abfd, src->n_value * 8, dst->e_value);              \
00429        else if (NEEDS_PAGE (src->n_sclass)) {                           \
00430          H_PUT_32 (abfd, src->n_value &= ~PAGE_MASK, dst->e_value);     \
00431        }                                                       \
00432     }                                                          \
00433    while (0)
00434 
00435 /* Detect section-relative absolute symbols so they get flagged with a sym
00436    index of -1.
00437 */
00438 #define SECTION_RELATIVE_ABSOLUTE_SYMBOL_P(RELOC, SECT) \
00439   ((*(RELOC)->sym_ptr_ptr)->section->output_section == (SECT) \
00440    && (RELOC)->howto->name[0] == 'A')
00441 
00442 /********************** RELOCATION DIRECTIVES **********************/
00443 
00444 struct external_reloc_v0
00445 {
00446   char r_vaddr[4];
00447   char r_symndx[2];
00448   char r_reserved[2];
00449   char r_type[2];
00450 };
00451 
00452 struct external_reloc
00453 {
00454   char r_vaddr[4];
00455   char r_symndx[4];
00456   char r_reserved[2]; /* extended pmad byte for COFF2 */
00457   char r_type[2];
00458 };
00459 
00460 #define RELOC struct external_reloc
00461 #define RELSZ_V0 10                 /* FIXME -- coffcode.h needs fixing */
00462 #define RELSZ 12                    /* for COFF1/2 */
00463 
00464 /* various relocation types.  */
00465 #define R_ABS     0x0000            /* no relocation */
00466 #define R_REL13   0x002A            /* 13-bit direct reference (???) */
00467 #define R_PARTLS7 0x0028            /* 7 LSBs of an address */
00468 #define R_PARTMS9 0x0029            /* 9MSBs of an address */
00469 #define R_EXTWORD 0x002B            /* 23-bit direct reference */
00470 #define R_EXTWORD16 0x002C          /* 16-bit direct reference to 23-bit addr*/
00471 #define R_EXTWORDMS7 0x002D         /* upper 7 bits of 23-bit address */
00472 
00473 #endif /* COFF_TI_H */