1 |
/* IBM RS/6000 "XCOFF" back-end for BFD. |
/* IBM RS/6000 "XCOFF" back-end for BFD. |
2 |
Copyright 2001, 2002 |
Copyright 2001, 2002, 2003, 2004 |
3 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
4 |
Written by Tom Rix |
Written by Tom Rix |
5 |
Contributed by Redhat. |
Contributed by Redhat. |
28 |
#include "sysdep.h" |
#include "sysdep.h" |
29 |
#include "libbfd.h" |
#include "libbfd.h" |
30 |
|
|
31 |
const bfd_target * xcoff64_core_p PARAMS ((bfd *)); |
const bfd_target *xcoff64_core_p |
32 |
boolean xcoff64_core_file_matches_executable_p PARAMS ((bfd *, bfd *)); |
PARAMS ((bfd *)); |
33 |
char * xcoff64_core_file_failing_command PARAMS ((bfd *)); |
bfd_boolean xcoff64_core_file_matches_executable_p |
34 |
int xcoff64_core_file_failing_signal PARAMS ((bfd *)); |
PARAMS ((bfd *, bfd *)); |
35 |
|
char *xcoff64_core_file_failing_command |
36 |
|
PARAMS ((bfd *)); |
37 |
|
int xcoff64_core_file_failing_signal |
38 |
|
PARAMS ((bfd *)); |
39 |
|
|
40 |
/* Aix 5.1 system include file. */ |
/* Aix 5.1 system include file. */ |
41 |
|
|
66 |
if (bfd_seek (abfd, 0, SEEK_SET) != 0) |
if (bfd_seek (abfd, 0, SEEK_SET) != 0) |
67 |
goto xcoff64_core_p_error; |
goto xcoff64_core_p_error; |
68 |
|
|
69 |
if (sizeof (struct core_dumpxx) |
if (sizeof (struct core_dumpxx) |
70 |
!= bfd_bread (&core, sizeof (struct core_dumpxx), abfd)) |
!= bfd_bread (&core, sizeof (struct core_dumpxx), abfd)) |
71 |
goto xcoff64_core_p_error; |
goto xcoff64_core_p_error; |
72 |
|
|
73 |
if (bfd_stat (abfd, &statbuf) < 0) |
if (bfd_stat (abfd, &statbuf) < 0) |
74 |
goto xcoff64_core_p_error; |
goto xcoff64_core_p_error; |
75 |
|
|
76 |
/* Sanity checks |
/* Sanity checks |
86 |
See rs6000-core.c for comment on size of core |
See rs6000-core.c for comment on size of core |
87 |
If there isn't enough of a real core file, bail. */ |
If there isn't enough of a real core file, bail. */ |
88 |
|
|
89 |
if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1)) |
if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1)) |
90 |
|| (0 != core.c_entries) |
|| (0 != core.c_entries) |
91 |
|| (! (IS_PROC64 (&core.c_u.U_proc))) |
|| (! (IS_PROC64 (&core.c_u.U_proc))) |
92 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox))) |
93 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_loader))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_loader))) |
94 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize))) |
95 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_thr))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_thr))) |
96 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_segregion))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_segregion))) |
97 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_stack))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_stack))) |
98 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size))) |
99 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_data))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_data))) |
100 |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize))) |
|| ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize))) |
101 |
|| (! (core.c_flag & UBLOCK_VALID)) |
|| (! (core.c_flag & UBLOCK_VALID)) |
102 |
|| (! (core.c_flag & LE_VALID))) |
|| (! (core.c_flag & LE_VALID))) |
103 |
goto xcoff64_core_p_error; |
goto xcoff64_core_p_error; |
104 |
|
|
105 |
/* Check for trucated stack or general truncating. */ |
/* Check for truncated stack or general truncating. */ |
106 |
if ((! (core.c_flag & USTACK_VALID)) |
if ((! (core.c_flag & USTACK_VALID)) |
107 |
|| (core.c_flag & CORE_TRUNC)) |
|| (core.c_flag & CORE_TRUNC)) |
108 |
{ |
{ |
109 |
bfd_set_error (bfd_error_file_truncated); |
bfd_set_error (bfd_error_file_truncated); |
113 |
|
|
114 |
new_core_hdr = (struct core_dumpxx *) |
new_core_hdr = (struct core_dumpxx *) |
115 |
bfd_zalloc (abfd, sizeof (struct core_dumpxx)); |
bfd_zalloc (abfd, sizeof (struct core_dumpxx)); |
116 |
if (NULL == new_core_hdr) |
if (NULL == new_core_hdr) |
117 |
return return_value; |
return return_value; |
118 |
|
|
119 |
memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx)); |
memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx)); |
121 |
|
|
122 |
/* .stack section. */ |
/* .stack section. */ |
123 |
sec = bfd_make_section_anyway (abfd, ".stack"); |
sec = bfd_make_section_anyway (abfd, ".stack"); |
124 |
if (NULL == sec) |
if (NULL == sec) |
125 |
return return_value; |
return return_value; |
126 |
|
|
127 |
sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
128 |
sec->_raw_size = core.c_size; |
sec->size = core.c_size; |
129 |
sec->vma = core.c_stackorg; |
sec->vma = core.c_stackorg; |
130 |
sec->filepos = core.c_stack; |
sec->filepos = core.c_stack; |
131 |
|
|
132 |
/* .reg section for all registers. */ |
/* .reg section for all registers. */ |
133 |
sec = bfd_make_section_anyway (abfd, ".reg"); |
sec = bfd_make_section_anyway (abfd, ".reg"); |
134 |
if (NULL == sec) |
if (NULL == sec) |
135 |
return return_value; |
return return_value; |
136 |
|
|
137 |
sec->flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY; |
sec->flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY; |
138 |
sec->_raw_size = sizeof (struct __context64); |
sec->size = sizeof (struct __context64); |
139 |
sec->vma = 0; |
sec->vma = 0; |
140 |
sec->filepos = 0; |
sec->filepos = 0; |
141 |
sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64; |
sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64; |
142 |
|
|
143 |
/* .ldinfo section. |
/* .ldinfo section. |
144 |
To actually find out how long this section is in this particular |
To actually find out how long this section is in this particular |
145 |
core dump would require going down the whole list of struct |
core dump would require going down the whole list of struct |
146 |
ld_info's. See if we can just fake it. */ |
ld_info's. See if we can just fake it. */ |
147 |
sec = bfd_make_section_anyway (abfd, ".ldinfo"); |
sec = bfd_make_section_anyway (abfd, ".ldinfo"); |
148 |
if (NULL == sec) |
if (NULL == sec) |
149 |
return return_value; |
return return_value; |
150 |
|
|
151 |
sec->flags = SEC_HAS_CONTENTS; |
sec->flags = SEC_HAS_CONTENTS; |
152 |
sec->_raw_size = core.c_lsize; |
sec->size = core.c_lsize; |
153 |
sec->vma = 0; |
sec->vma = 0; |
154 |
sec->filepos = core.c_loader; |
sec->filepos = core.c_loader; |
155 |
|
|
156 |
/* AIX 4 adds data sections from loaded objects to the core file, |
/* AIX 4 adds data sections from loaded objects to the core file, |
157 |
which can be found by examining ldinfo, and anonymously mmapped |
which can be found by examining ldinfo, and anonymously mmapped |
158 |
regions. */ |
regions. */ |
159 |
|
|
160 |
/* .data section from executable. */ |
/* .data section from executable. */ |
161 |
sec = bfd_make_section_anyway (abfd, ".data"); |
sec = bfd_make_section_anyway (abfd, ".data"); |
162 |
if (NULL == sec) |
if (NULL == sec) |
163 |
return return_value; |
return return_value; |
164 |
|
|
165 |
sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
166 |
sec->_raw_size = core.c_datasize; |
sec->size = core.c_datasize; |
167 |
sec->vma = core.c_dataorg; |
sec->vma = core.c_dataorg; |
168 |
sec->filepos = core.c_data; |
sec->filepos = core.c_data; |
169 |
|
|
170 |
/* .data sections from loaded objects. */ |
/* .data sections from loaded objects. */ |
171 |
ld_offset = core.c_loader; |
ld_offset = core.c_loader; |
172 |
|
|
173 |
while (1) |
while (1) |
174 |
{ |
{ |
175 |
if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0) |
if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0) |
176 |
return return_value; |
return return_value; |
177 |
|
|
178 |
if (sizeof (struct __ld_info64) != |
if (sizeof (struct __ld_info64) != |
179 |
bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd)) |
bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd)) |
180 |
return return_value; |
return return_value; |
181 |
|
|
182 |
if (ldinfo.ldinfo_core) |
if (ldinfo.ldinfo_core) |
183 |
{ |
{ |
184 |
sec = bfd_make_section_anyway (abfd, ".data"); |
sec = bfd_make_section_anyway (abfd, ".data"); |
185 |
if (NULL == sec) |
if (NULL == sec) |
186 |
return return_value; |
return return_value; |
187 |
|
|
188 |
sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
189 |
sec->_raw_size = ldinfo.ldinfo_datasize; |
sec->size = ldinfo.ldinfo_datasize; |
190 |
sec->vma = ldinfo.ldinfo_dataorg; |
sec->vma = ldinfo.ldinfo_dataorg; |
191 |
sec->filepos = ldinfo.ldinfo_core; |
sec->filepos = ldinfo.ldinfo_core; |
192 |
} |
} |
197 |
} |
} |
198 |
|
|
199 |
/* .vmdata sections from anonymously mmapped regions. */ |
/* .vmdata sections from anonymously mmapped regions. */ |
200 |
if (core.c_vmregions) |
if (core.c_vmregions) |
201 |
{ |
{ |
202 |
if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0) |
if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0) |
203 |
return return_value; |
return return_value; |
204 |
|
|
205 |
for (i = 0; i < core.c_vmregions; i++) |
for (i = 0; i < core.c_vmregions; i++) |
206 |
if (sizeof (struct vm_infox) != |
if (sizeof (struct vm_infox) != |
207 |
bfd_bread (&vminfo, sizeof (struct vm_infox), abfd)) |
bfd_bread (&vminfo, sizeof (struct vm_infox), abfd)) |
208 |
return return_value; |
return return_value; |
209 |
|
|
210 |
if (vminfo.vminfo_offset) |
if (vminfo.vminfo_offset) |
211 |
{ |
{ |
212 |
sec = bfd_make_section_anyway (abfd, ".vmdata"); |
sec = bfd_make_section_anyway (abfd, ".vmdata"); |
213 |
if (NULL == sec) |
if (NULL == sec) |
214 |
return return_value; |
return return_value; |
215 |
|
|
216 |
sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
217 |
sec->_raw_size = vminfo.vminfo_size; |
sec->size = vminfo.vminfo_size; |
218 |
sec->vma = vminfo.vminfo_addr; |
sec->vma = vminfo.vminfo_addr; |
219 |
sec->filepos = vminfo.vminfo_offset; |
sec->filepos = vminfo.vminfo_offset; |
220 |
} |
} |
221 |
} |
} |
222 |
|
|
223 |
return_value = abfd->xvec; /* This is garbage for now. */ |
return_value = abfd->xvec; /* This is garbage for now. */ |
224 |
|
|
225 |
xcoff64_core_p_error: |
xcoff64_core_p_error: |
226 |
if (bfd_get_error () != bfd_error_system_call) |
if (bfd_get_error () != bfd_error_system_call) |
227 |
bfd_set_error (bfd_error_wrong_format); |
bfd_set_error (bfd_error_wrong_format); |
228 |
|
|
229 |
return return_value; |
return return_value; |
230 |
} |
} |
231 |
|
|
232 |
/* Return `true' if given core is from the given executable. */ |
/* Return `TRUE' if given core is from the given executable. */ |
233 |
|
|
234 |
boolean |
bfd_boolean |
235 |
xcoff64_core_file_matches_executable_p (core_bfd, exec_bfd) |
xcoff64_core_file_matches_executable_p (core_bfd, exec_bfd) |
236 |
bfd *core_bfd; |
bfd *core_bfd; |
237 |
bfd *exec_bfd; |
bfd *exec_bfd; |
240 |
char *path, *s; |
char *path, *s; |
241 |
size_t alloc; |
size_t alloc; |
242 |
const char *str1, *str2; |
const char *str1, *str2; |
243 |
boolean return_value = false; |
bfd_boolean return_value = FALSE; |
244 |
|
|
245 |
/* Get the header. */ |
/* Get the header. */ |
246 |
if (bfd_seek (core_bfd, 0, SEEK_SET) != 0) |
if (bfd_seek (core_bfd, 0, SEEK_SET) != 0) |
247 |
return return_value; |
return return_value; |
248 |
|
|
249 |
if (sizeof (struct core_dumpxx) != |
if (sizeof (struct core_dumpxx) != |
250 |
bfd_bread (&core, sizeof (struct core_dumpxx), core_bfd)) |
bfd_bread (&core, sizeof (struct core_dumpxx), core_bfd)) |
251 |
return return_value; |
return return_value; |
252 |
|
|
253 |
if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0) |
if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0) |
254 |
return return_value; |
return return_value; |
255 |
|
|
256 |
alloc = 100; |
alloc = 100; |
257 |
path = bfd_malloc (alloc); |
path = bfd_malloc (alloc); |
258 |
if (path == NULL) |
if (path == NULL) |
259 |
return return_value; |
return return_value; |
260 |
|
|
261 |
s = path; |
s = path; |
268 |
if (*s == '\0') |
if (*s == '\0') |
269 |
break; |
break; |
270 |
++s; |
++s; |
271 |
if (s == path + alloc) |
if (s == path + alloc) |
272 |
{ |
{ |
273 |
char *n; |
char *n; |
274 |
|
|
275 |
alloc *= 2; |
alloc *= 2; |
276 |
n = bfd_realloc (path, alloc); |
n = bfd_realloc (path, alloc); |
277 |
if (n == NULL) |
if (n == NULL) |
278 |
goto xcoff64_core_file_matches_executable_p_end_1; |
goto xcoff64_core_file_matches_executable_p_end_1; |
279 |
|
|
280 |
s = n + (path - s); |
s = n + (path - s); |
289 |
str1 = str1 != NULL ? str1 + 1 : path; |
str1 = str1 != NULL ? str1 + 1 : path; |
290 |
str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename; |
str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename; |
291 |
|
|
292 |
if (strcmp (str1, str2) == 0) |
if (strcmp (str1, str2) == 0) |
293 |
return_value = true; |
return_value = TRUE; |
294 |
|
|
295 |
xcoff64_core_file_matches_executable_p_end_1: |
xcoff64_core_file_matches_executable_p_end_1: |
296 |
free (path); |
free (path); |
304 |
struct core_dumpxx *c = core_hdr (abfd); |
struct core_dumpxx *c = core_hdr (abfd); |
305 |
char *return_value = 0; |
char *return_value = 0; |
306 |
|
|
307 |
if (NULL != c) |
if (NULL != c) |
308 |
return_value = c->c_u.U_proc.pi_comm; |
return_value = c->c_u.U_proc.pi_comm; |
309 |
|
|
310 |
return return_value; |
return return_value; |
317 |
struct core_dumpxx *c = core_hdr (abfd); |
struct core_dumpxx *c = core_hdr (abfd); |
318 |
int return_value = 0; |
int return_value = 0; |
319 |
|
|
320 |
if (NULL != c) |
if (NULL != c) |
321 |
return_value = c->c_signo; |
return_value = c->c_signo; |
322 |
|
|
323 |
return return_value; |
return return_value; |
325 |
|
|
326 |
#else /* AIX_5_CORE */ |
#else /* AIX_5_CORE */ |
327 |
|
|
328 |
const bfd_target * xcoff64_core_p PARAMS ((bfd *)); |
const bfd_target *xcoff64_core_p |
329 |
boolean xcoff64_core_file_matches_executable_p PARAMS ((bfd *, bfd *)); |
PARAMS ((bfd *)); |
330 |
char * xcoff64_core_file_failing_command PARAMS ((bfd *)); |
bfd_boolean xcoff64_core_file_matches_executable_p |
331 |
int xcoff64_core_file_failing_signal PARAMS ((bfd *)); |
PARAMS ((bfd *, bfd *)); |
332 |
|
char *xcoff64_core_file_failing_command |
333 |
|
PARAMS ((bfd *)); |
334 |
|
int xcoff64_core_file_failing_signal |
335 |
|
PARAMS ((bfd *)); |
336 |
|
|
337 |
const bfd_target * |
const bfd_target * |
338 |
xcoff64_core_p (abfd) |
xcoff64_core_p (abfd) |
342 |
return 0; |
return 0; |
343 |
} |
} |
344 |
|
|
345 |
boolean |
bfd_boolean |
346 |
xcoff64_core_file_matches_executable_p (core_bfd, exec_bfd) |
xcoff64_core_file_matches_executable_p (core_bfd, exec_bfd) |
347 |
bfd *core_bfd ATTRIBUTE_UNUSED; |
bfd *core_bfd ATTRIBUTE_UNUSED; |
348 |
bfd *exec_bfd ATTRIBUTE_UNUSED; |
bfd *exec_bfd ATTRIBUTE_UNUSED; |
349 |
{ |
{ |
350 |
return false; |
return FALSE; |
351 |
} |
} |
352 |
|
|
353 |
char * |
char * |