aix5ppc-core.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /* IBM RS/6000 "XCOFF" back-end for BFD.
  2. Copyright (C) 2001-2022 Free Software Foundation, Inc.
  3. Written by Tom Rix
  4. Contributed by Red Hat Inc.
  5. This file is part of BFD, the Binary File Descriptor library.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  17. MA 02110-1301, USA. */
  18. #include "sysdep.h"
  19. #include "bfd.h"
  20. bfd_cleanup xcoff64_core_p (bfd *);
  21. bool xcoff64_core_file_matches_executable_p (bfd *, bfd *);
  22. char *xcoff64_core_file_failing_command (bfd *);
  23. int xcoff64_core_file_failing_signal (bfd *);
  24. #ifdef AIX_5_CORE
  25. #include "libbfd.h"
  26. /* Aix 5.1 system include file. */
  27. /* Need to define this macro so struct ld_info64 get included. */
  28. #define __LDINFO_PTRACE64__
  29. #include <sys/ldr.h>
  30. #include <core.h>
  31. /* The default architecture and machine for matching core files. */
  32. #define DEFAULT_ARCHITECTURE bfd_arch_powerpc
  33. #define DEFAULT_MACHINE bfd_mach_ppc_620
  34. #define core_hdr(abfd) ((struct core_dumpxx *) abfd->tdata.any)
  35. #define CHECK_FILE_OFFSET(s, v) \
  36. ((bfd_signed_vma)(v) < 0 || (bfd_signed_vma)(v) > (bfd_signed_vma)(s).st_size)
  37. bfd_cleanup
  38. xcoff64_core_p (bfd *abfd)
  39. {
  40. enum bfd_architecture arch;
  41. unsigned long mach;
  42. struct core_dumpxx core, *new_core_hdr;
  43. struct stat statbuf;
  44. asection *sec;
  45. struct __ld_info64 ldinfo;
  46. bfd_vma ld_offset;
  47. bfd_size_type i;
  48. struct vm_infox vminfo;
  49. flagword flags;
  50. /* Get the header. */
  51. if (bfd_seek (abfd, 0, SEEK_SET) != 0)
  52. goto xcoff64_core_p_error;
  53. if (sizeof (struct core_dumpxx)
  54. != bfd_bread (&core, sizeof (struct core_dumpxx), abfd))
  55. goto xcoff64_core_p_error;
  56. if (bfd_stat (abfd, &statbuf) < 0)
  57. goto xcoff64_core_p_error;
  58. /* Sanity checks
  59. c_flag has CORE_VERSION_1, Aix 4+
  60. c_entries = 0 for Aix 4.3+
  61. IS_PROC64 is a macro defined in procinfo.h, test for 64 bit process.
  62. We will still be confused if a Aix 4.3 64 bit core file is
  63. copied over to a Aix 5 machine.
  64. Check file header offsets
  65. See rs6000-core.c for comment on size of core
  66. If there isn't enough of a real core file, bail. */
  67. if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1))
  68. || (0 != core.c_entries)
  69. || (! (IS_PROC64 (&core.c_u.U_proc)))
  70. || ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox)))
  71. || ((CHECK_FILE_OFFSET (statbuf, core.c_loader)))
  72. || ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize)))
  73. || ((CHECK_FILE_OFFSET (statbuf, core.c_thr)))
  74. || ((CHECK_FILE_OFFSET (statbuf, core.c_segregion)))
  75. || ((CHECK_FILE_OFFSET (statbuf, core.c_stack)))
  76. || ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size)))
  77. || ((CHECK_FILE_OFFSET (statbuf, core.c_data)))
  78. || ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize)))
  79. || (! (core.c_flag & UBLOCK_VALID))
  80. || (! (core.c_flag & LE_VALID)))
  81. goto xcoff64_core_p_error;
  82. /* Check for truncated stack or general truncating. */
  83. if ((! (core.c_flag & USTACK_VALID))
  84. || (core.c_flag & CORE_TRUNC))
  85. {
  86. bfd_set_error (bfd_error_file_truncated);
  87. return NULL;
  88. }
  89. new_core_hdr = bfd_zalloc (abfd, sizeof (struct core_dumpxx));
  90. if (NULL == new_core_hdr)
  91. return NULL;
  92. memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx));
  93. /* The core_hdr() macro is no longer used here because it would
  94. expand to code relying on gcc's cast-as-lvalue extension,
  95. which was removed in gcc 4.0. */
  96. abfd->tdata.any = new_core_hdr;
  97. /* .stack section. */
  98. flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
  99. sec = bfd_make_section_anyway_with_flags (abfd, ".stack", flags);
  100. if (NULL == sec)
  101. return NULL;
  102. sec->size = core.c_size;
  103. sec->vma = core.c_stackorg;
  104. sec->filepos = core.c_stack;
  105. /* .reg section for all registers. */
  106. flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
  107. sec = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
  108. if (NULL == sec)
  109. return NULL;
  110. sec->size = sizeof (struct __context64);
  111. sec->vma = 0;
  112. sec->filepos = 0;
  113. sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64;
  114. /* .ldinfo section.
  115. To actually find out how long this section is in this particular
  116. core dump would require going down the whole list of struct
  117. ld_info's. See if we can just fake it. */
  118. flags = SEC_HAS_CONTENTS;
  119. sec = bfd_make_section_anyway_with_flags (abfd, ".ldinfo", flags);
  120. if (NULL == sec)
  121. return NULL;
  122. sec->size = core.c_lsize;
  123. sec->vma = 0;
  124. sec->filepos = core.c_loader;
  125. /* AIX 4 adds data sections from loaded objects to the core file,
  126. which can be found by examining ldinfo, and anonymously mmapped
  127. regions. */
  128. /* .data section from executable. */
  129. flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
  130. sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
  131. if (NULL == sec)
  132. return NULL;
  133. sec->size = core.c_datasize;
  134. sec->vma = core.c_dataorg;
  135. sec->filepos = core.c_data;
  136. /* .data sections from loaded objects. */
  137. ld_offset = core.c_loader;
  138. while (1)
  139. {
  140. if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0)
  141. return NULL;
  142. if (sizeof (struct __ld_info64) !=
  143. bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd))
  144. return NULL;
  145. if (ldinfo.ldinfo_core)
  146. {
  147. flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
  148. sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
  149. if (NULL == sec)
  150. return NULL;
  151. sec->size = ldinfo.ldinfo_datasize;
  152. sec->vma = ldinfo.ldinfo_dataorg;
  153. sec->filepos = ldinfo.ldinfo_core;
  154. }
  155. if (0 == ldinfo.ldinfo_next)
  156. break;
  157. ld_offset += ldinfo.ldinfo_next;
  158. }
  159. /* .vmdata sections from anonymously mmapped regions. */
  160. if (core.c_vmregions)
  161. {
  162. if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0)
  163. return NULL;
  164. for (i = 0; i < core.c_vmregions; i++)
  165. if (sizeof (struct vm_infox) !=
  166. bfd_bread (&vminfo, sizeof (struct vm_infox), abfd))
  167. return NULL;
  168. if (vminfo.vminfo_offset)
  169. {
  170. flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
  171. sec = bfd_make_section_anyway_with_flags (abfd, ".vmdata", flags);
  172. if (NULL == sec)
  173. return NULL;
  174. sec->size = vminfo.vminfo_size;
  175. sec->vma = vminfo.vminfo_addr;
  176. sec->filepos = vminfo.vminfo_offset;
  177. }
  178. }
  179. /* Set the architecture and machine. */
  180. arch = DEFAULT_ARCHITECTURE;
  181. mach = DEFAULT_MACHINE;
  182. bfd_default_set_arch_mach (abfd, arch, mach);
  183. return _bfd_no_cleanup;
  184. xcoff64_core_p_error:
  185. if (bfd_get_error () != bfd_error_system_call)
  186. bfd_set_error (bfd_error_wrong_format);
  187. return NULL;
  188. }
  189. /* Return `TRUE' if given core is from the given executable. */
  190. bool
  191. xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
  192. {
  193. struct core_dumpxx core;
  194. char *path, *s;
  195. size_t alloc;
  196. const char *str1, *str2;
  197. bool return_value = false;
  198. /* Get the header. */
  199. if (bfd_seek (core_bfd, 0, SEEK_SET) != 0)
  200. return return_value;
  201. if (sizeof (struct core_dumpxx) !=
  202. bfd_bread (&core, sizeof (struct core_dumpxx), core_bfd))
  203. return return_value;
  204. if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0)
  205. return return_value;
  206. alloc = 100;
  207. path = bfd_malloc (alloc);
  208. if (path == NULL)
  209. return return_value;
  210. s = path;
  211. while (1)
  212. {
  213. if (bfd_bread (s, 1, core_bfd) != 1)
  214. goto xcoff64_core_file_matches_executable_p_end_1;
  215. if (*s == '\0')
  216. break;
  217. ++s;
  218. if (s == path + alloc)
  219. {
  220. char *n;
  221. alloc *= 2;
  222. n = bfd_realloc (path, alloc);
  223. if (n == NULL)
  224. goto xcoff64_core_file_matches_executable_p_end_1;
  225. s = n + (path - s);
  226. path = n;
  227. }
  228. }
  229. str1 = strrchr (path, '/');
  230. str2 = strrchr (bfd_get_filename (exec_bfd), '/');
  231. /* Step over character '/'. */
  232. str1 = str1 != NULL ? str1 + 1 : path;
  233. str2 = str2 != NULL ? str2 + 1 : bfd_get_filename (exec_bfd);
  234. if (strcmp (str1, str2) == 0)
  235. return_value = true;
  236. xcoff64_core_file_matches_executable_p_end_1:
  237. free (path);
  238. return return_value;
  239. }
  240. char *
  241. xcoff64_core_file_failing_command (bfd *abfd)
  242. {
  243. struct core_dumpxx *c = core_hdr (abfd);
  244. char *return_value = 0;
  245. if (NULL != c)
  246. return_value = c->c_u.U_proc.pi_comm;
  247. return return_value;
  248. }
  249. int
  250. xcoff64_core_file_failing_signal (bfd *abfd)
  251. {
  252. struct core_dumpxx *c = core_hdr (abfd);
  253. int return_value = 0;
  254. if (NULL != c)
  255. return_value = c->c_signo;
  256. return return_value;
  257. }
  258. #else /* AIX_5_CORE */
  259. bfd_cleanup
  260. xcoff64_core_p (bfd *abfd ATTRIBUTE_UNUSED)
  261. {
  262. bfd_set_error (bfd_error_wrong_format);
  263. return 0;
  264. }
  265. bool
  266. xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
  267. {
  268. return generic_core_file_matches_executable_p (core_bfd, exec_bfd);
  269. }
  270. char *
  271. xcoff64_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
  272. {
  273. return 0;
  274. }
  275. int
  276. xcoff64_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
  277. {
  278. return 0;
  279. }
  280. #endif /* AIX_5_CORE */