2009-06-05 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / bfd / aix5ppc-core.c
CommitLineData
eb1e0e80 1/* IBM RS/6000 "XCOFF" back-end for BFD.
e0c88096 2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
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
cd123cb7 11 the Free Software Foundation; either version 3 of the License, or
eb1e0e80
NC
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 23
3db64b00 24#include "sysdep.h"
eb1e0e80
NC
25#include "bfd.h"
26
e729279b
NC
27const bfd_target *xcoff64_core_p (bfd *);
28bfd_boolean xcoff64_core_file_matches_executable_p (bfd *, bfd *);
29char *xcoff64_core_file_failing_command (bfd *);
30int xcoff64_core_file_failing_signal (bfd *);
eb1e0e80 31
9bf46c00
AM
32#ifdef AIX_5_CORE
33
9bf46c00
AM
34#include "libbfd.h"
35
eb1e0e80
NC
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
e0c88096
NC
43/* The default architecture and machine for matching core files. */
44#define DEFAULT_ARCHITECTURE bfd_arch_powerpc
45#define DEFAULT_MACHINE bfd_mach_ppc_620
46
eb1e0e80
NC
47#define core_hdr(abfd) ((struct core_dumpxx *) abfd->tdata.any)
48
49#define CHECK_FILE_OFFSET(s, v) \
50 ((bfd_signed_vma)(v) < 0 || (bfd_signed_vma)(v) > (bfd_signed_vma)(s).st_size)
51
52const bfd_target *
e729279b 53xcoff64_core_p (bfd *abfd)
eb1e0e80 54{
e0c88096
NC
55 enum bfd_architecture arch;
56 unsigned long mach;
eb1e0e80
NC
57 struct core_dumpxx core, *new_core_hdr;
58 struct stat statbuf;
59 asection *sec;
60 struct __ld_info64 ldinfo;
61 bfd_vma ld_offset;
62 bfd_size_type i;
63 struct vm_infox vminfo;
fd6212e6 64 const bfd_target *return_value = NULL;
117ed4f8 65 flagword flags;
eb1e0e80
NC
66
67 /* Get the header. */
68 if (bfd_seek (abfd, 0, SEEK_SET) != 0)
69 goto xcoff64_core_p_error;
70
b34976b6 71 if (sizeof (struct core_dumpxx)
d1e66cd4 72 != bfd_bread (&core, sizeof (struct core_dumpxx), abfd))
eb1e0e80
NC
73 goto xcoff64_core_p_error;
74
b34976b6 75 if (bfd_stat (abfd, &statbuf) < 0)
eb1e0e80
NC
76 goto xcoff64_core_p_error;
77
78 /* Sanity checks
79 c_flag has CORE_VERSION_1, Aix 4+
80 c_entries = 0 for Aix 4.3+
81 IS_PROC64 is a macro defined in procinfo.h, test for 64 bit process.
82
83 We will still be confused if a Aix 4.3 64 bit core file is
84 copied over to a Aix 5 machine.
85
86 Check file header offsets
87
88 See rs6000-core.c for comment on size of core
89 If there isn't enough of a real core file, bail. */
90
b34976b6
AM
91 if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1))
92 || (0 != core.c_entries)
93 || (! (IS_PROC64 (&core.c_u.U_proc)))
94 || ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox)))
95 || ((CHECK_FILE_OFFSET (statbuf, core.c_loader)))
96 || ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize)))
97 || ((CHECK_FILE_OFFSET (statbuf, core.c_thr)))
98 || ((CHECK_FILE_OFFSET (statbuf, core.c_segregion)))
99 || ((CHECK_FILE_OFFSET (statbuf, core.c_stack)))
100 || ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size)))
101 || ((CHECK_FILE_OFFSET (statbuf, core.c_data)))
102 || ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize)))
103 || (! (core.c_flag & UBLOCK_VALID))
104 || (! (core.c_flag & LE_VALID)))
eb1e0e80
NC
105 goto xcoff64_core_p_error;
106
5c4491d3 107 /* Check for truncated stack or general truncating. */
b34976b6 108 if ((! (core.c_flag & USTACK_VALID))
eb1e0e80
NC
109 || (core.c_flag & CORE_TRUNC))
110 {
111 bfd_set_error (bfd_error_file_truncated);
112
113 return return_value;
114 }
115
e729279b 116 new_core_hdr = bfd_zalloc (abfd, sizeof (struct core_dumpxx));
b34976b6 117 if (NULL == new_core_hdr)
eb1e0e80
NC
118 return return_value;
119
120 memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx));
fd6212e6
NC
121 /* The core_hdr() macro is no longer used here because it would
122 expand to code relying on gcc's cast-as-lvalue extension,
123 which was removed in gcc 4.0. */
124 abfd->tdata.any = new_core_hdr;
eb1e0e80
NC
125
126 /* .stack section. */
117ed4f8
AM
127 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
128 sec = bfd_make_section_anyway_with_flags (abfd, ".stack", flags);
b34976b6 129 if (NULL == sec)
eb1e0e80
NC
130 return return_value;
131
eea6121a 132 sec->size = core.c_size;
eb1e0e80
NC
133 sec->vma = core.c_stackorg;
134 sec->filepos = core.c_stack;
135
136 /* .reg section for all registers. */
117ed4f8
AM
137 flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
138 sec = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
b34976b6 139 if (NULL == sec)
eb1e0e80
NC
140 return return_value;
141
eea6121a 142 sec->size = sizeof (struct __context64);
eb1e0e80
NC
143 sec->vma = 0;
144 sec->filepos = 0;
145 sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64;
146
147 /* .ldinfo section.
148 To actually find out how long this section is in this particular
b34976b6 149 core dump would require going down the whole list of struct
eb1e0e80 150 ld_info's. See if we can just fake it. */
117ed4f8
AM
151 flags = SEC_HAS_CONTENTS;
152 sec = bfd_make_section_anyway_with_flags (abfd, ".ldinfo", flags);
eb1e0e80
NC
153 if (NULL == sec)
154 return return_value;
155
eea6121a 156 sec->size = core.c_lsize;
eb1e0e80
NC
157 sec->vma = 0;
158 sec->filepos = core.c_loader;
159
160 /* AIX 4 adds data sections from loaded objects to the core file,
161 which can be found by examining ldinfo, and anonymously mmapped
162 regions. */
b34976b6 163
eb1e0e80 164 /* .data section from executable. */
117ed4f8
AM
165 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
166 sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
b34976b6 167 if (NULL == sec)
eb1e0e80
NC
168 return return_value;
169
eea6121a 170 sec->size = core.c_datasize;
eb1e0e80
NC
171 sec->vma = core.c_dataorg;
172 sec->filepos = core.c_data;
173
174 /* .data sections from loaded objects. */
175 ld_offset = core.c_loader;
b34976b6
AM
176
177 while (1)
eb1e0e80 178 {
b34976b6 179 if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0)
eb1e0e80
NC
180 return return_value;
181
182 if (sizeof (struct __ld_info64) !=
b34976b6 183 bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd))
eb1e0e80
NC
184 return return_value;
185
b34976b6 186 if (ldinfo.ldinfo_core)
eb1e0e80 187 {
117ed4f8
AM
188 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
189 sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
b34976b6 190 if (NULL == sec)
eb1e0e80
NC
191 return return_value;
192
eea6121a 193 sec->size = ldinfo.ldinfo_datasize;
eb1e0e80
NC
194 sec->vma = ldinfo.ldinfo_dataorg;
195 sec->filepos = ldinfo.ldinfo_core;
196 }
197
198 if (0 == ldinfo.ldinfo_next)
199 break;
200 ld_offset += ldinfo.ldinfo_next;
201 }
202
203 /* .vmdata sections from anonymously mmapped regions. */
b34976b6 204 if (core.c_vmregions)
eb1e0e80 205 {
b34976b6 206 if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0)
eb1e0e80
NC
207 return return_value;
208
b34976b6 209 for (i = 0; i < core.c_vmregions; i++)
eb1e0e80 210 if (sizeof (struct vm_infox) !=
b34976b6 211 bfd_bread (&vminfo, sizeof (struct vm_infox), abfd))
eb1e0e80
NC
212 return return_value;
213
b34976b6 214 if (vminfo.vminfo_offset)
eb1e0e80 215 {
117ed4f8
AM
216 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
217 sec = bfd_make_section_anyway_with_flags (abfd, ".vmdata", flags);
b34976b6 218 if (NULL == sec)
eb1e0e80
NC
219 return return_value;
220
eea6121a 221 sec->size = vminfo.vminfo_size;
eb1e0e80
NC
222 sec->vma = vminfo.vminfo_addr;
223 sec->filepos = vminfo.vminfo_offset;
224 }
225 }
226
e0c88096
NC
227 /* Set the architecture and machine. */
228 arch = DEFAULT_ARCHITECTURE;
229 mach = DEFAULT_MACHINE;
230 bfd_default_set_arch_mach (abfd, arch, mach);
231
7cefacd3 232 return_value = (bfd_target *) abfd->xvec; /* This is garbage for now. */
b34976b6 233
eb1e0e80 234 xcoff64_core_p_error:
b34976b6 235 if (bfd_get_error () != bfd_error_system_call)
eb1e0e80 236 bfd_set_error (bfd_error_wrong_format);
b34976b6 237
eb1e0e80
NC
238 return return_value;
239}
240
b34976b6 241/* Return `TRUE' if given core is from the given executable. */
eb1e0e80 242
b34976b6 243bfd_boolean
e729279b 244xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
eb1e0e80
NC
245{
246 struct core_dumpxx core;
247 char *path, *s;
248 size_t alloc;
249 const char *str1, *str2;
b34976b6 250 bfd_boolean return_value = FALSE;
eb1e0e80
NC
251
252 /* Get the header. */
b34976b6 253 if (bfd_seek (core_bfd, 0, SEEK_SET) != 0)
eb1e0e80 254 return return_value;
b34976b6 255
eb1e0e80 256 if (sizeof (struct core_dumpxx) !=
b34976b6 257 bfd_bread (&core, sizeof (struct core_dumpxx), core_bfd))
eb1e0e80
NC
258 return return_value;
259
b34976b6 260 if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0)
eb1e0e80
NC
261 return return_value;
262
263 alloc = 100;
264 path = bfd_malloc (alloc);
b34976b6 265 if (path == NULL)
eb1e0e80
NC
266 return return_value;
267
268 s = path;
269
270 while (1)
271 {
d1e66cd4 272 if (bfd_bread (s, 1, core_bfd) != 1)
eb1e0e80
NC
273 goto xcoff64_core_file_matches_executable_p_end_1;
274
275 if (*s == '\0')
276 break;
277 ++s;
b34976b6 278 if (s == path + alloc)
eb1e0e80
NC
279 {
280 char *n;
281
282 alloc *= 2;
283 n = bfd_realloc (path, alloc);
b34976b6 284 if (n == NULL)
eb1e0e80
NC
285 goto xcoff64_core_file_matches_executable_p_end_1;
286
287 s = n + (path - s);
288 path = n;
289 }
290 }
291
292 str1 = strrchr (path, '/');
293 str2 = strrchr (exec_bfd->filename, '/');
294
295 /* Step over character '/'. */
296 str1 = str1 != NULL ? str1 + 1 : path;
297 str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
298
b34976b6
AM
299 if (strcmp (str1, str2) == 0)
300 return_value = TRUE;
eb1e0e80
NC
301
302 xcoff64_core_file_matches_executable_p_end_1:
303 free (path);
304 return return_value;
305}
306
307char *
e729279b 308xcoff64_core_file_failing_command (bfd *abfd)
eb1e0e80
NC
309{
310 struct core_dumpxx *c = core_hdr (abfd);
311 char *return_value = 0;
312
b34976b6 313 if (NULL != c)
eb1e0e80
NC
314 return_value = c->c_u.U_proc.pi_comm;
315
316 return return_value;
317}
318
319int
e729279b 320xcoff64_core_file_failing_signal (bfd *abfd)
eb1e0e80
NC
321{
322 struct core_dumpxx *c = core_hdr (abfd);
323 int return_value = 0;
324
b34976b6 325 if (NULL != c)
eb1e0e80
NC
326 return_value = c->c_signo;
327
328 return return_value;
329}
330
331#else /* AIX_5_CORE */
332
eb1e0e80 333const bfd_target *
e729279b 334xcoff64_core_p (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
335{
336 bfd_set_error (bfd_error_wrong_format);
337 return 0;
338}
339
9bf46c00
AM
340bfd_boolean
341xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
342{
343 return generic_core_file_matches_executable_p (core_bfd, exec_bfd);
344}
345
eb1e0e80 346char *
e729279b 347xcoff64_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
348{
349 return 0;
350}
351
352int
e729279b 353xcoff64_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
eb1e0e80
NC
354{
355 return 0;
356}
357
358#endif /* AIX_5_CORE */
This page took 0.465133 seconds and 4 git commands to generate.