|
|
1.1 ! root 1: /* Work with core dump and executable files, for GDB. ! 2: Copyright (C) 1986, 1987 Free Software Foundation, Inc. ! 3: ! 4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY ! 5: WARRANTY. No author or distributor accepts responsibility to anyone ! 6: for the consequences of using it or for whether it serves any ! 7: particular purpose or works at all, unless he says so in writing. ! 8: Refer to the GDB General Public License for full details. ! 9: ! 10: Everyone is granted permission to copy, modify and redistribute GDB, ! 11: but only under the conditions described in the GDB General Public ! 12: License. A copy of this license is supposed to have been given to you ! 13: along with GDB so you can know your rights and responsibilities. It ! 14: should be in a file named COPYING. Among other things, the copyright ! 15: notice and this notice must be preserved on all copies. ! 16: ! 17: In other words, go ahead and share GDB, but don't try to stop ! 18: anyone else from sharing it farther. Help stamp out software hoarding! ! 19: */ ! 20: ! 21: #include "initialize.h" ! 22: #include "defs.h" ! 23: #include "param.h" ! 24: ! 25: #include <a.out.h> ! 26: #include <stdio.h> ! 27: #include <signal.h> ! 28: #include <sys/param.h> ! 29: #include <sys/dir.h> ! 30: #include <sys/file.h> ! 31: #include <sys/stat.h> ! 32: ! 33: /* Recognize COFF format systems because a.out.h defines AOUTHDR. */ ! 34: #ifdef AOUTHDR ! 35: #define COFF_FORMAT ! 36: #endif ! 37: ! 38: #ifdef NEW_SUN_CORE ! 39: #include <sys/core.h> ! 40: #else /* not NEW_SUN_CORE */ ! 41: #ifdef UMAX_CORE ! 42: #include <sys/ptrace.h> ! 43: #else /* not UMAX_CORE */ ! 44: #include <sys/user.h> ! 45: #ifdef HP9K320 ! 46: #include <sys/reg.h> ! 47: #include <sys/trap.h> ! 48: #ifdef HPUX_VERSION_5 ! 49: #define e_PS e_regs[PS] ! 50: #define e_PC e_regs[PC] ! 51: #endif /* HPUX_VERSION_5 */ ! 52: #endif /* HP9K320 */ ! 53: #endif /* not UMAX_CORE */ ! 54: #endif /* not NEW_SUN_CORE */ ! 55: ! 56: #ifndef N_TXTADDR ! 57: #define N_TXTADDR(hdr) 0 ! 58: #endif /* no N_TXTADDR */ ! 59: ! 60: #ifndef N_DATADDR ! 61: #define N_DATADDR(hdr) hdr.a_text ! 62: #endif /* no N_DATADDR */ ! 63: ! 64: /* Make COFF and non-COFF names for things a little more compatible ! 65: to reduce conditionals later. */ ! 66: ! 67: #ifdef COFF_FORMAT ! 68: #define a_magic magic ! 69: #endif ! 70: ! 71: #ifndef COFF_FORMAT ! 72: #define AOUTHDR struct exec ! 73: #endif ! 74: ! 75: extern char *sys_siglist[]; ! 76: ! 77: START_FILE ! 78: ! 79: /* Hook for `exec_file_command' command to call. */ ! 80: ! 81: void (*exec_file_display_hook) (); ! 82: ! 83: /* File names of core file and executable file. */ ! 84: ! 85: static char *corefile; ! 86: static char *execfile; ! 87: ! 88: /* Descriptors on which core file and executable file are open. ! 89: Note that the execchan is closed when an inferior is created ! 90: and reopened if the inferior dies or is killed. */ ! 91: ! 92: static int corechan; ! 93: static int execchan; ! 94: ! 95: /* Last modification time of executable file. ! 96: Also used in source.c to compare against mtime of a source file. */ ! 97: ! 98: int exec_mtime; ! 99: ! 100: /* Virtual addresses of bounds of the two areas of memory in the core file. */ ! 101: ! 102: static CORE_ADDR data_start; ! 103: static CORE_ADDR data_end; ! 104: static CORE_ADDR stack_start; ! 105: static CORE_ADDR stack_end; ! 106: ! 107: /* Virtual addresses of bounds of two areas of memory in the exec file. ! 108: Note that the data area in the exec file is used only when there is no core file. */ ! 109: ! 110: CORE_ADDR text_start; ! 111: CORE_ADDR text_end; ! 112: ! 113: static CORE_ADDR exec_data_start; ! 114: static CORE_ADDR exec_data_end; ! 115: ! 116: /* Address in executable file of start of text area data. */ ! 117: ! 118: static int text_offset; ! 119: ! 120: /* Address in executable file of start of data area data. */ ! 121: ! 122: static int exec_data_offset; ! 123: ! 124: /* Address in core file of start of data area data. */ ! 125: ! 126: static int data_offset; ! 127: ! 128: /* Address in core file of start of stack area data. */ ! 129: ! 130: static int stack_offset; ! 131: ! 132: #ifdef COFF_FORMAT ! 133: /* various coff data structures */ ! 134: ! 135: static FILHDR file_hdr; ! 136: static SCNHDR text_hdr; ! 137: static SCNHDR data_hdr; ! 138: ! 139: #endif /* not COFF_FORMAT */ ! 140: ! 141: /* a.out header saved in core file. */ ! 142: ! 143: static AOUTHDR core_aouthdr; ! 144: ! 145: /* a.out header of exec file. */ ! 146: ! 147: static AOUTHDR exec_aouthdr; ! 148: ! 149: static void validate_files (); ! 150: unsigned int register_addr (); ! 151: ! 152: core_file_command (filename, from_tty) ! 153: char *filename; ! 154: int from_tty; ! 155: { ! 156: int val; ! 157: extern char registers[]; ! 158: ! 159: /* Discard all vestiges of any previous core file ! 160: and mark data and stack spaces as empty. */ ! 161: ! 162: if (corefile) ! 163: free (corefile); ! 164: corefile = 0; ! 165: ! 166: if (corechan >= 0) ! 167: close (corechan); ! 168: corechan = -1; ! 169: ! 170: data_start = 0; ! 171: data_end = 0; ! 172: stack_start = STACK_END_ADDR; ! 173: stack_end = STACK_END_ADDR; ! 174: ! 175: /* Now, if a new core file was specified, open it and digest it. */ ! 176: ! 177: if (filename) ! 178: { ! 179: if (have_inferior_p ()) ! 180: error ("To look at a core file, you must kill the inferior with \"kill\"."); ! 181: corechan = open (filename, O_RDONLY, 0); ! 182: if (corechan < 0) ! 183: perror_with_name (filename); ! 184: #ifdef NEW_SUN_CORE ! 185: { ! 186: struct core corestr; ! 187: ! 188: val = myread (corechan, &corestr, sizeof corestr); ! 189: if (val < 0) ! 190: perror_with_name (filename); ! 191: if (corestr.c_magic != CORE_MAGIC) ! 192: error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)", ! 193: filename, corestr.c_magic, (int) CORE_MAGIC); ! 194: else if (sizeof (struct core) != corestr.c_len) ! 195: error ("\"%s\" has an invalid struct core length (%d, expected %d)", ! 196: filename, corestr.c_len, (int) sizeof (struct core)); ! 197: ! 198: data_start = exec_data_start; ! 199: data_end = data_start + corestr.c_dsize; ! 200: stack_start = stack_end - corestr.c_ssize; ! 201: data_offset = sizeof corestr; ! 202: stack_offset = sizeof corestr + corestr.c_dsize; ! 203: ! 204: bcopy (&corestr.c_regs, registers, 16 * 4); ! 205: *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps; ! 206: *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc; ! 207: bcopy (corestr.c_fpstatus.fps_regs, ! 208: ®isters[REGISTER_BYTE (FP0_REGNUM)], ! 209: sizeof corestr.c_fpstatus.fps_regs); ! 210: bcopy (&corestr.c_fpstatus.fps_control, ! 211: ®isters[REGISTER_BYTE (FPC_REGNUM)], ! 212: sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs); ! 213: ! 214: bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec)); ! 215: ! 216: printf ("Core file is from \"%s\".\n", corestr.c_cmdname); ! 217: if (corestr.c_signo > 0) ! 218: printf ("Program terminated with signal %d, %s.\n", ! 219: corestr.c_signo, ! 220: corestr.c_signo < NSIG ! 221: ? sys_siglist[corestr.c_signo] ! 222: : "(undocumented)"); ! 223: } ! 224: #else /* not NEW_SUN_CORE */ ! 225: /* 4.2-style (and perhaps also sysV-style) core dump file. */ ! 226: { ! 227: #ifdef UMAX_CORE ! 228: struct ptrace_user u; ! 229: #else ! 230: struct user u; ! 231: #endif ! 232: int reg_offset; ! 233: ! 234: val = myread (corechan, &u, sizeof u); ! 235: if (val < 0) ! 236: perror_with_name (filename); ! 237: data_start = exec_data_start; ! 238: ! 239: #ifdef UMAX_CORE ! 240: data_end = data_start + u.pt_dsize; ! 241: stack_start = stack_end - u.pt_ssize; ! 242: data_offset = sizeof u; ! 243: stack_offset = data_offset + u.pt_dsize; ! 244: reg_offset = 0; ! 245: ! 246: bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR)); ! 247: printf ("Core file is from \"%s\".\n", u.pt_comm); ! 248: if (u.pt_signal > 0) ! 249: printf ("Program terminated with signal %d, %s.\n", ! 250: u.pt_signal, ! 251: u.pt_signal < NSIG ! 252: ? sys_siglist[u.pt_signal] ! 253: : "(undocumented)"); ! 254: #else /* not UMAX_CORE */ ! 255: data_end = data_start + NBPG * u.u_dsize; ! 256: stack_start = stack_end - NBPG * u.u_ssize; ! 257: data_offset = NBPG * UPAGES; ! 258: stack_offset = NBPG * (UPAGES + u.u_dsize); ! 259: reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR; ! 260: ! 261: /* I don't know where to find this info. ! 262: So, for now, mark it as not available. */ ! 263: core_aouthdr.a_magic = 0; ! 264: #endif /* not UMAX_CORE */ ! 265: ! 266: /* Read the register values out of the core file and store ! 267: them where `read_register' will find them. */ ! 268: ! 269: #ifdef HP9K320 ! 270: { ! 271: register int regno; ! 272: struct exception_stack es; ! 273: int val; ! 274: ! 275: val = lseek (corechan, (REGISTER_ADDR (reg_offset, 0)), 0); ! 276: if (val < 0) ! 277: perror_with_name (filename); ! 278: val = myread (corechan, es, ! 279: ((char *) &es.e_regs[R0] - (char *) &es.e_offset)); ! 280: if (val < 0) ! 281: perror_with_name (filename); ! 282: for (regno = 0; (regno < PS_REGNUM); regno++) ! 283: supply_register (regno, &es.e_regs[regno + R0]); ! 284: val = es.e_PS; ! 285: supply_register (regno++, &val); ! 286: supply_register (regno++, &es.e_PC); ! 287: for (; (regno < NUM_REGS); regno++) ! 288: { ! 289: char buf[MAX_REGISTER_RAW_SIZE]; ! 290: ! 291: val = lseek (corechan, (FP_REGISTER_ADDR (u, regno)), 0); ! 292: if (val < 0) ! 293: perror_with_name (filename); ! 294: ! 295: val = myread (corechan, buf, sizeof buf); ! 296: if (val < 0) ! 297: perror_with_name (filename); ! 298: supply_register (regno, buf); ! 299: } ! 300: } ! 301: #else /* not HP9K320 */ ! 302: { ! 303: register int regno; ! 304: ! 305: for (regno = 0; regno < NUM_REGS; regno++) ! 306: { ! 307: char buf[MAX_REGISTER_RAW_SIZE]; ! 308: ! 309: val = lseek (corechan, register_addr (regno, reg_offset), 0); ! 310: if (val < 0) ! 311: perror_with_name (filename); ! 312: ! 313: val = myread (corechan, buf, sizeof buf); ! 314: if (val < 0) ! 315: perror_with_name (filename); ! 316: supply_register (regno, buf); ! 317: } ! 318: } ! 319: #endif /* not HP9K320 */ ! 320: } ! 321: #endif /* not NEW_SUN_CORE */ ! 322: if (filename[0] == '/') ! 323: corefile = savestring (filename, strlen (filename)); ! 324: else ! 325: { ! 326: corefile = concat (current_directory, "/", filename); ! 327: } ! 328: ! 329: set_current_frame (read_register (FP_REGNUM)); ! 330: select_frame (get_current_frame (), 0); ! 331: validate_files (); ! 332: } ! 333: else if (from_tty) ! 334: printf ("No core file now.\n"); ! 335: } ! 336: ! 337: exec_file_command (filename, from_tty) ! 338: char *filename; ! 339: int from_tty; ! 340: { ! 341: int val; ! 342: ! 343: /* Eliminate all traces of old exec file. ! 344: Mark text segment as empty. */ ! 345: ! 346: if (execfile) ! 347: free (execfile); ! 348: execfile = 0; ! 349: data_start = 0; ! 350: data_end -= exec_data_start; ! 351: text_start = 0; ! 352: text_end = 0; ! 353: exec_data_start = 0; ! 354: exec_data_end = 0; ! 355: if (execchan >= 0) ! 356: close (execchan); ! 357: execchan = -1; ! 358: ! 359: /* Now open and digest the file the user requested, if any. */ ! 360: ! 361: if (filename) ! 362: { ! 363: execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, ! 364: &execfile); ! 365: if (execchan < 0) ! 366: perror_with_name (filename); ! 367: ! 368: #ifdef COFF_FORMAT ! 369: { ! 370: int aout_hdrsize; ! 371: int num_sections; ! 372: ! 373: if (read_file_hdr (execchan, &file_hdr) < 0) ! 374: error ("\"%s\": not in executable format.", execfile); ! 375: ! 376: aout_hdrsize = file_hdr.f_opthdr; ! 377: num_sections = file_hdr.f_nscns; ! 378: ! 379: if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0) ! 380: error ("\"%s\": can't read optional aouthdr", execfile); ! 381: ! 382: if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections) < 0) ! 383: error ("\"%s\": can't read text section header", execfile); ! 384: ! 385: if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 0) ! 386: error ("\"%s\": can't read data section header", execfile); ! 387: ! 388: text_start = exec_aouthdr.text_start; ! 389: text_end = text_start + exec_aouthdr.tsize; ! 390: text_offset = text_hdr.s_scnptr; ! 391: exec_data_start = exec_aouthdr.data_start; ! 392: exec_data_end = exec_data_start + exec_aouthdr.dsize; ! 393: exec_data_offset = data_hdr.s_scnptr; ! 394: data_start = exec_data_start; ! 395: data_end += exec_data_start; ! 396: exec_mtime = file_hdr.f_timdat; ! 397: } ! 398: #else /* not COFF_FORMAT */ ! 399: { ! 400: struct stat st_exec; ! 401: ! 402: #ifdef gould ! 403: FILHDR exec_coffhdr; ! 404: ! 405: val = myread (execchan, &exec_coffhdr, sizeof exec_coffhdr); ! 406: if (val < 0) ! 407: perror_with_name (filename); ! 408: #endif ! 409: val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR)); ! 410: ! 411: if (val < 0) ! 412: perror_with_name (filename); ! 413: ! 414: text_start = N_TXTADDR (exec_aouthdr); ! 415: exec_data_start = N_DATADDR (exec_aouthdr); ! 416: #ifdef gould ! 417: text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr); ! 418: exec_data_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr) ! 419: + exec_aouthdr.a_text; ! 420: #else ! 421: text_offset = N_TXTOFF (exec_aouthdr); ! 422: exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; ! 423: #endif ! 424: text_end = text_start + exec_aouthdr.a_text; ! 425: exec_data_end = exec_data_start + exec_aouthdr.a_data; ! 426: data_start = exec_data_start; ! 427: data_end += exec_data_start; ! 428: ! 429: fstat (execchan, &st_exec); ! 430: exec_mtime = st_exec.st_mtime; ! 431: } ! 432: #endif /* not COFF_FORMAT */ ! 433: ! 434: validate_files (); ! 435: } ! 436: else if (from_tty) ! 437: printf ("No exec file now.\n"); ! 438: ! 439: /* Tell display code (if any) about the changed file name. */ ! 440: if (exec_file_display_hook) ! 441: (*exec_file_display_hook) (filename); ! 442: } ! 443: ! 444: /* Call this to specify the hook for exec_file_command to call back. ! 445: This is called from the x-window display code. */ ! 446: ! 447: specify_exec_file_hook (hook) ! 448: void (*hook) (); ! 449: { ! 450: exec_file_display_hook = hook; ! 451: } ! 452: ! 453: /* The exec file must be closed before running an inferior. ! 454: If it is needed again after the inferior dies, it must ! 455: be reopened. */ ! 456: ! 457: close_exec_file () ! 458: { ! 459: if (execchan >= 0) ! 460: close (execchan); ! 461: execchan = -1; ! 462: } ! 463: ! 464: reopen_exec_file () ! 465: { ! 466: if (execchan < 0 && execfile != 0) ! 467: { ! 468: char *filename = concat (execfile, "", ""); ! 469: exec_file_command (filename, 0); ! 470: free (filename); ! 471: } ! 472: } ! 473: ! 474: /* If we have both a core file and an exec file, ! 475: print a warning if they don't go together. ! 476: This should really check that the core file came ! 477: from that exec file, but I don't know how to do it. */ ! 478: ! 479: static void ! 480: validate_files () ! 481: { ! 482: if (execfile != 0 && corefile != 0) ! 483: { ! 484: struct stat st_core; ! 485: ! 486: fstat (corechan, &st_core); ! 487: ! 488: if (core_aouthdr.a_magic != 0 ! 489: && bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr)) ! 490: printf ("Warning: core file does not match specified executable file.\n"); ! 491: else if (exec_mtime > st_core.st_mtime) ! 492: printf ("Warning: exec file is newer than core file.\n"); ! 493: } ! 494: } ! 495: ! 496: /* Return the name of the executable file as a string. ! 497: ERR nonzero means get error if there is none specified; ! 498: otherwise return 0 in that case. */ ! 499: ! 500: char * ! 501: get_exec_file (err) ! 502: int err; ! 503: { ! 504: if (err && execfile == 0) ! 505: error ("No executable file specified.\n\ ! 506: Use the \"exec-file\" and \"symbol-file\" commands."); ! 507: return execfile; ! 508: } ! 509: ! 510: int ! 511: have_core_file_p () ! 512: { ! 513: return corefile != 0; ! 514: } ! 515: ! 516: static void ! 517: files_info () ! 518: { ! 519: char *symfile; ! 520: extern char *get_sym_file (); ! 521: ! 522: if (execfile) ! 523: printf ("Executable file \"%s\".\n", execfile); ! 524: else ! 525: printf ("No executable file\n"); ! 526: if (corefile == 0) ! 527: printf ("No core dump file\n"); ! 528: else ! 529: printf ("Core dump file \"%s\".\n", corefile); ! 530: ! 531: if (have_inferior_p ()) ! 532: printf ("Using the running image of the program, rather than these files.\n"); ! 533: ! 534: symfile = get_sym_file (); ! 535: if (symfile != 0) ! 536: printf ("Symbols loaded from \"%s\".\n", symfile); ! 537: ! 538: if (! have_inferior_p ()) ! 539: { ! 540: if (execfile) ! 541: { ! 542: printf ("Text segment from 0x%x to 0x%x.\n", ! 543: text_start, text_end); ! 544: } ! 545: if (corefile) ! 546: { ! 547: printf ("Data segment from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n", ! 548: data_start, data_end, stack_start, stack_end); ! 549: } ! 550: else ! 551: { ! 552: printf ("Data segment in executable from 0x%x to 0x%x.\n", ! 553: exec_data_start, exec_data_end); ! 554: } ! 555: } ! 556: } ! 557: ! 558: /* Read "memory data" from core file and/or executable file */ ! 559: ! 560: read_memory (memaddr, myaddr, len) ! 561: CORE_ADDR memaddr; ! 562: char *myaddr; ! 563: int len; ! 564: { ! 565: if (have_inferior_p ()) ! 566: read_inferior_memory (memaddr, myaddr, len); ! 567: else ! 568: xfer_core_file (memaddr, myaddr, len, 0); ! 569: } ! 570: ! 571: /* Write LEN bytes of data starting at address MYADDR ! 572: into debugged program memory at address MEMADDR. ! 573: Returns zero if successful, or an errno value if ptrace failed. */ ! 574: ! 575: int ! 576: write_memory (memaddr, myaddr, len) ! 577: CORE_ADDR memaddr; ! 578: char *myaddr; ! 579: int len; ! 580: { ! 581: if (have_inferior_p ()) ! 582: return write_inferior_memory (memaddr, myaddr, len); ! 583: else ! 584: error ("Can write memory only when program being debugged is running."); ! 585: } ! 586: ! 587: xfer_core_file (memaddr, myaddr, len) ! 588: CORE_ADDR memaddr; ! 589: char *myaddr; ! 590: int len; ! 591: { ! 592: register int i; ! 593: register int val; ! 594: int xferchan; ! 595: char **xferfile; ! 596: int fileptr; ! 597: ! 598: while (len > 0) ! 599: { ! 600: xferfile = 0; ! 601: xferchan = 0; ! 602: ! 603: /* Determine which file the next bunch of addresses reside in, ! 604: and where in the file. Set the file's read/write pointer ! 605: to point at the proper place for the desired address ! 606: and set xferfile and xferchan for the correct file. ! 607: If desired address is nonexistent, leave them zero. ! 608: i is set to the number of bytes that can be handled ! 609: along with the next address. */ ! 610: ! 611: if (memaddr < text_start) ! 612: { ! 613: i = min (len, text_start - memaddr); ! 614: } ! 615: else if (memaddr >= text_end && memaddr < data_start) ! 616: { ! 617: i = min (len, data_start - memaddr); ! 618: } ! 619: else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end) ! 620: && memaddr < stack_start) ! 621: { ! 622: i = min (len, stack_start - memaddr); ! 623: } ! 624: else if (memaddr >= stack_end && stack_end != 0) ! 625: { ! 626: i = min (len, - memaddr); ! 627: } ! 628: /* Note that if there is no core file ! 629: data_start and data_end are equal. */ ! 630: else if (memaddr >= data_start && memaddr < data_end) ! 631: { ! 632: i = min (len, data_end - memaddr); ! 633: fileptr = memaddr - data_start + data_offset; ! 634: xferfile = &corefile; ! 635: xferchan = corechan; ! 636: } ! 637: /* Note that if there is no core file ! 638: stack_start and stack_end are equal. */ ! 639: else if (memaddr >= stack_start && memaddr < stack_end) ! 640: { ! 641: i = min (len, stack_end - memaddr); ! 642: fileptr = memaddr - stack_start + stack_offset; ! 643: xferfile = &corefile; ! 644: xferchan = corechan; ! 645: } ! 646: else if (corechan < 0 ! 647: && memaddr >= exec_data_start && memaddr < exec_data_end) ! 648: { ! 649: i = min (len, exec_data_end - memaddr); ! 650: fileptr = memaddr - exec_data_start + exec_data_offset; ! 651: xferfile = &execfile; ! 652: xferchan = execchan; ! 653: } ! 654: else if (memaddr >= text_start && memaddr < text_end) ! 655: { ! 656: i = min (len, text_end - memaddr); ! 657: fileptr = memaddr - text_start + text_offset; ! 658: xferfile = &execfile; ! 659: xferchan = execchan; ! 660: } ! 661: ! 662: /* Now we know which file to use. ! 663: Set up its pointer and transfer the data. */ ! 664: if (xferfile) ! 665: { ! 666: if (*xferfile == 0) ! 667: if (xferfile == &execfile) ! 668: error ("No program file to examine."); ! 669: else ! 670: error ("No core dump file or running program to examine."); ! 671: val = lseek (xferchan, fileptr, 0); ! 672: if (val < 0) ! 673: perror_with_name (*xferfile); ! 674: val = myread (xferchan, myaddr, i); ! 675: if (val < 0) ! 676: perror_with_name (*xferfile); ! 677: } ! 678: /* If this address is for nonexistent memory, ! 679: read zeros if reading, or do nothing if writing. */ ! 680: else ! 681: bzero (myaddr, i); ! 682: ! 683: memaddr += i; ! 684: myaddr += i; ! 685: len -= i; ! 686: } ! 687: } ! 688: ! 689: /* My replacement for the read system call. ! 690: Used like `read' but keeps going if `read' returns too soon. */ ! 691: ! 692: myread (desc, addr, len) ! 693: int desc; ! 694: char *addr; ! 695: int len; ! 696: { ! 697: register int val; ! 698: int orglen = len; ! 699: ! 700: while (len > 0) ! 701: { ! 702: val = read (desc, addr, len); ! 703: if (val < 0) ! 704: return val; ! 705: if (val == 0) ! 706: return orglen - len; ! 707: len -= val; ! 708: addr += val; ! 709: } ! 710: return orglen; ! 711: } ! 712: ! 713: #ifdef REGISTER_U_ADDR ! 714: ! 715: /* Return the address in the core dump or inferior of register REGNO. ! 716: BLOCKEND is the address of the end of the user structure. */ ! 717: ! 718: unsigned int ! 719: register_addr (regno, blockend) ! 720: int regno; ! 721: int blockend; ! 722: { ! 723: int addr; ! 724: ! 725: if (regno < 0 || regno >= NUM_REGS) ! 726: error ("Invalid register number %d.", regno); ! 727: ! 728: REGISTER_U_ADDR (addr, blockend, regno); ! 729: ! 730: return addr; ! 731: } ! 732: ! 733: #endif /* REGISTER_U_ADDR */ ! 734: ! 735: static ! 736: initialize () ! 737: { ! 738: corechan = -1; ! 739: execchan = -1; ! 740: corefile = 0; ! 741: execfile = 0; ! 742: exec_file_display_hook = 0; ! 743: ! 744: text_start = 0; ! 745: text_end = 0; ! 746: data_start = 0; ! 747: data_end = 0; ! 748: exec_data_start = 0; ! 749: exec_data_end = 0; ! 750: stack_start = STACK_END_ADDR; ! 751: stack_end = STACK_END_ADDR; ! 752: ! 753: add_com ("core-file", class_files, core_file_command, ! 754: "Use FILE as core dump for examining memory and registers.\n\ ! 755: No arg means have no core file."); ! 756: add_com ("exec-file", class_files, exec_file_command, ! 757: "Use FILE as program for getting contents of pure memory.\n\ ! 758: If FILE cannot be found as specified, your execution directory path\n\ ! 759: is searched for a command of that name.\n\ ! 760: No arg means have no executable file."); ! 761: add_info ("files", files_info, "Names of files being debugged."); ! 762: } ! 763: ! 764: END_FILE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.