Copyright 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
char*
elf_core_file_failing_command (bfd *abfd)
{
return elf_tdata (abfd)->core_command;
}
int
elf_core_file_failing_signal (bfd *abfd)
{
return elf_tdata (abfd)->core_signal;
}
bfd_boolean
elf_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
{
char* corename;
if (core_bfd->xvec != exec_bfd->xvec)
{
bfd_set_error (bfd_error_system_call);
return FALSE;
}
corename = elf_tdata (core_bfd)->core_program;
if (corename != NULL)
{
const char* execname = strrchr (exec_bfd->filename, '/');
execname = execname ? execname + 1 : exec_bfd->filename;
if (strcmp (execname, corename) != 0)
return FALSE;
}
return TRUE;
}
the file using the execution view of the file (program header table)
rather than the linking view. In fact, there is no section header
table in a core file.
The process status information (including the contents of the general
register set) and the floating point register set are stored in a
segment of type PT_NOTE. We handcraft a couple of extra bfd sections
that allow standard bfd access to the general registers (.reg) and the
floating point registers (.reg2). */
const bfd_target *
elf_core_file_p (bfd *abfd)
{
Elf_External_Ehdr x_ehdr;
Elf_Internal_Ehdr *i_ehdrp;
Elf_Internal_Phdr *i_phdrp;
unsigned int phindex;
const struct elf_backend_data *ebd;
struct bfd_preserve preserve;
bfd_size_type amt;
preserve.marker = NULL;
if (bfd_bread (&x_ehdr, sizeof (x_ehdr), abfd) != sizeof (x_ehdr))
{
if (bfd_get_error () != bfd_error_system_call)
goto wrong;
else
goto fail;
}
if (! elf_file_p (&x_ehdr))
goto wrong;
if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS)
goto wrong;
switch (x_ehdr.e_ident[EI_DATA])
{
case ELFDATA2MSB:
if (! bfd_big_endian (abfd))
goto wrong;
break;
case ELFDATA2LSB:
if (! bfd_little_endian (abfd))
goto wrong;
break;
default:
goto wrong;
}
if (!bfd_preserve_save (abfd, &preserve))
goto fail;
if (! (*abfd->xvec->_bfd_set_format[bfd_core]) (abfd))
goto fail;
preserve.marker = elf_tdata (abfd);
i_ehdrp = elf_elfheader (abfd);
elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
#if DEBUG & 1
elf_debug_file (i_ehdrp);
#endif
ebd = get_elf_backend_data (abfd);
BFD format expects. */
if (ebd->elf_machine_code != i_ehdrp->e_machine
&& (ebd->elf_machine_alt1 == 0
|| i_ehdrp->e_machine != ebd->elf_machine_alt1)
&& (ebd->elf_machine_alt2 == 0
|| i_ehdrp->e_machine != ebd->elf_machine_alt2))
{
const bfd_target * const *target_ptr;
if (ebd->elf_machine_code != EM_NONE)
goto wrong;
for which we do not have a specific backend. */
for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
{
const struct elf_backend_data *back;
if ((*target_ptr)->flavour != bfd_target_elf_flavour)
continue;
back = (const struct elf_backend_data *) (*target_ptr)->backend_data;
if (back->elf_machine_code == i_ehdrp->e_machine
|| (back->elf_machine_alt1 != 0
&& i_ehdrp->e_machine == back->elf_machine_alt1)
|| (back->elf_machine_alt2 != 0
&& i_ehdrp->e_machine == back->elf_machine_alt2))
{
object file, so reject the generic ELF target. */
goto wrong;
}
}
}
we are hosed. */
if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE)
goto wrong;
recorded in the file? */
if (i_ehdrp->e_phentsize != sizeof (Elf_External_Phdr))
goto wrong;
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
goto wrong;
amt = sizeof (*i_phdrp) * i_ehdrp->e_phnum;
i_phdrp = bfd_alloc (abfd, amt);
if (!i_phdrp)
goto fail;
elf_tdata (abfd)->phdr = i_phdrp;
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
{
Elf_External_Phdr x_phdr;
if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr))
goto fail;
elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex);
}
program headers since we need to know the architecture type
when processing the notes of some systems' core files. */
if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0)
&& ebd->elf_machine_code != EM_NONE)
goto fail;
information. We do this before processing the program headers
to allow the correct machine (as opposed to just the default
machine) to be set, making it possible for grok_prstatus and
grok_psinfo to rely on the mach setting. */
if (ebd->elf_backend_object_p != NULL
&& ! ebd->elf_backend_object_p (abfd))
goto wrong;
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
if (! bfd_section_from_phdr (abfd, i_phdrp + phindex, (int) phindex))
goto fail;
bfd_get_start_address (abfd) = i_ehdrp->e_entry;
bfd_preserve_finish (abfd, &preserve);
return abfd->xvec;
wrong:
bfd_check_format_matches, really shouldn't iterate on live bfd's to
check match/no-match like it does. We have to rely on that a call to
bfd_default_set_arch_mach with the previously known mach, undoes what
was done by the first bfd_default_set_arch_mach (with mach 0) here.
For this to work, only elf-data and the mach may be changed by the
target-specific elf_backend_object_p function. Note that saving the
whole bfd here and restoring it would be even worse; the first thing
you notice is that the cached bfd file position gets out of sync. */
bfd_set_error (bfd_error_wrong_format);
fail:
if (preserve.marker != NULL)
bfd_preserve_restore (abfd, &preserve);
return NULL;
}