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