Fix building for MS1 and M32C.
[deliverable/binutils-gdb.git] / bfd / aix5ppc-core.c
CommitLineData
eb1e0e80 1/* IBM RS/6000 "XCOFF" back-end for BFD.
9553c638 2 Copyright 2001, 2002, 2003, 2004
eb1e0e80
NC
3 Free Software Foundation, Inc.
4 Written by Tom Rix
e729279b 5 Contributed by Red Hat Inc.
eb1e0e80
NC
6
7 This file is part of BFD, the Binary File Descriptor library.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
3e110533 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
53e09e0a 22 MA 02110-1301, USA. */
eb1e0e80
NC
23
24#include "bfd.h"
25
26#ifdef AIX_5_CORE
27
28#include "sysdep.h"
29#include "libbfd.h"
30
e729279b
NC
31const bfd_target *xcoff64_core_p (bfd *);
32bfd_boolean xcoff64_core_file_matches_executable_p (bfd *, bfd *);
33char *xcoff64_core_file_failing_command (bfd *);
34int xcoff64_core_file_failing_signal (bfd *);
eb1e0e80
NC
35
36/* Aix 5.1 system include file. */
37
38/* Need to define this macro so struct ld_info64 get included. */
39#define __LDINFO_PTRACE64__
40#include <sys/ldr.h>
41#include <core.h>
42
43#define core_hdr(abfd) ((struct core_dumpxx *) abfd->tdata.any)
44
45#define CHECK_FILE_OFFSET(s, v) \
46 ((bfd_signed_vma)(v) < 0 || (bfd_signed_vma)(v) > (bfd_signed_vma)(s).st_size)
47
48const bfd_target *
e729279b 49xcoff64_core_p (bfd *abfd)
eb1e0e80
NC
50{
51 struct core_dumpxx core, *new_core_hdr;
52 struct stat statbuf;
53 asection *sec;
54 struct __ld_info64 ldinfo;
55 bfd_vma ld_offset;
56 bfd_size_type i;
57 struct vm_infox vminfo;
58 bfd_target *return_value = NULL;
59
60 /* Get the header. */
61 if (bfd_seek (abfd, 0, SEEK_SET) != 0)
62 goto xcoff64_core_p_error;
63
b34976b6 64 if (sizeof (struct core_dumpxx)
d1e66cd4 65 != bfd_bread (&core, sizeof (struct core_dumpxx), abfd))
eb1e0e80
NC
66 goto xcoff64_core_p_error;
67
b34976b6 68 if (bfd_stat (abfd, &statbuf) < 0)
eb1e0e80
NC
69 goto xcoff64_core_p_error;
70
71 /* Sanity checks
72 c_flag has CORE_VERSION_1, Aix 4+
73 c_entries = 0 for Aix 4.3+
74 IS_PROC64 is a macro defined in procinfo.h, test for 64 bit process.
75
76 We will still be confused if a Aix 4.3 64 bit core file is
77 copied over to a Aix 5 machine.
78
79 Check file header offsets
80
81 See rs6000-core.c for comment on size of core
82 If there isn't enough of a real core file, bail. */
83
b34976b6
AM
84 if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1))
85 || (0 != core.c_entries)
86 || (! (IS_PROC64 (&core.c_u.U_proc)))
87 || ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox)))
88 || ((CHECK_FILE_OFFSET (statbuf, core.c_loader)))
89 || ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize)))
90 || ((CHECK_FILE_OFFSET (statbuf, core.c_thr)))
91 || ((CHECK_FILE_OFFSET (statbuf, core.c_segregion)))
92 || ((CHECK_FILE_OFFSET (statbuf, core.c_stack)))
93 || ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size)))
94 || ((CHECK_FILE_OFFSET (statbuf, core.c_data)))
95 || ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize)))
96 || (! (core.c_flag & UBLOCK_VALID))
97 || (! (core.c_flag & LE_VALID)))
eb1e0e80
NC
98 goto xcoff64_core_p_error;
99
5c4491d3 100 /* Check for truncated stack or general truncating. */
b34976b6 101 if ((! (core.c_flag & USTACK_VALID))
eb1e0e80
NC
102 || (core.c_flag & CORE_TRUNC))
103 {
104 bfd_set_error (bfd_error_file_truncated);
105
106 return return_value;
107 }
108
e729279b 109 new_core_hdr = bfd_zalloc (abfd, sizeof (struct core_dumpxx));
b34976b6 110 if (NULL == new_core_hdr)
eb1e0e80
NC
111 return return_value;
112
113 memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx));
114 core_hdr(abfd) = (char *)new_core_hdr;
115
116 /* .stack section. */
117 sec = bfd_make_section_anyway (abfd, ".stack");
b34976b6 118 if (NULL == sec)
eb1e0e80
NC
119 return return_value;
120
121 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
eea6121a 122 sec->size = core.c_size;
eb1e0e80
NC
123 sec->vma = core.c_stackorg;
124 sec->filepos = core.c_stack;
125
126 /* .reg section for all registers. */
127 sec = bfd_make_section_anyway (abfd, ".reg");
b34976b6 128 if (NULL == sec)
eb1e0e80
NC
129 return return_value;
130
131 sec->flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
eea6121a 132 sec->size = sizeof (struct __context64);
eb1e0e80
NC
133 sec->vma = 0;
134 sec->filepos = 0;
135 sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64;
136
137 /* .ldinfo section.
138 To actually find out how long this section is in this particular
b34976b6 139 core dump would require going down the whole list of struct
eb1e0e80
NC
140 ld_info's. See if we can just fake it. */
141 sec = bfd_make_section_anyway (abfd, ".ldinfo");
142 if (NULL == sec)
143 return return_value;
144
145 sec->flags = SEC_HAS_CONTENTS;
eea6121a 146 sec->size = core.c_lsize;
eb1e0e80
NC
147 sec->vma = 0;
148 sec->filepos = core.c_loader;
149
150 /* AIX 4 adds data sections from loaded objects to the core file,
151 which can be found by examining ldinfo, and anonymously mmapped
152 regions. */
b34976b6 153
eb1e0e80
NC
154 /* .data section from executable. */
155 sec = bfd_make_section_anyway (abfd, ".data");
b34976b6 156 if (NULL == sec)
eb1e0e80
NC
157 return return_value;
158
159 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
eea6121a 160 sec->size = core.c_datasize;
eb1e0e80
NC
161 sec->vma = core.c_dataorg;
162 sec->filepos = core.c_data;
163
164 /* .data sections from loaded objects. */
165 ld_offset = core.c_loader;
b34976b6
AM
166
167 while (1)
eb1e0e80 168 {
b34976b6 169 if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0)
eb1e0e80
NC
170 return return_value;
171
172 if (sizeof (struct __ld_info64) !=
b34976b6 173 bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd))
eb1e0e80
NC
174 return return_value;
175
b34976b6 176 if (ldinfo.ldinfo_core)
eb1e0e80
NC
177 {
178 sec = bfd_make_section_anyway (abfd, ".data");
b34976b6 179 if (NULL == sec)
eb1e0e80
NC
180 return return_value;
181
182 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
eea6121a 183 sec->size = ldinfo.ldinfo_datasize;
eb1e0e80
NC
184 sec->vma = ldinfo.ldinfo_dataorg;
185 sec->filepos = ldinfo.ldinfo_core;
186 }
187
188 if (0 == ldinfo.ldinfo_next)
189 break;
190 ld_offset += ldinfo.ldinfo_next;
191 }
192
193 /* .vmdata sections from anonymously mmapped regions. */
b34976b6 194 if (core.c_vmregions)
eb1e0e80 195 {
b34976b6 196 if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0)
eb1e0e80
NC
197 return return_value;
198
b34976b6 199 for (i = 0; i < core.c_vmregions; i++)
eb1e0e80 200 if (sizeof (struct vm_infox) !=
b34976b6 201 bfd_bread (&vminfo, sizeof (struct vm_infox), abfd))
eb1e0e80
NC
202 return return_value;
203
b34976b6 204 if (vminfo.vminfo_offset)
eb1e0e80
NC
205 {
206 sec = bfd_make_section_anyway (abfd, ".vmdata");
b34976b6 207 if (NULL == sec)
eb1e0e80
NC
208 return return_value;
209
210 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
eea6121a 211 sec->size = vminfo.vminfo_size;
eb1e0e80
NC
212 sec->vma = vminfo.vminfo_addr;
213 sec->filepos = vminfo.vminfo_offset;
214 }
215 }
216
7cefacd3 217 return_value = (bfd_target *) abfd->xvec; /* This is garbage for now. */
b34976b6 218
eb1e0e80 219 xcoff64_core_p_error:
b34976b6 220 if (bfd_get_error () != bfd_error_system_call)
eb1e0e80 221 bfd_set_error (bfd_error_wrong_format);
b34976b6 222
eb1e0e80
NC
223 return return_value;
224}
225
b34976b6 226/* Return `TRUE' if given core is from the given executable. */
eb1e0e80 227
b34976b6 228bfd_boolean
e729279b 229xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
eb1e0e80
NC
230{
231 struct core_dumpxx core;
232 char *path, *s;
233 size_t alloc;
234 const char *str1, *str2;
b34976b6 235 bfd_boolean return_value = FALSE;
eb1e0e80
NC
236
237 /* Get the header. */
b34976b6 238 if (bfd_seek (core_bfd, 0, SEEK_SET) != 0)
eb1e0e80 239 return return_value;
b34976b6 240
eb1e0e80 241 if (sizeof (struct core_dumpxx) !=
b34976b6 242 bfd_bread (&core, sizeof (struct core_dumpxx), core_bfd))
eb1e0e80
NC
243 return return_value;
244
b34976b6 245 if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0)
eb1e0e80
NC
246 return return_value;
247
248 alloc = 100;
249 path = bfd_malloc (alloc);
b34976b6 250 if (path == NULL)
eb1e0e80
NC
251 return return_value;
252
253 s = path;
254
255 while (1)
256 {
d1e66cd4 257 if (bfd_bread (s, 1, core_bfd) != 1)
eb1e0e80
NC
258 goto xcoff64_core_file_matches_executable_p_end_1;
259
260 if (*s == '\0')
261 break;
262 ++s;
b34976b6 263 if (s == path + alloc)
eb1e0e80
NC
264 {
265 char *n;
266
267 alloc *= 2;
268 n = bfd_realloc (path, alloc);
b34976b6 269 if (n == NULL)
eb1e0e80
NC
270 goto xcoff64_core_file_matches_executable_p_end_1;
271
272 s = n + (path - s);
273 path = n;
274 }
275 }
276
277 str1 = strrchr (path, '/');
278 str2 = strrchr (exec_bfd->filename, '/');
279
280 /* Step over character '/'. */
281 str1 = str1 != NULL ? str1 + 1 : path;
282 str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
283
b34976b6
AM
284 if (strcmp (str1, str2) == 0)
285 return_value = TRUE;
eb1e0e80
NC
286
287 xcoff64_core_file_matches_executable_p_end_1:
288 free (path);
289 return return_value;
290}
291
292char *
e729279b 293xcoff64_core_file_failing_command (bfd *abfd)
eb1e0e80
NC
294{
295 struct core_dumpxx *c = core_hdr (abfd);
296 char *return_value = 0;
297
b34976b6 298 if (NULL != c)
eb1e0e80
NC
299 return_value = c->c_u.U_proc.pi_comm;
300
301 return return_value;
302}
303
304int
e729279b 305xcoff64_core_file_failing_signal (bfd *abfd)
eb1e0e80
NC
306{
307 struct core_dumpxx *c = core_hdr (abfd);
308 int return_value = 0;
309
b34976b6 310 if (NULL != c)
eb1e0e80
NC
311 return_value = c->c_signo;
312
313 return return_value;
314}
315
316#else /* AIX_5_CORE */
317
e729279b
NC
318const bfd_target *xcoff64_core_p (bfd *);
319bfd_boolean xcoff64_core_file_matches_executable_p (bfd *, bfd *);
320char *xcoff64_core_file_failing_command (bfd *);
321int xcoff64_core_file_failing_signal (bfd *);
eb1e0e80
NC
322
323const bfd_target *
e729279b 324xcoff64_core_p (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
325{
326 bfd_set_error (bfd_error_wrong_format);
327 return 0;
328}
329
b34976b6 330bfd_boolean
e729279b
NC
331xcoff64_core_file_matches_executable_p (bfd *core_bfd ATTRIBUTE_UNUSED,
332 bfd *exec_bfd ATTRIBUTE_UNUSED)
eb1e0e80 333{
b34976b6 334 return FALSE;
eb1e0e80
NC
335}
336
337char *
e729279b 338xcoff64_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
339{
340 return 0;
341}
342
343int
e729279b 344xcoff64_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
345{
346 return 0;
347}
348
349#endif /* AIX_5_CORE */
This page took 0.193112 seconds and 4 git commands to generate.