424 lines
14 KiB
C
424 lines
14 KiB
C
/*
|
|
* a.out specifics for Sequent Symmetry running Dynix 3.x
|
|
*/
|
|
#ifndef A_OUT_DYNIX3_H
|
|
#define A_OUT_DYNIX3_H
|
|
|
|
/* struct exec for Dynix 3
|
|
*
|
|
* a_gdtbl and a_bootstrap are only for standalone binaries.
|
|
* Shared data fields are not supported by the kernel as of Dynix 3.1,
|
|
* but are supported by Dynix compiler programs.
|
|
*/
|
|
struct external_exec {
|
|
unsigned char e_info[4];
|
|
unsigned char e_text[4];
|
|
unsigned char e_data[4];
|
|
unsigned char e_bss[4];
|
|
unsigned char e_syms[4];
|
|
unsigned char e_entry[4];
|
|
unsigned char e_trsize[4];
|
|
unsigned char e_drsize[4];
|
|
unsigned char e_g_code[8], e_g_data[8], e_g_desc[8];
|
|
unsigned char e_shdata[4];
|
|
unsigned char e_shbss[4];
|
|
unsigned char e_shdrsize[4];
|
|
unsigned char e_bootstrap[44];
|
|
unsigned char e_reserved[12];
|
|
unsigned char e_version[4];
|
|
};
|
|
|
|
/*
|
|
* Register information and structs for Dynix 3,
|
|
* culled from various system header files.
|
|
*/
|
|
|
|
/*
|
|
* 80387 structure, from ptrace(2) and in u area
|
|
*/
|
|
struct fpusave {
|
|
unsigned short fpu_control, fpu_rsvd1; /* control word */
|
|
unsigned short fpu_status, fpu_rsvd2; /* status word */
|
|
unsigned short fpu_tag, fpu_rsvd3; /* tag word */
|
|
unsigned long fpu_ip; /* IP offset */
|
|
unsigned short fpu_cs, fpu_rsvd4; /* CS selector */
|
|
unsigned long fpu_data_offset; /* data offset */
|
|
unsigned short fpu_op_sel, fpu_rsvd5; /* operand selector */
|
|
unsigned short fpu_stack[8][5]; /* 8 80-bit temp-reals from FPU stack*/
|
|
};
|
|
|
|
/*
|
|
* WTL1167 structure, from ptrace(2) and in u area
|
|
*/
|
|
#define FPA_NREGS 31
|
|
|
|
struct fpasave {
|
|
long fpa_pcr; /* context register */
|
|
long fpa_regs[FPA_NREGS]; /* register contents */
|
|
};
|
|
|
|
/*
|
|
* structure used by ptrace(2) XPT_RREGS and XPT_WREGS
|
|
*/
|
|
struct pt_regset {
|
|
int pr_eax;
|
|
int pr_ebx;
|
|
int pr_ecx;
|
|
int pr_edx;
|
|
int pr_esi;
|
|
int pr_edi;
|
|
int pr_ebp;
|
|
int pr_esp;
|
|
int pr_eip;
|
|
int pr_flags;
|
|
struct fpusave pr_fpu;
|
|
struct fpasave pr_fpa;
|
|
};
|
|
|
|
/*
|
|
* Register offsets in u area of core file
|
|
*/
|
|
#define SS (5)
|
|
#define ESP (4)
|
|
#define FLAGS (3)
|
|
#define CS (2)
|
|
#define EIP (1)
|
|
#define EAX (0)
|
|
#define ECX (-1)
|
|
#define EDX (-2)
|
|
#define EBX (-3)
|
|
#define EBP (-5)
|
|
#define ESI (-6)
|
|
#define EDI (-7)
|
|
|
|
/*
|
|
* Important offsets into Dynix struct user, for use in examination of a
|
|
* core file in a vaguely machine independant way. For lack of
|
|
* anything better, we use u_ar0 as a magic number, since it appears
|
|
* to have an identical value under all versions of Dynix 3.
|
|
*/
|
|
#define U_AR0_OFFSET 0x8
|
|
#define U_AR0_VALUE 0x7fffffe8
|
|
#define U_TSIZE_OFFSET 0x60
|
|
#define U_DSIZE_OFFSET 0x64
|
|
#define U_SSIZE_OFFSET 0x68
|
|
#define U_FPUSAVE_OFFSET 0x3ff
|
|
#define U_FPASAVE_OFFSET 0x3b0
|
|
|
|
#define EXEC_BYTES_SIZE (4 + BYTES_IN_WORD * 7)
|
|
|
|
#define OMAGIC 0x12eb /* .o */
|
|
#define ZMAGIC 0x22eb /* zero @ 0, demand load */
|
|
#define XMAGIC 0x32eb /* invalid @ 0, demand load */
|
|
#define SMAGIC 0x42eb /* standalone, not supported here */
|
|
|
|
#define N_BADMAG(x) ((OMAGIC != N_MAGIC(x)) && \
|
|
(ZMAGIC != N_MAGIC(x)) && \
|
|
(XMAGIC != N_MAGIC(x)) && \
|
|
(SMAGIC != N_MAGIC(x)))
|
|
|
|
#define TEXT_START_ADDR 0x1000
|
|
|
|
#define PAGE_SIZE 0x1000
|
|
#define SEGMENT_SIZE PAGE_SIZE
|
|
|
|
#define STACK_END_ADDR (0x40000000 - PAGE_SIZE)
|
|
|
|
#define N_SET_MACHTYPE(exec, machtype) \
|
|
((exec).a_info = \
|
|
((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
|
|
|
|
#define N_SET_FLAGS(exec, flags) \
|
|
((exec).a_info = \
|
|
((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
|
|
|
|
#define N_SET_MAGIC(exec, magic) \
|
|
((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
|
|
|
|
#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
|
|
#define N_MAGIC(x) ((x).a_info & 0xffff)
|
|
|
|
#define N_MAGIC_EXTERNAL(x) ((x).a_magic)
|
|
|
|
#define N_ADDRADJ(x) ((ZMAGIC == N_MAGIC(x) || XMAGIC == N_MAGIC(x)) ? 0x1000 : 0)
|
|
|
|
#if 0
|
|
/* Ignore shared segments for now... */
|
|
#define N_TXTOFF(x) ((OMAGIC == N_MAGIC(x)) ? sizeof(struct exec) : 0)
|
|
#define N_DATAOFF(x) (N_TXTOFF(x) + (x).a_text - N_ADDRADJ(x))
|
|
#define N_SHDATAOFF(x) (N_DATAOFF(x) + (x).a_data)
|
|
#define N_TROFF(x) (N_SHDATAOFF(x) + (x).a_shdata)
|
|
#define N_DROFF(x) (N_TROFF(x) + (x).a_trsize)
|
|
#define N_SHDROFF(x) (N_DROFF(x) + (x).a_drsize)
|
|
#define N_SYMOFF(x) (N_SHDROFF(x) + (x).a_shdrsize)
|
|
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
|
|
#endif
|
|
|
|
#define N_TXTOFF(x) ((OMAGIC == N_MAGIC(x)) ? sizeof(x) : 0)
|
|
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text - N_ADDRADJ(x))
|
|
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
|
|
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
|
|
#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
|
|
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
|
|
|
|
#define N_TXTADDR(x) \
|
|
(((OMAGIC == N_MAGIC(x)) || (SMAGIC == N_MAGIC(x))) ? 0 \
|
|
: TEXT_START_ADDR)
|
|
|
|
#define N_DATADDR(x) \
|
|
(OMAGIC == N_MAGIC(x) ? (N_TXTADDR(x) + (x).a_text) \
|
|
: (SEGMENT_SIZE + ((N_TXTADDR(x) + (x).a_text - 1) & \
|
|
~(SEGMENT_SIZE - 1))))
|
|
|
|
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
|
|
|
|
/* This may not be quite right */
|
|
#define N_TXTSIZE(x) ((x).a_text)
|
|
/* relocation stuff */
|
|
|
|
|
|
/* 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 {
|
|
bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
|
|
bfd_byte r_index[3]; /* symbol table index of symbol */
|
|
bfd_byte r_type[1]; /* relocation type */
|
|
};
|
|
|
|
#define RELOC_STD_BITS_PCREL_BIG 0x80
|
|
#define RELOC_STD_BITS_PCREL_LITTLE 0x01
|
|
|
|
#define RELOC_STD_BITS_LENGTH_BIG 0x60
|
|
#define RELOC_STD_BITS_LENGTH_SH_BIG 5 /* To shift to units place */
|
|
#define RELOC_STD_BITS_LENGTH_LITTLE 0x06
|
|
#define RELOC_STD_BITS_LENGTH_SH_LITTLE 1
|
|
|
|
#define RELOC_STD_BITS_EXTERN_BIG 0x10
|
|
#define RELOC_STD_BITS_EXTERN_LITTLE 0x08
|
|
|
|
#define RELOC_STD_BITS_BASEREL_BIG 0x08
|
|
#define RELOC_STD_BITS_BASEREL_LITTLE 0x08
|
|
|
|
#define RELOC_STD_BITS_JMPTABLE_BIG 0x04
|
|
#define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04
|
|
|
|
#define RELOC_STD_BITS_RELATIVE_BIG 0x02
|
|
#define RELOC_STD_BITS_RELATIVE_LITTLE 0x02
|
|
|
|
#define RELOC_STD_SIZE (BYTES_IN_WORD + 3 + 1) /* Bytes per relocation entry */
|
|
|
|
struct reloc_std_internal
|
|
{
|
|
bfd_vma r_address; /* Address (within segment) to be relocated. */
|
|
/* The meaning of r_symbolnum depends on r_extern. */
|
|
unsigned int r_symbolnum:24;
|
|
/* Nonzero means value is a pc-relative offset
|
|
and it should be relocated for changes in its own address
|
|
as well as for changes in the symbol or section specified. */
|
|
unsigned int r_pcrel:1;
|
|
/* Length (as exponent of 2) of the field to be relocated.
|
|
Thus, a value of 2 indicates 1<<2 bytes. */
|
|
unsigned int r_length:2;
|
|
/* 1 => relocate with value of symbol.
|
|
r_symbolnum is the index of the symbol
|
|
in files the symbol table.
|
|
0 => relocate with the address of a segment.
|
|
r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
|
|
(the N_EXT bit may be set also, but signifies nothing). */
|
|
unsigned int r_extern:1;
|
|
/* The next three bits are for SunOS shared libraries, and seem to
|
|
be undocumented. */
|
|
unsigned int r_baserel:1; /* Linkage table relative */
|
|
unsigned int r_jmptable:1; /* pc-relative to jump table */
|
|
unsigned int r_relative:1; /* "relative relocation" */
|
|
/* unused */
|
|
unsigned int r_pad:1; /* Padding -- set to zero */
|
|
};
|
|
|
|
|
|
/* EXTENDED RELOCS */
|
|
|
|
struct reloc_ext_external {
|
|
bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
|
|
bfd_byte r_index[3]; /* symbol table index of symbol */
|
|
bfd_byte r_type[1]; /* relocation type */
|
|
bfd_byte r_addend[BYTES_IN_WORD]; /* datum addend */
|
|
};
|
|
|
|
#define RELOC_EXT_BITS_EXTERN_BIG 0x80
|
|
#define RELOC_EXT_BITS_EXTERN_LITTLE 0x01
|
|
|
|
#define RELOC_EXT_BITS_TYPE_BIG 0x1F
|
|
#define RELOC_EXT_BITS_TYPE_SH_BIG 0
|
|
#define RELOC_EXT_BITS_TYPE_LITTLE 0xF8
|
|
#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3
|
|
|
|
#define RELOC_EXT_SIZE (BYTES_IN_WORD + 3 + 1 + BYTES_IN_WORD) /* Bytes per relocation entry */
|
|
|
|
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,
|
|
|
|
|
|
/* 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
|
|
};
|
|
|
|
|
|
struct reloc_internal {
|
|
bfd_vma r_address; /* offset of of data to relocate */
|
|
long r_index; /* symbol table index of symbol */
|
|
enum reloc_type r_type; /* relocation type */
|
|
bfd_vma r_addend; /* datum addend */
|
|
};
|
|
|
|
/* Q.
|
|
Should the length of the string table be 4 bytes or 8 bytes ?
|
|
|
|
Q.
|
|
What about archive indexes ?
|
|
|
|
*/
|
|
|
|
#define EXTERNAL_NLIST_SIZE (BYTES_IN_WORD+4+BYTES_IN_WORD)
|
|
|
|
/*
|
|
* All executables under Dynix are demand paged with read-only text,
|
|
* Thus no NMAGIC.
|
|
*
|
|
* ZMAGIC has a page of 0s at virtual 0,
|
|
* XMAGIC has an invalid page at virtual 0
|
|
*/
|
|
|
|
#define WRITE_HEADERS(abfd, execp) \
|
|
{ \
|
|
if (abfd->flags & D_PAGED) \
|
|
{ \
|
|
execp->a_text = obj_textsec (abfd)->_raw_size; \
|
|
/* Kludge to distinguish old- and new-style ZMAGIC. \
|
|
The latter includes the exec header in the text size. */ \
|
|
if (obj_textsec(abfd)->filepos == EXEC_BYTES_SIZE) \
|
|
execp->a_text += EXEC_BYTES_SIZE; \
|
|
N_SET_MAGIC (*execp, ZMAGIC); \
|
|
} \
|
|
else \
|
|
{ \
|
|
execp->a_text = obj_textsec (abfd)->_raw_size; \
|
|
if (abfd->flags & WP_TEXT) \
|
|
{ N_SET_MAGIC (*execp, ZMAGIC); } \
|
|
else \
|
|
{ N_SET_MAGIC(*execp, OMAGIC); } \
|
|
} \
|
|
if (abfd->flags & D_PAGED) \
|
|
{ \
|
|
data_pad = BFD_ALIGN(obj_datasec(abfd)->_raw_size, PAGE_SIZE) \
|
|
- obj_datasec(abfd)->_raw_size; \
|
|
\
|
|
if (data_pad > obj_bsssec(abfd)->_raw_size) \
|
|
execp->a_bss = 0; \
|
|
else \
|
|
execp->a_bss = obj_bsssec(abfd)->_raw_size - data_pad; \
|
|
execp->a_data = obj_datasec(abfd)->_raw_size + data_pad; \
|
|
} \
|
|
else \
|
|
{ \
|
|
execp->a_data = obj_datasec (abfd)->_raw_size; \
|
|
execp->a_bss = obj_bsssec (abfd)->_raw_size; \
|
|
} \
|
|
\
|
|
execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
|
|
execp->a_entry = bfd_get_start_address (abfd); \
|
|
\
|
|
execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
|
|
obj_reloc_entry_size (abfd)); \
|
|
execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
|
|
obj_reloc_entry_size (abfd)); \
|
|
NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
|
|
\
|
|
bfd_seek (abfd, 0L, false); \
|
|
bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd); \
|
|
/* Now write out reloc info, followed by syms and strings */ \
|
|
\
|
|
if (bfd_get_symcount (abfd) != 0) \
|
|
{ \
|
|
bfd_seek (abfd, \
|
|
(long)(N_SYMOFF(*execp)), false); \
|
|
\
|
|
NAME(aout,write_syms)(abfd); \
|
|
\
|
|
bfd_seek (abfd, (long)(N_TRELOFF(*execp)), false); \
|
|
\
|
|
if (!NAME(aout,squirt_out_relocs) (abfd, obj_textsec (abfd))) return false; \
|
|
bfd_seek (abfd, (long)(N_DRELOFF(*execp)), false); \
|
|
\
|
|
if (!NAME(aout,squirt_out_relocs)(abfd, obj_datasec (abfd))) return false; \
|
|
} \
|
|
}
|
|
#endif
|