* corefile.c (generic_core_file_matches_executable_p): New function.
[deliverable/binutils-gdb.git] / bfd / aix5ppc-core.c
CommitLineData
eb1e0e80 1/* IBM RS/6000 "XCOFF" back-end for BFD.
fd6212e6 2 Copyright 2001, 2002, 2003, 2004, 2005
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;
fd6212e6 58 const bfd_target *return_value = NULL;
eb1e0e80
NC
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));
fd6212e6
NC
114 /* The core_hdr() macro is no longer used here because it would
115 expand to code relying on gcc's cast-as-lvalue extension,
116 which was removed in gcc 4.0. */
117 abfd->tdata.any = new_core_hdr;
eb1e0e80
NC
118
119 /* .stack section. */
120 sec = bfd_make_section_anyway (abfd, ".stack");
b34976b6 121 if (NULL == sec)
eb1e0e80
NC
122 return return_value;
123
124 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
eea6121a 125 sec->size = core.c_size;
eb1e0e80
NC
126 sec->vma = core.c_stackorg;
127 sec->filepos = core.c_stack;
128
129 /* .reg section for all registers. */
130 sec = bfd_make_section_anyway (abfd, ".reg");
b34976b6 131 if (NULL == sec)
eb1e0e80
NC
132 return return_value;
133
134 sec->flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
eea6121a 135 sec->size = sizeof (struct __context64);
eb1e0e80
NC
136 sec->vma = 0;
137 sec->filepos = 0;
138 sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64;
139
140 /* .ldinfo section.
141 To actually find out how long this section is in this particular
b34976b6 142 core dump would require going down the whole list of struct
eb1e0e80
NC
143 ld_info's. See if we can just fake it. */
144 sec = bfd_make_section_anyway (abfd, ".ldinfo");
145 if (NULL == sec)
146 return return_value;
147
148 sec->flags = SEC_HAS_CONTENTS;
eea6121a 149 sec->size = core.c_lsize;
eb1e0e80
NC
150 sec->vma = 0;
151 sec->filepos = core.c_loader;
152
153 /* AIX 4 adds data sections from loaded objects to the core file,
154 which can be found by examining ldinfo, and anonymously mmapped
155 regions. */
b34976b6 156
eb1e0e80
NC
157 /* .data section from executable. */
158 sec = bfd_make_section_anyway (abfd, ".data");
b34976b6 159 if (NULL == sec)
eb1e0e80
NC
160 return return_value;
161
162 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
eea6121a 163 sec->size = core.c_datasize;
eb1e0e80
NC
164 sec->vma = core.c_dataorg;
165 sec->filepos = core.c_data;
166
167 /* .data sections from loaded objects. */
168 ld_offset = core.c_loader;
b34976b6
AM
169
170 while (1)
eb1e0e80 171 {
b34976b6 172 if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0)
eb1e0e80
NC
173 return return_value;
174
175 if (sizeof (struct __ld_info64) !=
b34976b6 176 bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd))
eb1e0e80
NC
177 return return_value;
178
b34976b6 179 if (ldinfo.ldinfo_core)
eb1e0e80
NC
180 {
181 sec = bfd_make_section_anyway (abfd, ".data");
b34976b6 182 if (NULL == sec)
eb1e0e80
NC
183 return return_value;
184
185 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
eea6121a 186 sec->size = ldinfo.ldinfo_datasize;
eb1e0e80
NC
187 sec->vma = ldinfo.ldinfo_dataorg;
188 sec->filepos = ldinfo.ldinfo_core;
189 }
190
191 if (0 == ldinfo.ldinfo_next)
192 break;
193 ld_offset += ldinfo.ldinfo_next;
194 }
195
196 /* .vmdata sections from anonymously mmapped regions. */
b34976b6 197 if (core.c_vmregions)
eb1e0e80 198 {
b34976b6 199 if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0)
eb1e0e80
NC
200 return return_value;
201
b34976b6 202 for (i = 0; i < core.c_vmregions; i++)
eb1e0e80 203 if (sizeof (struct vm_infox) !=
b34976b6 204 bfd_bread (&vminfo, sizeof (struct vm_infox), abfd))
eb1e0e80
NC
205 return return_value;
206
b34976b6 207 if (vminfo.vminfo_offset)
eb1e0e80
NC
208 {
209 sec = bfd_make_section_anyway (abfd, ".vmdata");
b34976b6 210 if (NULL == sec)
eb1e0e80
NC
211 return return_value;
212
213 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
eea6121a 214 sec->size = vminfo.vminfo_size;
eb1e0e80
NC
215 sec->vma = vminfo.vminfo_addr;
216 sec->filepos = vminfo.vminfo_offset;
217 }
218 }
219
7cefacd3 220 return_value = (bfd_target *) abfd->xvec; /* This is garbage for now. */
b34976b6 221
eb1e0e80 222 xcoff64_core_p_error:
b34976b6 223 if (bfd_get_error () != bfd_error_system_call)
eb1e0e80 224 bfd_set_error (bfd_error_wrong_format);
b34976b6 225
eb1e0e80
NC
226 return return_value;
227}
228
b34976b6 229/* Return `TRUE' if given core is from the given executable. */
eb1e0e80 230
b34976b6 231bfd_boolean
e729279b 232xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
eb1e0e80
NC
233{
234 struct core_dumpxx core;
235 char *path, *s;
236 size_t alloc;
237 const char *str1, *str2;
b34976b6 238 bfd_boolean return_value = FALSE;
eb1e0e80
NC
239
240 /* Get the header. */
b34976b6 241 if (bfd_seek (core_bfd, 0, SEEK_SET) != 0)
eb1e0e80 242 return return_value;
b34976b6 243
eb1e0e80 244 if (sizeof (struct core_dumpxx) !=
b34976b6 245 bfd_bread (&core, sizeof (struct core_dumpxx), core_bfd))
eb1e0e80
NC
246 return return_value;
247
b34976b6 248 if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0)
eb1e0e80
NC
249 return return_value;
250
251 alloc = 100;
252 path = bfd_malloc (alloc);
b34976b6 253 if (path == NULL)
eb1e0e80
NC
254 return return_value;
255
256 s = path;
257
258 while (1)
259 {
d1e66cd4 260 if (bfd_bread (s, 1, core_bfd) != 1)
eb1e0e80
NC
261 goto xcoff64_core_file_matches_executable_p_end_1;
262
263 if (*s == '\0')
264 break;
265 ++s;
b34976b6 266 if (s == path + alloc)
eb1e0e80
NC
267 {
268 char *n;
269
270 alloc *= 2;
271 n = bfd_realloc (path, alloc);
b34976b6 272 if (n == NULL)
eb1e0e80
NC
273 goto xcoff64_core_file_matches_executable_p_end_1;
274
275 s = n + (path - s);
276 path = n;
277 }
278 }
279
280 str1 = strrchr (path, '/');
281 str2 = strrchr (exec_bfd->filename, '/');
282
283 /* Step over character '/'. */
284 str1 = str1 != NULL ? str1 + 1 : path;
285 str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
286
b34976b6
AM
287 if (strcmp (str1, str2) == 0)
288 return_value = TRUE;
eb1e0e80
NC
289
290 xcoff64_core_file_matches_executable_p_end_1:
291 free (path);
292 return return_value;
293}
294
295char *
e729279b 296xcoff64_core_file_failing_command (bfd *abfd)
eb1e0e80
NC
297{
298 struct core_dumpxx *c = core_hdr (abfd);
299 char *return_value = 0;
300
b34976b6 301 if (NULL != c)
eb1e0e80
NC
302 return_value = c->c_u.U_proc.pi_comm;
303
304 return return_value;
305}
306
307int
e729279b 308xcoff64_core_file_failing_signal (bfd *abfd)
eb1e0e80
NC
309{
310 struct core_dumpxx *c = core_hdr (abfd);
311 int return_value = 0;
312
b34976b6 313 if (NULL != c)
eb1e0e80
NC
314 return_value = c->c_signo;
315
316 return return_value;
317}
318
319#else /* AIX_5_CORE */
320
e729279b 321const bfd_target *xcoff64_core_p (bfd *);
69d246d9 322#define xcoff64_core_file_matches_executable_p generic_core_file_matches_executable_p
e729279b
NC
323char *xcoff64_core_file_failing_command (bfd *);
324int xcoff64_core_file_failing_signal (bfd *);
eb1e0e80
NC
325
326const bfd_target *
e729279b 327xcoff64_core_p (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
328{
329 bfd_set_error (bfd_error_wrong_format);
330 return 0;
331}
332
eb1e0e80 333char *
e729279b 334xcoff64_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
335{
336 return 0;
337}
338
339int
e729279b 340xcoff64_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
341{
342 return 0;
343}
344
345#endif /* AIX_5_CORE */
This page took 0.192714 seconds and 4 git commands to generate.