]>
Commit | Line | Data |
---|---|---|
9783e04a | 1 | /* IBM RS/6000 "XCOFF" back-end for BFD. |
138b9b81 | 2 | Copyright (C) 1990, 1991, 1995 Free Software Foundation, Inc. |
9783e04a DM |
3 | FIXME: Can someone provide a transliteration of this name into ASCII? |
4 | Using the following chars caused a compiler warning on HIUX (so I replaced | |
5 | them with octal escapes), and isn't useful without an understanding of what | |
6 | character set it is. | |
7 | Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365, | |
8 | and John Gilmore. | |
9 | Archive support from Damon A. Permezel. | |
10 | Contributed by IBM Corporation and Cygnus Support. | |
11 | ||
12 | This file is part of BFD, the Binary File Descriptor library. | |
13 | ||
14 | This program is free software; you can redistribute it and/or modify | |
15 | it under the terms of the GNU General Public License as published by | |
16 | the Free Software Foundation; either version 2 of the License, or | |
17 | (at your option) any later version. | |
18 | ||
19 | This program is distributed in the hope that it will be useful, | |
20 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
22 | GNU General Public License for more details. | |
23 | ||
24 | You should have received a copy of the GNU General Public License | |
25 | along with this program; if not, write to the Free Software | |
138b9b81 | 26 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
9783e04a DM |
27 | |
28 | /* This port currently only handles reading object files, except when | |
29 | compiled on an RS/6000 host. -- no archive support, no core files. | |
30 | In all cases, it does not support writing. | |
31 | ||
32 | FIXMEmgo comments are left from Metin Ozisik's original port. | |
33 | ||
34 | This is in a separate file from coff-rs6000.c, because it includes | |
35 | system include files that conflict with coff/rs6000.h. | |
36 | */ | |
37 | ||
38 | /* Internalcoff.h and coffcode.h modify themselves based on this flag. */ | |
39 | #define RS6000COFF_C 1 | |
40 | ||
41 | #include "bfd.h" | |
42 | #include "sysdep.h" | |
43 | #include "libbfd.h" | |
44 | ||
138b9b81 | 45 | #ifdef AIX_CORE |
9783e04a DM |
46 | |
47 | /* AOUTHDR is defined by the above. We need another defn of it, from the | |
48 | system include files. Punt the old one and get us a new name for the | |
49 | typedef in the system include files. */ | |
50 | #ifdef AOUTHDR | |
51 | #undef AOUTHDR | |
52 | #endif | |
53 | #define AOUTHDR second_AOUTHDR | |
54 | ||
55 | #undef SCNHDR | |
56 | ||
57 | ||
58 | /* ------------------------------------------------------------------------ */ | |
59 | /* Support for core file stuff.. */ | |
60 | /* ------------------------------------------------------------------------ */ | |
61 | ||
62 | #include <sys/user.h> | |
63 | #include <sys/ldr.h> | |
64 | #include <sys/core.h> | |
65 | ||
66 | ||
67 | /* Number of special purpose registers supported by gdb. This value | |
68 | should match `tm.h' in gdb directory. Clean this mess up and use | |
69 | the macros in sys/reg.h. FIXMEmgo. */ | |
70 | ||
71 | #define NUM_OF_SPEC_REGS 7 | |
9783e04a DM |
72 | |
73 | #define core_hdr(bfd) (((Rs6kCorData*)(bfd->tdata.any))->hdr) | |
74 | #define core_datasec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->data_section) | |
75 | #define core_stacksec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->stack_section) | |
76 | #define core_regsec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->reg_section) | |
77 | #define core_reg2sec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->reg2_section) | |
78 | ||
138b9b81 PS |
79 | /* AIX 4.1 Changed the names and locations of a few items in the core file, |
80 | this seems to be the quickest easiet way to deal with it. | |
81 | ||
82 | Note however that encoding magic addresses (STACK_END_ADDR) is going | |
83 | to be _very_ fragile. But I don't see any easy way to get that info | |
84 | right now. */ | |
85 | #ifdef ALTERNATE_AIX_CORE_FORMAT | |
86 | #define CORE_DATA_SIZE_FIELD c_u.U_dsize | |
87 | #define CORE_COMM_FIELD c_u.U_comm | |
88 | #define SAVE_FIELD c_mst | |
89 | #define STACK_END_ADDR 0x2ff23000 | |
90 | #else | |
91 | #define CORE_DATA_SIZE_FIELD c_u.u_dsize | |
92 | #define CORE_COMM_FIELD c_u.u_comm | |
93 | #define SAVE_FIELD c_u.u_save | |
94 | #define STACK_END_ADDR 0x2ff80000 | |
95 | #endif | |
96 | ||
9783e04a DM |
97 | /* These are stored in the bfd's tdata */ |
98 | typedef struct { | |
138b9b81 | 99 | struct core_dump hdr; /* core file header */ |
9783e04a DM |
100 | asection *data_section, |
101 | *stack_section, | |
102 | *reg_section, /* section for GPRs and special registers. */ | |
103 | *reg2_section; /* section for FPRs. */ | |
104 | ||
105 | /* This tells us where everything is mapped (shared libraries and so on). | |
106 | GDB needs it. */ | |
107 | asection *ldinfo_section; | |
108 | #define core_ldinfosec(bfd) (((Rs6kCorData *)(bfd->tdata.any))->ldinfo_section) | |
109 | } Rs6kCorData; | |
110 | ||
111 | ||
112 | /* Decide if a given bfd represents a `core' file or not. There really is no | |
113 | magic number or anything like, in rs6000coff. */ | |
114 | ||
138b9b81 | 115 | const bfd_target * |
9783e04a DM |
116 | rs6000coff_core_p (abfd) |
117 | bfd *abfd; | |
118 | { | |
119 | int fd; | |
120 | struct core_dump coredata; | |
121 | struct stat statbuf; | |
122 | char *tmpptr; | |
123 | ||
124 | /* Use bfd_xxx routines, rather than O/S primitives to read coredata. FIXMEmgo */ | |
125 | fd = open (abfd->filename, O_RDONLY); | |
126 | if (fd < 0) | |
127 | { | |
138b9b81 | 128 | bfd_set_error (bfd_error_system_call); |
9783e04a DM |
129 | return NULL; |
130 | } | |
131 | ||
132 | if (fstat (fd, &statbuf) < 0) | |
133 | { | |
138b9b81 | 134 | bfd_set_error (bfd_error_system_call); |
9783e04a DM |
135 | close (fd); |
136 | return NULL; | |
137 | } | |
138 | if (read (fd, &coredata, sizeof (struct core_dump)) | |
139 | != sizeof (struct core_dump)) | |
140 | { | |
138b9b81 | 141 | bfd_set_error (bfd_error_wrong_format); |
9783e04a DM |
142 | close (fd); |
143 | return NULL; | |
144 | } | |
145 | ||
146 | if (close (fd) < 0) | |
147 | { | |
138b9b81 | 148 | bfd_set_error (bfd_error_system_call); |
9783e04a DM |
149 | return NULL; |
150 | } | |
151 | ||
152 | /* If the core file ulimit is too small, the system will first | |
153 | omit the data segment, then omit the stack, then decline to | |
154 | dump core altogether (as far as I know UBLOCK_VALID and LE_VALID | |
155 | are always set) (this is based on experimentation on AIX 3.2). | |
156 | Now, the thing is that GDB users will be surprised | |
157 | if segments just silently don't appear (well, maybe they would | |
158 | think to check "info files", I don't know), but we have no way of | |
159 | returning warnings (as opposed to errors). | |
160 | ||
161 | For the data segment, we have no choice but to keep going if it's | |
162 | not there, since the default behavior is not to dump it (regardless | |
163 | of the ulimit, it's based on SA_FULLDUMP). But for the stack segment, | |
164 | if it's not there, we refuse to have anything to do with this core | |
165 | file. The usefulness of a core dump without a stack segment is pretty | |
166 | limited anyway. */ | |
167 | ||
168 | if (!(coredata.c_flag & UBLOCK_VALID) | |
169 | || !(coredata.c_flag & LE_VALID)) | |
170 | { | |
138b9b81 | 171 | bfd_set_error (bfd_error_wrong_format); |
9783e04a DM |
172 | return NULL; |
173 | } | |
174 | ||
175 | if ((coredata.c_flag & CORE_TRUNC) | |
176 | || !(coredata.c_flag & USTACK_VALID)) | |
177 | { | |
138b9b81 | 178 | bfd_set_error (bfd_error_file_truncated); |
9783e04a DM |
179 | return NULL; |
180 | } | |
181 | ||
138b9b81 PS |
182 | /* Don't check the core file size for a full core, AIX 4.1 includes |
183 | additional shared library sections in a full core. */ | |
184 | if (!(coredata.c_flag & FULL_CORE) | |
185 | && ((bfd_vma)coredata.c_stack + coredata.c_size) != statbuf.st_size) | |
9783e04a DM |
186 | { |
187 | /* If the size is wrong, it means we're misinterpreting something. */ | |
138b9b81 | 188 | bfd_set_error (bfd_error_wrong_format); |
9783e04a DM |
189 | return NULL; |
190 | } | |
191 | ||
192 | /* Sanity check on the c_tab field. */ | |
193 | if ((u_long) coredata.c_tab < sizeof coredata || | |
194 | (u_long) coredata.c_tab >= statbuf.st_size || | |
195 | (long) coredata.c_tab >= (long)coredata.c_stack) | |
196 | { | |
138b9b81 | 197 | bfd_set_error (bfd_error_wrong_format); |
9783e04a DM |
198 | return NULL; |
199 | } | |
200 | ||
201 | /* maybe you should alloc space for the whole core chunk over here!! FIXMEmgo */ | |
202 | tmpptr = (char*)bfd_zalloc (abfd, sizeof (Rs6kCorData)); | |
203 | if (!tmpptr) | |
204 | { | |
138b9b81 | 205 | bfd_set_error (bfd_error_no_memory); |
9783e04a DM |
206 | return NULL; |
207 | } | |
208 | ||
209 | set_tdata (abfd, tmpptr); | |
210 | ||
138b9b81 PS |
211 | /* Copy core file header. */ |
212 | core_hdr (abfd) = coredata; | |
213 | ||
9783e04a DM |
214 | /* .stack section. */ |
215 | if ((core_stacksec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection))) | |
216 | == NULL) { | |
138b9b81 | 217 | bfd_set_error (bfd_error_no_memory); |
9783e04a DM |
218 | /* bfd_release (abfd, ???? ) */ |
219 | return NULL; | |
220 | } | |
221 | core_stacksec (abfd)->name = ".stack"; | |
138b9b81 | 222 | core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; |
9783e04a DM |
223 | core_stacksec (abfd)->_raw_size = coredata.c_size; |
224 | core_stacksec (abfd)->vma = STACK_END_ADDR - coredata.c_size; | |
225 | core_stacksec (abfd)->filepos = (int)coredata.c_stack; /*???? */ | |
226 | ||
227 | /* .reg section for GPRs and special registers. */ | |
228 | if ((core_regsec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection))) | |
229 | == NULL) { | |
138b9b81 | 230 | bfd_set_error (bfd_error_no_memory); |
9783e04a DM |
231 | /* bfd_release (abfd, ???? ) */ |
232 | return NULL; | |
233 | } | |
234 | core_regsec (abfd)->name = ".reg"; | |
138b9b81 | 235 | core_regsec (abfd)->flags = SEC_HAS_CONTENTS; |
9783e04a DM |
236 | core_regsec (abfd)->_raw_size = (32 + NUM_OF_SPEC_REGS) * 4; |
237 | core_regsec (abfd)->vma = 0; /* not used?? */ | |
238 | core_regsec (abfd)->filepos = | |
138b9b81 | 239 | (char*)&coredata.SAVE_FIELD - (char*)&coredata; |
9783e04a DM |
240 | |
241 | /* .reg2 section for FPRs (floating point registers). */ | |
242 | if ((core_reg2sec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection))) | |
243 | == NULL) { | |
138b9b81 | 244 | bfd_set_error (bfd_error_no_memory); |
9783e04a DM |
245 | /* bfd_release (abfd, ???? ) */ |
246 | return NULL; | |
247 | } | |
248 | core_reg2sec (abfd)->name = ".reg2"; | |
138b9b81 | 249 | core_reg2sec (abfd)->flags = SEC_HAS_CONTENTS; |
9783e04a DM |
250 | core_reg2sec (abfd)->_raw_size = 8 * 32; /* 32 FPRs. */ |
251 | core_reg2sec (abfd)->vma = 0; /* not used?? */ | |
252 | core_reg2sec (abfd)->filepos = | |
138b9b81 | 253 | (char*)&coredata.SAVE_FIELD.fpr[0] - (char*)&coredata; |
9783e04a DM |
254 | |
255 | if ((core_ldinfosec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection))) | |
256 | == NULL) { | |
138b9b81 | 257 | bfd_set_error (bfd_error_no_memory); |
9783e04a DM |
258 | /* bfd_release (abfd, ???? ) */ |
259 | return NULL; | |
260 | } | |
261 | core_ldinfosec (abfd)->name = ".ldinfo"; | |
138b9b81 | 262 | core_ldinfosec (abfd)->flags = SEC_HAS_CONTENTS; |
9783e04a DM |
263 | /* To actually find out how long this section is in this particular |
264 | core dump would require going down the whole list of struct ld_info's. | |
265 | See if we can just fake it. */ | |
266 | core_ldinfosec (abfd)->_raw_size = 0x7fffffff; | |
267 | /* Not relevant for ldinfo section. */ | |
268 | core_ldinfosec (abfd)->vma = 0; | |
138b9b81 | 269 | core_ldinfosec (abfd)->filepos = (file_ptr) coredata.c_tab; |
9783e04a DM |
270 | |
271 | /* set up section chain here. */ | |
272 | abfd->section_count = 4; | |
273 | abfd->sections = core_stacksec (abfd); | |
274 | core_stacksec (abfd)->next = core_regsec(abfd); | |
275 | core_regsec (abfd)->next = core_reg2sec (abfd); | |
276 | core_reg2sec (abfd)->next = core_ldinfosec (abfd); | |
277 | core_ldinfosec (abfd)->next = NULL; | |
278 | ||
279 | if (coredata.c_flag & FULL_CORE) | |
280 | { | |
281 | asection *sec = (asection *) bfd_zalloc (abfd, sizeof (asection)); | |
282 | if (sec == NULL) | |
283 | { | |
138b9b81 | 284 | bfd_set_error (bfd_error_no_memory); |
9783e04a DM |
285 | return NULL; |
286 | } | |
287 | sec->name = ".data"; | |
288 | sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; | |
138b9b81 PS |
289 | sec->_raw_size = coredata.CORE_DATA_SIZE_FIELD; |
290 | sec->vma = CDATA_ADDR (coredata.CORE_DATA_SIZE_FIELD); | |
9783e04a DM |
291 | sec->filepos = (int)coredata.c_stack + coredata.c_size; |
292 | ||
293 | sec->next = abfd->sections; | |
294 | abfd->sections = sec; | |
295 | ++abfd->section_count; | |
296 | } | |
297 | ||
298 | return abfd->xvec; /* this is garbage for now. */ | |
299 | } | |
300 | ||
301 | ||
302 | ||
303 | /* return `true' if given core is from the given executable.. */ | |
304 | boolean | |
305 | rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd) | |
306 | bfd *core_bfd; | |
307 | bfd *exec_bfd; | |
308 | { | |
309 | FILE *fd; | |
310 | struct core_dump coredata; | |
311 | struct ld_info ldinfo; | |
312 | char pathname [1024]; | |
138b9b81 | 313 | const char *str1, *str2; |
9783e04a DM |
314 | |
315 | /* Use bfd_xxx routines, rather than O/S primitives, do error checking!! | |
316 | FIXMEmgo */ | |
317 | /* Actually should be able to use bfd_get_section_contents now that | |
318 | we have a .ldinfo section. */ | |
319 | fd = fopen (core_bfd->filename, FOPEN_RB); | |
320 | ||
321 | fread (&coredata, sizeof (struct core_dump), 1, fd); | |
322 | fseek (fd, (long)coredata.c_tab, 0); | |
323 | fread (&ldinfo, (char*)&ldinfo.ldinfo_filename[0] - (char*)&ldinfo.ldinfo_next, | |
324 | 1, fd); | |
325 | fscanf (fd, "%s", pathname); | |
326 | ||
327 | str1 = strrchr (pathname, '/'); | |
328 | str2 = strrchr (exec_bfd->filename, '/'); | |
329 | ||
330 | /* step over character '/' */ | |
331 | str1 = str1 ? str1+1 : &pathname[0]; | |
332 | str2 = str2 ? str2+1 : exec_bfd->filename; | |
333 | ||
334 | fclose (fd); | |
335 | return strcmp (str1, str2) == 0; | |
336 | } | |
337 | ||
138b9b81 PS |
338 | char * |
339 | rs6000coff_core_file_failing_command (abfd) | |
340 | bfd *abfd; | |
341 | { | |
342 | char *com = core_hdr (abfd).CORE_COMM_FIELD; | |
343 | if (*com) | |
344 | return com; | |
345 | else | |
346 | return 0; | |
347 | } | |
348 | ||
349 | int | |
350 | rs6000coff_core_file_failing_signal (abfd) | |
351 | bfd *abfd; | |
352 | { | |
353 | return core_hdr (abfd).c_signo; | |
354 | } | |
355 | ||
9783e04a DM |
356 | |
357 | boolean | |
358 | rs6000coff_get_section_contents (abfd, section, location, offset, count) | |
359 | bfd *abfd; | |
360 | sec_ptr section; | |
361 | PTR location; | |
362 | file_ptr offset; | |
363 | int count; | |
364 | { | |
365 | if (count == 0) | |
366 | return true; | |
367 | ||
368 | /* Reading a core file's sections will be slightly different. For the | |
369 | rest of them we can use bfd_generic_get_section_contents () I suppose. */ | |
370 | /* Make sure this routine works for any bfd and any section. FIXMEmgo. */ | |
371 | ||
372 | if (abfd->format == bfd_core && strcmp (section->name, ".reg") == 0) { | |
373 | ||
374 | struct mstsave mstatus; | |
375 | int regoffset = (char*)&mstatus.gpr[0] - (char*)&mstatus; | |
376 | ||
377 | /* Assert that the only way this code will be executed is reading the | |
378 | whole section. */ | |
379 | if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS))) | |
380 | fprintf (stderr, "ERROR! in rs6000coff_get_section_contents()\n"); | |
381 | ||
382 | /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure | |
383 | in the core file. */ | |
384 | ||
385 | /* read GPR's into the location. */ | |
386 | if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1 | |
387 | || bfd_read(location, sizeof (mstatus.gpr), 1, abfd) != sizeof (mstatus.gpr)) | |
388 | return (false); /* on error */ | |
389 | ||
390 | /* increment location to the beginning of special registers in the section, | |
391 | reset register offset value to the beginning of first special register | |
392 | in mstsave structure, and read special registers. */ | |
393 | ||
394 | location = (PTR) ((char*)location + sizeof (mstatus.gpr)); | |
395 | regoffset = (char*)&mstatus.iar - (char*)&mstatus; | |
396 | ||
397 | if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1 | |
398 | || bfd_read(location, 4 * NUM_OF_SPEC_REGS, 1, abfd) != | |
399 | 4 * NUM_OF_SPEC_REGS) | |
400 | return (false); /* on error */ | |
401 | ||
402 | /* increment location address, and read the special registers.. */ | |
403 | /* FIXMEmgo */ | |
404 | return (true); | |
405 | } | |
406 | ||
407 | /* else, use default bfd section content transfer. */ | |
408 | else | |
138b9b81 | 409 | return _bfd_generic_get_section_contents |
9783e04a DM |
410 | (abfd, section, location, offset, count); |
411 | } | |
412 | ||
138b9b81 | 413 | #endif /* AIX_CORE */ |