121308Sache/* COFF information for TI COFF support. Definitions in this file should be 221308Sache customized in a target-specific file, and then this file included (see 321308Sache tic54x.h for an example). 421308Sache 5157184Sache Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 621308Sache 721308Sache This program is free software; you can redistribute it and/or modify 821308Sache it under the terms of the GNU General Public License as published by 921308Sache the Free Software Foundation; either version 2 of the License, or 1021308Sache (at your option) any later version. 1121308Sache 1221308Sache This program is distributed in the hope that it will be useful, 1358310Sache but WITHOUT ANY WARRANTY; without even the implied warranty of 1421308Sache MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1521308Sache GNU General Public License for more details. 1621308Sache 1721308Sache You should have received a copy of the GNU General Public License 1821308Sache along with this program; if not, write to the Free Software 1921308Sache Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2021308Sache#ifndef COFF_TI_H 2121308Sache#define COFF_TI_H 2221308Sache 2321308Sache/* Note "coff/external.h is not used because TI adds extra fields to the structures. */ 2458310Sache 2521308Sache/********************** FILE HEADER **********************/ 2621308Sache 2721308Sachestruct external_filehdr 2821308Sache { 2921308Sache char f_magic[2]; /* magic number */ 3021308Sache char f_nscns[2]; /* number of sections */ 3121308Sache char f_timdat[4]; /* time & date stamp */ 3221308Sache char f_symptr[4]; /* file pointer to symtab */ 3375406Sache char f_nsyms[4]; /* number of symtab entries */ 3475406Sache char f_opthdr[2]; /* sizeof(optional hdr) */ 3521308Sache char f_flags[2]; /* flags */ 3621308Sache char f_target_id[2]; /* magic no. (TI COFF-specific) */ 3721308Sache }; 3821308Sache 3921308Sache/* COFF0 has magic number in f_magic, and omits f_target_id from the file 4021308Sache header; for later versions, f_magic is 0xC1 for COFF1 and 0xC2 for COFF2 41157184Sache and the target-specific magic number is found in f_target_id */ 42157184Sache 43157184Sache#define TICOFF0MAGIC TI_TARGET_ID 44157184Sache#define TICOFF1MAGIC 0x00C1 45157184Sache#define TICOFF2MAGIC 0x00C2 4621308Sache#define TICOFF_AOUT_MAGIC 0x0108 /* magic number in optional header */ 4721308Sache#define TICOFF 1 /* customize coffcode.h */ 4821308Sache 4921308Sache/* The target_id field changes depending on the particular CPU target */ 5021308Sache/* for COFF0, the target id appeared in f_magic, where COFFX magic is now */ 5121308Sache#ifndef TI_TARGET_ID 5221308Sache#error "TI_TARGET_ID needs to be defined for your CPU" 5321308Sache#endif 5421308Sache 5521308Sache/* Which bfd_arch to use... */ 5621308Sache#ifndef TICOFF_TARGET_ARCH 5721308Sache#error "TICOFF_TARGET_ARCH needs to be defined for your CPU" 5821308Sache#endif 5921308Sache 6021308Sache#ifndef TICOFF_TARGET_MACHINE_GET 6121308Sache#define TICOFF_TARGET_MACHINE_GET(FLAGS) 0 6221308Sache#endif 6321308Sache 6421308Sache#ifndef TICOFF_TARGET_MACHINE_SET 6521308Sache#define TICOFF_TARGET_MACHINE_SET(FLAGSP, MACHINE) 6621308Sache#endif 6721308Sache 6821308Sache/* Default to COFF2 for file output */ 6921308Sache#ifndef TICOFF_DEFAULT_MAGIC 7021308Sache#define TICOFF_DEFAULT_MAGIC TICOFF2MAGIC 7121308Sache#endif 7221308Sache 7321308Sache/* This value is made available in the rare case where a bfd is unavailable */ 7421308Sache#ifndef OCTETS_PER_BYTE_POWER 7521308Sache#error "OCTETS_PER_BYTE_POWER not defined for this CPU" 7621308Sache#else 7721308Sache#define OCTETS_PER_BYTE (1<<OCTETS_PER_BYTE_POWER) 7821308Sache#endif 7921308Sache 80119610Sache/* default alignment is on a byte (not octet!) boundary */ 81119610Sache#ifndef COFF_DEFAULT_SECTION_ALIGNMENT_POWER 8221308Sache#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0 8321308Sache#endif 84136644Sache 85119610Sache/* TI COFF encodes the section alignment in the section header flags */ 86119610Sache#define COFF_ALIGN_IN_SECTION_HEADER 1 87119610Sache#define COFF_ALIGN_IN_S_FLAGS 1 88119610Sache/* requires a power-of-two argument */ 89119610Sache#define COFF_ENCODE_ALIGNMENT(S,X) ((S).s_flags |= (((unsigned)(X)&0xF)<<8)) 9021308Sache/* result is a power of two */ 9121308Sache#define COFF_DECODE_ALIGNMENT(X) (((X)>>8)&0xF) 9221308Sache 9321308Sache#define COFF0_P(ABFD) (bfd_coff_filhsz(ABFD) == FILHSZ_V0) 9421308Sache#define COFF2_P(ABFD) (bfd_coff_scnhsz(ABFD) != SCNHSZ_V01) 9521308Sache 96119610Sache#define COFF0_BADMAG(x) ((x).f_magic != TICOFF0MAGIC) 97119610Sache#define COFF1_BADMAG(x) ((x).f_magic != TICOFF1MAGIC || (x).f_target_id != TI_TARGET_ID) 98119610Sache#define COFF2_BADMAG(x) ((x).f_magic != TICOFF2MAGIC || (x).f_target_id != TI_TARGET_ID) 99119610Sache 100119610Sache/* we need to read/write an extra field in the coff file header */ 101119610Sache#ifndef COFF_ADJUST_FILEHDR_IN_POST 102119610Sache#define COFF_ADJUST_FILEHDR_IN_POST(abfd, src, dst) \ 10321308Sache do \ 10421308Sache { \ 10521308Sache ((struct internal_filehdr *)(dst))->f_target_id = \ 10621308Sache H_GET_16 (abfd, ((FILHDR *)(src))->f_target_id); \ 10721308Sache } \ 10821308Sache while (0) 10921308Sache#endif 11075406Sache 11121308Sache#ifndef COFF_ADJUST_FILEHDR_OUT_POST 11221308Sache#define COFF_ADJUST_FILEHDR_OUT_POST(abfd, src, dst) \ 11375406Sache do \ 11421308Sache { \ 11521308Sache H_PUT_16 (abfd, ((struct internal_filehdr *)(src))->f_target_id, \ 11621308Sache ((FILHDR *)(dst))->f_target_id); \ 117119610Sache } \ 11821308Sache while (0) 11921308Sache#endif 12021308Sache 12121308Sache#define FILHDR struct external_filehdr 12221308Sache#define FILHSZ 22 12321308Sache#define FILHSZ_V0 20 /* COFF0 omits target_id field */ 12421308Sache 12521308Sache/* File header flags */ 12621308Sache#define F_RELFLG (0x0001) 12721308Sache#define F_EXEC (0x0002) 12821308Sache#define F_LNNO (0x0004) 12921308Sache#define F_VERS (0x0010) /* TMS320C4x code */ 13021308Sache/* F_LSYMS needs to be redefined in your source file */ 13121308Sache#define F_LSYMS_TICOFF (0x0010) /* normal COFF is 0x8 */ 13221308Sache 13321308Sache#define F_10 0x00 /* file built for TMS320C1x devices */ 13421308Sache#define F_20 0x10 /* file built for TMS320C2x devices */ 135119610Sache#define F_25 0x20 /* file built for TMS320C2x/C5x devices */ 136119610Sache#define F_LENDIAN 0x0100 /* 16 bits/word, LSB first */ 137119610Sache#define F_SYMMERGE 0x1000 /* duplicate symbols were removed */ 138119610Sache 13921308Sache/********************** OPTIONAL HEADER **********************/ 14021308Sache 14121308Sache 14221308Sachetypedef struct 14321308Sache{ 14421308Sache char magic[2]; /* type of file (0x108) */ 14558310Sache char vstamp[2]; /* version stamp */ 14658310Sache char tsize[4]; /* text size in bytes, padded to FW bdry*/ 14721308Sache char dsize[4]; /* initialized data " " */ 14821308Sache char bsize[4]; /* uninitialized data " " */ 14921308Sache char entry[4]; /* entry pt. */ 15021308Sache char text_start[4]; /* base of text used for this file */ 15121308Sache char data_start[4]; /* base of data used for this file */ 15221308Sache} 153119610SacheAOUTHDR; 154119610Sache 155119610Sache 156119610Sache#define AOUTHDRSZ 28 15721308Sache#define AOUTSZ 28 15821308Sache 15921308Sache 16021308Sache/********************** SECTION HEADER **********************/ 161/* COFF0, COFF1 */ 162struct external_scnhdr_v01 { 163 char s_name[8]; /* section name */ 164 char s_paddr[4]; /* physical address, aliased s_nlib */ 165 char s_vaddr[4]; /* virtual address */ 166 char s_size[4]; /* section size (in WORDS) */ 167 char s_scnptr[4]; /* file ptr to raw data for section */ 168 char s_relptr[4]; /* file ptr to relocation */ 169 char s_lnnoptr[4]; /* file ptr to line numbers */ 170 char s_nreloc[2]; /* number of relocation entries */ 171 char s_nlnno[2]; /* number of line number entries*/ 172 char s_flags[2]; /* flags */ 173 char s_reserved[1]; /* reserved */ 174 char s_page[1]; /* section page number (LOAD) */ 175}; 176 177/* COFF2 */ 178struct external_scnhdr { 179 char s_name[8]; /* section name */ 180 char s_paddr[4]; /* physical address, aliased s_nlib */ 181 char s_vaddr[4]; /* virtual address */ 182 char s_size[4]; /* section size (in WORDS) */ 183 char s_scnptr[4]; /* file ptr to raw data for section */ 184 char s_relptr[4]; /* file ptr to relocation */ 185 char s_lnnoptr[4]; /* file ptr to line numbers */ 186 char s_nreloc[4]; /* number of relocation entries */ 187 char s_nlnno[4]; /* number of line number entries*/ 188 char s_flags[4]; /* flags */ 189 char s_reserved[2]; /* reserved */ 190 char s_page[2]; /* section page number (LOAD) */ 191}; 192 193/* 194 * Special section flags 195 */ 196 197/* TI COFF defines these flags; 198 STYP_CLINK: the section should be excluded from the final 199 linker output if there are no references found to any symbol in the section 200 STYP_BLOCK: the section should be blocked, i.e. if the section would cross 201 a page boundary, it is started at a page boundary instead. 202 TI COFF puts the section alignment power of two in the section flags 203 e.g. 2**N is alignment, flags |= (N & 0xF) << 8 204*/ 205#define STYP_CLINK (0x4000) 206#define STYP_BLOCK (0x1000) 207#define STYP_ALIGN (0x0F00) /* TI COFF stores section alignment here */ 208 209#define SCNHDR_V01 struct external_scnhdr_v01 210#define SCNHDR struct external_scnhdr 211#define SCNHSZ_V01 40 /* for v0 and v1 */ 212#define SCNHSZ 48 213 214/* COFF2 changes the offsets and sizes of these fields 215 Assume we're dealing with the COFF2 scnhdr structure, and adjust 216 accordingly 217 */ 218#define GET_SCNHDR_NRELOC(ABFD, LOC) \ 219 (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, LOC)) 220#define PUT_SCNHDR_NRELOC(ABFD, VAL, LOC) \ 221 (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, LOC)) 222#define GET_SCNHDR_NLNNO(ABFD, LOC) \ 223 (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 2)) 224#define PUT_SCNHDR_NLNNO(ABFD, VAL, LOC) \ 225 (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 2)) 226#define GET_SCNHDR_FLAGS(ABFD, LOC) \ 227 (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 4)) 228#define PUT_SCNHDR_FLAGS(ABFD, VAL, LOC) \ 229 (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 4)) 230#define GET_SCNHDR_PAGE(ABFD, LOC) \ 231 (COFF2_P (ABFD) ? H_GET_16 (ABFD, LOC) : (unsigned) H_GET_8 (ABFD, (LOC) - 7)) 232/* on output, make sure that the "reserved" field is zero */ 233#define PUT_SCNHDR_PAGE(ABFD, VAL, LOC) \ 234 (COFF2_P (ABFD) \ 235 ? H_PUT_16 (ABFD, VAL, LOC) \ 236 : H_PUT_8 (ABFD, VAL, (LOC) - 7), H_PUT_8 (ABFD, 0, (LOC) - 8)) 237 238/* TI COFF stores section size as number of bytes (address units, not octets), 239 so adjust to be number of octets, which is what BFD expects */ 240#define GET_SCNHDR_SIZE(ABFD, SZP) \ 241 (H_GET_32 (ABFD, SZP) * bfd_octets_per_byte (ABFD)) 242#define PUT_SCNHDR_SIZE(ABFD, SZ, SZP) \ 243 H_PUT_32 (ABFD, (SZ) / bfd_octets_per_byte (ABFD), SZP) 244 245#define COFF_ADJUST_SCNHDR_IN_POST(ABFD, EXT, INT) \ 246 do \ 247 { \ 248 ((struct internal_scnhdr *)(INT))->s_page = \ 249 GET_SCNHDR_PAGE (ABFD, ((SCNHDR *)(EXT))->s_page); \ 250 } \ 251 while (0) 252 253/* The line number and reloc overflow checking in coff_swap_scnhdr_out in 254 coffswap.h doesn't use PUT_X for s_nlnno and s_nreloc. 255 Due to different sized v0/v1/v2 section headers, we have to re-write these 256 fields. 257 */ 258#define COFF_ADJUST_SCNHDR_OUT_POST(ABFD, INT, EXT) \ 259 do \ 260 { \ 261 PUT_SCNHDR_NLNNO (ABFD, ((struct internal_scnhdr *)(INT))->s_nlnno, \ 262 ((SCNHDR *)(EXT))->s_nlnno); \ 263 PUT_SCNHDR_NRELOC (ABFD, ((struct internal_scnhdr *)(INT))->s_nreloc,\ 264 ((SCNHDR *)(EXT))->s_nreloc); \ 265 PUT_SCNHDR_FLAGS (ABFD, ((struct internal_scnhdr *)(INT))->s_flags, \ 266 ((SCNHDR *)(EXT))->s_flags); \ 267 PUT_SCNHDR_PAGE (ABFD, ((struct internal_scnhdr *)(INT))->s_page, \ 268 ((SCNHDR *)(EXT))->s_page); \ 269 } \ 270 while (0) 271 272/* 273 * names of "special" sections 274 */ 275#define _TEXT ".text" 276#define _DATA ".data" 277#define _BSS ".bss" 278#define _CINIT ".cinit" /* initialized C data */ 279#define _SCONST ".const" /* constants */ 280#define _SWITCH ".switch" /* switch tables */ 281#define _STACK ".stack" /* C stack */ 282#define _SYSMEM ".sysmem" /* used for malloc et al. syscalls */ 283 284/********************** LINE NUMBERS **********************/ 285 286/* 1 line number entry for every "breakpointable" source line in a section. 287 * Line numbers are grouped on a per function basis; first entry in a function 288 * grouping will have l_lnno = 0 and in place of physical address will be the 289 * symbol table index of the function name. 290 */ 291struct external_lineno { 292 union { 293 char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ 294 char l_paddr[4]; /* (physical) address of line number */ 295 } l_addr; 296 char l_lnno[2]; /* line number */ 297}; 298 299#define LINENO struct external_lineno 300#define LINESZ 6 301 302 303/********************** SYMBOLS **********************/ 304 305/* NOTE: this is what a local label looks like in assembly source; what it 306 looks like in COFF output is undefined */ 307#define TICOFF_LOCAL_LABEL_P(NAME) \ 308((NAME[0] == '$' && NAME[1] >= '0' && NAME[1] <= '9' && NAME[2] == '\0') \ 309 || NAME[strlen(NAME)-1] == '?') 310 311#define E_SYMNMLEN 8 /* # characters in a symbol name */ 312#define E_FILNMLEN 14 /* # characters in a file name */ 313#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ 314 315struct external_syment 316{ 317 union { 318 char e_name[E_SYMNMLEN]; 319 struct { 320 char e_zeroes[4]; 321 char e_offset[4]; 322 } e; 323 } e; 324 char e_value[4]; 325 char e_scnum[2]; 326 char e_type[2]; 327 char e_sclass[1]; 328 char e_numaux[1]; 329}; 330 331 332#define N_BTMASK (017) 333#define N_TMASK (060) 334#define N_BTSHFT (4) 335#define N_TSHIFT (2) 336 337 338union external_auxent { 339 struct { 340 char x_tagndx[4]; /* str, un, or enum tag indx */ 341 union { 342 struct { 343 char x_lnno[2]; /* declaration line number */ 344 char x_size[2]; /* str/union/array size */ 345 } x_lnsz; 346 char x_fsize[4]; /* size of function */ 347 } x_misc; 348 union { 349 struct { /* if ISFCN, tag, or .bb */ 350 char x_lnnoptr[4]; /* ptr to fcn line # */ 351 char x_endndx[4]; /* entry ndx past block end */ 352 } x_fcn; 353 struct { /* if ISARY, up to 4 dimen. */ 354 char x_dimen[E_DIMNUM][2]; 355 } x_ary; 356 } x_fcnary; 357 char x_tvndx[2]; /* tv index */ 358 } x_sym; 359 360 union { 361 char x_fname[E_FILNMLEN]; 362 struct { 363 char x_zeroes[4]; 364 char x_offset[4]; 365 } x_n; 366 } x_file; 367 368 struct { 369 char x_scnlen[4]; /* section length */ 370 char x_nreloc[2]; /* # relocation entries */ 371 char x_nlinno[2]; /* # line numbers */ 372 } x_scn; 373 374 struct { 375 char x_tvfill[4]; /* tv fill value */ 376 char x_tvlen[2]; /* length of .tv */ 377 char x_tvran[2][2]; /* tv range */ 378 } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ 379 380 381}; 382 383#define SYMENT struct external_syment 384#define SYMESZ 18 385#define AUXENT union external_auxent 386#define AUXESZ 18 387 388/* section lengths are in target bytes (not host bytes) */ 389#define GET_SCN_SCNLEN(ABFD, EXT) \ 390 (H_GET_32 (ABFD, (EXT)->x_scn.x_scnlen) * bfd_octets_per_byte (ABFD)) 391#define PUT_SCN_SCNLEN(ABFD, INT, EXT) \ 392 H_PUT_32 (ABFD, (INT) / bfd_octets_per_byte (ABFD), (EXT)->x_scn.x_scnlen) 393 394/* lnsz size is in bits in COFF file, in bytes in BFD */ 395#define GET_LNSZ_SIZE(abfd, ext) \ 396 (H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size) / (class != C_FIELD ? 8 : 1)) 397 398#define PUT_LNSZ_SIZE(abfd, in, ext) \ 399 H_PUT_16 (abfd, ((class != C_FIELD) ? (in) * 8 : (in)), \ 400 ext->x_sym.x_misc.x_lnsz.x_size) 401 402/* TI COFF stores offsets for MOS and MOU in bits; BFD expects bytes 403 Also put the load page flag of the section into the symbol value if it's an 404 address. */ 405#ifndef NEEDS_PAGE 406#define NEEDS_PAGE(X) 0 407#define PAGE_MASK 0 408#endif 409#define COFF_ADJUST_SYM_IN_POST(ABFD, EXT, INT) \ 410 do \ 411 { \ 412 struct internal_syment *dst = (struct internal_syment *)(INT); \ 413 if (dst->n_sclass == C_MOS || dst->n_sclass == C_MOU) \ 414 dst->n_value /= 8; \ 415 else if (NEEDS_PAGE (dst->n_sclass)) { \ 416 asection *scn = coff_section_from_bfd_index (abfd, dst->n_scnum); \ 417 dst->n_value |= (scn->lma & PAGE_MASK); \ 418 } \ 419 } \ 420 while (0) 421 422#define COFF_ADJUST_SYM_OUT_POST(ABFD, INT, EXT) \ 423 do \ 424 { \ 425 struct internal_syment *src = (struct internal_syment *)(INT); \ 426 SYMENT *dst = (SYMENT *)(EXT); \ 427 if (src->n_sclass == C_MOU || src->n_sclass == C_MOS) \ 428 H_PUT_32 (abfd, src->n_value * 8, dst->e_value); \ 429 else if (NEEDS_PAGE (src->n_sclass)) { \ 430 H_PUT_32 (abfd, src->n_value &= ~PAGE_MASK, dst->e_value); \ 431 } \ 432 } \ 433 while (0) 434 435/* Detect section-relative absolute symbols so they get flagged with a sym 436 index of -1. 437*/ 438#define SECTION_RELATIVE_ABSOLUTE_SYMBOL_P(RELOC, SECT) \ 439 ((*(RELOC)->sym_ptr_ptr)->section->output_section == (SECT) \ 440 && (RELOC)->howto->name[0] == 'A') 441 442/********************** RELOCATION DIRECTIVES **********************/ 443 444struct external_reloc_v0 445{ 446 char r_vaddr[4]; 447 char r_symndx[2]; 448 char r_reserved[2]; 449 char r_type[2]; 450}; 451 452struct external_reloc 453{ 454 char r_vaddr[4]; 455 char r_symndx[4]; 456 char r_reserved[2]; /* extended pmad byte for COFF2 */ 457 char r_type[2]; 458}; 459 460#define RELOC struct external_reloc 461#define RELSZ_V0 10 /* FIXME -- coffcode.h needs fixing */ 462#define RELSZ 12 /* for COFF1/2 */ 463 464/* various relocation types. */ 465#define R_ABS 0x0000 /* no relocation */ 466#define R_REL13 0x002A /* 13-bit direct reference (???) */ 467#define R_PARTLS7 0x0028 /* 7 LSBs of an address */ 468#define R_PARTMS9 0x0029 /* 9MSBs of an address */ 469#define R_EXTWORD 0x002B /* 23-bit direct reference */ 470#define R_EXTWORD16 0x002C /* 16-bit direct reference to 23-bit addr*/ 471#define R_EXTWORDMS7 0x002D /* upper 7 bits of 23-bit address */ 472 473#endif /* COFF_TI_H */ 474