1 /* BFD back-end for HP/UX core files. 2 Copyright 1993, 1994, 1996, 1998, 1999, 2001, 2002, 2003, 2004 3 Free Software Foundation, Inc. 4 Written by Stu Grossman, Cygnus Support. 5 Converted to back-end form by Ian Lance Taylor, Cygnus SUpport 6 7 This file is part of BFD, the Binary File Descriptor library. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23 /* This file can only be compiled on systems which use HP/UX style 24 core files. */ 25 26 #include "bfd.h" 27 #include "sysdep.h" 28 #include "libbfd.h" 29 30 #if defined (HOST_HPPAHPUX) || defined (HOST_HP300HPUX) || defined (HOST_HPPAMPEIX) 31 32 /* FIXME: sys/core.h doesn't exist for HPUX version 7. HPUX version 33 5, 6, and 7 core files seem to be standard trad-core.c type core 34 files; can we just use trad-core.c in addition to this file? */ 35 36 #include <sys/core.h> 37 #include <sys/utsname.h> 38 39 #endif /* HOST_HPPAHPUX */ 40 41 #ifdef HOST_HPPABSD 42 43 /* Not a very swift place to put it, but that's where the BSD port 44 puts them. */ 45 #include "/hpux/usr/include/sys/core.h" 46 47 #endif /* HOST_HPPABSD */ 48 49 #include <sys/param.h> 50 #ifdef HAVE_DIRENT_H 51 # include <dirent.h> 52 #else 53 # ifdef HAVE_SYS_NDIR_H 54 # include <sys/ndir.h> 55 # endif 56 # ifdef HAVE_SYS_DIR_H 57 # include <sys/dir.h> 58 # endif 59 # ifdef HAVE_NDIR_H 60 # include <ndir.h> 61 # endif 62 #endif 63 #include <signal.h> 64 #include <machine/reg.h> 65 #include <sys/user.h> /* After a.out.h */ 66 #include <sys/file.h> 67 68 /* Kludge: There's no explicit mechanism provided by sys/core.h to 69 conditionally know whether a proc_info has thread id fields. 70 However, CORE_ANON_SHMEM shows up first at 10.30, which is 71 happily also when meaningful thread id's show up in proc_info. */ 72 #if defined(CORE_ANON_SHMEM) 73 #define PROC_INFO_HAS_THREAD_ID (1) 74 #endif 75 76 /* This type appears at HP-UX 10.30. Defining it if not defined 77 by sys/core.h allows us to build for older HP-UX's, and (since 78 it won't be encountered in core-dumps from older HP-UX's) is 79 harmless. */ 80 #if !defined(CORE_ANON_SHMEM) 81 #define CORE_ANON_SHMEM 0x00000200 /* anonymous shared memory */ 82 #endif 83 84 /* These are stored in the bfd's tdata */ 85 86 /* .lwpid and .user_tid are only valid if PROC_INFO_HAS_THREAD_ID, else they 87 are set to 0. Also, until HP-UX implements MxN threads, .user_tid and 88 .lwpid are synonymous. */ 89 struct hpux_core_struct 90 { 91 int sig; 92 int lwpid; /* Kernel thread ID. */ 93 unsigned long user_tid; /* User thread ID. */ 94 char cmd[MAXCOMLEN + 1]; 95 }; 96 97 #define core_hdr(bfd) ((bfd)->tdata.hpux_core_data) 98 #define core_signal(bfd) (core_hdr(bfd)->sig) 99 #define core_command(bfd) (core_hdr(bfd)->cmd) 100 #define core_kernel_thread_id(bfd) (core_hdr(bfd)->lwpid) 101 #define core_user_thread_id(bfd) (core_hdr(bfd)->user_tid) 102 103 static asection *make_bfd_asection 104 PARAMS ((bfd *, const char *, flagword, bfd_size_type, bfd_vma, 105 unsigned int)); 106 static const bfd_target *hpux_core_core_file_p 107 PARAMS ((bfd *)); 108 static char *hpux_core_core_file_failing_command 109 PARAMS ((bfd *)); 110 static int hpux_core_core_file_failing_signal 111 PARAMS ((bfd *)); 112 static bfd_boolean hpux_core_core_file_matches_executable_p 113 PARAMS ((bfd *, bfd *)); 114 static void swap_abort 115 PARAMS ((void)); 116 117 static asection * 118 make_bfd_asection (abfd, name, flags, _raw_size, vma, alignment_power) 119 bfd *abfd; 120 const char *name; 121 flagword flags; 122 bfd_size_type _raw_size; 123 bfd_vma vma; 124 unsigned int alignment_power; 125 { 126 asection *asect; 127 char *newname; 128 129 newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1); 130 if (!newname) 131 return NULL; 132 133 strcpy (newname, name); 134 135 asect = bfd_make_section_anyway (abfd, newname); 136 if (!asect) 137 return NULL; 138 139 asect->flags = flags; 140 asect->_raw_size = _raw_size; 141 asect->vma = vma; 142 asect->filepos = bfd_tell (abfd); 143 asect->alignment_power = alignment_power; 144 145 return asect; 146 } 147 148 /* this function builds a bfd target if the file is a corefile. 149 It returns null or 0 if it finds out thaat it is not a core file. 150 The way it checks this is by looking for allowed 'type' field values. 151 These are declared in sys/core.h 152 There are some values which are 'reserved for future use'. In particular 153 CORE_NONE is actually defined as 0. This may be a catch-all for cases 154 in which the core file is generated by some non-hpux application. 155 (I am just guessing here!) 156 */ 157 static const bfd_target * 158 hpux_core_core_file_p (abfd) 159 bfd *abfd; 160 { 161 int good_sections = 0; 162 int unknown_sections = 0; 163 164 core_hdr (abfd) = (struct hpux_core_struct *) 165 bfd_zalloc (abfd, (bfd_size_type) sizeof (struct hpux_core_struct)); 166 if (!core_hdr (abfd)) 167 return NULL; 168 169 while (1) 170 { 171 int val; 172 struct corehead core_header; 173 174 val = bfd_bread ((void *) &core_header, 175 (bfd_size_type) sizeof core_header, abfd); 176 if (val <= 0) 177 break; 178 switch (core_header.type) 179 { 180 case CORE_KERNEL: 181 case CORE_FORMAT: 182 /* Just skip this. */ 183 bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR); 184 good_sections++; 185 break; 186 case CORE_EXEC: 187 { 188 struct proc_exec proc_exec; 189 if (bfd_bread ((void *) &proc_exec, (bfd_size_type) core_header.len, 190 abfd) != core_header.len) 191 break; 192 strncpy (core_command (abfd), proc_exec.cmd, MAXCOMLEN + 1); 193 good_sections++; 194 } 195 break; 196 case CORE_PROC: 197 { 198 struct proc_info proc_info; 199 char secname[100]; /* Of arbitrary size, but plenty large. */ 200 201 /* We need to read this section, 'cause we need to determine 202 whether the core-dumped app was threaded before we create 203 any .reg sections. */ 204 if (bfd_bread (&proc_info, (bfd_size_type) core_header.len, abfd) 205 != core_header.len) 206 break; 207 208 /* However, we also want to create those sections with the 209 file positioned at the start of the record, it seems. */ 210 if (bfd_seek (abfd, (file_ptr) -core_header.len, SEEK_CUR) != 0) 211 break; 212 213 #if defined(PROC_INFO_HAS_THREAD_ID) 214 core_kernel_thread_id (abfd) = proc_info.lwpid; 215 core_user_thread_id (abfd) = proc_info.user_tid; 216 #else 217 core_kernel_thread_id (abfd) = 0; 218 core_user_thread_id (abfd) = 0; 219 #endif 220 /* If the program was unthreaded, then we'll just create a 221 .reg section. 222 223 If the program was threaded, then we'll create .reg/XXXXX 224 section for each thread, where XXXXX is a printable 225 representation of the kernel thread id. We'll also 226 create a .reg section for the thread that was running 227 and signalled at the time of the core-dump (i.e., this 228 is effectively an alias, needed to keep GDB happy.) 229 230 Note that we use `.reg/XXXXX' as opposed to '.regXXXXX' 231 because GDB expects that .reg2 will be the floating- 232 point registers. */ 233 if (core_kernel_thread_id (abfd) == 0) 234 { 235 if (!make_bfd_asection (abfd, ".reg", 236 SEC_HAS_CONTENTS, 237 core_header.len, 238 (int) &proc_info - (int) & proc_info.hw_regs, 239 2)) 240 goto fail; 241 } 242 else 243 { 244 /* There are threads. Is this the one that caused the 245 core-dump? We'll claim it was the running thread. */ 246 if (proc_info.sig != -1) 247 { 248 if (!make_bfd_asection (abfd, ".reg", 249 SEC_HAS_CONTENTS, 250 core_header.len, 251 (int) &proc_info - (int) & proc_info.hw_regs, 252 2)) 253 goto fail; 254 } 255 /* We always make one of these sections, for every thread. */ 256 sprintf (secname, ".reg/%d", core_kernel_thread_id (abfd)); 257 if (!make_bfd_asection (abfd, secname, 258 SEC_HAS_CONTENTS, 259 core_header.len, 260 (int) &proc_info - (int) & proc_info.hw_regs, 261 2)) 262 goto fail; 263 } 264 core_signal (abfd) = proc_info.sig; 265 if (bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR) != 0) 266 break; 267 good_sections++; 268 } 269 break; 270 271 case CORE_DATA: 272 case CORE_STACK: 273 case CORE_TEXT: 274 case CORE_MMF: 275 case CORE_SHM: 276 case CORE_ANON_SHMEM: 277 if (!make_bfd_asection (abfd, ".data", 278 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, 279 core_header.len, core_header.addr, 2)) 280 goto fail; 281 282 bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR); 283 good_sections++; 284 break; 285 286 case CORE_NONE: 287 /* Let's not punt if we encounter a section of unknown 288 type. Rather, let's make a note of it. If we later 289 see that there were also "good" sections, then we'll 290 declare that this a core file, but we'll also warn that 291 it may be incompatible with this gdb. 292 */ 293 unknown_sections++; 294 break; 295 296 default: 297 goto fail; /*unrecognized core file type */ 298 } 299 } 300 301 /* OK, we believe you. You're a core file (sure, sure). */ 302 303 /* Were there sections of unknown type? If so, yet there were 304 at least some complete sections of known type, then, issue 305 a warning. Possibly the core file was generated on a version 306 of HP-UX that is incompatible with that for which this gdb was 307 built. 308 */ 309 if ((unknown_sections > 0) && (good_sections > 0)) 310 (*_bfd_error_handler) 311 ("%s appears to be a core file,\nbut contains unknown sections. It may have been created on an incompatible\nversion of HP-UX. As a result, some information may be unavailable.\n", 312 abfd->filename); 313 314 return abfd->xvec; 315 316 fail: 317 bfd_release (abfd, core_hdr (abfd)); 318 core_hdr (abfd) = NULL; 319 bfd_section_list_clear (abfd); 320 return NULL; 321 } 322 323 static char * 324 hpux_core_core_file_failing_command (abfd) 325 bfd *abfd; 326 { 327 return core_command (abfd); 328 } 329 330 static int 331 hpux_core_core_file_failing_signal (abfd) 332 bfd *abfd; 333 { 334 return core_signal (abfd); 335 } 336 337 static bfd_boolean 338 hpux_core_core_file_matches_executable_p (core_bfd, exec_bfd) 339 bfd *core_bfd ATTRIBUTE_UNUSED; 340 bfd *exec_bfd ATTRIBUTE_UNUSED; 341 { 342 return TRUE; /* FIXME, We have no way of telling at this point */ 343 } 344 345 /* If somebody calls any byte-swapping routines, shoot them. */ 346 static void 347 swap_abort () 348 { 349 abort(); /* This way doesn't require any declaration for ANSI to fuck up */ 350 } 351 352 #define NO_GET ((bfd_vma (*) (const void *)) swap_abort) 353 #define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort) 354 #define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort) 355 #define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort) 356 #define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort) 357 #define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort) 358 359 const bfd_target hpux_core_vec = 360 { 361 "hpux-core", 362 bfd_target_unknown_flavour, 363 BFD_ENDIAN_BIG, /* target byte order */ 364 BFD_ENDIAN_BIG, /* target headers byte order */ 365 (HAS_RELOC | EXEC_P | /* object flags */ 366 HAS_LINENO | HAS_DEBUG | 367 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 368 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 369 0, /* symbol prefix */ 370 ' ', /* ar_pad_char */ 371 16, /* ar_max_namelen */ 372 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data */ 373 NO_GET, NO_GETS, NO_PUT, /* 32 bit data */ 374 NO_GET, NO_GETS, NO_PUT, /* 16 bit data */ 375 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs */ 376 NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs */ 377 NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs */ 378 379 { /* bfd_check_format */ 380 _bfd_dummy_target, /* unknown format */ 381 _bfd_dummy_target, /* object file */ 382 _bfd_dummy_target, /* archive */ 383 hpux_core_core_file_p /* a core file */ 384 }, 385 { /* bfd_set_format */ 386 bfd_false, bfd_false, 387 bfd_false, bfd_false 388 }, 389 { /* bfd_write_contents */ 390 bfd_false, bfd_false, 391 bfd_false, bfd_false 392 }, 393 394 BFD_JUMP_TABLE_GENERIC (_bfd_generic), 395 BFD_JUMP_TABLE_COPY (_bfd_generic), 396 BFD_JUMP_TABLE_CORE (hpux_core), 397 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 398 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), 399 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 400 BFD_JUMP_TABLE_WRITE (_bfd_generic), 401 BFD_JUMP_TABLE_LINK (_bfd_nolink), 402 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 403 404 NULL, 405 406 (PTR) 0 /* backend_data */ 407 }; 408