Commit | Line | Data |
---|---|---|
fb3be09b JG |
1 | /* BFD backend for local host's a.out binaries |
2 | Copyright (C) 1990-1991 Free Software Foundation, Inc. | |
3 | Written by Cygnus Support. Probably John Gilmore's fault. | |
c4cd3fc6 | 4 | |
fb3be09b | 5 | This file is part of BFD, the Binary File Descriptor library. |
c4cd3fc6 | 6 | |
fb3be09b | 7 | This program is free software; you can redistribute it and/or modify |
c4cd3fc6 | 8 | it under the terms of the GNU General Public License as published by |
fb3be09b JG |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. | |
c4cd3fc6 | 11 | |
fb3be09b | 12 | This program is distributed in the hope that it will be useful, |
c4cd3fc6 JG |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
fb3be09b JG |
18 | along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
c4cd3fc6 | 20 | |
c4cd3fc6 | 21 | #include "bfd.h" |
bbc8d484 | 22 | #include "sysdep.h" |
c4cd3fc6 JG |
23 | #include "libbfd.h" |
24 | ||
25 | #include <a.out.h> | |
fb3be09b | 26 | #include "libaout.h" /* BFD a.out internal data structures */ |
c4cd3fc6 JG |
27 | |
28 | #include "trad-core.h" /* Traditional Unix core files */ | |
29 | ||
fb3be09b JG |
30 | /*======== This next section is stolen from ../include/a.out.gnu.h |
31 | ======== for all the losing Unix systems that don't provide these | |
32 | ======== macros. | |
33 | ||
34 | When porting to a new system, you must supply: | |
35 | ||
36 | HOST_PAGE_SIZE | |
37 | HOST_SEGMENT_SIZE | |
38 | HOST_MACHINE_ARCH (optional) | |
39 | HOST_MACHINE_MACHINE (optional) | |
40 | HOST_TEXT_START_ADDR | |
41 | HOST_STACK_END_ADDR | |
42 | ||
43 | in the ../include/h-systemname.h file. */ | |
44 | ||
45 | #define PAGE_SIZE HOST_PAGE_SIZE | |
46 | #define SEGMENT_SIZE HOST_SEGMENT_SIZE | |
47 | #define TEXT_START_ADDR HOST_TEXT_START_ADDR | |
48 | #define STACK_END_ADDR HOST_STACK_END_ADDR | |
49 | ||
50 | /*======== Stolen section begins below. =================================*/ | |
51 | ||
52 | #define a_info a_magic /* Old traditional Unix */ | |
c4cd3fc6 | 53 | |
fb3be09b JG |
54 | #define N_MAGIC(exec) ((exec).a_info & 0xffff) |
55 | #define N_SET_MAGIC(exec, magic) \ | |
56 | ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) | |
57 | ||
58 | /* Virtual Address of text segment from the a.out file. For OMAGIC, | |
59 | (almost always "unlinked .o's" these days), should be zero. | |
60 | For linked files, should reflect reality if we know it. */ | |
61 | ||
62 | #ifndef N_TXTADDR | |
63 | #define N_TXTADDR(x) (N_MAGIC(x)==OMAGIC? 0 : TEXT_START_ADDR) | |
64 | #endif | |
65 | ||
66 | #ifndef N_BADMAG | |
67 | #define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ | |
68 | && N_MAGIC(x) != NMAGIC \ | |
69 | && N_MAGIC(x) != ZMAGIC) | |
70 | #endif | |
71 | ||
72 | /* This complexity is for encapsulated COFF support */ | |
73 | #ifndef _N_HDROFF | |
74 | #define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec)) | |
75 | #endif | |
76 | ||
77 | #ifndef N_TXTOFF | |
78 | #define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? \ | |
79 | _N_HDROFF((x)) + sizeof (struct exec) : \ | |
80 | sizeof (struct exec)) | |
81 | #endif | |
82 | ||
83 | ||
84 | #ifndef N_DATOFF | |
85 | #define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) | |
86 | #endif | |
87 | ||
88 | #ifndef N_TRELOFF | |
89 | #define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data ) | |
90 | #endif | |
91 | ||
92 | #ifndef N_DRELOFF | |
93 | #define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize ) | |
94 | #endif | |
95 | ||
96 | #ifndef N_SYMOFF | |
97 | #define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize ) | |
98 | #endif | |
99 | ||
100 | #ifndef N_STROFF | |
101 | #define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) | |
102 | #endif | |
103 | ||
104 | /* Address of text segment in memory after it is loaded. */ | |
105 | #ifndef N_TXTADDR | |
106 | #define N_TXTADDR(x) 0 | |
107 | #endif | |
108 | ||
109 | #ifndef N_DATADDR | |
110 | #define N_DATADDR(x) \ | |
111 | (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+(x).a_text) \ | |
112 | : (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1)))) | |
113 | #endif | |
114 | ||
115 | /* Address of bss segment in memory after it is loaded. */ | |
116 | #ifndef N_BSSADDR | |
117 | #define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) | |
118 | #endif | |
119 | ||
120 | ||
121 | static bfd_target *NAME(host_aout,callback) (); | |
c4cd3fc6 JG |
122 | |
123 | /*SUPPRESS558*/ | |
124 | /*SUPPRESS529*/ | |
125 | ||
126 | bfd_target * | |
fb3be09b JG |
127 | DEFUN(NAME(host_aout,object_p), (abfd), |
128 | bfd *abfd) | |
c4cd3fc6 JG |
129 | { |
130 | unsigned char magicbuf[4]; /* Raw bytes of magic number from file */ | |
bbc8d484 JG |
131 | struct external_exec exec_bytes; |
132 | struct internal_exec exec; | |
c4cd3fc6 | 133 | |
bbc8d484 JG |
134 | if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) |
135 | != EXEC_BYTES_SIZE) { | |
136 | bfd_error = wrong_format; | |
c4cd3fc6 | 137 | return 0; |
bbc8d484 | 138 | } |
c4cd3fc6 | 139 | |
bbc8d484 | 140 | exec.a_magic = bfd_h_get_32 (abfd, exec_bytes.a_magic); |
c4cd3fc6 | 141 | |
bbc8d484 JG |
142 | if (N_BADMAG (exec)) return 0; |
143 | ||
144 | NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, &exec); | |
145 | return NAME(aout,some_aout_object_p) (abfd, &exec, NAME(host_aout,callback)); | |
c4cd3fc6 JG |
146 | } |
147 | ||
148 | /* Set parameters about this a.out file that are machine-dependent. | |
fb3be09b JG |
149 | This routine is called from NAME(some_aout_object_p) just before it returns. |
150 | */ | |
c4cd3fc6 JG |
151 | |
152 | static bfd_target * | |
fb3be09b JG |
153 | DEFUN(NAME(host_aout,callback), (abfd), |
154 | bfd *abfd) | |
c4cd3fc6 | 155 | { |
fb3be09b JG |
156 | /* exec_hdr (abfd), a "struct internal_exec *", is just an abstraction, |
157 | as far as the BFD a.out layer cares. We use it as a "struct exec *". | |
158 | This routine moves any data from the exec header, | |
159 | which is needed by the BFD code, out to places known to BFD. This | |
160 | allows the rest of the BFD code to not know or care about the structure | |
161 | of exec_hdr (abfd). */ | |
162 | struct exec *execp = (struct exec *)exec_hdr (abfd); | |
c4cd3fc6 JG |
163 | |
164 | /* The virtual memory addresses of the sections */ | |
165 | obj_datasec (abfd)->vma = N_DATADDR(*execp); | |
166 | obj_bsssec (abfd)->vma = N_BSSADDR(*execp); | |
167 | obj_textsec (abfd)->vma = N_TXTADDR(*execp); | |
168 | ||
169 | /* The file offsets of the sections */ | |
170 | obj_textsec (abfd)->filepos = N_TXTOFF(*execp); | |
171 | obj_datasec (abfd)->filepos = N_DATOFF(*execp); | |
172 | ||
173 | /* The file offsets of the relocation info */ | |
174 | obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp); | |
175 | obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp); | |
176 | ||
177 | /* The file offsets of the string table and symbol table. */ | |
178 | obj_str_filepos (abfd) = N_STROFF (*execp); | |
179 | obj_sym_filepos (abfd) = N_SYMOFF (*execp); | |
180 | ||
181 | #ifdef HOST_MACHINE_ARCH | |
bbc8d484 JG |
182 | bfd_default_set_arch_mach(abfd, |
183 | HOST_MACHINE_ARCH, | |
c4cd3fc6 | 184 | #ifdef HOST_MACHINE_MACHINE |
bbc8d484 JG |
185 | HOST_MACHINE_MACHINE |
186 | #else /* not HOST_MACHINE_MACHINE */ | |
187 | 0 | |
188 | #endif /* not HOST_MACHINE_MACHINE */ | |
189 | ); | |
190 | #endif /* HOST_MACHINE_ARCH */ | |
c4cd3fc6 | 191 | |
fb3be09b | 192 | obj_reloc_entry_size (abfd) = sizeof (struct relocation_info); |
c4cd3fc6 JG |
193 | return abfd->xvec; |
194 | } | |
195 | ||
196 | ||
197 | boolean | |
fb3be09b JG |
198 | DEFUN(NAME(host_aout,mkobject), (abfd), |
199 | bfd *abfd) | |
c4cd3fc6 | 200 | { |
fb3be09b JG |
201 | /* This struct is just for allocating two things with one zalloc, so |
202 | they will be freed together, without violating alignment constraints. */ | |
203 | struct aout_exec { | |
204 | struct aoutdata aoutdata; | |
205 | struct exec exec; | |
206 | } *rawptr; | |
c4cd3fc6 JG |
207 | |
208 | bfd_error = system_call_error; | |
209 | ||
210 | /* Use an intermediate variable for clarity */ | |
fb3be09b | 211 | rawptr = (struct aout_exec *)bfd_zalloc (abfd, sizeof (struct aout_exec)); |
c4cd3fc6 JG |
212 | |
213 | if (rawptr == NULL) { | |
214 | bfd_error = no_memory; | |
215 | return false; | |
216 | } | |
217 | ||
fb3be09b JG |
218 | set_tdata (abfd, &rawptr->aoutdata); |
219 | /* exec_hdr (abfd), a "struct internal_exec *", is just an abstraction, | |
220 | as far as the BFD a.out layer cares. We use it as a "struct exec *". */ | |
221 | exec_hdr (abfd) = (struct internal_exec *) &rawptr->exec; | |
c4cd3fc6 JG |
222 | |
223 | /* For simplicity's sake we just make all the sections right here. */ | |
224 | ||
225 | obj_textsec (abfd) = (asection *)NULL; | |
226 | obj_datasec (abfd) = (asection *)NULL; | |
227 | obj_bsssec (abfd) = (asection *)NULL; | |
228 | bfd_make_section (abfd, ".text"); | |
229 | bfd_make_section (abfd, ".data"); | |
230 | bfd_make_section (abfd, ".bss"); | |
231 | ||
232 | return true; | |
233 | } | |
234 | ||
235 | /* Write an object file in host a.out format. | |
236 | Section contents have already been written. We write the | |
237 | file header, symbols, and relocation. */ | |
238 | ||
239 | boolean | |
fb3be09b JG |
240 | DEFUN(NAME(host_aout,write_object_contents), (abfd), |
241 | bfd *abfd) | |
c4cd3fc6 JG |
242 | { |
243 | /* This works because we are on the host system */ | |
fb3be09b | 244 | #define EXEC_BYTES_SIZE (sizeof (struct exec)) |
bbc8d484 | 245 | #define EXTERNAL_NLIST_SIZE (sizeof (struct nlist)) |
c4cd3fc6 JG |
246 | size_t data_pad = 0; |
247 | unsigned char exec_bytes[EXEC_BYTES_SIZE]; | |
fb3be09b | 248 | struct exec *execp = (struct exec *)exec_hdr (abfd); |
c4cd3fc6 JG |
249 | |
250 | execp->a_text = obj_textsec (abfd)->size; | |
251 | ||
fb3be09b JG |
252 | WRITE_HEADERS (abfd, execp); |
253 | return true; | |
254 | } | |
255 | \f | |
256 | /* We use BFD generic archive files. */ | |
257 | #define aout_32_openr_next_archived_file bfd_generic_openr_next_archived_file | |
258 | #define aout_32_generic_stat_arch_elt bfd_generic_stat_arch_elt | |
9e2dad8e | 259 | #define aout_32_slurp_armap bfd_false |
fb3be09b | 260 | #define aout_32_slurp_extended_name_table bfd_true |
9e2dad8e JG |
261 | #define aout_32_write_armap (PROTO (boolean, (*), \ |
262 | (bfd *arch, unsigned int elength, struct orl *map, int orl_count, \ | |
263 | int stridx))) bfd_false | |
264 | #define aout_32_truncate_arname bfd_dont_truncate_arname | |
c4cd3fc6 | 265 | |
9e2dad8e JG |
266 | /* No core file defined here -- configure in trad-core.c separately. */ |
267 | #define aout_32_core_file_failing_command bfd_false | |
268 | #define aout_32_core_file_failing_signal bfd_false | |
269 | #define aout_32_core_file_matches_executable_p bfd_true | |
270 | #define some_kinda_core_file_p bfd_false | |
c4cd3fc6 | 271 | |
fb3be09b JG |
272 | #define aout_32_bfd_debug_info_start bfd_void |
273 | #define aout_32_bfd_debug_info_end bfd_void | |
274 | #define aout_32_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void | |
c4cd3fc6 | 275 | |
9e2dad8e JG |
276 | #define aout_64_openr_next_archived_file aout_32_openr_next_archived_file |
277 | #define aout_64_generic_stat_arch_elt aout_32_generic_stat_arch_elt | |
278 | #define aout_64_slurp_armap aout_32_slurp_armap | |
279 | #define aout_64_slurp_extended_name_table aout_32_slurp_extended_name_table | |
280 | #define aout_64_write_armap aout_32_write_armap | |
281 | #define aout_64_truncate_arname aout_32_truncate_arname | |
282 | ||
283 | #define aout_64_core_file_failing_command aout_32_core_file_failing_command | |
284 | #define aout_64_core_file_failing_signal aout_32_core_file_failing_signal | |
285 | #define aout_64_core_file_matches_executable_p aout_32_core_file_matches_executable_p | |
286 | ||
287 | #define aout_64_bfd_debug_info_start aout_32_bfd_debug_info_start | |
288 | #define aout_64_bfd_debug_info_end aout_32_bfd_debug_info_end | |
289 | #define aout_64_bfd_debug_info_accumulate aout_32_bfd_debug_info_accumulate | |
290 | ||
c4cd3fc6 | 291 | |
fb3be09b JG |
292 | /* We implement these routines ourselves, rather than using the generic |
293 | a.out versions. */ | |
294 | #define aout_write_object_contents host_write_object_contents | |
c4cd3fc6 JG |
295 | |
296 | bfd_target host_aout_big_vec = | |
fb3be09b JG |
297 | { |
298 | "a.out-host-big", | |
9e2dad8e | 299 | bfd_target_aout_flavour, |
fb3be09b JG |
300 | true, /* target byte order */ |
301 | true, /* target headers byte order */ | |
302 | (HAS_RELOC | EXEC_P | /* object flags */ | |
303 | HAS_LINENO | HAS_DEBUG | | |
304 | HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), | |
305 | (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ | |
306 | ' ', /* ar_pad_char */ | |
307 | 16, /* ar_max_namelen */ | |
308 | 3, /* minimum alignment power */ | |
309 | _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */ | |
310 | _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */ | |
311 | ||
312 | {_bfd_dummy_target, NAME(host_aout,object_p), | |
9e2dad8e | 313 | bfd_generic_archive_p, some_kinda_core_file_p}, |
fb3be09b | 314 | {bfd_false, NAME(host_aout,mkobject), |
c4cd3fc6 | 315 | _bfd_generic_mkarchive, bfd_false}, |
fb3be09b | 316 | {bfd_false, NAME(host_aout,write_object_contents), /* bfd_write_contents */ |
c4cd3fc6 | 317 | _bfd_write_archive_contents, bfd_false}, |
fb3be09b JG |
318 | |
319 | JUMP_TABLE(JNAME(aout)) | |
c4cd3fc6 JG |
320 | }; |
321 | ||
322 | bfd_target host_aout_little_vec = | |
fb3be09b JG |
323 | { |
324 | "a.out-host-little", | |
9e2dad8e | 325 | bfd_target_aout_flavour, |
fb3be09b JG |
326 | false, /* target byte order */ |
327 | false, /* target headers byte order */ | |
328 | (HAS_RELOC | EXEC_P | /* object flags */ | |
329 | HAS_LINENO | HAS_DEBUG | | |
330 | HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), | |
331 | (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ | |
332 | ' ', /* ar_pad_char */ | |
333 | 16, /* ar_max_namelen */ | |
334 | 3, /* minimum alignment power */ | |
9e2dad8e JG |
335 | _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putb16, /* data */ |
336 | _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* hdrs */ | |
fb3be09b JG |
337 | |
338 | {_bfd_dummy_target, NAME(host_aout,object_p), | |
9e2dad8e | 339 | bfd_generic_archive_p, some_kinda_core_file_p}, |
fb3be09b | 340 | {bfd_false, NAME(host_aout,mkobject), |
c4cd3fc6 | 341 | _bfd_generic_mkarchive, bfd_false}, |
fb3be09b | 342 | {bfd_false, NAME(host_aout,write_object_contents), /* bfd_write_contents */ |
c4cd3fc6 | 343 | _bfd_write_archive_contents, bfd_false}, |
fb3be09b JG |
344 | |
345 | JUMP_TABLE(JNAME(aout)) | |
c4cd3fc6 | 346 | }; |