cisco-core.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /* BFD back-end for CISCO crash dumps.
  2. Copyright (C) 1994-2022 Free Software Foundation, Inc.
  3. This file is part of BFD, the Binary File Descriptor library.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  15. MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include "bfd.h"
  18. #include "libbfd.h"
  19. /* core_file_failing_signal returns a host signal (this probably should
  20. be fixed). */
  21. #include <signal.h>
  22. /* for MSVC builds */
  23. #ifndef SIGTRAP
  24. # define SIGTRAP 5
  25. #endif
  26. #ifndef SIGEMT
  27. # define SIGEMT 6
  28. #endif
  29. #ifndef SIGBUS
  30. # define SIGBUS 10
  31. #endif
  32. int crash_info_locs[] =
  33. {
  34. 0x0250, /* mips, ppc, x86, i960 */
  35. 0x0400, /* m68k, mips, x86, i960 */
  36. 0x0FFC, /* m68k, mips, ppc, x86, i960 */
  37. 0x3000, /* ppc */
  38. 0x4FFC, /* m68k */
  39. -1
  40. };
  41. #define CRASH_MAGIC 0xdead1234
  42. #define MASK_ADDR(x) ((x) & 0x0fffffff) /* Mask crash info address */
  43. typedef enum
  44. {
  45. CRASH_REASON_NOTCRASHED = 0,
  46. CRASH_REASON_EXCEPTION = 1,
  47. CRASH_REASON_CORRUPT = 2,
  48. } crashreason;
  49. typedef struct
  50. {
  51. char magic[4]; /* Magic number */
  52. char version[4]; /* Version number */
  53. char reason[4]; /* Crash reason */
  54. char cpu_vector[4]; /* CPU vector for exceptions */
  55. char registers[4]; /* Pointer to saved registers */
  56. char rambase[4]; /* Base of RAM (not in V1 crash info) */
  57. char textbase[4]; /* Base of .text section (not in V3 crash info) */
  58. char database[4]; /* Base of .data section (not in V3 crash info) */
  59. char bssbase[4]; /* Base of .bss section (not in V3 crash info) */
  60. } crashinfo_external;
  61. struct cisco_core_struct
  62. {
  63. int sig;
  64. };
  65. #define cisco_core_file_matches_executable_p generic_core_file_matches_executable_p
  66. #define cisco_core_file_pid _bfd_nocore_core_file_pid
  67. /* Examine the file for a crash info struct at the offset given by
  68. CRASH_INFO_LOC. */
  69. static bfd_cleanup
  70. cisco_core_file_validate (bfd *abfd, int crash_info_loc)
  71. {
  72. char buf[4];
  73. unsigned int crashinfo_offset;
  74. crashinfo_external crashinfo;
  75. bfd_size_type nread;
  76. unsigned int magic;
  77. unsigned int version;
  78. unsigned int rambase;
  79. sec_ptr asect;
  80. struct stat statbuf;
  81. size_t amt;
  82. flagword flags;
  83. if (bfd_seek (abfd, (file_ptr) crash_info_loc, SEEK_SET) != 0)
  84. return NULL;
  85. nread = bfd_bread (buf, (bfd_size_type) 4, abfd);
  86. if (nread != 4)
  87. {
  88. if (bfd_get_error () != bfd_error_system_call)
  89. bfd_set_error (bfd_error_wrong_format);
  90. return NULL;
  91. }
  92. crashinfo_offset = MASK_ADDR (bfd_get_32 (abfd, buf));
  93. if (bfd_seek (abfd, (file_ptr) crashinfo_offset, SEEK_SET) != 0)
  94. {
  95. /* Most likely we failed because of a bogus (huge) offset */
  96. bfd_set_error (bfd_error_wrong_format);
  97. return NULL;
  98. }
  99. nread = bfd_bread (&crashinfo, (bfd_size_type) sizeof (crashinfo), abfd);
  100. if (nread != sizeof (crashinfo))
  101. {
  102. if (bfd_get_error () != bfd_error_system_call)
  103. bfd_set_error (bfd_error_wrong_format);
  104. return NULL;
  105. }
  106. if (bfd_stat (abfd, &statbuf) < 0)
  107. {
  108. bfd_set_error (bfd_error_system_call);
  109. return NULL;
  110. }
  111. magic = bfd_get_32 (abfd, crashinfo.magic);
  112. if (magic != CRASH_MAGIC)
  113. {
  114. bfd_set_error (bfd_error_wrong_format);
  115. return NULL;
  116. }
  117. version = bfd_get_32 (abfd, crashinfo.version);
  118. if (version == 0)
  119. {
  120. bfd_set_error (bfd_error_wrong_format);
  121. return NULL;
  122. }
  123. else if (version == 1)
  124. {
  125. /* V1 core dumps don't specify the dump base, assume 0 */
  126. rambase = 0;
  127. }
  128. else
  129. {
  130. rambase = bfd_get_32 (abfd, crashinfo.rambase);
  131. }
  132. /* OK, we believe you. You're a core file. */
  133. amt = sizeof (struct cisco_core_struct);
  134. abfd->tdata.cisco_core_data = (struct cisco_core_struct *) bfd_zmalloc (amt);
  135. if (abfd->tdata.cisco_core_data == NULL)
  136. return NULL;
  137. switch ((crashreason) bfd_get_32 (abfd, crashinfo.reason))
  138. {
  139. case CRASH_REASON_NOTCRASHED:
  140. /* Crash file probably came from write core. */
  141. abfd->tdata.cisco_core_data->sig = 0;
  142. break;
  143. case CRASH_REASON_CORRUPT:
  144. /* The crash context area was corrupt -- proceed with caution.
  145. We have no way of passing this information back to the caller. */
  146. abfd->tdata.cisco_core_data->sig = 0;
  147. break;
  148. case CRASH_REASON_EXCEPTION:
  149. /* Crash occured due to CPU exception. */
  150. /* This is 68k-specific; for MIPS we'll need to interpret
  151. cpu_vector differently based on the target configuration
  152. (since CISCO core files don't seem to have the processor
  153. encoded in them). */
  154. switch (bfd_get_32 (abfd, crashinfo.cpu_vector))
  155. {
  156. /* bus error */
  157. case 2 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
  158. /* address error */
  159. case 3 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
  160. /* illegal instruction */
  161. case 4 : abfd->tdata.cisco_core_data->sig = SIGILL; break;
  162. /* zero divide */
  163. case 5 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  164. /* chk instruction */
  165. case 6 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  166. /* trapv instruction */
  167. case 7 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  168. /* privilege violation */
  169. case 8 : abfd->tdata.cisco_core_data->sig = SIGSEGV; break;
  170. /* trace trap */
  171. case 9 : abfd->tdata.cisco_core_data->sig = SIGTRAP; break;
  172. /* line 1010 emulator */
  173. case 10: abfd->tdata.cisco_core_data->sig = SIGILL; break;
  174. /* line 1111 emulator */
  175. case 11: abfd->tdata.cisco_core_data->sig = SIGILL; break;
  176. /* Coprocessor protocol violation. Using a standard MMU or FPU
  177. this cannot be triggered by software. Call it a SIGBUS. */
  178. case 13: abfd->tdata.cisco_core_data->sig = SIGBUS; break;
  179. /* interrupt */
  180. case 31: abfd->tdata.cisco_core_data->sig = SIGINT; break;
  181. /* breakpoint */
  182. case 33: abfd->tdata.cisco_core_data->sig = SIGTRAP; break;
  183. /* floating point err */
  184. case 48: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  185. /* floating point err */
  186. case 49: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  187. /* zero divide */
  188. case 50: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  189. /* underflow */
  190. case 51: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  191. /* operand error */
  192. case 52: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  193. /* overflow */
  194. case 53: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  195. /* NAN */
  196. case 54: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
  197. default:
  198. #ifndef SIGEMT
  199. #define SIGEMT SIGTRAP
  200. #endif
  201. /* "software generated"*/
  202. abfd->tdata.cisco_core_data->sig = SIGEMT;
  203. }
  204. break;
  205. default:
  206. /* Unknown crash reason. */
  207. abfd->tdata.cisco_core_data->sig = 0;
  208. break;
  209. }
  210. /* Create a ".data" section that maps the entire file, which is
  211. essentially a dump of the target system's RAM. */
  212. flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
  213. asect = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
  214. if (asect == NULL)
  215. goto error_return;
  216. /* The size of memory is the size of the core file itself. */
  217. asect->size = statbuf.st_size;
  218. asect->vma = rambase;
  219. asect->filepos = 0;
  220. /* Create a ".crash" section to allow access to the saved
  221. crash information. */
  222. flags = SEC_HAS_CONTENTS;
  223. asect = bfd_make_section_anyway_with_flags (abfd, ".crash", flags);
  224. if (asect == NULL)
  225. goto error_return;
  226. asect->vma = 0;
  227. asect->filepos = crashinfo_offset;
  228. asect->size = sizeof (crashinfo);
  229. /* Create a ".reg" section to allow access to the saved
  230. registers. */
  231. asect = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
  232. if (asect == NULL)
  233. goto error_return;
  234. asect->vma = 0;
  235. asect->filepos = bfd_get_32 (abfd, crashinfo.registers) - rambase;
  236. /* Since we don't know the exact size of the saved register info,
  237. choose a register section size that is either the remaining part
  238. of the file, or 1024, whichever is smaller. */
  239. nread = statbuf.st_size - asect->filepos;
  240. asect->size = (nread < 1024) ? nread : 1024;
  241. return _bfd_no_cleanup;
  242. /* Get here if we have already started filling out the BFD
  243. and there is an error of some kind. */
  244. error_return:
  245. bfd_release (abfd, abfd->tdata.any);
  246. abfd->tdata.any = NULL;
  247. bfd_section_list_clear (abfd);
  248. return NULL;
  249. }
  250. static bfd_cleanup
  251. cisco_core_file_p (bfd *abfd)
  252. {
  253. int *crash_info_locp;
  254. bfd_cleanup cleanup = NULL;
  255. for (crash_info_locp = crash_info_locs;
  256. *crash_info_locp != -1 && cleanup == NULL;
  257. crash_info_locp++)
  258. {
  259. cleanup = cisco_core_file_validate (abfd, *crash_info_locp);
  260. }
  261. return cleanup;
  262. }
  263. static char *
  264. cisco_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
  265. {
  266. return NULL;
  267. }
  268. static int
  269. cisco_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
  270. {
  271. return abfd->tdata.cisco_core_data->sig;
  272. }
  273. extern const bfd_target core_cisco_le_vec;
  274. const bfd_target core_cisco_be_vec =
  275. {
  276. "cisco-ios-core-big",
  277. bfd_target_unknown_flavour,
  278. BFD_ENDIAN_BIG, /* target byte order */
  279. BFD_ENDIAN_BIG, /* target headers byte order */
  280. (HAS_RELOC | EXEC_P /* object flags */
  281. | HAS_LINENO | HAS_DEBUG
  282. | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
  283. (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
  284. 0, /* symbol prefix */
  285. ' ', /* ar_pad_char */
  286. 16, /* ar_max_namelen */
  287. 0, /* match priority. */
  288. TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
  289. bfd_getb64, bfd_getb_signed_64, bfd_putb64,
  290. bfd_getb32, bfd_getb_signed_32, bfd_putb32,
  291. bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
  292. bfd_getb64, bfd_getb_signed_64, bfd_putb64,
  293. bfd_getb32, bfd_getb_signed_32, bfd_putb32,
  294. bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
  295. { /* bfd_check_format */
  296. _bfd_dummy_target, /* unknown format */
  297. _bfd_dummy_target, /* object file */
  298. _bfd_dummy_target, /* archive */
  299. cisco_core_file_p /* a core file */
  300. },
  301. { /* bfd_set_format */
  302. _bfd_bool_bfd_false_error,
  303. _bfd_bool_bfd_false_error,
  304. _bfd_bool_bfd_false_error,
  305. _bfd_bool_bfd_false_error
  306. },
  307. { /* bfd_write_contents */
  308. _bfd_bool_bfd_false_error,
  309. _bfd_bool_bfd_false_error,
  310. _bfd_bool_bfd_false_error,
  311. _bfd_bool_bfd_false_error
  312. },
  313. BFD_JUMP_TABLE_GENERIC (_bfd_generic),
  314. BFD_JUMP_TABLE_COPY (_bfd_generic),
  315. BFD_JUMP_TABLE_CORE (cisco),
  316. BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
  317. BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
  318. BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
  319. BFD_JUMP_TABLE_WRITE (_bfd_generic),
  320. BFD_JUMP_TABLE_LINK (_bfd_nolink),
  321. BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
  322. &core_cisco_le_vec,
  323. NULL /* backend_data */
  324. };
  325. const bfd_target core_cisco_le_vec =
  326. {
  327. "cisco-ios-core-little",
  328. bfd_target_unknown_flavour,
  329. BFD_ENDIAN_LITTLE, /* target byte order */
  330. BFD_ENDIAN_LITTLE, /* target headers byte order */
  331. (HAS_RELOC | EXEC_P /* object flags */
  332. | HAS_LINENO | HAS_DEBUG
  333. | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
  334. (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
  335. 0, /* symbol prefix */
  336. ' ', /* ar_pad_char */
  337. 16, /* ar_max_namelen */
  338. 0, /* match_priority */
  339. TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
  340. bfd_getl64, bfd_getl_signed_64, bfd_putl64,
  341. bfd_getl32, bfd_getl_signed_32, bfd_putl32,
  342. bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
  343. bfd_getl64, bfd_getl_signed_64, bfd_putl64,
  344. bfd_getl32, bfd_getl_signed_32, bfd_putl32,
  345. bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
  346. { /* bfd_check_format */
  347. _bfd_dummy_target, /* unknown format */
  348. _bfd_dummy_target, /* object file */
  349. _bfd_dummy_target, /* archive */
  350. cisco_core_file_p /* a core file */
  351. },
  352. { /* bfd_set_format */
  353. _bfd_bool_bfd_false_error,
  354. _bfd_bool_bfd_false_error,
  355. _bfd_bool_bfd_false_error,
  356. _bfd_bool_bfd_false_error
  357. },
  358. { /* bfd_write_contents */
  359. _bfd_bool_bfd_false_error,
  360. _bfd_bool_bfd_false_error,
  361. _bfd_bool_bfd_false_error,
  362. _bfd_bool_bfd_false_error
  363. },
  364. BFD_JUMP_TABLE_GENERIC (_bfd_generic),
  365. BFD_JUMP_TABLE_COPY (_bfd_generic),
  366. BFD_JUMP_TABLE_CORE (cisco),
  367. BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
  368. BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
  369. BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
  370. BFD_JUMP_TABLE_WRITE (_bfd_generic),
  371. BFD_JUMP_TABLE_LINK (_bfd_nolink),
  372. BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
  373. &core_cisco_be_vec,
  374. NULL /* backend_data */
  375. };