1 |
/* ELF core file support for BFD. |
/* ELF core file support for BFD. |
2 |
Copyright 1995, 1996, 1997, 1998, 2000, 2001, 2002 |
Copyright 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005 |
3 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
6 |
|
|
7 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
10 |
(at your option) any later version. |
(at your option) any later version. |
11 |
|
|
12 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
GNU General Public License for more details. |
16 |
|
|
17 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
18 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
20 |
|
|
21 |
char* |
char* |
22 |
elf_core_file_failing_command (abfd) |
elf_core_file_failing_command (bfd *abfd) |
|
bfd *abfd; |
|
23 |
{ |
{ |
24 |
return elf_tdata (abfd)->core_command; |
return elf_tdata (abfd)->core_command; |
25 |
} |
} |
26 |
|
|
27 |
int |
int |
28 |
elf_core_file_failing_signal (abfd) |
elf_core_file_failing_signal (bfd *abfd) |
|
bfd *abfd; |
|
29 |
{ |
{ |
30 |
return elf_tdata (abfd)->core_signal; |
return elf_tdata (abfd)->core_signal; |
31 |
} |
} |
32 |
|
|
33 |
boolean |
bfd_boolean |
34 |
elf_core_file_matches_executable_p (core_bfd, exec_bfd) |
elf_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd) |
|
bfd *core_bfd; |
|
|
bfd *exec_bfd; |
|
35 |
{ |
{ |
36 |
char* corename; |
char* corename; |
37 |
|
|
40 |
if (core_bfd->xvec != exec_bfd->xvec) |
if (core_bfd->xvec != exec_bfd->xvec) |
41 |
{ |
{ |
42 |
bfd_set_error (bfd_error_system_call); |
bfd_set_error (bfd_error_system_call); |
43 |
return false; |
return FALSE; |
44 |
} |
} |
45 |
|
|
46 |
/* See if the name in the corefile matches the executable name. */ |
/* See if the name in the corefile matches the executable name. */ |
|
|
|
47 |
corename = elf_tdata (core_bfd)->core_program; |
corename = elf_tdata (core_bfd)->core_program; |
48 |
if (corename != NULL) |
if (corename != NULL) |
49 |
{ |
{ |
50 |
const char* execname = strrchr (exec_bfd->filename, '/'); |
const char* execname = strrchr (exec_bfd->filename, '/'); |
51 |
|
|
52 |
execname = execname ? execname + 1 : exec_bfd->filename; |
execname = execname ? execname + 1 : exec_bfd->filename; |
53 |
|
|
54 |
if (strcmp(execname, corename) != 0) |
if (strcmp (execname, corename) != 0) |
55 |
return false; |
return FALSE; |
56 |
} |
} |
57 |
|
|
58 |
return true; |
return TRUE; |
59 |
} |
} |
60 |
|
|
61 |
/* Core files are simply standard ELF formatted files that partition |
/* Core files are simply standard ELF formatted files that partition |
67 |
register set) and the floating point register set are stored in a |
register set) and the floating point register set are stored in a |
68 |
segment of type PT_NOTE. We handcraft a couple of extra bfd sections |
segment of type PT_NOTE. We handcraft a couple of extra bfd sections |
69 |
that allow standard bfd access to the general registers (.reg) and the |
that allow standard bfd access to the general registers (.reg) and the |
70 |
floating point registers (.reg2). |
floating point registers (.reg2). */ |
|
|
|
|
*/ |
|
71 |
|
|
72 |
const bfd_target * |
const bfd_target * |
73 |
elf_core_file_p (abfd) |
elf_core_file_p (bfd *abfd) |
|
bfd *abfd; |
|
74 |
{ |
{ |
75 |
Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ |
Elf_External_Ehdr x_ehdr; /* Elf file header, external form. */ |
76 |
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ |
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form. */ |
77 |
Elf_Internal_Phdr *i_phdrp; /* Elf program header, internal form */ |
Elf_Internal_Phdr *i_phdrp; /* Elf program header, internal form. */ |
78 |
unsigned int phindex; |
unsigned int phindex; |
79 |
struct elf_backend_data *ebd; |
const struct elf_backend_data *ebd; |
80 |
struct bfd_preserve preserve; |
struct bfd_preserve preserve; |
|
struct elf_obj_tdata *new_tdata = NULL; |
|
81 |
bfd_size_type amt; |
bfd_size_type amt; |
82 |
|
|
83 |
preserve.arch_info = abfd->arch_info; |
preserve.marker = NULL; |
84 |
|
|
85 |
/* Read in the ELF header in external format. */ |
/* Read in the ELF header in external format. */ |
86 |
if (bfd_bread ((PTR) &x_ehdr, (bfd_size_type) sizeof (x_ehdr), abfd) |
if (bfd_bread (&x_ehdr, sizeof (x_ehdr), abfd) != sizeof (x_ehdr)) |
|
!= sizeof (x_ehdr)) |
|
87 |
{ |
{ |
88 |
if (bfd_get_error () != bfd_error_system_call) |
if (bfd_get_error () != bfd_error_system_call) |
89 |
bfd_set_error (bfd_error_wrong_format); |
goto wrong; |
90 |
return NULL; |
else |
91 |
|
goto fail; |
92 |
} |
} |
93 |
|
|
94 |
/* Check the magic number. */ |
/* Check the magic number. */ |
95 |
if (! elf_file_p (&x_ehdr)) |
if (! elf_file_p (&x_ehdr)) |
96 |
goto wrong; |
goto wrong; |
97 |
|
|
98 |
/* FIXME: Check EI_VERSION here ! */ |
/* FIXME: Check EI_VERSION here ! */ |
99 |
|
|
100 |
/* Check the address size ("class"). */ |
/* Check the address size ("class"). */ |
101 |
if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS) |
if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS) |
104 |
/* Check the byteorder. */ |
/* Check the byteorder. */ |
105 |
switch (x_ehdr.e_ident[EI_DATA]) |
switch (x_ehdr.e_ident[EI_DATA]) |
106 |
{ |
{ |
107 |
case ELFDATA2MSB: /* Big-endian */ |
case ELFDATA2MSB: /* Big-endian. */ |
108 |
if (! bfd_big_endian (abfd)) |
if (! bfd_big_endian (abfd)) |
109 |
goto wrong; |
goto wrong; |
110 |
break; |
break; |
111 |
case ELFDATA2LSB: /* Little-endian */ |
case ELFDATA2LSB: /* Little-endian. */ |
112 |
if (! bfd_little_endian (abfd)) |
if (! bfd_little_endian (abfd)) |
113 |
goto wrong; |
goto wrong; |
114 |
break; |
break; |
116 |
goto wrong; |
goto wrong; |
117 |
} |
} |
118 |
|
|
119 |
|
if (!bfd_preserve_save (abfd, &preserve)) |
120 |
|
goto fail; |
121 |
|
|
122 |
/* Give abfd an elf_obj_tdata. */ |
/* Give abfd an elf_obj_tdata. */ |
123 |
amt = sizeof (struct elf_obj_tdata); |
if (! (*abfd->xvec->_bfd_set_format[bfd_core]) (abfd)) |
|
new_tdata = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt); |
|
|
if (new_tdata == NULL) |
|
|
return NULL; |
|
|
preserve.tdata = elf_tdata (abfd); |
|
|
elf_tdata (abfd) = new_tdata; |
|
|
|
|
|
/* Clear section information, since there might be a recognized bfd that |
|
|
we now check if we can replace, and we don't want to append to it. */ |
|
|
preserve.sections = abfd->sections; |
|
|
preserve.section_tail = abfd->section_tail; |
|
|
preserve.section_count = abfd->section_count; |
|
|
preserve.section_htab = abfd->section_htab; |
|
|
abfd->sections = NULL; |
|
|
abfd->section_tail = &abfd->sections; |
|
|
abfd->section_count = 0; |
|
|
if (!bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc)) |
|
124 |
goto fail; |
goto fail; |
125 |
|
preserve.marker = elf_tdata (abfd); |
126 |
|
|
127 |
/* Swap in the rest of the header, now that we have the byte order. */ |
/* Swap in the rest of the header, now that we have the byte order. */ |
128 |
i_ehdrp = elf_elfheader (abfd); |
i_ehdrp = elf_elfheader (abfd); |
153 |
|
|
154 |
for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++) |
for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++) |
155 |
{ |
{ |
156 |
struct elf_backend_data *back; |
const struct elf_backend_data *back; |
157 |
|
|
158 |
if ((*target_ptr)->flavour != bfd_target_elf_flavour) |
if ((*target_ptr)->flavour != bfd_target_elf_flavour) |
159 |
continue; |
continue; |
160 |
back = (struct elf_backend_data *) (*target_ptr)->backend_data; |
back = (const struct elf_backend_data *) (*target_ptr)->backend_data; |
161 |
if (back->elf_machine_code == i_ehdrp->e_machine) |
if (back->elf_machine_code == i_ehdrp->e_machine |
162 |
|
|| (back->elf_machine_alt1 != 0 |
163 |
|
&& i_ehdrp->e_machine == back->elf_machine_alt1) |
164 |
|
|| (back->elf_machine_alt2 != 0 |
165 |
|
&& i_ehdrp->e_machine == back->elf_machine_alt2)) |
166 |
{ |
{ |
167 |
/* target_ptr is an ELF backend which matches this |
/* target_ptr is an ELF backend which matches this |
168 |
object file, so reject the generic ELF target. */ |
object file, so reject the generic ELF target. */ |
187 |
|
|
188 |
/* Allocate space for the program headers. */ |
/* Allocate space for the program headers. */ |
189 |
amt = sizeof (*i_phdrp) * i_ehdrp->e_phnum; |
amt = sizeof (*i_phdrp) * i_ehdrp->e_phnum; |
190 |
i_phdrp = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt); |
i_phdrp = bfd_alloc (abfd, amt); |
191 |
if (!i_phdrp) |
if (!i_phdrp) |
192 |
goto fail; |
goto fail; |
193 |
|
|
197 |
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex) |
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex) |
198 |
{ |
{ |
199 |
Elf_External_Phdr x_phdr; |
Elf_External_Phdr x_phdr; |
200 |
if (bfd_bread ((PTR) &x_phdr, (bfd_size_type) sizeof (x_phdr), abfd) |
|
201 |
!= sizeof (x_phdr)) |
if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr)) |
202 |
goto fail; |
goto fail; |
203 |
|
|
204 |
elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex); |
elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex); |
207 |
/* Set the machine architecture. Do this before processing the |
/* Set the machine architecture. Do this before processing the |
208 |
program headers since we need to know the architecture type |
program headers since we need to know the architecture type |
209 |
when processing the notes of some systems' core files. */ |
when processing the notes of some systems' core files. */ |
210 |
if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0)) |
if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0) |
|
{ |
|
211 |
/* It's OK if this fails for the generic target. */ |
/* It's OK if this fails for the generic target. */ |
212 |
if (ebd->elf_machine_code != EM_NONE) |
&& ebd->elf_machine_code != EM_NONE) |
213 |
goto fail; |
goto fail; |
214 |
} |
|
215 |
|
/* Let the backend double check the format and override global |
216 |
|
information. We do this before processing the program headers |
217 |
|
to allow the correct machine (as opposed to just the default |
218 |
|
machine) to be set, making it possible for grok_prstatus and |
219 |
|
grok_psinfo to rely on the mach setting. */ |
220 |
|
if (ebd->elf_backend_object_p != NULL |
221 |
|
&& ! ebd->elf_backend_object_p (abfd)) |
222 |
|
goto wrong; |
223 |
|
|
224 |
/* Process each program header. */ |
/* Process each program header. */ |
225 |
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex) |
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex) |
226 |
{ |
if (! bfd_section_from_phdr (abfd, i_phdrp + phindex, (int) phindex)) |
227 |
if (! bfd_section_from_phdr (abfd, i_phdrp + phindex, (int) phindex)) |
goto fail; |
|
goto fail; |
|
|
} |
|
228 |
|
|
229 |
/* Save the entry point from the ELF header. */ |
/* Save the entry point from the ELF header. */ |
230 |
bfd_get_start_address (abfd) = i_ehdrp->e_entry; |
bfd_get_start_address (abfd) = i_ehdrp->e_entry; |
231 |
|
|
232 |
/* Let the backend double check the format and override global |
bfd_preserve_finish (abfd, &preserve); |
|
information. */ |
|
|
if (ebd->elf_backend_object_p) |
|
|
{ |
|
|
if (! (*ebd->elf_backend_object_p) (abfd)) |
|
|
goto wrong; |
|
|
} |
|
|
|
|
|
bfd_hash_table_free (&preserve.section_htab); |
|
233 |
return abfd->xvec; |
return abfd->xvec; |
234 |
|
|
235 |
wrong: |
wrong: |
245 |
bfd_set_error (bfd_error_wrong_format); |
bfd_set_error (bfd_error_wrong_format); |
246 |
|
|
247 |
fail: |
fail: |
248 |
abfd->arch_info = preserve.arch_info; |
if (preserve.marker != NULL) |
249 |
if (new_tdata != NULL) |
bfd_preserve_restore (abfd, &preserve); |
|
{ |
|
|
/* bfd_release frees all memory more recently bfd_alloc'd than |
|
|
its arg, as well as its arg. */ |
|
|
bfd_release (abfd, new_tdata); |
|
|
elf_tdata (abfd) = preserve.tdata; |
|
|
abfd->section_htab = preserve.section_htab; |
|
|
abfd->sections = preserve.sections; |
|
|
abfd->section_tail = preserve.section_tail; |
|
|
abfd->section_count = preserve.section_count; |
|
|
} |
|
250 |
return NULL; |
return NULL; |
251 |
} |
} |