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
|
/*
* 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
|