|  | /* BFD back-end for AIX on PS/2 core files. | 
|  | This was based on trad-core.c, which was written by John Gilmore of | 
|  | Cygnus Support. | 
|  | Copyright (C) 1988-2021 Free Software Foundation, Inc. | 
|  | Written by Minh Tran-Le <TRANLE@INTELLICORP.COM>. | 
|  | Converted to back end form by Ian Lance Taylor <ian@cygnus.com>. | 
|  |  | 
|  | 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 3 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.  */ | 
|  |  | 
|  | #include "sysdep.h" | 
|  | #include "bfd.h" | 
|  | #include "libbfd.h" | 
|  | #include "coff/i386.h" | 
|  | #include "coff/internal.h" | 
|  | #include "libcoff.h" | 
|  |  | 
|  | #include <signal.h> | 
|  |  | 
|  | #if defined (_AIX) && defined (_I386) | 
|  | #define NOCHECKS		/* This is for coredump.h.  */ | 
|  | #define _h_USER			/* Avoid including user.h from coredump.h.  */ | 
|  | #include <uinfo.h> | 
|  | #include <sys/i386/coredump.h> | 
|  | #endif /* _AIX && _I386 */ | 
|  |  | 
|  | /* Maybe this could work on some other i386 but I have not tried it | 
|  | * mtranle@paris - Tue Sep 24 12:49:35 1991 | 
|  | */ | 
|  |  | 
|  | #ifndef COR_MAGIC | 
|  | # define COR_MAGIC "core" | 
|  | #endif | 
|  |  | 
|  | /* Need this cast because ptr is really void *.  */ | 
|  | #define core_hdr(bfd) \ | 
|  | (((bfd->tdata.trad_core_data))->hdr) | 
|  | #define core_section(bfd,n) \ | 
|  | (((bfd)->tdata.trad_core_data)->sections[n]) | 
|  | #define core_regsec(bfd) \ | 
|  | (((bfd)->tdata.trad_core_data)->reg_section) | 
|  | #define core_reg2sec(bfd) \ | 
|  | (((bfd)->tdata.trad_core_data)->reg2_section) | 
|  |  | 
|  | /* These are stored in the bfd's tdata.  */ | 
|  | struct trad_core_struct | 
|  | { | 
|  | struct corehdr *hdr;		/* core file header */ | 
|  | asection *reg_section; | 
|  | asection *reg2_section; | 
|  | asection *sections[MAX_CORE_SEGS]; | 
|  | }; | 
|  |  | 
|  | static bfd_cleanup | 
|  | aix386_core_file_p (bfd *abfd) | 
|  | { | 
|  | int i, n; | 
|  | unsigned char longbuf[4];	/* Raw bytes of various header fields */ | 
|  | bfd_size_type core_size = sizeof (struct corehdr); | 
|  | size_t amt; | 
|  | struct corehdr *core; | 
|  | struct mergem | 
|  | { | 
|  | struct trad_core_struct coredata; | 
|  | struct corehdr internal_core; | 
|  | } *mergem; | 
|  | flagword flags; | 
|  |  | 
|  | amt = sizeof (longbuf); | 
|  | if (bfd_bread (longbuf, amt, abfd) != amt) | 
|  | { | 
|  | if (bfd_get_error () != bfd_error_system_call) | 
|  | bfd_set_error (bfd_error_wrong_format); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (strncmp (longbuf, COR_MAGIC, 4)) | 
|  | return 0; | 
|  |  | 
|  | if (bfd_seek (abfd, (file_ptr) 0, 0) != 0) | 
|  | return 0; | 
|  |  | 
|  | amt = sizeof (struct mergem); | 
|  | mergem = (struct mergem *) bfd_zalloc (abfd, amt); | 
|  | if (mergem == NULL) | 
|  | return 0; | 
|  |  | 
|  | core = &mergem->internal_core; | 
|  |  | 
|  | if ((bfd_bread (core, core_size, abfd)) != core_size) | 
|  | { | 
|  | if (bfd_get_error () != bfd_error_system_call) | 
|  | bfd_set_error (bfd_error_wrong_format); | 
|  | loser: | 
|  | bfd_release (abfd, (char *) mergem); | 
|  | abfd->tdata.any = NULL; | 
|  | bfd_section_list_clear (abfd); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | set_tdata (abfd, &mergem->coredata); | 
|  | core_hdr (abfd) = core; | 
|  |  | 
|  | /* Create the sections.  */ | 
|  | flags = SEC_HAS_CONTENTS; | 
|  | core_regsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg", | 
|  | flags); | 
|  | if (core_regsec (abfd) == NULL) | 
|  | goto loser; | 
|  |  | 
|  | core_regsec (abfd)->size = sizeof (core->cd_regs); | 
|  | core_regsec (abfd)->vma = (bfd_vma) -1; | 
|  |  | 
|  | /* We'll access the regs afresh in the core file, like any section.  */ | 
|  | core_regsec (abfd)->filepos = | 
|  | (file_ptr) offsetof (struct corehdr, cd_regs[0]); | 
|  |  | 
|  | flags = SEC_HAS_CONTENTS; | 
|  | core_reg2sec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg2", | 
|  | flags); | 
|  | if (core_reg2sec (abfd) == NULL) | 
|  | /* bfd_release frees everything allocated after it's arg.  */ | 
|  | goto loser; | 
|  |  | 
|  | core_reg2sec (abfd)->size = sizeof (core->cd_fpregs); | 
|  | core_reg2sec (abfd)->vma = (bfd_vma) -1; | 
|  | core_reg2sec (abfd)->filepos = | 
|  | (file_ptr) offsetof (struct corehdr, cd_fpregs); | 
|  |  | 
|  | for (i = 0, n = 0; (i < MAX_CORE_SEGS) && (core->cd_segs[i].cs_type); i++) | 
|  | { | 
|  | const char *sname; | 
|  | flagword flags; | 
|  |  | 
|  | if (core->cd_segs[i].cs_offset == 0) | 
|  | continue; | 
|  |  | 
|  | switch (core->cd_segs[i].cs_type) | 
|  | { | 
|  | case COR_TYPE_DATA: | 
|  | sname = ".data"; | 
|  | flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; | 
|  | break; | 
|  | case COR_TYPE_STACK: | 
|  | sname = ".stack"; | 
|  | flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; | 
|  | break; | 
|  | case COR_TYPE_LIBDATA: | 
|  | sname = ".libdata"; | 
|  | flags = SEC_ALLOC + SEC_HAS_CONTENTS; | 
|  | break; | 
|  | case COR_TYPE_WRITE: | 
|  | sname = ".writeable"; | 
|  | flags = SEC_ALLOC + SEC_HAS_CONTENTS; | 
|  | break; | 
|  | case COR_TYPE_MSC: | 
|  | sname = ".misc"; | 
|  | flags = SEC_ALLOC + SEC_HAS_CONTENTS; | 
|  | break; | 
|  | default: | 
|  | sname = ".unknown"; | 
|  | flags = SEC_ALLOC + SEC_HAS_CONTENTS; | 
|  | break; | 
|  | } | 
|  | core_section (abfd, n) = bfd_make_section_anyway_with_flags (abfd, | 
|  | sname, | 
|  | flags); | 
|  | if (core_section (abfd, n) == NULL) | 
|  | goto loser; | 
|  |  | 
|  | core_section (abfd, n)->size = core->cd_segs[i].cs_len; | 
|  | core_section (abfd, n)->vma       = core->cd_segs[i].cs_address; | 
|  | core_section (abfd, n)->filepos   = core->cd_segs[i].cs_offset; | 
|  | core_section (abfd, n)->alignment_power = 2; | 
|  | n++; | 
|  | } | 
|  |  | 
|  | return _bfd_no_cleanup; | 
|  | } | 
|  |  | 
|  | static char * | 
|  | aix386_core_file_failing_command (bfd *abfd) | 
|  | { | 
|  | return core_hdr (abfd)->cd_comm; | 
|  | } | 
|  |  | 
|  | static int | 
|  | aix386_core_file_failing_signal (bfd *abfd) | 
|  | { | 
|  | return core_hdr (abfd)->cd_cursig; | 
|  | } | 
|  |  | 
|  | #define aix386_core_file_matches_executable_p generic_core_file_matches_executable_p | 
|  |  | 
|  | #define aix386_core_file_pid _bfd_nocore_core_file_pid | 
|  |  | 
|  | /* If somebody calls any byte-swapping routines, shoot them.  */ | 
|  |  | 
|  | static void | 
|  | swap_abort (void) | 
|  | { | 
|  | /* This way doesn't require any declaration for ANSI to fuck up.  */ | 
|  | abort (); | 
|  | } | 
|  |  | 
|  | #define	NO_GET ((bfd_vma (*) (const void *)) swap_abort) | 
|  | #define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort) | 
|  | #define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort) | 
|  | #define	NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort) | 
|  | #define	NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort) | 
|  | #define	NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort) | 
|  |  | 
|  | const bfd_target core_aix386_vec = | 
|  | { | 
|  | "aix386-core", | 
|  | bfd_target_unknown_flavour, | 
|  | BFD_ENDIAN_BIG,		/* target byte order */ | 
|  | BFD_ENDIAN_BIG,		/* target headers byte order */ | 
|  | (HAS_RELOC | EXEC_P |		/* object flags */ | 
|  | HAS_LINENO | HAS_DEBUG | | 
|  | HAS_SYMS | HAS_LOCALS | WP_TEXT), | 
|  |  | 
|  | (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ | 
|  | 0,				/* leading underscore */ | 
|  | ' ',				/* ar_pad_char */ | 
|  | 16,				/* ar_max_namelen */ | 
|  | 0,				/* match priority.  */ | 
|  | TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */ | 
|  | NO_GET64, NO_GETS64, NO_PUT64, | 
|  | NO_GET, NO_GETS, NO_PUT, | 
|  | NO_GET, NO_GETS, NO_PUT,	/* data */ | 
|  | NO_GET64, NO_GETS64, NO_PUT64, | 
|  | NO_GET, NO_GETS, NO_PUT, | 
|  | NO_GET, NO_GETS, NO_PUT,	/* hdrs */ | 
|  |  | 
|  | {				/* bfd_check_format */ | 
|  | _bfd_dummy_target, | 
|  | _bfd_dummy_target, | 
|  | _bfd_dummy_target, | 
|  | aix386_core_file_p | 
|  | }, | 
|  | {				/* bfd_create_object */ | 
|  | _bfd_bool_bfd_false_error, | 
|  | _bfd_bool_bfd_false_error, | 
|  | _bfd_bool_bfd_false_error, | 
|  | _bfd_bool_bfd_false_error | 
|  | }, | 
|  | {				/* bfd_write_contents */ | 
|  | _bfd_bool_bfd_false_error, | 
|  | _bfd_bool_bfd_false_error, | 
|  | _bfd_bool_bfd_false_error, | 
|  | _bfd_bool_bfd_false_error | 
|  | }, | 
|  |  | 
|  | BFD_JUMP_TABLE_GENERIC (_bfd_generic), | 
|  | BFD_JUMP_TABLE_COPY (_bfd_generic), | 
|  | BFD_JUMP_TABLE_CORE (aix386), | 
|  | BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), | 
|  | BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), | 
|  | BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), | 
|  | BFD_JUMP_TABLE_WRITE (_bfd_generic), | 
|  | BFD_JUMP_TABLE_LINK (_bfd_nolink), | 
|  | BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), | 
|  |  | 
|  | NULL, | 
|  |  | 
|  | NULL | 
|  | }; |