📄 convex-tdep.c
字号:
/* Convex stuff for GDB. Copyright (C) 1990, 1991 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include "command.h"#include "symtab.h"#include "value.h"#include "frame.h"#include "inferior.h"#include "wait.h"#include <signal.h>#include <fcntl.h>#include "gdbcore.h"#include <sys/param.h>#include <sys/dir.h>#include <sys/user.h>#include <sys/ioctl.h>#include <sys/pcntl.h>#include <sys/thread.h>#include <sys/proc.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/mman.h>#include "gdbcmd.h"exec_file_command (filename, from_tty) char *filename; int from_tty;{ int val; int n; struct stat st_exec; /* Eliminate all traces of old exec file. Mark text segment as empty. */ if (execfile) free (execfile); execfile = 0; data_start = 0; data_end = 0; text_start = 0; text_end = 0; exec_data_start = 0; exec_data_end = 0; if (execchan >= 0) close (execchan); execchan = -1; n_exec = 0; /* Now open and digest the file the user requested, if any. */ if (filename) { filename = tilde_expand (filename); make_cleanup (free, filename); execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, &execfile); if (execchan < 0) perror_with_name (filename); if (myread (execchan, &filehdr, sizeof filehdr) < 0) perror_with_name (filename); if (! IS_SOFF_MAGIC (filehdr.h_magic)) error ("%s: not an executable file.", filename); if (myread (execchan, &opthdr, filehdr.h_opthdr) <= 0) perror_with_name (filename); /* Read through the section headers. For text, data, etc, record an entry in the exec file map. Record text_start and text_end. */ lseek (execchan, (long) filehdr.h_scnptr, 0); for (n = 0; n < filehdr.h_nscns; n++) { if (myread (execchan, &scnhdr, sizeof scnhdr) < 0) perror_with_name (filename); if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT && (scnhdr.s_flags & S_TYPMASK) <= S_COMON) { exec_map[n_exec].mem_addr = scnhdr.s_vaddr; exec_map[n_exec].mem_end = scnhdr.s_vaddr + scnhdr.s_size; exec_map[n_exec].file_addr = scnhdr.s_scnptr; exec_map[n_exec].type = scnhdr.s_flags & S_TYPMASK; n_exec++; if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT) { text_start = scnhdr.s_vaddr; text_end = scnhdr.s_vaddr + scnhdr.s_size; } } } fstat (execchan, &st_exec); exec_mtime = st_exec.st_mtime; validate_files (); } else if (from_tty) printf_filtered ("No exec file now.\n"); /* Tell display code (if any) about the changed file name. */ if (exec_file_display_hook) (*exec_file_display_hook) (filename);}/* Read data from SOFF exec or core file. Return 0 on success, EIO if address out of bounds. */intxfer_core_file (memaddr, myaddr, len) CORE_ADDR memaddr; char *myaddr; int len;{ register int i; register int n; register int val; int xferchan; char **xferfile; int fileptr; int returnval = 0; while (len > 0) { xferfile = 0; xferchan = 0; /* Determine which file the next bunch of addresses reside in, and where in the file. Set the file's read/write pointer to point at the proper place for the desired address and set xferfile and xferchan for the correct file. If desired address is nonexistent, leave them zero. i is set to the number of bytes that can be handled along with the next address. */ i = len; for (n = 0; n < n_core; n++) { if (memaddr >= core_map[n].mem_addr && memaddr < core_map[n].mem_end && (core_map[n].thread == -1 || core_map[n].thread == inferior_thread)) { i = min (len, core_map[n].mem_end - memaddr); fileptr = core_map[n].file_addr + memaddr - core_map[n].mem_addr; if (core_map[n].file_addr) { xferfile = &corefile; xferchan = corechan; } break; } else if (core_map[n].mem_addr >= memaddr && core_map[n].mem_addr < memaddr + i) i = core_map[n].mem_addr - memaddr; } if (!xferfile) for (n = 0; n < n_exec; n++) { if (memaddr >= exec_map[n].mem_addr && memaddr < exec_map[n].mem_end) { i = min (len, exec_map[n].mem_end - memaddr); fileptr = exec_map[n].file_addr + memaddr - exec_map[n].mem_addr; if (exec_map[n].file_addr) { xferfile = &execfile; xferchan = execchan; } break; } else if (exec_map[n].mem_addr >= memaddr && exec_map[n].mem_addr < memaddr + i) i = exec_map[n].mem_addr - memaddr; } /* Now we know which file to use. Set up its pointer and transfer the data. */ if (xferfile) { if (*xferfile == 0) if (xferfile == &execfile) error ("No program file to examine."); else error ("No core dump file or running program to examine."); val = lseek (xferchan, fileptr, 0); if (val < 0) perror_with_name (*xferfile); val = myread (xferchan, myaddr, i); if (val < 0) perror_with_name (*xferfile); } /* If this address is for nonexistent memory, read zeros if reading, or do nothing if writing. */ else { bzero (myaddr, i); returnval = EIO; } memaddr += i; myaddr += i; len -= i; } return returnval;}/* Here from info files command to print an address map. */print_maps (){ struct pmap ptrs[200]; int n; /* ID strings for core and executable file sections */ static char *idstr[] = { "0", "text", "data", "tdata", "bss", "tbss", "common", "ttext", "ctx", "tctx", "10", "11", "12", }; for (n = 0; n < n_core; n++) { core_map[n].which = 0; ptrs[n] = core_map[n]; } for (n = 0; n < n_exec; n++) { exec_map[n].which = 1; ptrs[n_core+n] = exec_map[n]; } qsort (ptrs, n_core + n_exec, sizeof *ptrs, ptr_cmp); for (n = 0; n < n_core + n_exec; n++) { struct pmap *p = &ptrs[n]; if (n > 0) { if (p->mem_addr < ptrs[n-1].mem_end) p->mem_addr = ptrs[n-1].mem_end; if (p->mem_addr >= p->mem_end) continue; } printf_filtered ("%08x .. %08x %-6s %s\n", p->mem_addr, p->mem_end, idstr[p->type], p->which ? execfile : corefile); }}/* Compare routine to put file sections in order. Sort into increasing order on address, and put core file sections before exec file sections if both files contain the same addresses. */static ptr_cmp (a, b) struct pmap *a, *b;{ if (a->mem_addr != b->mem_addr) return a->mem_addr - b->mem_addr; return a->which - b->which;}/* Trapped internal variables are used to handle special registers. A trapped i.v. calls a hook here every time it is dereferenced, to provide a new value for the variable, and it calls a hook here when a new value is assigned, to do something with the value. The vector registers are $vl, $vs, $vm, $vN, $VN (N in 0..7). The communication registers are $cN, $CN (N in 0..63). They not handled as regular registers because it's expensive to read them, and their size varies, and they have too many names. *//* Return 1 if NAME is a trapped internal variable, else 0. */intis_trapped_internalvar (name) char *name;{ if ((name[0] == 'c' || name[0] == 'C') && name[1] >= '0' && name[1] <= '9' && (name[2] == '\0' || (name[2] >= '0' && name[2] <= '9' && name[3] == '\0' && name[1] != '0')) && atoi (&name[1]) < 64) return 1; if ((name[0] == 'v' || name[0] == 'V') && (((name[1] & -8) == '0' && name[2] == '\0') || !strcmp (name, "vl") || !strcmp (name, "vs") || !strcmp (name, "vm"))) return 1; else return 0;}/* Return the value of trapped internal variable VAR */valuevalue_of_trapped_internalvar (var) struct internalvar *var;{ char *name = var->name; value val; struct type *type; long len = *read_vector_register (VL_REGNUM); if (len <= 0 || len > 128) len = 128; if (!strcmp (name, "vl")) { val = value_from_longest (builtin_type_int, (LONGEST) *read_vector_register_1 (VL_REGNUM)); } else if (!strcmp (name, "vs")) { val = value_from_longest (builtin_type_int, (LONGEST) *read_vector_register_1 (VS_REGNUM)); } else if (!strcmp (name, "vm")) { long vm[4]; long i, *p; bcopy (read_vector_register_1 (VM_REGNUM), vm, sizeof vm); type = vector_type (builtin_type_int, len); val = allocate_value (type); p = (long *) VALUE_CONTENTS (val); for (i = 0; i < len; i++) *p++ = !! (vm[3 - (i >> 5)] & (1 << (i & 037))); } else if (name[0] == 'V') { type = vector_type (builtin_type_long_long, len); val = allocate_value (type); bcopy (read_vector_register_1 (name[1] - '0'), VALUE_CONTENTS (val), TYPE_LENGTH (type)); } else if (name[0] == 'v') { long *p1, *p2; type = vector_type (builtin_type_long, len); val = allocate_value (type); p1 = read_vector_register_1 (name[1] - '0'); p2 = (long *) VALUE_CONTENTS (val); while (--len >= 0) {p1++; *p2++ = *p1++;} } else if (name[0] == 'c') val = value_from_longest (builtin_type_int, read_comm_register (atoi (&name[1]))); else if (name[0] == 'C') val = value_from_longest (builtin_type_long_long, read_comm_register (atoi (&name[1]))); VALUE_LVAL (val) = lval_internalvar; VALUE_INTERNALVAR (val) = var; return val;}/* Construct the type for a vector register's value -- array[LENGTH] of ELEMENT_TYPE. */static struct type *vector_type (element_type, length) struct type *element_type; long length;{ struct type *type = (struct type *) xmalloc (sizeof (struct type)); bzero (type, sizeof type); TYPE_CODE (type) = TYPE_CODE_ARRAY; TYPE_TARGET_TYPE (type) = element_type; TYPE_LENGTH (type) = length * TYPE_LENGTH (TYPE_TARGET_TYPE (type)); return type;}/* Handle a new value assigned to a trapped internal variable */voidset_trapped_internalvar (var, val, bitpos, bitsize, offset) struct internalvar *var; value val; int bitpos, bitsize, offset;{ char *name = var->name; long long newval = value_as_long (val); if (!strcmp (name, "vl")) write_vector_register (VL_REGNUM, 0, newval); else if (!strcmp (name, "vs")) write_vector_register (VS_REGNUM, 0, newval); else if (name[0] == 'c' || name[0] == 'C') write_comm_register (atoi (&name[1]), newval); else if (!strcmp (name, "vm")) error ("can't assign to $vm"); else { offset /= bitsize / 8; write_vector_register (name[1] - '0', offset, newval); }}/* Print an integer value when no format was specified. gdb normally prints these values in decimal, but the the leading 0x80000000 of pointers produces intolerable 10-digit negative numbers. If it looks like an address, print it in hex instead. */decout (stream, type, val) FILE *stream; struct type *type; LONGEST val;{ long lv = val; switch (output_radix) { case 0: if ((lv == val || (unsigned) lv == val) && ((lv & 0xf0000000) == 0x80000000 || ((lv & 0xf0000000) == 0xf0000000 && lv < STACK_END_ADDR))) { fprintf_filtered (stream, "%#x", lv); return; } case 10: fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%llu" : "%lld", val); return; case 8: if (TYPE_LENGTH (type) <= sizeof lv) fprintf_filtered (stream, "%#o", lv); else fprintf_filtered (stream, "%#llo", val); return; case 16: if (TYPE_LENGTH (type) <= sizeof lv) fprintf_filtered (stream, "%#x", lv);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -