| /* Find a variable's value in memory, for GDB, the GNU debugger. |
| Copyright 1986, 87, 89, 91, 94, 95, 96, 1998 |
| Free Software Foundation, Inc. |
| |
| This file is part of GDB. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the 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 of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place - Suite 330, |
| Boston, MA 02111-1307, USA. */ |
| |
| #include "defs.h" |
| #include "symtab.h" |
| #include "gdbtypes.h" |
| #include "frame.h" |
| #include "value.h" |
| #include "gdbcore.h" |
| #include "inferior.h" |
| #include "target.h" |
| #include "gdb_string.h" |
| #include "floatformat.h" |
| #include "symfile.h" /* for overlay functions */ |
| |
| /* This is used to indicate that we don't know the format of the floating point |
| number. Typically, this is useful for native ports, where the actual format |
| is irrelevant, since no conversions will be taking place. */ |
| |
| const struct floatformat floatformat_unknown; |
| |
| /* Registers we shouldn't try to store. */ |
| #if !defined (CANNOT_STORE_REGISTER) |
| #define CANNOT_STORE_REGISTER(regno) 0 |
| #endif |
| |
| static void write_register_gen PARAMS ((int, char *)); |
| |
| static int read_relative_register_raw_bytes_for_frame PARAMS ((int regnum, char *myaddr, struct frame_info * frame)); |
| |
| /* Basic byte-swapping routines. GDB has needed these for a long time... |
| All extract a target-format integer at ADDR which is LEN bytes long. */ |
| |
| #if TARGET_CHAR_BIT != 8 || HOST_CHAR_BIT != 8 |
| /* 8 bit characters are a pretty safe assumption these days, so we |
| assume it throughout all these swapping routines. If we had to deal with |
| 9 bit characters, we would need to make len be in bits and would have |
| to re-write these routines... */ |
| you lose |
| #endif |
| |
| LONGEST |
| extract_signed_integer (addr, len) |
| PTR addr; |
| int len; |
| { |
| LONGEST retval; |
| unsigned char *p; |
| unsigned char *startaddr = (unsigned char *) addr; |
| unsigned char *endaddr = startaddr + len; |
| |
| if (len > (int) sizeof (LONGEST)) |
| error ("\ |
| That operation is not available on integers of more than %d bytes.", |
| sizeof (LONGEST)); |
| |
| /* Start at the most significant end of the integer, and work towards |
| the least significant. */ |
| if (TARGET_BYTE_ORDER == BIG_ENDIAN) |
| { |
| p = startaddr; |
| /* Do the sign extension once at the start. */ |
| retval = ((LONGEST) * p ^ 0x80) - 0x80; |
| for (++p; p < endaddr; ++p) |
| retval = (retval << 8) | *p; |
| } |
| else |
| { |
| p = endaddr - 1; |
| /* Do the sign extension once at the start. */ |
| retval = ((LONGEST) * p ^ 0x80) - 0x80; |
| for (--p; p >= startaddr; --p) |
| retval = (retval << 8) | *p; |
| } |
| return retval; |
| } |
| |
| ULONGEST |
| extract_unsigned_integer (addr, len) |
| PTR addr; |
| int len; |
| { |
| ULONGEST retval; |
| unsigned char *p; |
| unsigned char *startaddr = (unsigned char *) addr; |
| unsigned char *endaddr = startaddr + len; |
| |
| if (len > (int) sizeof (ULONGEST)) |
| error ("\ |
| That operation is not available on integers of more than %d bytes.", |
| sizeof (ULONGEST)); |
| |
| /* Start at the most significant end of the integer, and work towards |
| the least significant. */ |
| retval = 0; |
| if (TARGET_BYTE_ORDER == BIG_ENDIAN) |
| { |
| for (p = startaddr; p < endaddr; ++p) |
| retval = (retval << 8) | *p; |
| } |
| else |
| { |
| for (p = endaddr - 1; p >= startaddr; --p) |
| retval = (retval << 8) | *p; |
| } |
| return retval; |
| } |
| |
| /* Sometimes a long long unsigned integer can be extracted as a |
| LONGEST value. This is done so that we can print these values |
| better. If this integer can be converted to a LONGEST, this |
| function returns 1 and sets *PVAL. Otherwise it returns 0. */ |
| |
| int |
| extract_long_unsigned_integer (addr, orig_len, pval) |
| PTR addr; |
| int orig_len; |
| LONGEST *pval; |
| { |
| char *p, *first_addr; |
| int len; |
| |
| len = orig_len; |
| if (TARGET_BYTE_ORDER == BIG_ENDIAN) |
| { |
| for (p = (char *) addr; |
| len > (int) sizeof (LONGEST) && p < (char *) addr + orig_len; |
| p++) |
| { |
| if (*p == 0) |
| len--; |
| else |
| break; |
| } |
| first_addr = p; |
| } |
| else |
| { |
| first_addr = (char *) addr; |
| for (p = (char *) addr + orig_len - 1; |
| len > (int) sizeof (LONGEST) && p >= (char *) addr; |
| p--) |
| { |
| if (*p == 0) |
| len--; |
| else |
| break; |
| } |
| } |
| |
| if (len <= (int) sizeof (LONGEST)) |
| { |
| *pval = (LONGEST) extract_unsigned_integer (first_addr, |
| sizeof (LONGEST)); |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| CORE_ADDR |
| extract_address (addr, len) |
| PTR addr; |
| int len; |
| { |
| /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure |
| whether we want this to be true eventually. */ |
| return (CORE_ADDR) extract_unsigned_integer (addr, len); |
| } |
| |
| void |
| store_signed_integer (addr, len, val) |
| PTR addr; |
| int len; |
| LONGEST val; |
| { |
| unsigned char *p; |
| unsigned char *startaddr = (unsigned char *) addr; |
| unsigned char *endaddr = startaddr + len; |
| |
| /* Start at the least significant end of the integer, and work towards |
| the most significant. */ |
| if (TARGET_BYTE_ORDER == BIG_ENDIAN) |
| { |
| for (p = endaddr - 1; p >= startaddr; --p) |
| { |
| *p = val & 0xff; |
| val >>= 8; |
| } |
| } |
| else |
| { |
| for (p = startaddr; p < endaddr; ++p) |
| { |
| *p = val & 0xff; |
| val >>= 8; |
| } |
| } |
| } |
| |
| void |
| store_unsigned_integer (addr, len, val) |
| PTR addr; |
| int len; |
| ULONGEST val; |
| { |
| unsigned char *p; |
| unsigned char *startaddr = (unsigned char *) addr; |
| unsigned char *endaddr = startaddr + len; |
| |
| /* Start at the least significant end of the integer, and work towards |
| the most significant. */ |
| if (TARGET_BYTE_ORDER == BIG_ENDIAN) |
| { |
| for (p = endaddr - 1; p >= startaddr; --p) |
| { |
| *p = val & 0xff; |
| val >>= 8; |
| } |
| } |
| else |
| { |
| for (p = startaddr; p < endaddr; ++p) |
| { |
| *p = val & 0xff; |
| val >>= 8; |
| } |
| } |
| } |
| |
| /* Store the literal address "val" into |
| gdb-local memory pointed to by "addr" |
| for "len" bytes. */ |
| void |
| store_address (addr, len, val) |
| PTR addr; |
| int len; |
| LONGEST val; |
| { |
| store_unsigned_integer (addr, len, val); |
| } |
| |
| /* Extract a floating-point number from a target-order byte-stream at ADDR. |
| Returns the value as type DOUBLEST. |
| |
| If the host and target formats agree, we just copy the raw data into the |
| appropriate type of variable and return, letting the host increase precision |
| as necessary. Otherwise, we call the conversion routine and let it do the |
| dirty work. */ |
| |
| DOUBLEST |
| extract_floating (addr, len) |
| PTR addr; |
| int len; |
| { |
| DOUBLEST dretval; |
| |
| if (len == sizeof (float)) |
| { |
| if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT) |
| { |
| float retval; |
| |
| memcpy (&retval, addr, sizeof (retval)); |
| return retval; |
| } |
| else |
| floatformat_to_doublest (TARGET_FLOAT_FORMAT, addr, &dretval); |
| } |
| else if (len == sizeof (double)) |
| { |
| if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT) |
| { |
| double retval; |
| |
| memcpy (&retval, addr, sizeof (retval)); |
| return retval; |
| } |
| else |
| floatformat_to_doublest (TARGET_DOUBLE_FORMAT, addr, &dretval); |
| } |
| else if (len == sizeof (DOUBLEST)) |
| { |
| if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT) |
| { |
| DOUBLEST retval; |
| |
| memcpy (&retval, addr, sizeof (retval)); |
| return retval; |
| } |
| else |
| floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, &dretval); |
| } |
| #ifdef TARGET_EXTRACT_FLOATING |
| else if (TARGET_EXTRACT_FLOATING (addr, len, &dretval)) |
| return dretval; |
| #endif |
| else |
| { |
| error ("Can't deal with a floating point number of %d bytes.", len); |
| } |
| |
| return dretval; |
| } |
| |
| void |
| store_floating (addr, len, val) |
| PTR addr; |
| int len; |
| DOUBLEST val; |
| { |
| if (len == sizeof (float)) |
| { |
| if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT) |
| { |
| float floatval = val; |
| |
| memcpy (addr, &floatval, sizeof (floatval)); |
| } |
| else |
| floatformat_from_doublest (TARGET_FLOAT_FORMAT, &val, addr); |
| } |
| else if (len == sizeof (double)) |
| { |
| if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT) |
| { |
| double doubleval = val; |
| |
| memcpy (addr, &doubleval, sizeof (doubleval)); |
| } |
| else |
| floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &val, addr); |
| } |
| else if (len == sizeof (DOUBLEST)) |
| { |
| if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT) |
| memcpy (addr, &val, sizeof (val)); |
| else |
| floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr); |
| } |
| #ifdef TARGET_STORE_FLOATING |
| else if (TARGET_STORE_FLOATING (addr, len, val)) |
| return; |
| #endif |
| else |
| { |
| error ("Can't deal with a floating point number of %d bytes.", len); |
| } |
| } |
| |
| |
| /* Return the address in which frame FRAME's value of register REGNUM |
| has been saved in memory. Or return zero if it has not been saved. |
| If REGNUM specifies the SP, the value we return is actually |
| the SP value, not an address where it was saved. */ |
| |
| CORE_ADDR |
| find_saved_register (frame, regnum) |
| struct frame_info *frame; |
| int regnum; |
| { |
| register struct frame_info *frame1 = NULL; |
| register CORE_ADDR addr = 0; |
| |
| if (frame == NULL) /* No regs saved if want current frame */ |
| return 0; |
| |
| #ifdef HAVE_REGISTER_WINDOWS |
| /* We assume that a register in a register window will only be saved |
| in one place (since the name changes and/or disappears as you go |
| towards inner frames), so we only call get_frame_saved_regs on |
| the current frame. This is directly in contradiction to the |
| usage below, which assumes that registers used in a frame must be |
| saved in a lower (more interior) frame. This change is a result |
| of working on a register window machine; get_frame_saved_regs |
| always returns the registers saved within a frame, within the |
| context (register namespace) of that frame. */ |
| |
| /* However, note that we don't want this to return anything if |
| nothing is saved (if there's a frame inside of this one). Also, |
| callers to this routine asking for the stack pointer want the |
| stack pointer saved for *this* frame; this is returned from the |
| next frame. */ |
| |
| if (REGISTER_IN_WINDOW_P (regnum)) |
| { |
| frame1 = get_next_frame (frame); |
| if (!frame1) |
| return 0; /* Registers of this frame are active. */ |
| |
| /* Get the SP from the next frame in; it will be this |
| current frame. */ |
| if (regnum != SP_REGNUM) |
| frame1 = frame; |
| |
| FRAME_INIT_SAVED_REGS (frame1); |
| return frame1->saved_regs[regnum]; /* ... which might be zero */ |
| } |
| #endif /* HAVE_REGISTER_WINDOWS */ |
| |
| /* Note that this next routine assumes that registers used in |
| frame x will be saved only in the frame that x calls and |
| frames interior to it. This is not true on the sparc, but the |
| above macro takes care of it, so we should be all right. */ |
| while (1) |
| { |
| QUIT; |
| frame1 = get_prev_frame (frame1); |
| if (frame1 == 0 || frame1 == frame) |
| break; |
| FRAME_INIT_SAVED_REGS (frame1); |
| if (frame1->saved_regs[regnum]) |
| addr = frame1->saved_regs[regnum]; |
| } |
| |
| return addr; |
| } |
| |
| /* Find register number REGNUM relative to FRAME and put its (raw, |
| target format) contents in *RAW_BUFFER. Set *OPTIMIZED if the |
| variable was optimized out (and thus can't be fetched). Set *LVAL |
| to lval_memory, lval_register, or not_lval, depending on whether |
| the value was fetched from memory, from a register, or in a strange |
| and non-modifiable way (e.g. a frame pointer which was calculated |
| rather than fetched). Set *ADDRP to the address, either in memory |
| on as a REGISTER_BYTE offset into the registers array. |
| |
| Note that this implementation never sets *LVAL to not_lval. But |
| it can be replaced by defining GET_SAVED_REGISTER and supplying |
| your own. |
| |
| The argument RAW_BUFFER must point to aligned memory. */ |
| |
| void |
| default_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) |
| char *raw_buffer; |
| int *optimized; |
| CORE_ADDR *addrp; |
| struct frame_info *frame; |
| int regnum; |
| enum lval_type *lval; |
| { |
| CORE_ADDR addr; |
| |
| if (!target_has_registers) |
| error ("No registers."); |
| |
| /* Normal systems don't optimize out things with register numbers. */ |
| if (optimized != NULL) |
| *optimized = 0; |
| addr = find_saved_register (frame, regnum); |
| if (addr != 0) |
| { |
| if (lval != NULL) |
| *lval = lval_memory; |
| if (regnum == SP_REGNUM) |
| { |
| if (raw_buffer != NULL) |
| { |
| /* Put it back in target format. */ |
| store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), (LONGEST) addr); |
| } |
| if (addrp != NULL) |
| *addrp = 0; |
| return; |
| } |
| if (raw_buffer != NULL) |
| read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum)); |
| } |
| else |
| { |
| if (lval != NULL) |
| *lval = lval_register; |
| addr = REGISTER_BYTE (regnum); |
| if (raw_buffer != NULL) |
| read_register_gen (regnum, raw_buffer); |
| } |
| if (addrp != NULL) |
| *addrp = addr; |
| } |
| |
| #if !defined (GET_SAVED_REGISTER) |
| #define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \ |
| default_get_saved_register(raw_buffer, optimized, addrp, frame, regnum, lval) |
| #endif |
| void |
| get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) |
| char *raw_buffer; |
| int *optimized; |
| CORE_ADDR *addrp; |
| struct frame_info *frame; |
| int regnum; |
| enum lval_type *lval; |
| { |
| GET_SAVED_REGISTER (raw_buffer, optimized, addrp, frame, regnum, lval); |
| } |
| |
| /* Copy the bytes of register REGNUM, relative to the input stack frame, |
| into our memory at MYADDR, in target byte order. |
| The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). |
| |
| Returns 1 if could not be read, 0 if could. */ |
| |
| static int |
| read_relative_register_raw_bytes_for_frame (regnum, myaddr, frame) |
| int regnum; |
| char *myaddr; |
| struct frame_info *frame; |
| { |
| int optim; |
| if (regnum == FP_REGNUM && frame) |
| { |
| /* Put it back in target format. */ |
| store_address (myaddr, REGISTER_RAW_SIZE (FP_REGNUM), |
| (LONGEST) FRAME_FP (frame)); |
| |
| return 0; |
| } |
| |
| get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame, |
| regnum, (enum lval_type *) NULL); |
| |
| if (register_valid[regnum] < 0) |
| return 1; /* register value not available */ |
| |
| return optim; |
| } |
| |
| /* Copy the bytes of register REGNUM, relative to the current stack frame, |
| into our memory at MYADDR, in target byte order. |
| The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). |
| |
| Returns 1 if could not be read, 0 if could. */ |
| |
| int |
| read_relative_register_raw_bytes (regnum, myaddr) |
| int regnum; |
| char *myaddr; |
| { |
| return read_relative_register_raw_bytes_for_frame (regnum, myaddr, |
| selected_frame); |
| } |
| |
| /* Return a `value' with the contents of register REGNUM |
| in its virtual format, with the type specified by |
| REGISTER_VIRTUAL_TYPE. |
| |
| NOTE: returns NULL if register value is not available. |
| Caller will check return value or die! */ |
| |
| value_ptr |
| value_of_register (regnum) |
| int regnum; |
| { |
| CORE_ADDR addr; |
| int optim; |
| register value_ptr reg_val; |
| char raw_buffer[MAX_REGISTER_RAW_SIZE]; |
| enum lval_type lval; |
| |
| get_saved_register (raw_buffer, &optim, &addr, |
| selected_frame, regnum, &lval); |
| |
| if (register_valid[regnum] < 0) |
| return NULL; /* register value not available */ |
| |
| reg_val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum)); |
| |
| /* Convert raw data to virtual format if necessary. */ |
| |
| if (REGISTER_CONVERTIBLE (regnum)) |
| { |
| REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum), |
| raw_buffer, VALUE_CONTENTS_RAW (reg_val)); |
| } |
| else if (REGISTER_RAW_SIZE (regnum) == REGISTER_VIRTUAL_SIZE (regnum)) |
| memcpy (VALUE_CONTENTS_RAW (reg_val), raw_buffer, |
| REGISTER_RAW_SIZE (regnum)); |
| else |
| internal_error ("Register \"%s\" (%d) has conflicting raw (%d) and virtual (%d) size", |
| REGISTER_NAME (regnum), |
| regnum, |
| REGISTER_RAW_SIZE (regnum), |
| REGISTER_VIRTUAL_SIZE (regnum)); |
| VALUE_LVAL (reg_val) = lval; |
| VALUE_ADDRESS (reg_val) = addr; |
| VALUE_REGNO (reg_val) = regnum; |
| VALUE_OPTIMIZED_OUT (reg_val) = optim; |
| return reg_val; |
| } |
| |
| /* Low level examining and depositing of registers. |
| |
| The caller is responsible for making |
| sure that the inferior is stopped before calling the fetching routines, |
| or it will get garbage. (a change from GDB version 3, in which |
| the caller got the value from the last stop). */ |
| |
| /* Contents and state of the registers (in target byte order). */ |
| |
| char *registers; |
| |
| /* VALID_REGISTER is non-zero if it has been fetched, -1 if the |
| register value was not available. */ |
| |
| signed char *register_valid; |
| |
| /* The thread/process associated with the current set of registers. For now, |
| -1 is special, and means `no current process'. */ |
| int registers_pid = -1; |
| |
| /* Indicate that registers may have changed, so invalidate the cache. */ |
| |
| void |
| registers_changed () |
| { |
| int i; |
| int numregs = ARCH_NUM_REGS; |
| |
| registers_pid = -1; |
| |
| /* Force cleanup of any alloca areas if using C alloca instead of |
| a builtin alloca. This particular call is used to clean up |
| areas allocated by low level target code which may build up |
| during lengthy interactions between gdb and the target before |
| gdb gives control to the user (ie watchpoints). */ |
| alloca (0); |
| |
| for (i = 0; i < numregs; i++) |
| register_valid[i] = 0; |
| |
| if (registers_changed_hook) |
| registers_changed_hook (); |
| } |
| |
| /* Indicate that all registers have been fetched, so mark them all valid. */ |
| void |
| registers_fetched () |
| { |
| int i; |
| int numregs = ARCH_NUM_REGS; |
| for (i = 0; i < numregs; i++) |
| register_valid[i] = 1; |
| } |
| |
| /* read_register_bytes and write_register_bytes are generally a *BAD* |
| idea. They are inefficient because they need to check for partial |
| updates, which can only be done by scanning through all of the |
| registers and seeing if the bytes that are being read/written fall |
| inside of an invalid register. [The main reason this is necessary |
| is that register sizes can vary, so a simple index won't suffice.] |
| It is far better to call read_register_gen and write_register_gen |
| if you want to get at the raw register contents, as it only takes a |
| regno as an argument, and therefore can't do a partial register |
| update. |
| |
| Prior to the recent fixes to check for partial updates, both read |
| and write_register_bytes always checked to see if any registers |
| were stale, and then called target_fetch_registers (-1) to update |
| the whole set. This caused really slowed things down for remote |
| targets. */ |
| |
| /* Copy INLEN bytes of consecutive data from registers |
| starting with the INREGBYTE'th byte of register data |
| into memory at MYADDR. */ |
| |
| void |
| read_register_bytes (inregbyte, myaddr, inlen) |
| int inregbyte; |
| char *myaddr; |
| int inlen; |
| { |
| int inregend = inregbyte + inlen; |
| int regno; |
| |
| if (registers_pid != inferior_pid) |
| { |
| registers_changed (); |
| registers_pid = inferior_pid; |
| } |
| |
| /* See if we are trying to read bytes from out-of-date registers. If so, |
| update just those registers. */ |
| |
| for (regno = 0; regno < NUM_REGS; regno++) |
| { |
| int regstart, regend; |
| |
| if (register_valid[regno]) |
| continue; |
| |
| if (REGISTER_NAME (regno) == NULL || *REGISTER_NAME (regno) == '\0') |
| continue; |
| |
| regstart = REGISTER_BYTE (regno); |
| regend = regstart + REGISTER_RAW_SIZE (regno); |
| |
| if (regend <= inregbyte || inregend <= regstart) |
| /* The range the user wants to read doesn't overlap with regno. */ |
| continue; |
| |
| /* We've found an invalid register where at least one byte will be read. |
| Update it from the target. */ |
| target_fetch_registers (regno); |
| |
| if (!register_valid[regno]) |
| error ("read_register_bytes: Couldn't update register %d.", regno); |
| } |
| |
| if (myaddr != NULL) |
| memcpy (myaddr, ®isters[inregbyte], inlen); |
| } |
| |
| /* Read register REGNO into memory at MYADDR, which must be large enough |
| for REGISTER_RAW_BYTES (REGNO). Target byte-order. |
| If the register is known to be the size of a CORE_ADDR or smaller, |
| read_register can be used instead. */ |
| void |
| read_register_gen (regno, myaddr) |
| int regno; |
| char *myaddr; |
| { |
| if (registers_pid != inferior_pid) |
| { |
| registers_changed (); |
| registers_pid = inferior_pid; |
| } |
| |
| if (!register_valid[regno]) |
| target_fetch_registers (regno); |
| memcpy (myaddr, ®isters[REGISTER_BYTE (regno)], |
| REGISTER_RAW_SIZE (regno)); |
| } |
| |
| /* Write register REGNO at MYADDR to the target. MYADDR points at |
| REGISTER_RAW_BYTES(REGNO), which must be in target byte-order. */ |
| |
| static void |
| write_register_gen (regno, myaddr) |
| int regno; |
| char *myaddr; |
| { |
| int size; |
| |
| /* On the sparc, writing %g0 is a no-op, so we don't even want to change |
| the registers array if something writes to this register. */ |
| if (CANNOT_STORE_REGISTER (regno)) |
| return; |
| |
| if (registers_pid != inferior_pid) |
| { |
| registers_changed (); |
| registers_pid = inferior_pid; |
| } |
| |
| size = REGISTER_RAW_SIZE (regno); |
| |
| /* If we have a valid copy of the register, and new value == old value, |
| then don't bother doing the actual store. */ |
| |
| if (register_valid[regno] |
| && memcmp (®isters[REGISTER_BYTE (regno)], myaddr, size) == 0) |
| return; |
| |
| target_prepare_to_store (); |
| |
| memcpy (®isters[REGISTER_BYTE (regno)], myaddr, size); |
| |
| register_valid[regno] = 1; |
| |
| target_store_registers (regno); |
| } |
| |
| /* Copy INLEN bytes of consecutive data from memory at MYADDR |
| into registers starting with the MYREGSTART'th byte of register data. */ |
| |
| void |
| write_register_bytes (myregstart, myaddr, inlen) |
| int myregstart; |
| char *myaddr; |
| int inlen; |
| { |
| int myregend = myregstart + inlen; |
| int regno; |
| |
| target_prepare_to_store (); |
| |
| /* Scan through the registers updating any that are covered by the range |
| myregstart<=>myregend using write_register_gen, which does nice things |
| like handling threads, and avoiding updates when the new and old contents |
| are the same. */ |
| |
| for (regno = 0; regno < NUM_REGS; regno++) |
| { |
| int regstart, regend; |
| |
| regstart = REGISTER_BYTE (regno); |
| regend = regstart + REGISTER_RAW_SIZE (regno); |
| |
| /* Is this register completely outside the range the user is writing? */ |
| if (myregend <= regstart || regend <= myregstart) |
| /* do nothing */ ; |
| |
| /* Is this register completely within the range the user is writing? */ |
| else if (myregstart <= regstart && regend <= myregend) |
| write_register_gen (regno, myaddr + (regstart - myregstart)); |
| |
| /* The register partially overlaps the range being written. */ |
| else |
| { |
| char regbuf[MAX_REGISTER_RAW_SIZE]; |
| /* What's the overlap between this register's bytes and |
| those the caller wants to write? */ |
| int overlapstart = max (regstart, myregstart); |
| int overlapend = min (regend, myregend); |
| |
| /* We may be doing a partial update of an invalid register. |
| Update it from the target before scribbling on it. */ |
| read_register_gen (regno, regbuf); |
| |
| memcpy (registers + overlapstart, |
| myaddr + (overlapstart - myregstart), |
| overlapend - overlapstart); |
| |
| target_store_registers (regno); |
| } |
| } |
| } |
| |
| |
| /* Return the raw contents of register REGNO, regarding it as an integer. */ |
| /* This probably should be returning LONGEST rather than CORE_ADDR. */ |
| |
| CORE_ADDR |
| read_register (regno) |
| int regno; |
| { |
| if (registers_pid != inferior_pid) |
| { |
| registers_changed (); |
| registers_pid = inferior_pid; |
| } |
| |
| if (!register_valid[regno]) |
| target_fetch_registers (regno); |
| |
| return (CORE_ADDR) extract_address (®isters[REGISTER_BYTE (regno)], |
| REGISTER_RAW_SIZE (regno)); |
| } |
| |
| CORE_ADDR |
| read_register_pid (regno, pid) |
| int regno, pid; |
| { |
| int save_pid; |
| CORE_ADDR retval; |
| |
| if (pid == inferior_pid) |
| return read_register (regno); |
| |
| save_pid = inferior_pid; |
| |
| inferior_pid = pid; |
| |
| retval = read_register (regno); |
| |
| inferior_pid = save_pid; |
| |
| return retval; |
| } |
| |
| /* Store VALUE, into the raw contents of register number REGNO. |
| This should probably write a LONGEST rather than a CORE_ADDR */ |
| |
| void |
| write_register (regno, val) |
| int regno; |
| LONGEST val; |
| { |
| PTR buf; |
| int size; |
| |
| /* On the sparc, writing %g0 is a no-op, so we don't even want to change |
| the registers array if something writes to this register. */ |
| if (CANNOT_STORE_REGISTER (regno)) |
| return; |
| |
| if (registers_pid != inferior_pid) |
| { |
| registers_changed (); |
| registers_pid = inferior_pid; |
| } |
| |
| size = REGISTER_RAW_SIZE (regno); |
| buf = alloca (size); |
| store_signed_integer (buf, size, (LONGEST) val); |
| |
| /* If we have a valid copy of the register, and new value == old value, |
| then don't bother doing the actual store. */ |
| |
| if (register_valid[regno] |
| && memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0) |
| return; |
| |
| target_prepare_to_store (); |
| |
| memcpy (®isters[REGISTER_BYTE (regno)], buf, size); |
| |
| register_valid[regno] = 1; |
| |
| target_store_registers (regno); |
| } |
| |
| void |
| write_register_pid (regno, val, pid) |
| int regno; |
| CORE_ADDR val; |
| int pid; |
| { |
| int save_pid; |
| |
| if (pid == inferior_pid) |
| { |
| write_register (regno, val); |
| return; |
| } |
| |
| save_pid = inferior_pid; |
| |
| inferior_pid = pid; |
| |
| write_register (regno, val); |
| |
| inferior_pid = save_pid; |
| } |
| |
| /* Record that register REGNO contains VAL. |
| This is used when the value is obtained from the inferior or core dump, |
| so there is no need to store the value there. |
| |
| If VAL is a NULL pointer, then it's probably an unsupported register. We |
| just set it's value to all zeros. We might want to record this fact, and |
| report it to the users of read_register and friends. |
| */ |
| |
| void |
| supply_register (regno, val) |
| int regno; |
| char *val; |
| { |
| #if 1 |
| if (registers_pid != inferior_pid) |
| { |
| registers_changed (); |
| registers_pid = inferior_pid; |
| } |
| #endif |
| |
| register_valid[regno] = 1; |
| if (val) |
| memcpy (®isters[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno)); |
| else |
| memset (®isters[REGISTER_BYTE (regno)], '\000', REGISTER_RAW_SIZE (regno)); |
| |
| /* On some architectures, e.g. HPPA, there are a few stray bits in some |
| registers, that the rest of the code would like to ignore. */ |
| #ifdef CLEAN_UP_REGISTER_VALUE |
| CLEAN_UP_REGISTER_VALUE (regno, ®isters[REGISTER_BYTE (regno)]); |
| #endif |
| } |
| |
| |
| /* This routine is getting awfully cluttered with #if's. It's probably |
| time to turn this into READ_PC and define it in the tm.h file. |
| Ditto for write_pc. |
| |
| 1999-06-08: The following were re-written so that it assumes the |
| existance of a TARGET_READ_PC et.al. macro. A default generic |
| version of that macro is made available where needed. |
| |
| Since the ``TARGET_READ_PC'' et.al. macro is going to be controlled |
| by the multi-arch framework, it will eventually be possible to |
| eliminate the intermediate read_pc_pid(). The client would call |
| TARGET_READ_PC directly. (cagney). */ |
| |
| #ifndef TARGET_READ_PC |
| #define TARGET_READ_PC generic_target_read_pc |
| #endif |
| |
| CORE_ADDR |
| generic_target_read_pc (pid) |
| { |
| #ifdef PC_REGNUM |
| if (PC_REGNUM >= 0) |
| { |
| CORE_ADDR pc_val = ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, pid)); |
| return pc_val; |
| } |
| #endif |
| internal_error ("generic_target_read_pc"); |
| return 0; |
| } |
| |
| CORE_ADDR |
| read_pc_pid (pid) |
| int pid; |
| { |
| int saved_inferior_pid; |
| CORE_ADDR pc_val; |
| |
| /* In case pid != inferior_pid. */ |
| saved_inferior_pid = inferior_pid; |
| inferior_pid = pid; |
| |
| pc_val = TARGET_READ_PC (pid); |
| |
| inferior_pid = saved_inferior_pid; |
| return pc_val; |
| } |
| |
| CORE_ADDR |
| read_pc () |
| { |
| return read_pc_pid (inferior_pid); |
| } |
| |
| #ifndef TARGET_WRITE_PC |
| #define TARGET_WRITE_PC generic_target_write_pc |
| #endif |
| |
| void |
| generic_target_write_pc (pc, pid) |
| CORE_ADDR pc; |
| int pid; |
| { |
| #ifdef PC_REGNUM |
| if (PC_REGNUM >= 0) |
| write_register_pid (PC_REGNUM, pc, pid); |
| #ifdef NPC_REGNUM |
| if (NPC_REGNUM >= 0) |
| write_register_pid (NPC_REGNUM, pc + 4, pid); |
| #ifdef NNPC_REGNUM |
| if (NNPC_REGNUM >= 0) |
| write_register_pid (NNPC_REGNUM, pc + 8, pid); |
| #endif |
| #endif |
| #else |
| internal_error ("generic_target_write_pc"); |
| #endif |
| } |
| |
| void |
| write_pc_pid (pc, pid) |
| CORE_ADDR pc; |
| int pid; |
| { |
| int saved_inferior_pid; |
| |
| /* In case pid != inferior_pid. */ |
| saved_inferior_pid = inferior_pid; |
| inferior_pid = pid; |
| |
| TARGET_WRITE_PC (pc, pid); |
| |
| inferior_pid = saved_inferior_pid; |
| } |
| |
| void |
| write_pc (pc) |
| CORE_ADDR pc; |
| { |
| write_pc_pid (pc, inferior_pid); |
| } |
| |
| /* Cope with strage ways of getting to the stack and frame pointers */ |
| |
| #ifndef TARGET_READ_SP |
| #define TARGET_READ_SP generic_target_read_sp |
| #endif |
| |
| CORE_ADDR |
| generic_target_read_sp () |
| { |
| #ifdef SP_REGNUM |
| if (SP_REGNUM >= 0) |
| return read_register (SP_REGNUM); |
| #endif |
| internal_error ("generic_target_read_sp"); |
| } |
| |
| CORE_ADDR |
| read_sp () |
| { |
| return TARGET_READ_SP (); |
| } |
| |
| #ifndef TARGET_WRITE_SP |
| #define TARGET_WRITE_SP generic_target_write_sp |
| #endif |
| |
| void |
| generic_target_write_sp (val) |
| CORE_ADDR val; |
| { |
| #ifdef SP_REGNUM |
| if (SP_REGNUM >= 0) |
| { |
| write_register (SP_REGNUM, val); |
| return; |
| } |
| #endif |
| internal_error ("generic_target_write_sp"); |
| } |
| |
| void |
| write_sp (val) |
| CORE_ADDR val; |
| { |
| TARGET_WRITE_SP (val); |
| } |
| |
| #ifndef TARGET_READ_FP |
| #define TARGET_READ_FP generic_target_read_fp |
| #endif |
| |
| CORE_ADDR |
| generic_target_read_fp () |
| { |
| #ifdef FP_REGNUM |
| if (FP_REGNUM >= 0) |
| return read_register (FP_REGNUM); |
| #endif |
| internal_error ("generic_target_read_fp"); |
| } |
| |
| CORE_ADDR |
| read_fp () |
| { |
| return TARGET_READ_FP (); |
| } |
| |
| #ifndef TARGET_WRITE_FP |
| #define TARGET_WRITE_FP generic_target_write_fp |
| #endif |
| |
| void |
| generic_target_write_fp (val) |
| CORE_ADDR val; |
| { |
| #ifdef FP_REGNUM |
| if (FP_REGNUM >= 0) |
| { |
| write_register (FP_REGNUM, val); |
| return; |
| } |
| #endif |
| internal_error ("generic_target_write_fp"); |
| } |
| |
| void |
| write_fp (val) |
| CORE_ADDR val; |
| { |
| TARGET_WRITE_FP (val); |
| } |
| |
| /* Will calling read_var_value or locate_var_value on SYM end |
| up caring what frame it is being evaluated relative to? SYM must |
| be non-NULL. */ |
| int |
| symbol_read_needs_frame (sym) |
| struct symbol *sym; |
| { |
| switch (SYMBOL_CLASS (sym)) |
| { |
| /* All cases listed explicitly so that gcc -Wall will detect it if |
| we failed to consider one. */ |
| case LOC_REGISTER: |
| case LOC_ARG: |
| case LOC_REF_ARG: |
| case LOC_REGPARM: |
| case LOC_REGPARM_ADDR: |
| case LOC_LOCAL: |
| case LOC_LOCAL_ARG: |
| case LOC_BASEREG: |
| case LOC_BASEREG_ARG: |
| case LOC_THREAD_LOCAL_STATIC: |
| return 1; |
| |
| case LOC_UNDEF: |
| case LOC_CONST: |
| case LOC_STATIC: |
| case LOC_INDIRECT: |
| case LOC_TYPEDEF: |
| |
| case LOC_LABEL: |
| /* Getting the address of a label can be done independently of the block, |
| even if some *uses* of that address wouldn't work so well without |
| the right frame. */ |
| |
| case LOC_BLOCK: |
| case LOC_CONST_BYTES: |
| case LOC_UNRESOLVED: |
| case LOC_OPTIMIZED_OUT: |
| return 0; |
| } |
| return 1; |
| } |
| |
| /* Given a struct symbol for a variable, |
| and a stack frame id, read the value of the variable |
| and return a (pointer to a) struct value containing the value. |
| If the variable cannot be found, return a zero pointer. |
| If FRAME is NULL, use the selected_frame. */ |
| |
| value_ptr |
| read_var_value (var, frame) |
| register struct symbol *var; |
| struct frame_info *frame; |
| { |
| register value_ptr v; |
| struct type *type = SYMBOL_TYPE (var); |
| CORE_ADDR addr; |
| register int len; |
| |
| v = allocate_value (type); |
| VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */ |
| VALUE_BFD_SECTION (v) = SYMBOL_BFD_SECTION (var); |
| |
| len = TYPE_LENGTH (type); |
| |
| if (frame == NULL) |
| frame = selected_frame; |
| |
| switch (SYMBOL_CLASS (var)) |
| { |
| case LOC_CONST: |
| /* Put the constant back in target format. */ |
| store_signed_integer (VALUE_CONTENTS_RAW (v), len, |
| (LONGEST) SYMBOL_VALUE (var)); |
| VALUE_LVAL (v) = not_lval; |
| return v; |
| |
| case LOC_LABEL: |
| /* Put the constant back in target format. */ |
| if (overlay_debugging) |
| store_address (VALUE_CONTENTS_RAW (v), len, |
| (LONGEST) symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), |
| SYMBOL_BFD_SECTION (var))); |
| else |
| store_address (VALUE_CONTENTS_RAW (v), len, |
| (LONGEST) SYMBOL_VALUE_ADDRESS (var)); |
| VALUE_LVAL (v) = not_lval; |
| return v; |
| |
| case LOC_CONST_BYTES: |
| { |
| char *bytes_addr; |
| bytes_addr = SYMBOL_VALUE_BYTES (var); |
| memcpy (VALUE_CONTENTS_RAW (v), bytes_addr, len); |
| VALUE_LVAL (v) = not_lval; |
| return v; |
| } |
| |
| case LOC_STATIC: |
| if (overlay_debugging) |
| addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), |
| SYMBOL_BFD_SECTION (var)); |
| else |
| addr = SYMBOL_VALUE_ADDRESS (var); |
| break; |
| |
| case LOC_INDIRECT: |
| /* The import slot does not have a real address in it from the |
| dynamic loader (dld.sl on HP-UX), if the target hasn't begun |
| execution yet, so check for that. */ |
| if (!target_has_execution) |
| error ("\ |
| Attempt to access variable defined in different shared object or load module when\n\ |
| addresses have not been bound by the dynamic loader. Try again when executable is running."); |
| |
| addr = SYMBOL_VALUE_ADDRESS (var); |
| addr = read_memory_unsigned_integer |
| (addr, TARGET_PTR_BIT / TARGET_CHAR_BIT); |
| break; |
| |
| case LOC_ARG: |
| if (frame == NULL) |
| return 0; |
| addr = FRAME_ARGS_ADDRESS (frame); |
| if (!addr) |
| return 0; |
| addr += SYMBOL_VALUE (var); |
| break; |
| |
| case LOC_REF_ARG: |
| if (frame == NULL) |
| return 0; |
| addr = FRAME_ARGS_ADDRESS (frame); |
| if (!addr) |
| return 0; |
| addr += SYMBOL_VALUE (var); |
| addr = read_memory_unsigned_integer |
| (addr, TARGET_PTR_BIT / TARGET_CHAR_BIT); |
| break; |
| |
| case LOC_LOCAL: |
| case LOC_LOCAL_ARG: |
| if (frame == NULL) |
| return 0; |
| addr = FRAME_LOCALS_ADDRESS (frame); |
| addr += SYMBOL_VALUE (var); |
| break; |
| |
| case LOC_BASEREG: |
| case LOC_BASEREG_ARG: |
| { |
| char buf[MAX_REGISTER_RAW_SIZE]; |
| get_saved_register (buf, NULL, NULL, frame, SYMBOL_BASEREG (var), |
| NULL); |
| addr = extract_address (buf, REGISTER_RAW_SIZE (SYMBOL_BASEREG (var))); |
| addr += SYMBOL_VALUE (var); |
| break; |
| } |
| |
| case LOC_THREAD_LOCAL_STATIC: |
| { |
| char buf[MAX_REGISTER_RAW_SIZE]; |
| |
| get_saved_register (buf, NULL, NULL, frame, SYMBOL_BASEREG (var), |
| NULL); |
| addr = extract_address (buf, REGISTER_RAW_SIZE (SYMBOL_BASEREG (var))); |
| addr += SYMBOL_VALUE (var); |
| break; |
| } |
| |
| case LOC_TYPEDEF: |
| error ("Cannot look up value of a typedef"); |
| break; |
| |
| case LOC_BLOCK: |
| if (overlay_debugging) |
| VALUE_ADDRESS (v) = symbol_overlayed_address |
| (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_BFD_SECTION (var)); |
| else |
| VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); |
| return v; |
| |
| case LOC_REGISTER: |
| case LOC_REGPARM: |
| case LOC_REGPARM_ADDR: |
| { |
| struct block *b; |
| int regno = SYMBOL_VALUE (var); |
| value_ptr regval; |
| |
| if (frame == NULL) |
| return 0; |
| b = get_frame_block (frame); |
| |
| if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR) |
| { |
| regval = value_from_register (lookup_pointer_type (type), |
| regno, |
| frame); |
| |
| if (regval == NULL) |
| error ("Value of register variable not available."); |
| |
| addr = value_as_pointer (regval); |
| VALUE_LVAL (v) = lval_memory; |
| } |
| else |
| { |
| regval = value_from_register (type, regno, frame); |
| |
| if (regval == NULL) |
| error ("Value of register variable not available."); |
| return regval; |
| } |
| } |
| break; |
| |
| case LOC_UNRESOLVED: |
| { |
| struct minimal_symbol *msym; |
| |
| msym = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL); |
| if (msym == NULL) |
| return 0; |
| if (overlay_debugging) |
| addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (msym), |
| SYMBOL_BFD_SECTION (msym)); |
| else |
| addr = SYMBOL_VALUE_ADDRESS (msym); |
| } |
| break; |
| |
| case LOC_OPTIMIZED_OUT: |
| VALUE_LVAL (v) = not_lval; |
| VALUE_OPTIMIZED_OUT (v) = 1; |
| return v; |
| |
| default: |
| error ("Cannot look up value of a botched symbol."); |
| break; |
| } |
| |
| VALUE_ADDRESS (v) = addr; |
| VALUE_LAZY (v) = 1; |
| return v; |
| } |
| |
| /* Return a value of type TYPE, stored in register REGNUM, in frame |
| FRAME. |
| |
| NOTE: returns NULL if register value is not available. |
| Caller will check return value or die! */ |
| |
| value_ptr |
| value_from_register (type, regnum, frame) |
| struct type *type; |
| int regnum; |
| struct frame_info *frame; |
| { |
| char raw_buffer[MAX_REGISTER_RAW_SIZE]; |
| CORE_ADDR addr; |
| int optim; |
| value_ptr v = allocate_value (type); |
| char *value_bytes = 0; |
| int value_bytes_copied = 0; |
| int num_storage_locs; |
| enum lval_type lval; |
| int len; |
| |
| CHECK_TYPEDEF (type); |
| len = TYPE_LENGTH (type); |
| |
| VALUE_REGNO (v) = regnum; |
| |
| num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ? |
| ((len - 1) / REGISTER_RAW_SIZE (regnum)) + 1 : |
| 1); |
| |
| if (num_storage_locs > 1 |
| #ifdef GDB_TARGET_IS_H8500 |
| || TYPE_CODE (type) == TYPE_CODE_PTR |
| #endif |
| ) |
| { |
| /* Value spread across multiple storage locations. */ |
| |
| int local_regnum; |
| int mem_stor = 0, reg_stor = 0; |
| int mem_tracking = 1; |
| CORE_ADDR last_addr = 0; |
| CORE_ADDR first_addr = 0; |
| |
| value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE); |
| |
| /* Copy all of the data out, whereever it may be. */ |
| |
| #ifdef GDB_TARGET_IS_H8500 |
| /* This piece of hideosity is required because the H8500 treats registers |
| differently depending upon whether they are used as pointers or not. As a |
| pointer, a register needs to have a page register tacked onto the front. |
| An alternate way to do this would be to have gcc output different register |
| numbers for the pointer & non-pointer form of the register. But, it |
| doesn't, so we're stuck with this. */ |
| |
| if (TYPE_CODE (type) == TYPE_CODE_PTR |
| && len > 2) |
| { |
| int page_regnum; |
| |
| switch (regnum) |
| { |
| case R0_REGNUM: |
| case R1_REGNUM: |
| case R2_REGNUM: |
| case R3_REGNUM: |
| page_regnum = SEG_D_REGNUM; |
| break; |
| case R4_REGNUM: |
| case R5_REGNUM: |
| page_regnum = SEG_E_REGNUM; |
| break; |
| case R6_REGNUM: |
| case R7_REGNUM: |
| page_regnum = SEG_T_REGNUM; |
| break; |
| } |
| |
| value_bytes[0] = 0; |
| get_saved_register (value_bytes + 1, |
| &optim, |
| &addr, |
| frame, |
| page_regnum, |
| &lval); |
| |
| if (register_valid[page_regnum] == -1) |
| return NULL; /* register value not available */ |
| |
| if (lval == lval_register) |
| reg_stor++; |
| else |
| mem_stor++; |
| first_addr = addr; |
| last_addr = addr; |
| |
| get_saved_register (value_bytes + 2, |
| &optim, |
| &addr, |
| frame, |
| regnum, |
| &lval); |
| |
| if (register_valid[regnum] == -1) |
| return NULL; /* register value not available */ |
| |
| if (lval == lval_register) |
| reg_stor++; |
| else |
| { |
| mem_stor++; |
| mem_tracking = mem_tracking && (addr == last_addr); |
| } |
| last_addr = addr; |
| } |
| else |
| #endif /* GDB_TARGET_IS_H8500 */ |
| for (local_regnum = regnum; |
| value_bytes_copied < len; |
| (value_bytes_copied += REGISTER_RAW_SIZE (local_regnum), |
| ++local_regnum)) |
| { |
| get_saved_register (value_bytes + value_bytes_copied, |
| &optim, |
| &addr, |
| frame, |
| local_regnum, |
| &lval); |
| |
| if (register_valid[local_regnum] == -1) |
| return NULL; /* register value not available */ |
| |
| if (regnum == local_regnum) |
| first_addr = addr; |
| if (lval == lval_register) |
| reg_stor++; |
| else |
| { |
| mem_stor++; |
| |
| mem_tracking = |
| (mem_tracking |
| && (regnum == local_regnum |
| || addr == last_addr)); |
| } |
| last_addr = addr; |
| } |
| |
| if ((reg_stor && mem_stor) |
| || (mem_stor && !mem_tracking)) |
| /* Mixed storage; all of the hassle we just went through was |
| for some good purpose. */ |
| { |
| VALUE_LVAL (v) = lval_reg_frame_relative; |
| VALUE_FRAME (v) = FRAME_FP (frame); |
| VALUE_FRAME_REGNUM (v) = regnum; |
| } |
| else if (mem_stor) |
| { |
| VALUE_LVAL (v) = lval_memory; |
| VALUE_ADDRESS (v) = first_addr; |
| } |
| else if (reg_stor) |
| { |
| VALUE_LVAL (v) = lval_register; |
| VALUE_ADDRESS (v) = first_addr; |
| } |
| else |
| internal_error ("value_from_register: Value not stored anywhere!"); |
| |
| VALUE_OPTIMIZED_OUT (v) = optim; |
| |
| /* Any structure stored in more than one register will always be |
| an integral number of registers. Otherwise, you'd need to do |
| some fiddling with the last register copied here for little |
| endian machines. */ |
| |
| /* Copy into the contents section of the value. */ |
| memcpy (VALUE_CONTENTS_RAW (v), value_bytes, len); |
| |
| /* Finally do any conversion necessary when extracting this |
| type from more than one register. */ |
| #ifdef REGISTER_CONVERT_TO_TYPE |
| REGISTER_CONVERT_TO_TYPE (regnum, type, VALUE_CONTENTS_RAW (v)); |
| #endif |
| return v; |
| } |
| |
| /* Data is completely contained within a single register. Locate the |
| register's contents in a real register or in core; |
| read the data in raw format. */ |
| |
| get_saved_register (raw_buffer, &optim, &addr, frame, regnum, &lval); |
| |
| if (register_valid[regnum] == -1) |
| return NULL; /* register value not available */ |
| |
| VALUE_OPTIMIZED_OUT (v) = optim; |
| VALUE_LVAL (v) = lval; |
| VALUE_ADDRESS (v) = addr; |
| |
| /* Convert raw data to virtual format if necessary. */ |
| |
| if (REGISTER_CONVERTIBLE (regnum)) |
| { |
| REGISTER_CONVERT_TO_VIRTUAL (regnum, type, |
| raw_buffer, VALUE_CONTENTS_RAW (v)); |
| } |
| else |
| { |
| /* Raw and virtual formats are the same for this register. */ |
| |
| if (TARGET_BYTE_ORDER == BIG_ENDIAN && len < REGISTER_RAW_SIZE (regnum)) |
| { |
| /* Big-endian, and we want less than full size. */ |
| VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len; |
| } |
| |
| memcpy (VALUE_CONTENTS_RAW (v), raw_buffer + VALUE_OFFSET (v), len); |
| } |
| |
| return v; |
| } |
| |
| /* Given a struct symbol for a variable or function, |
| and a stack frame id, |
| return a (pointer to a) struct value containing the properly typed |
| address. */ |
| |
| value_ptr |
| locate_var_value (var, frame) |
| register struct symbol *var; |
| struct frame_info *frame; |
| { |
| CORE_ADDR addr = 0; |
| struct type *type = SYMBOL_TYPE (var); |
| value_ptr lazy_value; |
| |
| /* Evaluate it first; if the result is a memory address, we're fine. |
| Lazy evaluation pays off here. */ |
| |
| lazy_value = read_var_value (var, frame); |
| if (lazy_value == 0) |
| error ("Address of \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var)); |
| |
| if (VALUE_LAZY (lazy_value) |
| || TYPE_CODE (type) == TYPE_CODE_FUNC) |
| { |
| value_ptr val; |
| |
| addr = VALUE_ADDRESS (lazy_value); |
| val = value_from_longest (lookup_pointer_type (type), (LONGEST) addr); |
| VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (lazy_value); |
| return val; |
| } |
| |
| /* Not a memory address; check what the problem was. */ |
| switch (VALUE_LVAL (lazy_value)) |
| { |
| case lval_register: |
| case lval_reg_frame_relative: |
| error ("Address requested for identifier \"%s\" which is in a register.", |
| SYMBOL_SOURCE_NAME (var)); |
| break; |
| |
| default: |
| error ("Can't take address of \"%s\" which isn't an lvalue.", |
| SYMBOL_SOURCE_NAME (var)); |
| break; |
| } |
| return 0; /* For lint -- never reached */ |
| } |
| |
| |
| static void build_findvar PARAMS ((void)); |
| static void |
| build_findvar () |
| { |
| /* We allocate some extra slop since we do a lot of memcpy's around |
| `registers', and failing-soft is better than failing hard. */ |
| int sizeof_registers = REGISTER_BYTES + /* SLOP */ 256; |
| int sizeof_register_valid = NUM_REGS * sizeof (*register_valid); |
| registers = xmalloc (sizeof_registers); |
| memset (registers, 0, sizeof_registers); |
| register_valid = xmalloc (sizeof_register_valid); |
| memset (register_valid, 0, sizeof_register_valid); |
| } |
| |
| void _initialize_findvar PARAMS ((void)); |
| void |
| _initialize_findvar () |
| { |
| build_findvar (); |
| |
| register_gdbarch_swap (®isters, sizeof (registers), NULL); |
| register_gdbarch_swap (®ister_valid, sizeof (register_valid), NULL); |
| register_gdbarch_swap (NULL, 0, build_findvar); |
| } |