Commit | Line | Data |
---|---|---|
3624a4e2 JK |
1 | /* |
2 | * a.out specifics for Sequent Symmetry running Dynix 3.x | |
3 | */ | |
4 | #ifndef A_OUT_DYNIX3_H | |
5 | #define A_OUT_DYNIX3_H | |
6 | ||
7 | /* struct exec for Dynix 3 | |
8 | * | |
9 | * a_gdtbl and a_bootstrap are only for standalone binaries. | |
10 | * Shared data fields are not supported by the kernel as of Dynix 3.1, | |
11 | * but are supported by Dynix compiler programs. | |
12 | */ | |
13 | struct external_exec { | |
14 | unsigned char e_info[4]; | |
15 | unsigned char e_text[4]; | |
16 | unsigned char e_data[4]; | |
17 | unsigned char e_bss[4]; | |
18 | unsigned char e_syms[4]; | |
19 | unsigned char e_entry[4]; | |
20 | unsigned char e_trsize[4]; | |
21 | unsigned char e_drsize[4]; | |
22 | unsigned char e_g_code[8], e_g_data[8], e_g_desc[8]; | |
23 | unsigned char e_shdata[4]; | |
24 | unsigned char e_shbss[4]; | |
25 | unsigned char e_shdrsize[4]; | |
26 | unsigned char e_bootstrap[44]; | |
27 | unsigned char e_reserved[12]; | |
28 | unsigned char e_version[4]; | |
29 | }; | |
30 | ||
31 | /* | |
32 | * Register information and structs for Dynix 3, | |
33 | * culled from various system header files. | |
34 | */ | |
35 | ||
36 | /* | |
37 | * 80387 structure, from ptrace(2) and in u area | |
38 | */ | |
39 | struct fpusave { | |
40 | unsigned short fpu_control, fpu_rsvd1; /* control word */ | |
41 | unsigned short fpu_status, fpu_rsvd2; /* status word */ | |
42 | unsigned short fpu_tag, fpu_rsvd3; /* tag word */ | |
43 | unsigned long fpu_ip; /* IP offset */ | |
44 | unsigned short fpu_cs, fpu_rsvd4; /* CS selector */ | |
45 | unsigned long fpu_data_offset; /* data offset */ | |
46 | unsigned short fpu_op_sel, fpu_rsvd5; /* operand selector */ | |
47 | unsigned short fpu_stack[8][5]; /* 8 80-bit temp-reals from FPU stack*/ | |
48 | }; | |
49 | ||
50 | /* | |
51 | * WTL1167 structure, from ptrace(2) and in u area | |
52 | */ | |
53 | #define FPA_NREGS 31 | |
54 | ||
55 | struct fpasave { | |
56 | long fpa_pcr; /* context register */ | |
57 | long fpa_regs[FPA_NREGS]; /* register contents */ | |
58 | }; | |
59 | ||
60 | /* | |
61 | * structure used by ptrace(2) XPT_RREGS and XPT_WREGS | |
62 | */ | |
63 | struct pt_regset { | |
64 | int pr_eax; | |
65 | int pr_ebx; | |
66 | int pr_ecx; | |
67 | int pr_edx; | |
68 | int pr_esi; | |
69 | int pr_edi; | |
70 | int pr_ebp; | |
71 | int pr_esp; | |
72 | int pr_eip; | |
73 | int pr_flags; | |
74 | struct fpusave pr_fpu; | |
75 | struct fpasave pr_fpa; | |
76 | }; | |
77 | ||
78 | /* | |
79 | * Register offsets in u area of core file | |
80 | */ | |
81 | #define SS (5) | |
82 | #define ESP (4) | |
83 | #define FLAGS (3) | |
84 | #define CS (2) | |
85 | #define EIP (1) | |
86 | #define EAX (0) | |
87 | #define ECX (-1) | |
88 | #define EDX (-2) | |
89 | #define EBX (-3) | |
90 | #define EBP (-5) | |
91 | #define ESI (-6) | |
92 | #define EDI (-7) | |
93 | ||
94 | /* | |
95 | * Important offsets into Dynix struct user, for use in examination of a | |
96 | * core file in a vaguely machine independant way. For lack of | |
97 | * anything better, we use u_ar0 as a magic number, since it appears | |
98 | * to have an identical value under all versions of Dynix 3. | |
99 | */ | |
100 | #define U_AR0_OFFSET 0x8 | |
101 | #define U_AR0_VALUE 0x7fffffe8 | |
102 | #define U_TSIZE_OFFSET 0x60 | |
103 | #define U_DSIZE_OFFSET 0x64 | |
104 | #define U_SSIZE_OFFSET 0x68 | |
105 | #define U_FPUSAVE_OFFSET 0x3ff | |
106 | #define U_FPASAVE_OFFSET 0x3b0 | |
107 | ||
108 | #define EXEC_BYTES_SIZE (4 + BYTES_IN_WORD * 7) | |
109 | ||
110 | #define OMAGIC 0x12eb /* .o */ | |
111 | #define ZMAGIC 0x22eb /* zero @ 0, demand load */ | |
112 | #define XMAGIC 0x32eb /* invalid @ 0, demand load */ | |
113 | #define SMAGIC 0x42eb /* standalone, not supported here */ | |
114 | ||
115 | #define N_BADMAG(x) ((OMAGIC != N_MAGIC(x)) && \ | |
116 | (ZMAGIC != N_MAGIC(x)) && \ | |
117 | (XMAGIC != N_MAGIC(x)) && \ | |
118 | (SMAGIC != N_MAGIC(x))) | |
119 | ||
120 | #define TEXT_START_ADDR 0x1000 | |
121 | ||
122 | #define PAGE_SIZE 0x1000 | |
123 | #define SEGMENT_SIZE PAGE_SIZE | |
124 | ||
125 | #define STACK_END_ADDR (0x40000000 - PAGE_SIZE) | |
126 | ||
127 | #define N_SET_MACHTYPE(exec, machtype) \ | |
128 | ((exec).a_info = \ | |
129 | ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16)) | |
130 | ||
131 | #define N_SET_FLAGS(exec, flags) \ | |
132 | ((exec).a_info = \ | |
133 | ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24)) | |
134 | ||
135 | #define N_SET_MAGIC(exec, magic) \ | |
136 | ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) | |
137 | ||
138 | #define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) | |
139 | #define N_MAGIC(x) ((x).a_info & 0xffff) | |
140 | ||
141 | #define N_MAGIC_EXTERNAL(x) ((x).a_magic) | |
142 | ||
143 | #define N_ADDRADJ(x) ((ZMAGIC == N_MAGIC(x) || XMAGIC == N_MAGIC(x)) ? 0x1000 : 0) | |
144 | ||
145 | #if 0 | |
146 | /* Ignore shared segments for now... */ | |
147 | #define N_TXTOFF(x) ((OMAGIC == N_MAGIC(x)) ? sizeof(struct exec) : 0) | |
148 | #define N_DATAOFF(x) (N_TXTOFF(x) + (x).a_text - N_ADDRADJ(x)) | |
149 | #define N_SHDATAOFF(x) (N_DATAOFF(x) + (x).a_data) | |
150 | #define N_TROFF(x) (N_SHDATAOFF(x) + (x).a_shdata) | |
151 | #define N_DROFF(x) (N_TROFF(x) + (x).a_trsize) | |
152 | #define N_SHDROFF(x) (N_DROFF(x) + (x).a_drsize) | |
153 | #define N_SYMOFF(x) (N_SHDROFF(x) + (x).a_shdrsize) | |
154 | #define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms) | |
155 | #endif | |
156 | ||
157 | #define N_TXTOFF(x) ((OMAGIC == N_MAGIC(x)) ? sizeof(x) : 0) | |
158 | #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text - N_ADDRADJ(x)) | |
159 | #define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data) | |
160 | #define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize) | |
161 | #define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize) | |
162 | #define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms) | |
163 | ||
164 | #define N_TXTADDR(x) \ | |
165 | (((OMAGIC == N_MAGIC(x)) || (SMAGIC == N_MAGIC(x))) ? 0 \ | |
166 | : TEXT_START_ADDR) | |
167 | ||
168 | #define N_DATADDR(x) \ | |
169 | (OMAGIC == N_MAGIC(x) ? (N_TXTADDR(x) + (x).a_text) \ | |
170 | : (SEGMENT_SIZE + ((N_TXTADDR(x) + (x).a_text - 1) & \ | |
171 | ~(SEGMENT_SIZE - 1)))) | |
172 | ||
173 | #define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) | |
174 | ||
175 | /* This may not be quite right */ | |
176 | #define N_TXTSIZE(x) ((x).a_text) | |
177 | /* relocation stuff */ | |
178 | ||
179 | ||
180 | /* Relocations | |
181 | ||
182 | There are two types of relocation flavours for a.out systems, | |
183 | standard and extended. The standard form is used on systems where | |
184 | the instruction has room for all the bits of an offset to the operand, whilst the | |
185 | extended form is used when an address operand has to be split over n | |
186 | instructions. Eg, on the 68k, each move instruction can reference | |
187 | the target with a displacement of 16 or 32 bits. On the sparc, move | |
188 | instructions use an offset of 14 bits, so the offset is stored in | |
189 | the reloc field, and the data in the section is ignored. | |
190 | */ | |
191 | ||
192 | /* This structure describes a single relocation to be performed. | |
193 | The text-relocation section of the file is a vector of these structures, | |
194 | all of which apply to the text section. | |
195 | Likewise, the data-relocation section applies to the data section. */ | |
196 | ||
197 | struct reloc_std_external { | |
198 | bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */ | |
199 | bfd_byte r_index[3]; /* symbol table index of symbol */ | |
200 | bfd_byte r_type[1]; /* relocation type */ | |
201 | }; | |
202 | ||
203 | #define RELOC_STD_BITS_PCREL_BIG 0x80 | |
204 | #define RELOC_STD_BITS_PCREL_LITTLE 0x01 | |
205 | ||
206 | #define RELOC_STD_BITS_LENGTH_BIG 0x60 | |
207 | #define RELOC_STD_BITS_LENGTH_SH_BIG 5 /* To shift to units place */ | |
208 | #define RELOC_STD_BITS_LENGTH_LITTLE 0x06 | |
209 | #define RELOC_STD_BITS_LENGTH_SH_LITTLE 1 | |
210 | ||
211 | #define RELOC_STD_BITS_EXTERN_BIG 0x10 | |
212 | #define RELOC_STD_BITS_EXTERN_LITTLE 0x08 | |
213 | ||
214 | #define RELOC_STD_BITS_BASEREL_BIG 0x08 | |
215 | #define RELOC_STD_BITS_BASEREL_LITTLE 0x08 | |
216 | ||
217 | #define RELOC_STD_BITS_JMPTABLE_BIG 0x04 | |
218 | #define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04 | |
219 | ||
220 | #define RELOC_STD_BITS_RELATIVE_BIG 0x02 | |
221 | #define RELOC_STD_BITS_RELATIVE_LITTLE 0x02 | |
222 | ||
223 | #define RELOC_STD_SIZE (BYTES_IN_WORD + 3 + 1) /* Bytes per relocation entry */ | |
224 | ||
225 | struct reloc_std_internal | |
226 | { | |
227 | bfd_vma r_address; /* Address (within segment) to be relocated. */ | |
228 | /* The meaning of r_symbolnum depends on r_extern. */ | |
229 | unsigned int r_symbolnum:24; | |
230 | /* Nonzero means value is a pc-relative offset | |
231 | and it should be relocated for changes in its own address | |
232 | as well as for changes in the symbol or section specified. */ | |
233 | unsigned int r_pcrel:1; | |
234 | /* Length (as exponent of 2) of the field to be relocated. | |
235 | Thus, a value of 2 indicates 1<<2 bytes. */ | |
236 | unsigned int r_length:2; | |
237 | /* 1 => relocate with value of symbol. | |
238 | r_symbolnum is the index of the symbol | |
239 | in files the symbol table. | |
240 | 0 => relocate with the address of a segment. | |
241 | r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS | |
242 | (the N_EXT bit may be set also, but signifies nothing). */ | |
243 | unsigned int r_extern:1; | |
244 | /* The next three bits are for SunOS shared libraries, and seem to | |
245 | be undocumented. */ | |
246 | unsigned int r_baserel:1; /* Linkage table relative */ | |
247 | unsigned int r_jmptable:1; /* pc-relative to jump table */ | |
248 | unsigned int r_relative:1; /* "relative relocation" */ | |
249 | /* unused */ | |
250 | unsigned int r_pad:1; /* Padding -- set to zero */ | |
251 | }; | |
252 | ||
253 | ||
254 | /* EXTENDED RELOCS */ | |
255 | ||
256 | struct reloc_ext_external { | |
257 | bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */ | |
258 | bfd_byte r_index[3]; /* symbol table index of symbol */ | |
259 | bfd_byte r_type[1]; /* relocation type */ | |
260 | bfd_byte r_addend[BYTES_IN_WORD]; /* datum addend */ | |
261 | }; | |
262 | ||
263 | #define RELOC_EXT_BITS_EXTERN_BIG 0x80 | |
264 | #define RELOC_EXT_BITS_EXTERN_LITTLE 0x01 | |
265 | ||
266 | #define RELOC_EXT_BITS_TYPE_BIG 0x1F | |
267 | #define RELOC_EXT_BITS_TYPE_SH_BIG 0 | |
268 | #define RELOC_EXT_BITS_TYPE_LITTLE 0xF8 | |
269 | #define RELOC_EXT_BITS_TYPE_SH_LITTLE 3 | |
270 | ||
271 | #define RELOC_EXT_SIZE (BYTES_IN_WORD + 3 + 1 + BYTES_IN_WORD) /* Bytes per relocation entry */ | |
272 | ||
273 | enum reloc_type | |
274 | { | |
275 | ||
276 | ||
277 | ||
278 | ||
279 | ||
280 | /* simple relocations */ | |
281 | RELOC_8, /* data[0:7] = addend + sv */ | |
282 | RELOC_16, /* data[0:15] = addend + sv */ | |
283 | RELOC_32, /* data[0:31] = addend + sv */ | |
284 | /* pc-rel displacement */ | |
285 | RELOC_DISP8, /* data[0:7] = addend - pc + sv */ | |
286 | RELOC_DISP16, /* data[0:15] = addend - pc + sv */ | |
287 | RELOC_DISP32, /* data[0:31] = addend - pc + sv */ | |
288 | /* Special */ | |
289 | RELOC_WDISP30, /* data[0:29] = (addend + sv - pc)>>2 */ | |
290 | RELOC_WDISP22, /* data[0:21] = (addend + sv - pc)>>2 */ | |
291 | RELOC_HI22, /* data[0:21] = (addend + sv)>>10 */ | |
292 | RELOC_22, /* data[0:21] = (addend + sv) */ | |
293 | RELOC_13, /* data[0:12] = (addend + sv) */ | |
294 | RELOC_LO10, /* data[0:9] = (addend + sv) */ | |
295 | RELOC_SFA_BASE, | |
296 | RELOC_SFA_OFF13, | |
297 | /* P.I.C. (base-relative) */ | |
298 | RELOC_BASE10, /* Not sure - maybe we can do this the */ | |
299 | RELOC_BASE13, /* right way now */ | |
300 | RELOC_BASE22, | |
301 | /* for some sort of pc-rel P.I.C. (?) */ | |
302 | RELOC_PC10, | |
303 | RELOC_PC22, | |
304 | /* P.I.C. jump table */ | |
305 | RELOC_JMP_TBL, | |
306 | /* reputedly for shared libraries somehow */ | |
307 | RELOC_SEGOFF16, | |
308 | RELOC_GLOB_DAT, | |
309 | RELOC_JMP_SLOT, | |
310 | RELOC_RELATIVE, | |
311 | ||
312 | RELOC_11, | |
313 | RELOC_WDISP2_14, | |
314 | RELOC_WDISP19, | |
315 | RELOC_HHI22, /* data[0:21] = (addend + sv) >> 42 */ | |
316 | RELOC_HLO10, /* data[0:9] = (addend + sv) >> 32 */ | |
317 | ||
318 | /* 29K relocation types */ | |
319 | RELOC_JUMPTARG, | |
320 | RELOC_CONST, | |
321 | RELOC_CONSTH, | |
322 | ||
323 | ||
324 | /* Q . | |
325 | What are the other ones, | |
326 | Since this is a clean slate, can we throw away the ones we dont | |
327 | understand ? Should we sort the values ? What about using a | |
328 | microcode format like the 68k ? | |
329 | */ | |
330 | NO_RELOC | |
331 | }; | |
332 | ||
333 | ||
334 | struct reloc_internal { | |
335 | bfd_vma r_address; /* offset of of data to relocate */ | |
336 | long r_index; /* symbol table index of symbol */ | |
337 | enum reloc_type r_type; /* relocation type */ | |
338 | bfd_vma r_addend; /* datum addend */ | |
339 | }; | |
340 | ||
341 | /* Q. | |
342 | Should the length of the string table be 4 bytes or 8 bytes ? | |
343 | ||
344 | Q. | |
345 | What about archive indexes ? | |
346 | ||
347 | */ | |
348 | ||
349 | #define EXTERNAL_NLIST_SIZE (BYTES_IN_WORD+4+BYTES_IN_WORD) | |
350 | ||
351 | /* | |
352 | * All executables under Dynix are demand paged with read-only text, | |
353 | * Thus no NMAGIC. | |
354 | * | |
355 | * ZMAGIC has a page of 0s at virtual 0, | |
356 | * XMAGIC has an invalid page at virtual 0 | |
357 | */ | |
358 | ||
359 | #define WRITE_HEADERS(abfd, execp) \ | |
360 | { \ | |
361 | if (abfd->flags & D_PAGED) \ | |
362 | { \ | |
363 | execp->a_text = obj_textsec (abfd)->_raw_size; \ | |
364 | /* Kludge to distinguish old- and new-style ZMAGIC. \ | |
365 | The latter includes the exec header in the text size. */ \ | |
366 | if (obj_textsec(abfd)->filepos == EXEC_BYTES_SIZE) \ | |
367 | execp->a_text += EXEC_BYTES_SIZE; \ | |
368 | N_SET_MAGIC (*execp, ZMAGIC); \ | |
369 | } \ | |
370 | else \ | |
371 | { \ | |
372 | execp->a_text = obj_textsec (abfd)->_raw_size; \ | |
373 | if (abfd->flags & WP_TEXT) \ | |
374 | { N_SET_MAGIC (*execp, ZMAGIC); } \ | |
375 | else \ | |
376 | { N_SET_MAGIC(*execp, OMAGIC); } \ | |
377 | } \ | |
378 | if (abfd->flags & D_PAGED) \ | |
379 | { \ | |
380 | data_pad = BFD_ALIGN(obj_datasec(abfd)->_raw_size, PAGE_SIZE) \ | |
381 | - obj_datasec(abfd)->_raw_size; \ | |
382 | \ | |
383 | if (data_pad > obj_bsssec(abfd)->_raw_size) \ | |
384 | execp->a_bss = 0; \ | |
385 | else \ | |
386 | execp->a_bss = obj_bsssec(abfd)->_raw_size - data_pad; \ | |
387 | execp->a_data = obj_datasec(abfd)->_raw_size + data_pad; \ | |
388 | } \ | |
389 | else \ | |
390 | { \ | |
391 | execp->a_data = obj_datasec (abfd)->_raw_size; \ | |
392 | execp->a_bss = obj_bsssec (abfd)->_raw_size; \ | |
393 | } \ | |
394 | \ | |
395 | execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \ | |
396 | execp->a_entry = bfd_get_start_address (abfd); \ | |
397 | \ | |
398 | execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \ | |
399 | obj_reloc_entry_size (abfd)); \ | |
400 | execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \ | |
401 | obj_reloc_entry_size (abfd)); \ | |
402 | NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \ | |
403 | \ | |
404 | bfd_seek (abfd, 0L, false); \ | |
405 | bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd); \ | |
406 | /* Now write out reloc info, followed by syms and strings */ \ | |
407 | \ | |
408 | if (bfd_get_symcount (abfd) != 0) \ | |
409 | { \ | |
410 | bfd_seek (abfd, \ | |
411 | (long)(N_SYMOFF(*execp)), false); \ | |
412 | \ | |
413 | NAME(aout,write_syms)(abfd); \ | |
414 | \ | |
415 | bfd_seek (abfd, (long)(N_TRELOFF(*execp)), false); \ | |
416 | \ | |
417 | if (!NAME(aout,squirt_out_relocs) (abfd, obj_textsec (abfd))) return false; \ | |
418 | bfd_seek (abfd, (long)(N_DRELOFF(*execp)), false); \ | |
419 | \ | |
420 | if (!NAME(aout,squirt_out_relocs)(abfd, obj_datasec (abfd))) return false; \ | |
421 | } \ | |
422 | } | |
423 | #endif |