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