1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
|
/**
* @namespace biew_plugins_auto
* @file plugins/bin/aout64.h
* @brief This file contains `a.out' object-file definitions, including
* extensions to 64-bit fields.
* @version -
* @remark Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation,
* Inc. This file is part of the GNU C Library.
* The GNU C Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* The GNU C Library 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
* Library General Public License for more details.
* You should have received a copy of the GNU Library General Public
* License along with the GNU C Library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* @note Requires POSIX compatible development system
*
* @author GNU FSF
* @since 1995
**/
#ifndef __A_OUT_64_H__
#define __A_OUT_64_H__
#ifndef __SYS_DEP_H
#include "_sys_dep.h"
#endif
#ifdef __HAVE_PRAGMA_PACK__
#pragma pack(1)
#endif
/** This is the layout on disk of the 32-bit or 64-bit exec header. */
#define BYTES_IN_WORD 4
#define N_MAGIC(x) ((x) & 0xFFFF)
#define N_MACHTYPE(x) (((x) >> 16) & 0xff)
#define N_FLAGS(x) (((x) >> 24) & 0xff)
#ifndef external_exec
struct external_exec
{
tUInt8 e_info[4]; /**< magic number and stuff */
tUInt8 e_text[BYTES_IN_WORD]; /**< length of text section in bytes */
tUInt8 e_data[BYTES_IN_WORD]; /**< length of data section in bytes */
tUInt8 e_bss[BYTES_IN_WORD]; /**< length of bss area in bytes */
tUInt8 e_syms[BYTES_IN_WORD]; /**< length of symbol table in bytes */
tUInt8 e_entry[BYTES_IN_WORD]; /**< start address */
tUInt8 e_trsize[BYTES_IN_WORD]; /**< length of text relocation info */
tUInt8 e_drsize[BYTES_IN_WORD]; /**< length of data relocation info */
};
#define EXEC_BYTES_SIZE (4 + BYTES_IN_WORD * 7)
/** Magic numbers for a.out files */
#define OMAGIC64 0x1001 /**< Code indicating object file */
#define ZMAGIC64 0x1002 /**< Code indicating demand-paged executable. */
#define NMAGIC64 0x1003 /**< Code indicating pure executable. */
/* There is no 64-bit QMAGIC as far as I know. */
#define N_BADMAG64(x) (N_MAGIC(x) != OMAGIC64 \
&& N_MAGIC(x) != NMAGIC64 \
&& N_MAGIC(x) != ZMAGIC64)
#define OMAGIC 0x0107 /**< ...object file or impure executable. */
#define NMAGIC 0x0108 /**< Code indicating pure executable. */
#define ZMAGIC 0x010B /**< Code indicating demand-paged executable. */
#define BMAGIC 0x010D /**< Used by a b.out object. */
#define CMAGIC 0x0111 /**< Code indicating core file. */
/** This indicates a demand-paged executable with the header in the text.
It is used by 386BSD (and variants) and Linux, at least. */
#ifndef QMAGIC
#define QMAGIC 0x00CC
#endif
# ifndef N_BADMAG
# define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
&& N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC \
&& N_MAGIC(x) != QMAGIC)
# endif /* N_BADMAG */
#endif
#ifdef QMAGIC
#define N_IS_QMAGIC(x) (N_MAGIC (x) == QMAGIC)
#else
#define N_IS_QMAGIC(x) (0)
#endif
/**
The difference between TARGET_PAGE_SIZE and N_SEGSIZE is that TARGET_PAGE_SIZE is
the finest granularity at which you can page something, thus it
controls the padding (if any) before the text segment of a ZMAGIC
file. N_SEGSIZE is the resolution at which things can be marked as
read-only versus read/write, so it controls the padding between the
text segment and the data segment (in memory; on disk the padding
between them is TARGET_PAGE_SIZE). TARGET_PAGE_SIZE and N_SEGSIZE are the same
for most machines, but different for sun3. */
/**
By default, segment size is constant. But some machines override this
to be a function of the a.out header (e.g. machine type). */
#ifndef N_SEGSIZE
#define N_SEGSIZE(x) SEGMENT_SIZE
#endif
/**
Virtual memory address of the text section.
This is getting very complicated. A good reason to discard a.out format
for something that specifies these fields explicitly. But til then...
* OMAGIC and NMAGIC files:
(object files: text for "relocatable addr 0" right after the header)
start at 0, offset is EXEC_BYTES_SIZE, size as stated.
* The text address, offset, and size of ZMAGIC files depend
on the entry point of the file:
* entry point below TEXT_START_ADDR:
(hack for SunOS shared libraries)
start at 0, offset is 0, size as stated.
* If N_HEADER_IN_TEXT(x) is true (which defaults to being the
case when the entry point is EXEC_BYTES_SIZE or further into a page):
no padding is needed; text can start after exec header. Sun
considers the text segment of such files to include the exec header;
for BFD's purposes, we don't, which makes more work for us.
start at TEXT_START_ADDR + EXEC_BYTES_SIZE, offset is EXEC_BYTES_SIZE,
size as stated minus EXEC_BYTES_SIZE.
* If N_HEADER_IN_TEXT(x) is false (which defaults to being the case when
the entry point is less than EXEC_BYTES_SIZE into a page (e.g. page
aligned)): (padding is needed so that text can start at a page boundary)
start at TEXT_START_ADDR, offset TARGET_PAGE_SIZE, size as stated.
Specific configurations may want to hardwire N_HEADER_IN_TEXT,
for efficiency or to allow people to play games with the entry point.
In that case, you would #define N_HEADER_IN_TEXT(x) as 1 for sunos,
and as 0 for most other hosts (Sony News, Vax Ultrix, etc).
(Do this in the appropriate bfd target file.)
(The default is a heuristic that will break if people try changing
the entry point, perhaps with the ld -e flag.)
* QMAGIC is always like a ZMAGIC for which N_HEADER_IN_TEXT is true,
and for which the starting address is TARGET_PAGE_SIZE (or should this be
SEGMENT_SIZE?) (TEXT_START_ADDR only applies to ZMAGIC, not to QMAGIC).
*/
/** This macro is only relevant for ZMAGIC files; QMAGIC always has the header
in the text. */
#ifndef N_HEADER_IN_TEXT
#define N_HEADER_IN_TEXT(x) (((x).a_entry & (TARGET_PAGE_SIZE-1)) >= EXEC_BYTES_SIZE)
#endif
/** Sun shared libraries, not linux. This macro is only relevant for ZMAGIC
files. */
#ifndef N_SHARED_LIB
#define N_SHARED_LIB(x) ((x).a_entry < TEXT_START_ADDR)
#endif
/**
Returning 0 not TEXT_START_ADDR for OMAGIC and NMAGIC is based on
the assumption that we are dealing with a .o file, not an
executable. This is necessary for OMAGIC (but means we don't work
right on the output from ld -N); more questionable for NMAGIC. */
#ifndef N_TXTADDR
#define N_TXTADDR(x) \
(/** The address of a QMAGIC file is always one page in, */ \
/** with the header in the text. */ \
N_IS_QMAGIC (x) ? TARGET_PAGE_SIZE + EXEC_BYTES_SIZE : \
N_MAGIC(x) != ZMAGIC ? 0 : /**< object file or NMAGIC */\
N_SHARED_LIB(x) ? 0 : \
N_HEADER_IN_TEXT(x) ? \
TEXT_START_ADDR + EXEC_BYTES_SIZE : /**< no padding */\
TEXT_START_ADDR /**< a page of padding */\
)
#endif
/**
If N_HEADER_IN_TEXT is not true for ZMAGIC, there is some padding
to make the text segment start at a certain boundary. For most
systems, this boundary is TARGET_PAGE_SIZE. But for Linux, in the
time-honored tradition of crazy ZMAGIC hacks, it is 1024 which is
not what TARGET_PAGE_SIZE needs to be for QMAGIC. */
#ifndef ZMAGIC_DISK_BLOCK_SIZE
#define ZMAGIC_DISK_BLOCK_SIZE TARGET_PAGE_SIZE
#endif
#define N_DISK_BLOCK_SIZE(x) \
(N_MAGIC(x) == ZMAGIC ? ZMAGIC_DISK_BLOCK_SIZE : TARGET_PAGE_SIZE)
/** Offset in an a.out of the start of the text section. */
#ifndef N_TXTOFF
#define N_TXTOFF(x) \
(/** For {O,N,Q}MAGIC, no padding. */ \
N_MAGIC(x) != ZMAGIC ? EXEC_BYTES_SIZE : \
N_SHARED_LIB(x) ? 0 : \
N_HEADER_IN_TEXT(x) ? \
EXEC_BYTES_SIZE : /**< no padding */\
ZMAGIC_DISK_BLOCK_SIZE /**< a page of padding */\
)
#endif
/**
Size of the text section. It's always as stated, except that we
offset it to `undo' the adjustment to N_TXTADDR and N_TXTOFF
for ZMAGIC files that nominally include the exec header
as part of the first page of text. (BFD doesn't consider the
exec header to be part of the text segment.) */
#ifndef N_TXTSIZE
#define N_TXTSIZE(x) \
(/** For QMAGIC, we don't consider the header part of the text section. */\
N_IS_QMAGIC (x) ? (x).a_text - EXEC_BYTES_SIZE : \
(N_MAGIC(x) != ZMAGIC || N_SHARED_LIB(x)) ? (x).a_text : \
N_HEADER_IN_TEXT(x) ? \
(x).a_text - EXEC_BYTES_SIZE: /**< no padding */\
(x).a_text /**< a page of padding */\
)
#endif
/**
The address of the data segment in virtual memory.
It is the text segment address, plus text segment size, rounded
up to a N_SEGSIZE boundary for pure or pageable files. */
#ifndef N_DATADDR
#define N_DATADDR(x) \
(N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+N_TXTSIZE(x)) \
: (N_SEGSIZE(x) + ((N_TXTADDR(x)+N_TXTSIZE(x)-1) & ~(N_SEGSIZE(x)-1))))
#endif
/** The address of the BSS segment -- immediately after the data segment. */
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
/** Offsets of the various portions of the file after the text segment. */
/**
For {Q,Z}MAGIC, there is padding to make the data segment start on
a page boundary. Most of the time the a_text field (and thus
N_TXTSIZE) already contains this padding. It is possible that for
BSDI and/or 386BSD it sometimes doesn't contain the padding, and
perhaps we should be adding it here. But this seems kind of
questionable and probably should be BSDI/386BSD-specific if we do
do it.
For NMAGIC (at least for hp300 BSD, probably others), there is
padding in memory only, not on disk, so we must *not* ever pad here
for NMAGIC. */
#ifndef N_DATOFF
#define N_DATOFF(x) \
(N_TXTOFF(x) + N_TXTSIZE(x))
#endif
#ifndef N_TRELOFF
#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data )
#endif
#ifndef N_DRELOFF
#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize )
#endif
#ifndef N_SYMOFF
#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize )
#endif
#ifndef N_STROFF
#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
#endif
/** Symbols */
#ifndef external_nlist
struct external_nlist {
tUInt8 e_strx[BYTES_IN_WORD]; /**< index into string table of name */
tUInt8 e_type[1]; /**< type of symbol */
tUInt8 e_other[1]; /**< misc info (usually empty) */
tUInt8 e_desc[2]; /**< description field */
tUInt8 e_value[BYTES_IN_WORD]; /**< value of symbol */
};
#define EXTERNAL_NLIST_SIZE (BYTES_IN_WORD+4+BYTES_IN_WORD)
#endif
struct internal_nlist {
tUInt32 n_strx; /**< index into string table of name */
tUInt8 n_type; /**< type of symbol */
tUInt8 n_other; /**< misc info (usually empty) */
tUInt16 n_desc; /**< description field */
tUInt32 n_value; /**< value of symbol */
};
/** The n_type field is the symbol type, containing: */
#define N_UNDF 0 /**< Undefined symbol */
#define N_ABS 2 /**< Absolute symbol -- defined at particular addr */
#define N_TEXT 4 /**< Text sym -- defined at offset in text seg */
#define N_DATA 6 /**< Data sym -- defined at offset in data seg */
#define N_BSS 8 /**< BSS sym -- defined at offset in zero'd seg */
#define N_COMM 0x12 /**< Common symbol (visible after shared lib dynlink) */
#define N_FN 0x1f /**< File name of .o file */
#define N_FN_SEQ 0x0C /**< N_FN from Sequent compilers (sigh) */
/** Note: N_EXT can only be usefully OR-ed with N_UNDF, N_ABS, N_TEXT,
N_DATA, or N_BSS. When the low-order bit of other types is set,
(e.g. N_WARNING versus N_FN), they are two different types. */
#define N_EXT 1 /**< External symbol (as opposed to local-to-this-file) */
#define N_TYPE 0x1e
#define N_STAB 0xe0 /**< If any of these bits are on, it's a debug symbol */
#define N_INDR 0x0a
/** The following symbols refer to set elements.
All the N_SET[ATDB] symbols with the same name form one set.
Space is allocated for the set in the text section, and each set
elements value is stored into one word of the space.
The first word of the space is the length of the set (number of elements).
The address of the set is made into an N_SETV symbol
whose name is the same as the name of the set.
This symbol acts like a N_DATA global symbol
in that it can satisfy undefined external references. */
/** These appear as input to LD, in a .o file. */
#define N_SETA 0x14 /**< Absolute set element symbol */
#define N_SETT 0x16 /**< Text set element symbol */
#define N_SETD 0x18 /**< Data set element symbol */
#define N_SETB 0x1A /**< Bss set element symbol */
/** This is output from LD. */
#define N_SETV 0x1C /**< Pointer to set vector in data area. */
/** Warning symbol. The text gives a warning message, the next symbol
in the table will be undefined. When the symbol is referenced, the
message is printed. */
#define N_WARNING 0x1e
/** Weak symbols. These are a GNU extension to the a.out format. The
semantics are those of ELF weak symbols. Weak symbols are always
externally visible. The N_WEAK? values are squeezed into the
available slots. The value of a N_WEAKU symbol is 0. The values
of the other types are the definitions. */
#define N_WEAKU 0x0d /**< Weak undefined symbol. */
#define N_WEAKA 0x0e /**< Weak absolute symbol. */
#define N_WEAKT 0x0f /**< Weak text symbol. */
#define N_WEAKD 0x10 /**< Weak data symbol. */
#define N_WEAKB 0x11 /**< Weak bss symbol. */
/** Relocations
There are two types of relocation flavours for a.out systems,
standard and extended. The standard form is used on systems where the
instruction has room for all the bits of an offset to the operand, whilst
the extended form is used when an address operand has to be split over n
instructions. Eg, on the 68k, each move instruction can reference
the target with a displacement of 16 or 32 bits. On the sparc, move
instructions use an offset of 14 bits, so the offset is stored in
the reloc field, and the data in the section is ignored.
*/
/** This structure describes a single relocation to be performed.
The text-relocation section of the file is a vector of these structures,
all of which apply to the text section.
Likewise, the data-relocation section applies to the data section. */
struct reloc_std_external {
tUInt8 r_address[BYTES_IN_WORD]; /**< offset of of data to relocate */
tUInt8 r_index[3]; /**< symbol table index of symbol */
tUInt8 r_type[1]; /**< relocation type */
};
#define RELOC_STD_BITS_PCREL_BIG ((unsigned int) 0x80)
#define RELOC_STD_BITS_PCREL_LITTLE ((unsigned int) 0x01)
#define RELOC_STD_BITS_LENGTH_BIG ((unsigned int) 0x60)
#define RELOC_STD_BITS_LENGTH_SH_BIG 5
#define RELOC_STD_BITS_LENGTH_LITTLE ((unsigned int) 0x06)
#define RELOC_STD_BITS_LENGTH_SH_LITTLE 1
#define RELOC_STD_BITS_EXTERN_BIG ((unsigned int) 0x10)
#define RELOC_STD_BITS_EXTERN_LITTLE ((unsigned int) 0x08)
#define RELOC_STD_BITS_BASEREL_BIG ((unsigned int) 0x08)
#define RELOC_STD_BITS_BASEREL_LITTLE ((unsigned int) 0x10)
#define RELOC_STD_BITS_JMPTABLE_BIG ((unsigned int) 0x04)
#define RELOC_STD_BITS_JMPTABLE_LITTLE ((unsigned int) 0x20)
#define RELOC_STD_BITS_RELATIVE_BIG ((unsigned int) 0x02)
#define RELOC_STD_BITS_RELATIVE_LITTLE ((unsigned int) 0x40)
#define RELOC_STD_SIZE (BYTES_IN_WORD + 3 + 1) /**< Bytes per relocation entry */
/** EXTENDED RELOCS */
struct reloc_ext_external {
tUInt8 r_address[BYTES_IN_WORD]; /**< offset of of data to relocate */
tUInt8 r_index[3]; /**< symbol table index of symbol */
tUInt8 r_type[1]; /**< relocation type */
tUInt8 r_addend[BYTES_IN_WORD]; /**< datum addend */
};
#define RELOC_EXT_BITS_EXTERN_BIG ((unsigned int) 0x80)
#define RELOC_EXT_BITS_EXTERN_LITTLE ((unsigned int) 0x01)
#define RELOC_EXT_BITS_TYPE_BIG ((unsigned int) 0x1F)
#define RELOC_EXT_BITS_TYPE_SH_BIG 0
#define RELOC_EXT_BITS_TYPE_LITTLE ((unsigned int) 0xF8)
#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3
/** Bytes per relocation entry */
#define RELOC_EXT_SIZE (BYTES_IN_WORD + 3 + 1 + BYTES_IN_WORD)
enum reloc_type
{
/** simple relocations */
RELOC_8, /**< data[0:7] = addend + sv */
RELOC_16, /**< data[0:15] = addend + sv */
RELOC_32, /**< data[0:31] = addend + sv */
/** pc-rel displacement */
RELOC_DISP8, /**< data[0:7] = addend - pc + sv */
RELOC_DISP16, /**< data[0:15] = addend - pc + sv */
RELOC_DISP32, /**< data[0:31] = addend - pc + sv */
/** Special */
RELOC_WDISP30, /**< data[0:29] = (addend + sv - pc)>>2 */
RELOC_WDISP22, /**< data[0:21] = (addend + sv - pc)>>2 */
RELOC_HI22, /**< data[0:21] = (addend + sv)>>10 */
RELOC_22, /**< data[0:21] = (addend + sv) */
RELOC_13, /**< data[0:12] = (addend + sv) */
RELOC_LO10, /**< data[0:9] = (addend + sv) */
RELOC_SFA_BASE,
RELOC_SFA_OFF13,
/** P.I.C. (base-relative) */
RELOC_BASE10, /**< Not sure - maybe we can do this the */
RELOC_BASE13, /**< right way now */
RELOC_BASE22,
/** for some sort of pc-rel P.I.C. (?) */
RELOC_PC10,
RELOC_PC22,
/** P.I.C. jump table */
RELOC_JMP_TBL,
/** reputedly for shared libraries somehow */
RELOC_SEGOFF16,
RELOC_GLOB_DAT,
RELOC_JMP_SLOT,
RELOC_RELATIVE,
RELOC_11,
RELOC_WDISP2_14,
RELOC_WDISP19,
RELOC_HHI22, /**< data[0:21] = (addend + sv) >> 42 */
RELOC_HLO10, /**< data[0:9] = (addend + sv) >> 32 */
/** 29K relocation types */
RELOC_JUMPTARG,
RELOC_CONST,
RELOC_CONSTH,
/** All the new ones I can think of, for sparc v9 */
RELOC_64, /**< data[0:63] = addend + sv */
RELOC_DISP64, /**< data[0:63] = addend - pc + sv */
RELOC_WDISP21, /**< data[0:20] = (addend + sv - pc)>>2 */
RELOC_DISP21, /**< data[0:20] = addend - pc + sv */
RELOC_DISP14, /**< data[0:13] = addend - pc + sv */
/** Q .
What are the other ones,
Since this is a clean slate, can we throw away the ones we dont
understand ? Should we sort the values ? What about using a
microcode format like the 68k ?
*/
NO_RELOC
};
#ifdef __HAVE_PRAGMA_PACK__
#pragma pack()
#endif
#endif /* __A_OUT_64_H__ */
|