/* Using the frame specified in BATON, return the value of register REGNUM, treated as a pointer. */ static CORE_ADDR dwarf_expr_read_reg (void *baton, int dwarf_regnum) { struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; CORE_ADDR result; int regnum; regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum); result = address_from_register (builtin_type_void_data_ptr, regnum, debaton->frame); return result; }
static CORE_ADDR read_reg (void *baton, int reg) { struct frame_info *next_frame = (struct frame_info *) baton; struct gdbarch *gdbarch = get_frame_arch (next_frame); int regnum; char *buf; regnum = DWARF2_REG_TO_REGNUM (reg); buf = (char *) alloca (register_size (gdbarch, regnum)); frame_unwind_register (next_frame, regnum, buf); return extract_typed_address (buf, builtin_type_void_data_ptr); }
/* Evaluate a location description, starting at DATA and with length SIZE, to find the current location of variable VAR in the context of FRAME. */ static struct value * dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, unsigned char *data, unsigned short size, struct objfile *objfile) { CORE_ADDR result; struct value *retval; struct dwarf_expr_baton baton; struct dwarf_expr_context *ctx; if (size == 0) { retval = allocate_value (SYMBOL_TYPE (var)); VALUE_LVAL (retval) = not_lval; VALUE_OPTIMIZED_OUT (retval) = 1; } baton.frame = frame; baton.objfile = objfile; ctx = new_dwarf_expr_context (); ctx->baton = &baton; ctx->read_reg = dwarf_expr_read_reg; ctx->read_mem = dwarf_expr_read_mem; ctx->get_frame_base = dwarf_expr_frame_base; ctx->get_tls_address = dwarf_expr_tls_address; dwarf_expr_eval (ctx, data, size); result = dwarf_expr_fetch (ctx, 0); if (ctx->in_reg) { int regnum = DWARF2_REG_TO_REGNUM (result); retval = value_from_register (SYMBOL_TYPE (var), regnum, frame); } else { retval = allocate_value (SYMBOL_TYPE (var)); VALUE_BFD_SECTION (retval) = SYMBOL_BFD_SECTION (var); VALUE_LVAL (retval) = lval_memory; VALUE_LAZY (retval) = 1; VALUE_ADDRESS (retval) = result; } free_dwarf_expr_context (ctx); return retval; }
/* Print a natural-language description of SYMBOL to STREAM. */ static int locexpr_describe_location (struct symbol *symbol, struct ui_file *stream) { /* FIXME: be more extensive. */ struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); if (dlbaton->size == 1 && dlbaton->data[0] >= DW_OP_reg0 && dlbaton->data[0] <= DW_OP_reg31) { int regno = DWARF2_REG_TO_REGNUM (dlbaton->data[0] - DW_OP_reg0); fprintf_filtered (stream, "a variable in register %s", REGISTER_NAME (regno)); return 1; } /* The location expression for a TLS variable looks like this (on a 64-bit LE machine): DW_AT_location : 10 byte block: 3 4 0 0 0 0 0 0 0 e0 (DW_OP_addr: 4; DW_OP_GNU_push_tls_address) 0x3 is the encoding for DW_OP_addr, which has an operand as long as the size of an address on the target machine (here is 8 bytes). 0xe0 is the encoding for DW_OP_GNU_push_tls_address. The operand represents the offset at which the variable is within the thread local storage. */ if (dlbaton->size > 1 && dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address) if (dlbaton->data[0] == DW_OP_addr) { int bytes_read; CORE_ADDR offset = dwarf2_read_address (&dlbaton->data[1], &dlbaton->data[dlbaton->size - 1], &bytes_read); fprintf_filtered (stream, "a thread-local variable at offset %s in the " "thread-local storage for `%s'", paddr_nz (offset), dlbaton->objfile->name); return 1; } fprintf_filtered (stream, "a variable with complex or multiple locations (DWARF2)"); return 1; }
/* Using the frame specified in BATON, read register REGNUM. The lval type will be returned in LVALP, and for lval_memory the register save address will be returned in ADDRP. */ static CORE_ADDR dwarf_expr_read_reg (void *baton, int dwarf_regnum) { struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; CORE_ADDR result, save_addr; enum lval_type lval_type; char *buf; int optimized, regnum, realnum, regsize; regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum); regsize = register_size (current_gdbarch, regnum); buf = (char *) alloca (regsize); frame_register (debaton->frame, regnum, &optimized, &lval_type, &save_addr, &realnum, buf); /* NOTE: cagney/2003-05-22: This extract is assuming that a DWARF 2 address is always unsigned. That may or may not be true. */ result = extract_unsigned_integer (buf, regsize); return result; }
/* Evaluate a location description, starting at DATA and with length SIZE, to find the current location of variable VAR in the context of FRAME. */ static struct value * dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, gdb_byte *data, unsigned short size, struct objfile *objfile) { struct gdbarch *arch = get_frame_arch (frame); struct value *retval; struct dwarf_expr_baton baton; struct dwarf_expr_context *ctx; if (size == 0) { retval = allocate_value (SYMBOL_TYPE (var)); VALUE_LVAL (retval) = not_lval; set_value_optimized_out (retval, 1); } baton.frame = frame; baton.objfile = objfile; ctx = new_dwarf_expr_context (); ctx->baton = &baton; ctx->read_reg = dwarf_expr_read_reg; ctx->read_mem = dwarf_expr_read_mem; ctx->get_frame_base = dwarf_expr_frame_base; ctx->get_tls_address = dwarf_expr_tls_address; dwarf_expr_eval (ctx, data, size); if (ctx->num_pieces > 0) { int i; long offset = 0; bfd_byte *contents; retval = allocate_value (SYMBOL_TYPE (var)); contents = value_contents_raw (retval); for (i = 0; i < ctx->num_pieces; i++) { struct dwarf_expr_piece *p = &ctx->pieces[i]; if (p->in_reg) { bfd_byte regval[MAX_REGISTER_SIZE]; int gdb_regnum = DWARF2_REG_TO_REGNUM (p->value); get_frame_register (frame, gdb_regnum, regval); memcpy (contents + offset, regval, p->size); } else /* In memory? */ { read_memory (p->value, contents + offset, p->size); } offset += p->size; } } else if (ctx->in_reg) { CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0); int gdb_regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum); retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame); } else { CORE_ADDR address = dwarf_expr_fetch (ctx, 0); retval = allocate_value (SYMBOL_TYPE (var)); VALUE_LVAL (retval) = lval_memory; set_value_lazy (retval, 1); VALUE_ADDRESS (retval) = address; } free_dwarf_expr_context (ctx); return retval; }