📄 findvar.c
字号:
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}/* 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. */valueread_var_value (var, frame) register struct symbol *var; FRAME frame;{ register value v; struct frame_info *fi; 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. */ len = TYPE_LENGTH (type); if (frame == 0) frame = selected_frame; switch (SYMBOL_CLASS (var)) { case LOC_CONST: memcpy (VALUE_CONTENTS_RAW (v), &SYMBOL_VALUE (var), len); SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (v), len); VALUE_LVAL (v) = not_lval; return v; case LOC_LABEL: addr = SYMBOL_VALUE_ADDRESS (var); memcpy (VALUE_CONTENTS_RAW (v), &addr, len); SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (v), len); 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: addr = SYMBOL_VALUE_ADDRESS (var); break; case LOC_ARG: if (SYMBOL_BASEREG_VALID (var)) { addr = FRAME_GET_BASEREG_VALUE (frame, SYMBOL_BASEREG (var)); } else { fi = get_frame_info (frame); if (fi == NULL) return 0; addr = FRAME_ARGS_ADDRESS (fi); } if (!addr) { return 0; } addr += SYMBOL_VALUE (var); break; case LOC_REF_ARG: if (SYMBOL_BASEREG_VALID (var)) { addr = FRAME_GET_BASEREG_VALUE (frame, SYMBOL_BASEREG (var)); } else { fi = get_frame_info (frame); if (fi == NULL) return 0; addr = FRAME_ARGS_ADDRESS (fi); } if (!addr) { return 0; } addr += SYMBOL_VALUE (var); read_memory (addr, (char *) &addr, sizeof (CORE_ADDR)); break; case LOC_LOCAL: case LOC_LOCAL_ARG: if (SYMBOL_BASEREG_VALID (var)) { addr = FRAME_GET_BASEREG_VALUE (frame, SYMBOL_BASEREG (var)); } else { fi = get_frame_info (frame); if (fi == NULL) return 0; addr = FRAME_LOCALS_ADDRESS (fi); } addr += SYMBOL_VALUE (var); break; case LOC_TYPEDEF: error ("Cannot look up value of a typedef"); break; case LOC_BLOCK: VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); return v; case LOC_REGISTER: case LOC_REGPARM: { struct block *b; if (frame == NULL) return 0; b = get_frame_block (frame); v = value_from_register (type, SYMBOL_VALUE (var), frame); /* Nonzero if a struct which is located in a register or a LOC_ARG really contains the address of the struct, not the struct itself. GCC_P is nonzero if the function was compiled with GCC. */#if !defined (REG_STRUCT_HAS_ADDR)#define REG_STRUCT_HAS_ADDR(gcc_p) 0#endif if (REG_STRUCT_HAS_ADDR (BLOCK_GCC_COMPILED (b)) && ( (TYPE_CODE (type) == TYPE_CODE_STRUCT) || (TYPE_CODE (type) == TYPE_CODE_UNION))) addr = *(CORE_ADDR *)VALUE_CONTENTS (v); else return v; } break; 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. */valuevalue_from_register (type, regnum, frame) struct type *type; int regnum; FRAME frame;{ char raw_buffer [MAX_REGISTER_RAW_SIZE]; char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; CORE_ADDR addr; int optim; value v = allocate_value (type); int len = TYPE_LENGTH (type); char *value_bytes = 0; int value_bytes_copied = 0; int num_storage_locs; enum lval_type lval; 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) { /* 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; value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE); /* Copy all of the data out, whereever it may be. */ 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 (lval == lval_register) reg_stor++; else { mem_stor++; if (regnum == local_regnum) first_addr = addr; 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 fatal ("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); 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); VALUE_OPTIMIZED_OUT (v) = optim; VALUE_LVAL (v) = lval; VALUE_ADDRESS (v) = addr; /* Convert the raw contents to virtual contents. (Just copy them if the formats are the same.) */ REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer); if (REGISTER_CONVERTIBLE (regnum)) { /* When the raw and virtual formats differ, the virtual format corresponds to a specific data type. If we want that type, copy the data into the value. Otherwise, do a type-conversion. */ if (type != REGISTER_VIRTUAL_TYPE (regnum)) { /* eg a variable of type `float' in a 68881 register with raw type `extended' and virtual type `double'. Fetch it as a `double' and then convert to `float'. */ v = allocate_value (REGISTER_VIRTUAL_TYPE (regnum)); memcpy (VALUE_CONTENTS_RAW (v), virtual_buffer, len); v = value_cast (type, v); } else memcpy (VALUE_CONTENTS_RAW (v), virtual_buffer, len); } else { /* Raw and virtual formats are the same for this register. */#if TARGET_BYTE_ORDER == BIG_ENDIAN if (len < REGISTER_RAW_SIZE (regnum)) { /* Big-endian, and we want less than full size. */ VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len; }#endif memcpy (VALUE_CONTENTS_RAW (v), virtual_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. */valuelocate_var_value (var, frame) register struct symbol *var; FRAME frame;{ CORE_ADDR addr = 0; struct type *type = SYMBOL_TYPE (var); value 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_NAME (var)); if (VALUE_LAZY (lazy_value) || TYPE_CODE (type) == TYPE_CODE_FUNC) { addr = VALUE_ADDRESS (lazy_value); return value_from_longest (lookup_pointer_type (type), (LONGEST) addr); } /* 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_NAME (var)); break; default: error ("Can't take address of \"%s\" which isn't an lvalue.", SYMBOL_NAME (var)); break; } return 0; /* For lint -- never reached */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -