trad-core.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /* BFD back end for traditional Unix core files (U-area and raw sections)
  2. Copyright (C) 1988-2022 Free Software Foundation, Inc.
  3. Written by John Gilmore of Cygnus Support.
  4. This file is part of BFD, the Binary File Descriptor library.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. MA 02110-1301, USA. */
  17. #include "sysdep.h"
  18. #include "bfd.h"
  19. #include "libbfd.h"
  20. #include "libaout.h" /* BFD a.out internal data structures */
  21. #include <sys/param.h>
  22. #include <dirent.h>
  23. #include <signal.h>
  24. #include <sys/user.h> /* After a.out.h */
  25. #ifdef TRAD_HEADER
  26. #include TRAD_HEADER
  27. #endif
  28. #ifndef NBPG
  29. # define NBPG getpagesize()
  30. #endif
  31. struct trad_core_struct
  32. {
  33. asection *data_section;
  34. asection *stack_section;
  35. asection *reg_section;
  36. struct user u;
  37. };
  38. #define core_upage(bfd) (&((bfd)->tdata.trad_core_data->u))
  39. #define core_datasec(bfd) ((bfd)->tdata.trad_core_data->data_section)
  40. #define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section)
  41. #define core_regsec(bfd) ((bfd)->tdata.trad_core_data->reg_section)
  42. /* forward declarations */
  43. #define trad_unix_core_file_matches_executable_p generic_core_file_matches_executable_p
  44. #define trad_unix_core_file_pid _bfd_nocore_core_file_pid
  45. /* Handle 4.2-style (and perhaps also sysV-style) core dump file. */
  46. static bfd_cleanup
  47. trad_unix_core_file_p (bfd *abfd)
  48. {
  49. int val;
  50. struct user u;
  51. struct trad_core_struct *rawptr;
  52. size_t amt;
  53. flagword flags;
  54. #ifdef TRAD_CORE_USER_OFFSET
  55. /* If defined, this macro is the file position of the user struct. */
  56. if (bfd_seek (abfd, (file_ptr) TRAD_CORE_USER_OFFSET, SEEK_SET) != 0)
  57. return 0;
  58. #endif
  59. val = bfd_bread ((void *) &u, (bfd_size_type) sizeof u, abfd);
  60. if (val != sizeof u)
  61. {
  62. /* Too small to be a core file */
  63. bfd_set_error (bfd_error_wrong_format);
  64. return 0;
  65. }
  66. /* Sanity check perhaps??? */
  67. if (u.u_dsize > 0x1000000) /* Remember, it's in pages... */
  68. {
  69. bfd_set_error (bfd_error_wrong_format);
  70. return 0;
  71. }
  72. if (u.u_ssize > 0x1000000)
  73. {
  74. bfd_set_error (bfd_error_wrong_format);
  75. return 0;
  76. }
  77. /* Check that the size claimed is no greater than the file size. */
  78. {
  79. struct stat statbuf;
  80. if (bfd_stat (abfd, &statbuf) < 0)
  81. return 0;
  82. if ((ufile_ptr) NBPG * (UPAGES + u.u_dsize
  83. #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
  84. - u.u_tsize
  85. #endif
  86. + u.u_ssize)
  87. > (ufile_ptr) statbuf.st_size)
  88. {
  89. bfd_set_error (bfd_error_wrong_format);
  90. return 0;
  91. }
  92. #ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE
  93. if (((ufile_ptr) NBPG * (UPAGES + u.u_dsize + u.u_ssize)
  94. #ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED
  95. /* Some systems write the file too big. */
  96. + TRAD_CORE_EXTRA_SIZE_ALLOWED
  97. #endif
  98. )
  99. < (ufile_ptr) statbuf.st_size)
  100. {
  101. /* The file is too big. Maybe it's not a core file
  102. or we otherwise have bad values for u_dsize and u_ssize). */
  103. bfd_set_error (bfd_error_wrong_format);
  104. return 0;
  105. }
  106. #endif
  107. }
  108. /* OK, we believe you. You're a core file (sure, sure). */
  109. /* Allocate both the upage and the struct core_data at once, so
  110. a single free() will free them both. */
  111. amt = sizeof (struct trad_core_struct);
  112. rawptr = (struct trad_core_struct *) bfd_zmalloc (amt);
  113. if (rawptr == NULL)
  114. return 0;
  115. abfd->tdata.trad_core_data = rawptr;
  116. rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
  117. /* Create the sections. */
  118. flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
  119. core_stacksec(abfd) = bfd_make_section_anyway_with_flags (abfd, ".stack",
  120. flags);
  121. if (core_stacksec (abfd) == NULL)
  122. goto fail;
  123. core_datasec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".data",
  124. flags);
  125. if (core_datasec (abfd) == NULL)
  126. goto fail;
  127. core_regsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg",
  128. SEC_HAS_CONTENTS);
  129. if (core_regsec (abfd) == NULL)
  130. goto fail;
  131. core_datasec (abfd)->size = NBPG * u.u_dsize
  132. #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
  133. - NBPG * u.u_tsize
  134. #endif
  135. ;
  136. core_stacksec (abfd)->size = NBPG * u.u_ssize;
  137. core_regsec (abfd)->size = NBPG * UPAGES; /* Larger than sizeof struct u */
  138. /* What a hack... we'd like to steal it from the exec file,
  139. since the upage does not seem to provide it. FIXME. */
  140. #ifdef HOST_DATA_START_ADDR
  141. core_datasec (abfd)->vma = HOST_DATA_START_ADDR;
  142. #else
  143. core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize);
  144. #endif
  145. #ifdef HOST_STACK_START_ADDR
  146. core_stacksec (abfd)->vma = HOST_STACK_START_ADDR;
  147. #else
  148. core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize);
  149. #endif
  150. /* This is tricky. As the "register section", we give them the entire
  151. upage and stack. u.u_ar0 points to where "register 0" is stored.
  152. There are two tricks with this, though. One is that the rest of the
  153. registers might be at positive or negative (or both) displacements
  154. from *u_ar0. The other is that u_ar0 is sometimes an absolute address
  155. in kernel memory, and on other systems it is an offset from the beginning
  156. of the `struct user'.
  157. As a practical matter, we don't know where the registers actually are,
  158. so we have to pass the whole area to GDB. We encode the value of u_ar0
  159. by setting the .regs section up so that its virtual memory address
  160. 0 is at the place pointed to by u_ar0 (by setting the vma of the start
  161. of the section to -u_ar0). GDB uses this info to locate the regs,
  162. using minor trickery to get around the offset-or-absolute-addr problem. */
  163. core_regsec (abfd)->vma = - (bfd_vma) (unsigned long) u.u_ar0;
  164. core_datasec (abfd)->filepos = NBPG * UPAGES;
  165. core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize
  166. #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
  167. - NBPG * u.u_tsize
  168. #endif
  169. ;
  170. core_regsec (abfd)->filepos = 0; /* Register segment is the upage */
  171. /* Align to word at least */
  172. core_stacksec (abfd)->alignment_power = 2;
  173. core_datasec (abfd)->alignment_power = 2;
  174. core_regsec (abfd)->alignment_power = 2;
  175. return _bfd_no_cleanup;
  176. fail:
  177. bfd_release (abfd, abfd->tdata.any);
  178. abfd->tdata.any = NULL;
  179. bfd_section_list_clear (abfd);
  180. return NULL;
  181. }
  182. static char *
  183. trad_unix_core_file_failing_command (bfd *abfd)
  184. {
  185. #ifndef NO_CORE_COMMAND
  186. char *com = abfd->tdata.trad_core_data->u.u_comm;
  187. if (*com)
  188. return com;
  189. else
  190. #endif
  191. return 0;
  192. }
  193. static int
  194. trad_unix_core_file_failing_signal (bfd *ignore_abfd ATTRIBUTE_UNUSED)
  195. {
  196. #ifdef TRAD_UNIX_CORE_FILE_FAILING_SIGNAL
  197. return TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(ignore_abfd);
  198. #else
  199. return -1; /* FIXME, where is it? */
  200. #endif
  201. }
  202. /* If somebody calls any byte-swapping routines, shoot them. */
  203. static void
  204. swap_abort (void)
  205. {
  206. abort (); /* This way doesn't require any declaration for ANSI to fuck up */
  207. }
  208. #define NO_GET ((bfd_vma (*) (const void *)) swap_abort)
  209. #define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
  210. #define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
  211. #define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
  212. #define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
  213. #define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
  214. const bfd_target core_trad_vec =
  215. {
  216. "trad-core",
  217. bfd_target_unknown_flavour,
  218. BFD_ENDIAN_UNKNOWN, /* target byte order */
  219. BFD_ENDIAN_UNKNOWN, /* target headers byte order */
  220. (HAS_RELOC | EXEC_P | /* object flags */
  221. HAS_LINENO | HAS_DEBUG |
  222. HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
  223. (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
  224. 0, /* symbol prefix */
  225. ' ', /* ar_pad_char */
  226. 16, /* ar_max_namelen */
  227. 0, /* match priority. */
  228. TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
  229. NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data */
  230. NO_GET, NO_GETS, NO_PUT, /* 32 bit data */
  231. NO_GET, NO_GETS, NO_PUT, /* 16 bit data */
  232. NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs */
  233. NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs */
  234. NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs */
  235. { /* bfd_check_format */
  236. _bfd_dummy_target, /* unknown format */
  237. _bfd_dummy_target, /* object file */
  238. _bfd_dummy_target, /* archive */
  239. trad_unix_core_file_p /* a core file */
  240. },
  241. { /* bfd_set_format */
  242. _bfd_bool_bfd_false_error,
  243. _bfd_bool_bfd_false_error,
  244. _bfd_bool_bfd_false_error,
  245. _bfd_bool_bfd_false_error
  246. },
  247. { /* bfd_write_contents */
  248. _bfd_bool_bfd_false_error,
  249. _bfd_bool_bfd_false_error,
  250. _bfd_bool_bfd_false_error,
  251. _bfd_bool_bfd_false_error
  252. },
  253. BFD_JUMP_TABLE_GENERIC (_bfd_generic),
  254. BFD_JUMP_TABLE_COPY (_bfd_generic),
  255. BFD_JUMP_TABLE_CORE (trad_unix),
  256. BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
  257. BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
  258. BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
  259. BFD_JUMP_TABLE_WRITE (_bfd_generic),
  260. BFD_JUMP_TABLE_LINK (_bfd_nolink),
  261. BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
  262. NULL,
  263. NULL /* backend_data */
  264. };