Home | History | Annotate | Line # | Download | only in bfd
      1 /* BFD back end for NetBSD style core files
      2    Copyright (C) 1988-2025 Free Software Foundation, Inc.
      3    Written by Paul Kranenburg, EUR
      4 
      5    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
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 #include "sysdep.h"
     23 #include "bfd.h"
     24 #include "libbfd.h"
     25 #include "libaout.h"	       /* BFD a.out internal data structures.  */
     26 
     27 #include <sys/param.h>
     28 #include <sys/dir.h>
     29 #include <signal.h>
     30 #include <sys/core.h>
     31 
     32 /* The machine ID for OpenBSD/sparc64 and older versions of
     33    NetBSD/sparc64 overlaps with M_MIPS1.  */
     34 #define M_SPARC64_OPENBSD	M_MIPS1
     35 
     36 /* Offset of StackGhost cookie within `struct md_coredump' on
     37    OpenBSD/sparc.  */
     38 #define SPARC_WCOOKIE_OFFSET	344
     39 
     40 /* Offset of StackGhost cookie within `struct md_coredump' on
     41    OpenBSD/sparc64.  */
     42 #define SPARC64_WCOOKIE_OFFSET	832
     43 
     44 #define netbsd_core_file_matches_executable_p generic_core_file_matches_executable_p
     45 #define netbsd_core_file_pid _bfd_nocore_core_file_pid
     46 
     47 struct netbsd_core_struct
     48 {
     49   struct core core;
     50 };
     51 
     52 /* Handle NetBSD-style core dump file.  */
     53 
     54 static bfd_cleanup
     55 netbsd_core_file_p (bfd *abfd)
     56 {
     57   int val;
     58   unsigned i;
     59   file_ptr offset;
     60   asection *asect;
     61   struct core core;
     62   struct coreseg coreseg;
     63   struct netbsd_core_struct *rawptr;
     64 
     65   val = bfd_read (&core, sizeof core, abfd);
     66   if (val != sizeof core)
     67     {
     68       /* Too small to be a core file.  */
     69       bfd_set_error (bfd_error_wrong_format);
     70       return 0;
     71     }
     72 
     73   if (CORE_GETMAGIC (core) != COREMAGIC)
     74     {
     75       bfd_set_error (bfd_error_wrong_format);
     76       return 0;
     77     }
     78 
     79   rawptr = bfd_alloc (abfd, sizeof (*rawptr) + 1);
     80   if (rawptr == NULL)
     81     return 0;
     82 
     83   abfd->tdata.netbsd_core_data = rawptr;
     84   rawptr->core = core;
     85   /* Ensure core_file_failing_command string is terminated.  This is
     86      just to stop buffer overflows on fuzzed files.  */
     87   ((char *) rawptr)[sizeof (*rawptr)] = 0;
     88 
     89   offset = core.c_hdrsize;
     90   for (i = 0; i < core.c_nseg; i++)
     91     {
     92       const char *sname;
     93       flagword flags;
     94 
     95       if (bfd_seek (abfd, offset, SEEK_SET) != 0)
     96 	goto punt;
     97 
     98       val = bfd_read (&coreseg, sizeof coreseg, abfd);
     99       if (val != sizeof coreseg)
    100 	{
    101 	  bfd_set_error (bfd_error_file_truncated);
    102 	  goto punt;
    103 	}
    104       if (CORE_GETMAGIC (coreseg) != CORESEGMAGIC)
    105 	{
    106 	  bfd_set_error (bfd_error_wrong_format);
    107 	  goto punt;
    108 	}
    109 
    110       offset += core.c_seghdrsize;
    111 
    112       switch (CORE_GETFLAG (coreseg))
    113 	{
    114 	case CORE_CPU:
    115 	  sname = ".reg";
    116 	  flags = SEC_ALLOC + SEC_HAS_CONTENTS;
    117 	  break;
    118 	case CORE_DATA:
    119 	  sname = ".data";
    120 	  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
    121 	  break;
    122 	case CORE_STACK:
    123 	  sname = ".stack";
    124 	  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
    125 	  break;
    126 	default:
    127 	  sname = ".unknown";
    128 	  flags = SEC_ALLOC + SEC_HAS_CONTENTS;
    129 	  break;
    130 	}
    131       asect = bfd_make_section_anyway_with_flags (abfd, sname, flags);
    132       if (asect == NULL)
    133 	goto punt;
    134 
    135       asect->size = coreseg.c_size;
    136       asect->vma = coreseg.c_addr;
    137       asect->filepos = offset;
    138       asect->alignment_power = 2;
    139 
    140       if (CORE_GETFLAG (coreseg) == CORE_CPU)
    141 	{
    142 	  bfd_size_type wcookie_offset;
    143 
    144 	  switch (CORE_GETMID (core))
    145 	    {
    146 	    case M_SPARC_NETBSD:
    147 	      wcookie_offset = SPARC_WCOOKIE_OFFSET;
    148 	      break;
    149 	    case M_SPARC64_OPENBSD:
    150 	      wcookie_offset = SPARC64_WCOOKIE_OFFSET;
    151 	      break;
    152 	    default:
    153 	      wcookie_offset = 0;
    154 	      break;
    155 	    }
    156 
    157 	  if (wcookie_offset > 0 && coreseg.c_size > wcookie_offset)
    158 	    {
    159 	      /* Truncate the .reg section.  */
    160 	      asect->size = wcookie_offset;
    161 
    162 	      /* And create the .wcookie section.  */
    163 	      flags = SEC_ALLOC + SEC_HAS_CONTENTS;
    164 	      asect = bfd_make_section_anyway_with_flags (abfd, ".wcookie",
    165 							  flags);
    166 	      if (asect == NULL)
    167 		goto punt;
    168 
    169 	      asect->size = coreseg.c_size - wcookie_offset;
    170 	      asect->vma = 0;
    171 	      asect->filepos = offset + wcookie_offset;
    172 	      asect->alignment_power = 2;
    173 	    }
    174 	}
    175 
    176       offset += coreseg.c_size;
    177     }
    178 
    179   /* Set architecture from machine ID.  */
    180   switch (CORE_GETMID (core))
    181     {
    182     case M_ALPHA_NETBSD:
    183       bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
    184       break;
    185 
    186     case M_ARM6_NETBSD:
    187       bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_3);
    188       break;
    189 
    190     case M_X86_64_NETBSD:
    191       bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
    192       break;
    193 
    194     case M_386_NETBSD:
    195       bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386);
    196       break;
    197 
    198     case M_68K_NETBSD:
    199     case M_68K4K_NETBSD:
    200       bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
    201       break;
    202 
    203     case M_HPPA_OPENBSD:
    204       bfd_default_set_arch_mach (abfd, bfd_arch_hppa, bfd_mach_hppa11);
    205       break;
    206 
    207     case M_POWERPC_NETBSD:
    208       bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc);
    209       break;
    210 
    211     case M_SPARC_NETBSD:
    212       bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
    213       break;
    214 
    215     case M_SPARC64_NETBSD:
    216     case M_SPARC64_OPENBSD:
    217       bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9);
    218       break;
    219 
    220     case M_VAX_NETBSD:
    221     case M_VAX4K_NETBSD:
    222       bfd_default_set_arch_mach (abfd, bfd_arch_vax, 0);
    223       break;
    224     }
    225 
    226   /* OK, we believe you.  You're a core file (sure, sure).  */
    227   return _bfd_no_cleanup;
    228 
    229  punt:
    230   bfd_release (abfd, abfd->tdata.any);
    231   abfd->tdata.any = NULL;
    232   bfd_section_list_clear (abfd);
    233   return 0;
    234 }
    235 
    236 static char*
    237 netbsd_core_file_failing_command (bfd *abfd)
    238 {
    239   /*return core_command (abfd);*/
    240   return abfd->tdata.netbsd_core_data->core.c_name;
    241 }
    242 
    243 static int
    244 netbsd_core_file_failing_signal (bfd *abfd)
    245 {
    246   /*return core_signal (abfd);*/
    247   return abfd->tdata.netbsd_core_data->core.c_signo;
    248 }
    249 
    250 /* If somebody calls any byte-swapping routines, shoot them.  */
    252 
    253 static void
    254 swap_abort (void)
    255 {
    256  /* This way doesn't require any declaration for ANSI to fuck up.  */
    257   abort ();
    258 }
    259 
    260 #define	NO_GET ((bfd_vma (*) (const void *)) swap_abort)
    261 #define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
    262 #define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
    263 #define	NO_GET64 ((uint64_t (*) (const void *)) swap_abort)
    264 #define	NO_PUT64 ((void (*) (uint64_t, void *)) swap_abort)
    265 #define	NO_GETS64 ((int64_t (*) (const void *)) swap_abort)
    266 
    267 const bfd_target core_netbsd_vec =
    268   {
    269     "netbsd-core",
    270     bfd_target_unknown_flavour,
    271     BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
    272     BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
    273     (HAS_RELOC | EXEC_P |	/* Object flags.  */
    274      HAS_LINENO | HAS_DEBUG |
    275      HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
    276     (SEC_HAS_CONTENTS |		/* Section flags.  */
    277      SEC_ALLOC | SEC_LOAD | SEC_RELOC),
    278     0,				/* Symbol prefix.  */
    279     ' ',			/* ar_pad_char.  */
    280     16,				/* ar_max_namelen.  */
    281     0,				/* Match priority.  */
    282     TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
    283     NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data.  */
    284     NO_GET, NO_GETS, NO_PUT,		/* 32 bit data.  */
    285     NO_GET, NO_GETS, NO_PUT,		/* 16 bit data.  */
    286     NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs.  */
    287     NO_GET, NO_GETS, NO_PUT,		/* 32 bit hdrs.  */
    288     NO_GET, NO_GETS, NO_PUT,		/* 16 bit hdrs.  */
    289 
    290     {					/* bfd_check_format.  */
    291       _bfd_dummy_target,		/* Unknown format.  */
    292       _bfd_dummy_target,		/* Object file.  */
    293       _bfd_dummy_target,		/* Archive.  */
    294       netbsd_core_file_p		/* A core file.  */
    295     },
    296     {					/* bfd_set_format.  */
    297       _bfd_bool_bfd_false_error,
    298       _bfd_bool_bfd_false_error,
    299       _bfd_bool_bfd_false_error,
    300       _bfd_bool_bfd_false_error
    301     },
    302     {					/* bfd_write_contents.  */
    303       _bfd_bool_bfd_false_error,
    304       _bfd_bool_bfd_false_error,
    305       _bfd_bool_bfd_false_error,
    306       _bfd_bool_bfd_false_error
    307     },
    308 
    309     BFD_JUMP_TABLE_GENERIC (_bfd_generic),
    310     BFD_JUMP_TABLE_COPY (_bfd_generic),
    311     BFD_JUMP_TABLE_CORE (netbsd),
    312     BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
    313     BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
    314     BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
    315     BFD_JUMP_TABLE_WRITE (_bfd_generic),
    316     BFD_JUMP_TABLE_LINK (_bfd_nolink),
    317     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
    318 
    319     NULL,
    320 
    321     NULL				/* Backend_data.  */
    322   };
    323