customized in a target-specific file, and then this file included (see
tic54x.h for an example).
Copyright 2000, 2001, 2002, 2003, 2008 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef COFF_TI_H
#define COFF_TI_H
struct external_filehdr
{
char f_magic[2];
char f_nscns[2];
char f_timdat[4];
char f_symptr[4];
char f_nsyms[4];
char f_opthdr[2];
char f_flags[2];
char f_target_id[2];
};
header; for later versions, f_magic is 0xC1 for COFF1 and 0xC2 for COFF2
and the target-specific magic number is found in f_target_id */
#define TICOFF0MAGIC TI_TARGET_ID
#define TICOFF1MAGIC 0x00C1
#define TICOFF2MAGIC 0x00C2
#define TICOFF_AOUT_MAGIC 0x0108 /* magic number in optional header */
#define TICOFF 1 /* customize coffcode.h */
#ifndef TI_TARGET_ID
#error "TI_TARGET_ID needs to be defined for your CPU"
#endif
#ifndef TICOFF_TARGET_ARCH
#error "TICOFF_TARGET_ARCH needs to be defined for your CPU"
#endif
#ifndef TICOFF_TARGET_MACHINE_GET
#define TICOFF_TARGET_MACHINE_GET(FLAGS) 0
#endif
#ifndef TICOFF_TARGET_MACHINE_SET
#define TICOFF_TARGET_MACHINE_SET(FLAGSP, MACHINE)
#endif
#ifndef TICOFF_DEFAULT_MAGIC
#define TICOFF_DEFAULT_MAGIC TICOFF2MAGIC
#endif
#ifndef OCTETS_PER_BYTE_POWER
#error "OCTETS_PER_BYTE_POWER not defined for this CPU"
#else
#define OCTETS_PER_BYTE (1<<OCTETS_PER_BYTE_POWER)
#endif
#ifndef COFF_DEFAULT_SECTION_ALIGNMENT_POWER
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
#endif
#define COFF_ALIGN_IN_SECTION_HEADER 1
#define COFF_ALIGN_IN_S_FLAGS 1
#define COFF_ENCODE_ALIGNMENT(S,X) ((S).s_flags |= (((unsigned)(X)&0xF)<<8))
#define COFF_DECODE_ALIGNMENT(X) (((X)>>8)&0xF)
#define COFF0_P(ABFD) (bfd_coff_filhsz(ABFD) == FILHSZ_V0)
#define COFF2_P(ABFD) (bfd_coff_scnhsz(ABFD) != SCNHSZ_V01)
#define COFF0_BADMAG(x) ((x).f_magic != TICOFF0MAGIC)
#define COFF1_BADMAG(x) ((x).f_magic != TICOFF1MAGIC || (x).f_target_id != TI_TARGET_ID)
#define COFF2_BADMAG(x) ((x).f_magic != TICOFF2MAGIC || (x).f_target_id != TI_TARGET_ID)
#ifndef COFF_ADJUST_FILEHDR_IN_POST
#define COFF_ADJUST_FILEHDR_IN_POST(abfd, src, dst) \
do \
{ \
((struct internal_filehdr *)(dst))->f_target_id = \
H_GET_16 (abfd, ((FILHDR *)(src))->f_target_id); \
} \
while (0)
#endif
#ifndef COFF_ADJUST_FILEHDR_OUT_POST
#define COFF_ADJUST_FILEHDR_OUT_POST(abfd, src, dst) \
do \
{ \
H_PUT_16 (abfd, ((struct internal_filehdr *)(src))->f_target_id, \
((FILHDR *)(dst))->f_target_id); \
} \
while (0)
#endif
#define FILHDR struct external_filehdr
#define FILHSZ 22
#define FILHSZ_V0 20 /* COFF0 omits target_id field */
#define F_RELFLG (0x0001)
#define F_EXEC (0x0002)
#define F_LNNO (0x0004)
#define F_VERS (0x0010) /* TMS320C4x code */
#define F_LSYMS_TICOFF (0x0010) /* normal COFF is 0x8 */
#define F_10 0x00 /* file built for TMS320C1x devices */
#define F_20 0x10 /* file built for TMS320C2x devices */
#define F_25 0x20 /* file built for TMS320C2x/C5x devices */
#define F_LENDIAN 0x0100 /* 16 bits/word, LSB first */
#define F_SYMMERGE 0x1000 /* duplicate symbols were removed */
typedef struct
{
char magic[2];
char vstamp[2];
char tsize[4];
char dsize[4];
char bsize[4];
char entry[4];
char text_start[4];
char data_start[4];
}
AOUTHDR;
#define AOUTHDRSZ 28
#define AOUTSZ 28
struct external_scnhdr_v01 {
char s_name[8];
char s_paddr[4];
char s_vaddr[4];
char s_size[4];
char s_scnptr[4];
char s_relptr[4];
char s_lnnoptr[4];
char s_nreloc[2];
char s_nlnno[2];
char s_flags[2];
char s_reserved[1];
char s_page[1];
};
struct external_scnhdr {
char s_name[8];
char s_paddr[4];
char s_vaddr[4];
char s_size[4];
char s_scnptr[4];
char s_relptr[4];
char s_lnnoptr[4];
char s_nreloc[4];
char s_nlnno[4];
char s_flags[4];
char s_reserved[2];
char s_page[2];
};
* Special section flags
*/
STYP_CLINK: the section should be excluded from the final
linker output if there are no references found to any symbol in the section
STYP_BLOCK: the section should be blocked, i.e. if the section would cross
a page boundary, it is started at a page boundary instead.
TI COFF puts the section alignment power of two in the section flags
e.g. 2**N is alignment, flags |= (N & 0xF) << 8
*/
#define STYP_CLINK (0x4000)
#define STYP_BLOCK (0x1000)
#define STYP_ALIGN (0x0F00) /* TI COFF stores section alignment here */
#define SCNHDR_V01 struct external_scnhdr_v01
#define SCNHDR struct external_scnhdr
#define SCNHSZ_V01 40 /* for v0 and v1 */
#define SCNHSZ 48
Assume we're dealing with the COFF2 scnhdr structure, and adjust
accordingly. Note: The GNU C versions of some of these macros
are necessary in order to avoid compile time warnings triggered
gcc's array bounds checking. The PUT_SCNHDR_PAGE macro also has
the advantage on not evaluating LOC twice. */
#define GET_SCNHDR_NRELOC(ABFD, LOC) \
(COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, LOC))
#define PUT_SCNHDR_NRELOC(ABFD, VAL, LOC) \
(COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, LOC))
#ifdef __GNUC__
#define GET_SCNHDR_NLNNO(ABFD, LOC) \
({ \
int nlnno; \
char * ptr = (LOC); \
if (COFF2_P (ABFD)) \
nlnno = H_GET_32 (ABFD, ptr); \
else \
nlnno = H_GET_16 (ABFD, ptr - 2); \
nlnno; \
})
#define PUT_SCNHDR_NLNNO(ABFD, VAL, LOC) \
do \
{ \
char * ptr = (LOC); \
if (COFF2_P (ABFD)) \
H_PUT_32 (ABFD, VAL, ptr); \
else \
H_PUT_16 (ABFD, VAL, ptr - 2); \
} \
while (0)
#define GET_SCNHDR_FLAGS(ABFD, LOC) \
({ \
int flags; \
char * ptr = (LOC); \
if (COFF2_P (ABFD)) \
flags = H_GET_32 (ABFD, ptr); \
else \
flags = H_GET_16 (ABFD, ptr - 4); \
flags; \
})
#define PUT_SCNHDR_FLAGS(ABFD, VAL, LOC) \
do \
{ \
char * ptr = (LOC); \
if (COFF2_P (ABFD)) \
H_PUT_32 (ABFD, VAL, ptr); \
else \
H_PUT_16 (ABFD, VAL, ptr - 4); \
} \
while (0)
#define GET_SCNHDR_PAGE(ABFD, LOC) \
({ \
unsigned page; \
char * ptr = (LOC); \
if (COFF2_P (ABFD)) \
page = H_GET_16 (ABFD, ptr); \
else \
page = (unsigned) H_GET_8 (ABFD, ptr - 7); \
page; \
})
#define PUT_SCNHDR_PAGE(ABFD, VAL, LOC) \
do \
{ \
char * ptr = (LOC); \
if (COFF2_P (ABFD)) \
H_PUT_16 (ABFD, VAL, ptr); \
else \
{ \
H_PUT_8 (ABFD, VAL, ptr - 7); \
H_PUT_8 (ABFD, 0, ptr - 8); \
} \
} \
while (0)
#else
#define GET_SCNHDR_NLNNO(ABFD, LOC) \
(COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 2))
#define PUT_SCNHDR_NLNNO(ABFD, VAL, LOC) \
(COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 2))
#define GET_SCNHDR_FLAGS(ABFD, LOC) \
(COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 4))
#define PUT_SCNHDR_FLAGS(ABFD, VAL, LOC) \
(COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 4))
#define GET_SCNHDR_PAGE(ABFD, LOC) \
(COFF2_P (ABFD) ? H_GET_16 (ABFD, LOC) : (unsigned) H_GET_8 (ABFD, (LOC) - 7))
#define PUT_SCNHDR_PAGE(ABFD, VAL, LOC) \
(COFF2_P (ABFD) \
? H_PUT_16 (ABFD, VAL, LOC) \
: H_PUT_8 (ABFD, VAL, (LOC) - 7), H_PUT_8 (ABFD, 0, (LOC) - 8))
#endif
so adjust to be number of octets, which is what BFD expects */
#define GET_SCNHDR_SIZE(ABFD, SZP) \
(H_GET_32 (ABFD, SZP) * bfd_octets_per_byte (ABFD))
#define PUT_SCNHDR_SIZE(ABFD, SZ, SZP) \
H_PUT_32 (ABFD, (SZ) / bfd_octets_per_byte (ABFD), SZP)
#define COFF_ADJUST_SCNHDR_IN_POST(ABFD, EXT, INT) \
do \
{ \
((struct internal_scnhdr *)(INT))->s_page = \
GET_SCNHDR_PAGE (ABFD, ((SCNHDR *)(EXT))->s_page); \
} \
while (0)
coffswap.h doesn't use PUT_X for s_nlnno and s_nreloc.
Due to different sized v0/v1/v2 section headers, we have to re-write these
fields.
*/
#define COFF_ADJUST_SCNHDR_OUT_POST(ABFD, INT, EXT) \
do \
{ \
PUT_SCNHDR_NLNNO (ABFD, ((struct internal_scnhdr *)(INT))->s_nlnno, \
((SCNHDR *)(EXT))->s_nlnno); \
PUT_SCNHDR_NRELOC (ABFD, ((struct internal_scnhdr *)(INT))->s_nreloc,\
((SCNHDR *)(EXT))->s_nreloc); \
PUT_SCNHDR_FLAGS (ABFD, ((struct internal_scnhdr *)(INT))->s_flags, \
((SCNHDR *)(EXT))->s_flags); \
PUT_SCNHDR_PAGE (ABFD, ((struct internal_scnhdr *)(INT))->s_page, \
((SCNHDR *)(EXT))->s_page); \
} \
while (0)
* names of "special" sections
*/
#define _TEXT ".text"
#define _DATA ".data"
#define _BSS ".bss"
#define _CINIT ".cinit" /* initialized C data */
#define _SCONST ".const" /* constants */
#define _SWITCH ".switch" /* switch tables */
#define _STACK ".stack" /* C stack */
#define _SYSMEM ".sysmem" /* used for malloc et al. syscalls */
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
struct external_lineno {
union {
char l_symndx[4];
char l_paddr[4];
} l_addr;
char l_lnno[2];
};
#define LINENO struct external_lineno
#define LINESZ 6
looks like in COFF output is undefined */
#define TICOFF_LOCAL_LABEL_P(NAME) \
((NAME[0] == '$' && NAME[1] >= '0' && NAME[1] <= '9' && NAME[2] == '\0') \
|| NAME[strlen(NAME)-1] == '?')
#define E_SYMNMLEN 8 /* # characters in a symbol name */
#define E_FILNMLEN 14 /* # characters in a file name */
#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
struct external_syment
{
union {
char e_name[E_SYMNMLEN];
struct {
char e_zeroes[4];
char e_offset[4];
} e;
} e;
char e_value[4];
char e_scnum[2];
char e_type[2];
char e_sclass[1];
char e_numaux[1];
};
#define N_BTMASK (017)
#define N_TMASK (060)
#define N_BTSHFT (4)
#define N_TSHIFT (2)
union external_auxent {
struct {
char x_tagndx[4];
union {
struct {
char x_lnno[2];
char x_size[2];
} x_lnsz;
char x_fsize[4];
} x_misc;
union {
struct {
char x_lnnoptr[4];
char x_endndx[4];
} x_fcn;
struct {
char x_dimen[E_DIMNUM][2];
} x_ary;
} x_fcnary;
char x_tvndx[2];
} x_sym;
union {
char x_fname[E_FILNMLEN];
struct {
char x_zeroes[4];
char x_offset[4];
} x_n;
} x_file;
struct {
char x_scnlen[4];
char x_nreloc[2];
char x_nlinno[2];
} x_scn;
struct {
char x_tvfill[4];
char x_tvlen[2];
char x_tvran[2][2];
} x_tv;
};
#define SYMENT struct external_syment
#define SYMESZ 18
#define AUXENT union external_auxent
#define AUXESZ 18
#define GET_SCN_SCNLEN(ABFD, EXT) \
(H_GET_32 (ABFD, (EXT)->x_scn.x_scnlen) * bfd_octets_per_byte (ABFD))
#define PUT_SCN_SCNLEN(ABFD, INT, EXT) \
H_PUT_32 (ABFD, (INT) / bfd_octets_per_byte (ABFD), (EXT)->x_scn.x_scnlen)
#define GET_LNSZ_SIZE(abfd, ext) \
(H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size) / (class != C_FIELD ? 8 : 1))
#define PUT_LNSZ_SIZE(abfd, in, ext) \
H_PUT_16 (abfd, ((class != C_FIELD) ? (in) * 8 : (in)), \
ext->x_sym.x_misc.x_lnsz.x_size)
Also put the load page flag of the section into the symbol value if it's an
address. */
#ifndef NEEDS_PAGE
#define NEEDS_PAGE(X) 0
#define PAGE_MASK 0
#endif
#define COFF_ADJUST_SYM_IN_POST(ABFD, EXT, INT) \
do \
{ \
struct internal_syment *dst = (struct internal_syment *)(INT); \
if (dst->n_sclass == C_MOS || dst->n_sclass == C_MOU) \
dst->n_value /= 8; \
else if (NEEDS_PAGE (dst->n_sclass)) { \
asection *scn = coff_section_from_bfd_index (abfd, dst->n_scnum); \
dst->n_value |= (scn->lma & PAGE_MASK); \
} \
} \
while (0)
#define COFF_ADJUST_SYM_OUT_POST(ABFD, INT, EXT) \
do \
{ \
struct internal_syment *src = (struct internal_syment *)(INT); \
SYMENT *dst = (SYMENT *)(EXT); \
if (src->n_sclass == C_MOU || src->n_sclass == C_MOS) \
H_PUT_32 (abfd, src->n_value * 8, dst->e_value); \
else if (NEEDS_PAGE (src->n_sclass)) { \
H_PUT_32 (abfd, src->n_value &= ~PAGE_MASK, dst->e_value); \
} \
} \
while (0)
index of -1.
*/
#define SECTION_RELATIVE_ABSOLUTE_SYMBOL_P(RELOC, SECT) \
((*(RELOC)->sym_ptr_ptr)->section->output_section == (SECT) \
&& (RELOC)->howto->name[0] == 'A')
struct external_reloc_v0
{
char r_vaddr[4];
char r_symndx[2];
char r_reserved[2];
char r_type[2];
};
struct external_reloc
{
char r_vaddr[4];
char r_symndx[4];
char r_reserved[2];
char r_type[2];
};
#define RELOC struct external_reloc
#define RELSZ_V0 10 /* FIXME -- coffcode.h needs fixing */
#define RELSZ 12 /* for COFF1/2 */
#define R_ABS 0x0000 /* no relocation */
#define R_REL13 0x002A /* 13-bit direct reference (???) */
#define R_PARTLS7 0x0028 /* 7 LSBs of an address */
#define R_PARTMS9 0x0029 /* 9MSBs of an address */
#define R_EXTWORD 0x002B /* 23-bit direct reference */
#define R_EXTWORD16 0x002C /* 16-bit direct reference to 23-bit addr*/
#define R_EXTWORDMS7 0x002D /* upper 7 bits of 23-bit address */
#endif