2003-04-13 Daniel Jacobowitz <drow@mvista.com>
* dwarf2expr.c (dwarf2_read_address): Renamed from read_address; made non-static. (execute_stack_op): All callers updated. * dwarf2expr.h: Add prototype for dwarf2_read_address. * dwarf2loc.c (find_location_expression): New function. (dwarf_expr_frame_base): Call it. (dwarf2_evaluate_loc_desc): Handle 0-length location expressions. (dwarf2_tracepoint_var_ref): New function, broken out from locexpr_tracepoint_var_ref. (locexpr_tracepoint_var_ref): Call dwarf2_tracepoint_var_ref. Make static. (loclist_read_variable, loclist_read_needs_frame): New functions. (loclist_describe_location, loclist_tracepoint_var_ref): New functions. (dwarf2_loclist_funcs): New struct location_funcs. * dwarf2loc.h (struct dwarf2_loclist_baton): New type. (struct dwarf2_locexpr_baton): Add comments. (dwarf2_loclist_funcs): New extern. * dwarf2read.c (struct comp_unit_head): Remove DIE member, add base_address and base_known. (dwarf_loc_buffer): New variable. (struct dwarf2_pinfo): Add dwarf_loc_buffer and dwarf_loc_size. (DWARF_LOC_BUFFER, DWARF_LOC_SIZE): New macros. (dwarf2_has_info): Initialize dwarf_loc_offset. (dwarf2_build_psymtabs): Read in .debug_loc. (dwarf2_build_psymtabs_hard): Use DWARF_LOC_BUFFER and DWARF_LOC_SIZE. (psymtab_to_symtab_1): Likewise. Move base address calculation here, from... (dwarf2_get_pc_bounds): ... here. Use the base address from cu_header. (dwarf2_symbol_mark_computed): Handle location lists.
This commit is contained in:
parent
6aca59a359
commit
0d53c4c49f
6 changed files with 388 additions and 112 deletions
|
@ -1,3 +1,38 @@
|
|||
2003-04-13 Daniel Jacobowitz <drow@mvista.com>
|
||||
|
||||
* dwarf2expr.c (dwarf2_read_address): Renamed from read_address;
|
||||
made non-static.
|
||||
(execute_stack_op): All callers updated.
|
||||
* dwarf2expr.h: Add prototype for dwarf2_read_address.
|
||||
* dwarf2loc.c (find_location_expression): New function.
|
||||
(dwarf_expr_frame_base): Call it.
|
||||
(dwarf2_evaluate_loc_desc): Handle 0-length location expressions.
|
||||
(dwarf2_tracepoint_var_ref): New function, broken out from
|
||||
locexpr_tracepoint_var_ref.
|
||||
(locexpr_tracepoint_var_ref): Call dwarf2_tracepoint_var_ref.
|
||||
Make static.
|
||||
(loclist_read_variable, loclist_read_needs_frame): New functions.
|
||||
(loclist_describe_location, loclist_tracepoint_var_ref): New
|
||||
functions.
|
||||
(dwarf2_loclist_funcs): New struct location_funcs.
|
||||
* dwarf2loc.h (struct dwarf2_loclist_baton): New type.
|
||||
(struct dwarf2_locexpr_baton): Add comments.
|
||||
(dwarf2_loclist_funcs): New extern.
|
||||
* dwarf2read.c (struct comp_unit_head): Remove DIE member, add
|
||||
base_address and base_known.
|
||||
(dwarf_loc_buffer): New variable.
|
||||
(struct dwarf2_pinfo): Add dwarf_loc_buffer and dwarf_loc_size.
|
||||
(DWARF_LOC_BUFFER, DWARF_LOC_SIZE): New macros.
|
||||
(dwarf2_has_info): Initialize dwarf_loc_offset.
|
||||
(dwarf2_build_psymtabs): Read in .debug_loc.
|
||||
(dwarf2_build_psymtabs_hard): Use DWARF_LOC_BUFFER and
|
||||
DWARF_LOC_SIZE.
|
||||
(psymtab_to_symtab_1): Likewise. Move base address calculation
|
||||
here, from...
|
||||
(dwarf2_get_pc_bounds): ... here. Use the base address from
|
||||
cu_header.
|
||||
(dwarf2_symbol_mark_computed): Handle location lists.
|
||||
|
||||
2003-04-13 Daniel Jacobowitz <drow@mvista.com>
|
||||
|
||||
* minsyms.c (install_minimal_symbols): Only switch to gnu-v3 mode
|
||||
|
|
|
@ -170,13 +170,13 @@ read_sleb128 (unsigned char *buf, unsigned char *buf_end, LONGEST * r)
|
|||
BUF_END. The address is returned, and *BYTES_READ is set to the
|
||||
number of bytes read from BUF. */
|
||||
|
||||
static CORE_ADDR
|
||||
read_address (unsigned char *buf, unsigned char *buf_end, int *bytes_read)
|
||||
CORE_ADDR
|
||||
dwarf2_read_address (unsigned char *buf, unsigned char *buf_end, int *bytes_read)
|
||||
{
|
||||
CORE_ADDR result;
|
||||
|
||||
if (buf_end - buf < TARGET_ADDR_BIT / TARGET_CHAR_BIT)
|
||||
error ("read_address: Corrupted DWARF expression.");
|
||||
error ("dwarf2_read_address: Corrupted DWARF expression.");
|
||||
|
||||
*bytes_read = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
|
||||
result = extract_address (buf, TARGET_ADDR_BIT / TARGET_CHAR_BIT);
|
||||
|
@ -277,7 +277,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
|||
break;
|
||||
|
||||
case DW_OP_addr:
|
||||
result = read_address (op_ptr, op_end, &bytes_read);
|
||||
result = dwarf2_read_address (op_ptr, op_end, &bytes_read);
|
||||
op_ptr += bytes_read;
|
||||
break;
|
||||
|
||||
|
@ -467,9 +467,10 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
|||
|
||||
(ctx->read_mem) (ctx->baton, buf, result,
|
||||
TARGET_ADDR_BIT / TARGET_CHAR_BIT);
|
||||
result = read_address (buf,
|
||||
buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT,
|
||||
&bytes_read);
|
||||
result = dwarf2_read_address (buf,
|
||||
buf + (TARGET_ADDR_BIT
|
||||
/ TARGET_CHAR_BIT),
|
||||
&bytes_read);
|
||||
}
|
||||
result = result + offset;
|
||||
ctx->stack_len = before_stack_len;
|
||||
|
@ -528,9 +529,10 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
|||
|
||||
(ctx->read_mem) (ctx->baton, buf, result,
|
||||
TARGET_ADDR_BIT / TARGET_CHAR_BIT);
|
||||
result = read_address (buf,
|
||||
buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT,
|
||||
&bytes_read);
|
||||
result = dwarf2_read_address (buf,
|
||||
buf + (TARGET_ADDR_BIT
|
||||
/ TARGET_CHAR_BIT),
|
||||
&bytes_read);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -540,9 +542,10 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
|||
int bytes_read;
|
||||
|
||||
(ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
|
||||
result = read_address (buf,
|
||||
buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT,
|
||||
&bytes_read);
|
||||
result = dwarf2_read_address (buf,
|
||||
buf + (TARGET_ADDR_BIT
|
||||
/ TARGET_CHAR_BIT),
|
||||
&bytes_read);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -99,5 +99,7 @@ unsigned char *read_uleb128 (unsigned char *buf, unsigned char *buf_end,
|
|||
ULONGEST * r);
|
||||
unsigned char *read_sleb128 (unsigned char *buf, unsigned char *buf_end,
|
||||
LONGEST * r);
|
||||
CORE_ADDR dwarf2_read_address (unsigned char *buf, unsigned char *buf_end,
|
||||
int *bytes_read);
|
||||
|
||||
#endif
|
||||
|
|
254
gdb/dwarf2loc.c
254
gdb/dwarf2loc.c
|
@ -40,6 +40,62 @@
|
|||
#define DWARF2_REG_TO_REGNUM(REG) (REG)
|
||||
#endif
|
||||
|
||||
/* A helper function for dealing with location lists. Given a
|
||||
symbol baton (BATON) and a pc value (PC), find the appropriate
|
||||
location expression, set *LOCEXPR_LENGTH, and return a pointer
|
||||
to the beginning of the expression. Returns NULL on failure.
|
||||
|
||||
For now, only return the first matching location expression; there
|
||||
can be more than one in the list. */
|
||||
|
||||
static char *
|
||||
find_location_expression (struct dwarf2_loclist_baton *baton,
|
||||
int *locexpr_length, CORE_ADDR pc)
|
||||
{
|
||||
CORE_ADDR base_address = baton->base_address;
|
||||
CORE_ADDR low, high;
|
||||
char *loc_ptr, *buf_end;
|
||||
unsigned int addr_size = TARGET_ADDR_BIT / TARGET_CHAR_BIT, length;
|
||||
CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
|
||||
|
||||
loc_ptr = baton->data;
|
||||
buf_end = baton->data + baton->size;
|
||||
|
||||
while (1)
|
||||
{
|
||||
low = dwarf2_read_address (loc_ptr, buf_end, &length);
|
||||
loc_ptr += length;
|
||||
high = dwarf2_read_address (loc_ptr, buf_end, &length);
|
||||
loc_ptr += length;
|
||||
|
||||
/* An end-of-list entry. */
|
||||
if (low == 0 && high == 0)
|
||||
return NULL;
|
||||
|
||||
/* A base-address-selection entry. */
|
||||
if ((low & base_mask) == base_mask)
|
||||
{
|
||||
base_address = high;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, a location expression entry. */
|
||||
low += base_address;
|
||||
high += base_address;
|
||||
|
||||
length = extract_unsigned_integer (loc_ptr, 2);
|
||||
loc_ptr += 2;
|
||||
|
||||
if (pc >= low && pc < high)
|
||||
{
|
||||
*locexpr_length = length;
|
||||
return loc_ptr;
|
||||
}
|
||||
|
||||
loc_ptr += length;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the baton used when performing dwarf2 expression
|
||||
evaluation. */
|
||||
struct dwarf_expr_baton
|
||||
|
@ -91,12 +147,28 @@ dwarf_expr_frame_base (void *baton, unsigned char **start, size_t * length)
|
|||
get_frame_base_address(), and then implement a dwarf2 specific
|
||||
this_base method. */
|
||||
struct symbol *framefunc;
|
||||
struct dwarf2_locexpr_baton *symbaton;
|
||||
struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
|
||||
|
||||
framefunc = get_frame_function (debaton->frame);
|
||||
symbaton = SYMBOL_LOCATION_BATON (framefunc);
|
||||
*start = symbaton->data;
|
||||
*length = symbaton->size;
|
||||
|
||||
if (SYMBOL_LOCATION_FUNCS (framefunc) == &dwarf2_loclist_funcs)
|
||||
{
|
||||
struct dwarf2_loclist_baton *symbaton;
|
||||
symbaton = SYMBOL_LOCATION_BATON (framefunc);
|
||||
*start = find_location_expression (symbaton, length,
|
||||
get_frame_pc (debaton->frame));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct dwarf2_locexpr_baton *symbaton;
|
||||
symbaton = SYMBOL_LOCATION_BATON (framefunc);
|
||||
*length = symbaton->size;
|
||||
*start = symbaton->data;
|
||||
}
|
||||
|
||||
if (*start == NULL)
|
||||
error ("Could not find the frame base for \"%s\".",
|
||||
SYMBOL_NATURAL_NAME (framefunc));
|
||||
}
|
||||
|
||||
/* Using the objfile specified in BATON, find the address for the
|
||||
|
@ -130,6 +202,13 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
|
|||
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;
|
||||
|
||||
|
@ -241,8 +320,55 @@ dwarf2_loc_desc_needs_frame (unsigned char *data, unsigned short size)
|
|||
return baton.needs_frame;
|
||||
}
|
||||
|
||||
static void
|
||||
dwarf2_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
|
||||
struct axs_value * value, unsigned char *data,
|
||||
int size)
|
||||
{
|
||||
if (size == 0)
|
||||
error ("Symbol \"%s\" has been optimized out.",
|
||||
SYMBOL_PRINT_NAME (symbol));
|
||||
|
||||
if (size == 1
|
||||
&& data[0] >= DW_OP_reg0
|
||||
&& data[0] <= DW_OP_reg31)
|
||||
{
|
||||
value->kind = axs_lvalue_register;
|
||||
value->u.reg = data[0] - DW_OP_reg0;
|
||||
}
|
||||
else if (data[0] == DW_OP_regx)
|
||||
{
|
||||
ULONGEST reg;
|
||||
read_uleb128 (data + 1, data + size, ®);
|
||||
value->kind = axs_lvalue_register;
|
||||
value->u.reg = reg;
|
||||
}
|
||||
else if (data[0] == DW_OP_fbreg)
|
||||
{
|
||||
/* And this is worse than just minimal; we should honor the frame base
|
||||
as above. */
|
||||
int frame_reg;
|
||||
LONGEST frame_offset;
|
||||
unsigned char *buf_end;
|
||||
|
||||
buf_end = read_sleb128 (data + 1, data + size, &frame_offset);
|
||||
if (buf_end != data + size)
|
||||
error ("Unexpected opcode after DW_OP_fbreg for symbol \"%s\".",
|
||||
SYMBOL_PRINT_NAME (symbol));
|
||||
|
||||
TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset);
|
||||
ax_reg (ax, frame_reg);
|
||||
ax_const_l (ax, frame_offset);
|
||||
ax_simple (ax, aop_add);
|
||||
|
||||
ax_const_l (ax, frame_offset);
|
||||
ax_simple (ax, aop_add);
|
||||
value->kind = axs_lvalue_memory;
|
||||
}
|
||||
else
|
||||
error ("Unsupported DWARF opcode in the location of \"%s\".",
|
||||
SYMBOL_PRINT_NAME (symbol));
|
||||
}
|
||||
|
||||
/* Return the value of SYMBOL in FRAME using the DWARF-2 expression
|
||||
evaluator to calculate the location. */
|
||||
|
@ -296,57 +422,13 @@ locexpr_describe_location (struct symbol *symbol, struct ui_file *stream)
|
|||
publicly available stub with tracepoint support for me to test
|
||||
against. When there is one this function should be revisited. */
|
||||
|
||||
void
|
||||
static void
|
||||
locexpr_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
|
||||
struct axs_value * value)
|
||||
{
|
||||
struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
|
||||
|
||||
if (dlbaton->size == 0)
|
||||
error ("Symbol \"%s\" has been optimized out.",
|
||||
SYMBOL_PRINT_NAME (symbol));
|
||||
|
||||
if (dlbaton->size == 1
|
||||
&& dlbaton->data[0] >= DW_OP_reg0
|
||||
&& dlbaton->data[0] <= DW_OP_reg31)
|
||||
{
|
||||
value->kind = axs_lvalue_register;
|
||||
value->u.reg = dlbaton->data[0] - DW_OP_reg0;
|
||||
}
|
||||
else if (dlbaton->data[0] == DW_OP_regx)
|
||||
{
|
||||
ULONGEST reg;
|
||||
read_uleb128 (dlbaton->data + 1, dlbaton->data + dlbaton->size,
|
||||
®);
|
||||
value->kind = axs_lvalue_register;
|
||||
value->u.reg = reg;
|
||||
}
|
||||
else if (dlbaton->data[0] == DW_OP_fbreg)
|
||||
{
|
||||
/* And this is worse than just minimal; we should honor the frame base
|
||||
as above. */
|
||||
int frame_reg;
|
||||
LONGEST frame_offset;
|
||||
unsigned char *buf_end;
|
||||
|
||||
buf_end = read_sleb128 (dlbaton->data + 1, dlbaton->data + dlbaton->size,
|
||||
&frame_offset);
|
||||
if (buf_end != dlbaton->data + dlbaton->size)
|
||||
error ("Unexpected opcode after DW_OP_fbreg for symbol \"%s\".",
|
||||
SYMBOL_PRINT_NAME (symbol));
|
||||
|
||||
TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset);
|
||||
ax_reg (ax, frame_reg);
|
||||
ax_const_l (ax, frame_offset);
|
||||
ax_simple (ax, aop_add);
|
||||
|
||||
ax_const_l (ax, frame_offset);
|
||||
ax_simple (ax, aop_add);
|
||||
value->kind = axs_lvalue_memory;
|
||||
}
|
||||
else
|
||||
error ("Unsupported DWARF opcode in the location of \"%s\".",
|
||||
SYMBOL_PRINT_NAME (symbol));
|
||||
dwarf2_tracepoint_var_ref (symbol, ax, value, dlbaton->data, dlbaton->size);
|
||||
}
|
||||
|
||||
/* The set of location functions used with the DWARF-2 expression
|
||||
|
@ -357,3 +439,75 @@ struct location_funcs dwarf2_locexpr_funcs = {
|
|||
locexpr_describe_location,
|
||||
locexpr_tracepoint_var_ref
|
||||
};
|
||||
|
||||
|
||||
/* Wrapper functions for location lists. These generally find
|
||||
the appropriate location expression and call something above. */
|
||||
|
||||
/* Return the value of SYMBOL in FRAME using the DWARF-2 expression
|
||||
evaluator to calculate the location. */
|
||||
static struct value *
|
||||
loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
|
||||
{
|
||||
struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
|
||||
struct value *val;
|
||||
unsigned char *data;
|
||||
int size;
|
||||
|
||||
data = find_location_expression (dlbaton, &size,
|
||||
frame ? get_frame_pc (frame) : 0);
|
||||
if (data == NULL)
|
||||
error ("Variable \"%s\" is not available.", SYMBOL_NATURAL_NAME (symbol));
|
||||
|
||||
val = dwarf2_evaluate_loc_desc (symbol, frame, data, size, dlbaton->objfile);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Return non-zero iff we need a frame to evaluate SYMBOL. */
|
||||
static int
|
||||
loclist_read_needs_frame (struct symbol *symbol)
|
||||
{
|
||||
/* If there's a location list, then assume we need to have a frame
|
||||
to choose the appropriate location expression. With tracking of
|
||||
global variables this is not necessarily true, but such tracking
|
||||
is disabled in GCC at the moment until we figure out how to
|
||||
represent it. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print a natural-language description of SYMBOL to STREAM. */
|
||||
static int
|
||||
loclist_describe_location (struct symbol *symbol, struct ui_file *stream)
|
||||
{
|
||||
/* FIXME: Could print the entire list of locations. */
|
||||
fprintf_filtered (stream, "a variable with multiple locations");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Describe the location of SYMBOL as an agent value in VALUE, generating
|
||||
any necessary bytecode in AX. */
|
||||
static void
|
||||
loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
|
||||
struct axs_value * value)
|
||||
{
|
||||
struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
|
||||
unsigned char *data;
|
||||
int size;
|
||||
|
||||
data = find_location_expression (dlbaton, &size, ax->scope);
|
||||
if (data == NULL)
|
||||
error ("Variable \"%s\" is not available.", SYMBOL_NATURAL_NAME (symbol));
|
||||
|
||||
dwarf2_tracepoint_var_ref (symbol, ax, value, data, size);
|
||||
}
|
||||
|
||||
/* The set of location functions used with the DWARF-2 expression
|
||||
evaluator and location lists. */
|
||||
struct location_funcs dwarf2_loclist_funcs = {
|
||||
loclist_read_variable,
|
||||
loclist_read_needs_frame,
|
||||
loclist_describe_location,
|
||||
loclist_tracepoint_var_ref
|
||||
};
|
||||
|
|
|
@ -24,16 +24,41 @@
|
|||
/* This header is private to the DWARF-2 reader. It is shared between
|
||||
dwarf2read.c and dwarf2loc.c. */
|
||||
|
||||
/* The symbol location baton type used by the DWARF-2 reader (i.e.
|
||||
SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). */
|
||||
/* The symbol location baton types used by the DWARF-2 reader (i.e.
|
||||
SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). "struct
|
||||
dwarf2_locexpr_baton" is for a symbol with a single location
|
||||
expression; "struct dwarf2_loclist_baton" is for a symbol with a
|
||||
location list. */
|
||||
|
||||
struct dwarf2_locexpr_baton
|
||||
{
|
||||
/* Pointer to the start of the location expression. */
|
||||
unsigned char *data;
|
||||
|
||||
/* Length of the location expression. */
|
||||
unsigned short size;
|
||||
|
||||
/* The objfile containing the symbol whose location we're computing. */
|
||||
struct objfile *objfile;
|
||||
};
|
||||
|
||||
struct dwarf2_loclist_baton
|
||||
{
|
||||
/* The initial base address for the location list, based on the compilation
|
||||
unit. */
|
||||
CORE_ADDR base_address;
|
||||
|
||||
/* Pointer to the start of the location list. */
|
||||
unsigned char *data;
|
||||
|
||||
/* Length of the location list. */
|
||||
unsigned short size;
|
||||
|
||||
/* The objfile containing the symbol whose location we're computing. */
|
||||
struct objfile *objfile;
|
||||
};
|
||||
|
||||
extern struct location_funcs dwarf2_locexpr_funcs;
|
||||
extern struct location_funcs dwarf2_loclist_funcs;
|
||||
|
||||
#endif
|
||||
|
|
151
gdb/dwarf2read.c
151
gdb/dwarf2read.c
|
@ -220,9 +220,13 @@ struct comp_unit_head
|
|||
|
||||
struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
|
||||
|
||||
/* Pointer to the DIE associated with the compilation unit. */
|
||||
/* Base address of this compilation unit. */
|
||||
|
||||
struct die_info *die;
|
||||
CORE_ADDR base_address;
|
||||
|
||||
/* Non-zero if base_address has been set. */
|
||||
|
||||
int base_known;
|
||||
};
|
||||
|
||||
/* The line number information for a compilation unit (found in the
|
||||
|
@ -395,6 +399,7 @@ static char *dwarf_line_buffer;
|
|||
static char *dwarf_str_buffer;
|
||||
static char *dwarf_macinfo_buffer;
|
||||
static char *dwarf_ranges_buffer;
|
||||
static char *dwarf_loc_buffer;
|
||||
|
||||
/* A zeroed version of a partial die for initialization purposes. */
|
||||
static struct partial_die_info zeroed_partial_die;
|
||||
|
@ -511,6 +516,13 @@ struct dwarf2_pinfo
|
|||
|
||||
unsigned int dwarf_ranges_size;
|
||||
|
||||
/* Pointer to start of dwarf locations buffer for the objfile. */
|
||||
|
||||
char *dwarf_loc_buffer;
|
||||
|
||||
/* Size of dwarf locations buffer for the objfile. */
|
||||
|
||||
unsigned int dwarf_loc_size;
|
||||
};
|
||||
|
||||
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
|
||||
|
@ -526,6 +538,8 @@ struct dwarf2_pinfo
|
|||
#define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size)
|
||||
#define DWARF_RANGES_BUFFER(p) (PST_PRIVATE(p)->dwarf_ranges_buffer)
|
||||
#define DWARF_RANGES_SIZE(p) (PST_PRIVATE(p)->dwarf_ranges_size)
|
||||
#define DWARF_LOC_BUFFER(p) (PST_PRIVATE(p)->dwarf_loc_buffer)
|
||||
#define DWARF_LOC_SIZE(p) (PST_PRIVATE(p)->dwarf_loc_size)
|
||||
|
||||
/* Maintain an array of referenced fundamental types for the current
|
||||
compilation unit being read. For DWARF version 1, we have to construct
|
||||
|
@ -926,6 +940,7 @@ dwarf2_has_info (bfd *abfd)
|
|||
dwarf_frame_offset = 0;
|
||||
dwarf_eh_frame_offset = 0;
|
||||
dwarf_ranges_offset = 0;
|
||||
dwarf_loc_offset = 0;
|
||||
|
||||
bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
|
||||
if (dwarf_info_offset && dwarf_abbrev_offset)
|
||||
|
@ -1062,6 +1077,14 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
|
|||
else
|
||||
dwarf_ranges_buffer = NULL;
|
||||
|
||||
if (dwarf_loc_offset)
|
||||
dwarf_loc_buffer = dwarf2_read_section (objfile,
|
||||
dwarf_loc_offset,
|
||||
dwarf_loc_size,
|
||||
dwarf_loc_section);
|
||||
else
|
||||
dwarf_loc_buffer = NULL;
|
||||
|
||||
if (mainline
|
||||
|| (objfile->global_psymbols.size == 0
|
||||
&& objfile->static_psymbols.size == 0))
|
||||
|
@ -1283,6 +1306,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
|
|||
DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
|
||||
DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
|
||||
DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
|
||||
DWARF_LOC_BUFFER (pst) = dwarf_loc_buffer;
|
||||
DWARF_LOC_SIZE (pst) = dwarf_loc_size;
|
||||
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
||||
|
||||
/* Store the function that reads in the rest of the symbol table */
|
||||
|
@ -1607,6 +1632,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
|
|||
char *info_ptr;
|
||||
struct symtab *symtab;
|
||||
struct cleanup *back_to;
|
||||
struct attribute *attr;
|
||||
|
||||
/* Set local variables from the partial symbol table info. */
|
||||
offset = DWARF_INFO_OFFSET (pst);
|
||||
|
@ -1621,6 +1647,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
|
|||
dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
|
||||
dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
|
||||
dwarf_ranges_size = DWARF_RANGES_SIZE (pst);
|
||||
dwarf_loc_buffer = DWARF_LOC_BUFFER (pst);
|
||||
dwarf_loc_size = DWARF_LOC_SIZE (pst);
|
||||
baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
|
||||
cu_header_offset = offset;
|
||||
info_ptr = dwarf_info_buffer + offset;
|
||||
|
@ -1642,8 +1670,32 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
|
|||
|
||||
make_cleanup_free_die_list (dies);
|
||||
|
||||
/* Find the base address of the compilation unit for range lists and
|
||||
location lists. It will normally be specified by DW_AT_low_pc.
|
||||
In DWARF-3 draft 4, the base address could be overridden by
|
||||
DW_AT_entry_pc. It's been removed, but GCC still uses this for
|
||||
compilation units with discontinuous ranges. */
|
||||
|
||||
cu_header.base_known = 0;
|
||||
cu_header.base_address = 0;
|
||||
|
||||
attr = dwarf_attr (dies, DW_AT_entry_pc);
|
||||
if (attr)
|
||||
{
|
||||
cu_header.base_address = DW_ADDR (attr);
|
||||
cu_header.base_known = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
attr = dwarf_attr (dies, DW_AT_low_pc);
|
||||
if (attr)
|
||||
{
|
||||
cu_header.base_address = DW_ADDR (attr);
|
||||
cu_header.base_known = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do line number decoding in read_file_scope () */
|
||||
cu_header.die = dies;
|
||||
process_die (dies, objfile, &cu_header);
|
||||
|
||||
if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header))
|
||||
|
@ -2122,40 +2174,18 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
|
|||
.debug_renges section. */
|
||||
unsigned int offset = DW_UNSND (attr);
|
||||
/* Base address selection entry. */
|
||||
CORE_ADDR base = 0;
|
||||
int found_base = 0;
|
||||
CORE_ADDR base;
|
||||
int found_base;
|
||||
int dummy;
|
||||
unsigned int i;
|
||||
char *buffer;
|
||||
CORE_ADDR marker;
|
||||
int low_set;
|
||||
|
||||
/* The applicable base address is determined by (1) the closest
|
||||
preceding base address selection entry in the range list or
|
||||
(2) the DW_AT_low_pc of the compilation unit. */
|
||||
|
||||
/* ??? Was in dwarf3 draft4, and has since been removed.
|
||||
GCC still uses it though. */
|
||||
attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
|
||||
if (attr)
|
||||
{
|
||||
base = DW_ADDR (attr);
|
||||
found_base = 1;
|
||||
}
|
||||
|
||||
if (!found_base)
|
||||
{
|
||||
attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
|
||||
if (attr)
|
||||
{
|
||||
base = DW_ADDR (attr);
|
||||
found_base = 1;
|
||||
}
|
||||
}
|
||||
|
||||
found_base = cu_header->base_known;
|
||||
base = cu_header->base_address;
|
||||
buffer = dwarf_ranges_buffer + offset;
|
||||
|
||||
|
||||
/* Read in the largest possible address. */
|
||||
marker = read_address (obfd, buffer, cu_header, &dummy);
|
||||
if ((marker & mask) == mask)
|
||||
|
@ -7328,26 +7358,53 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
|
|||
const struct comp_unit_head *cu_header,
|
||||
struct objfile *objfile)
|
||||
{
|
||||
struct dwarf2_locexpr_baton *baton;
|
||||
|
||||
/* When support for location lists is added, this will go away. */
|
||||
if (!attr_form_is_block (attr))
|
||||
if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
|
||||
{
|
||||
dwarf2_complex_location_expr_complaint ();
|
||||
return;
|
||||
struct dwarf2_loclist_baton *baton;
|
||||
|
||||
baton = obstack_alloc (&objfile->symbol_obstack,
|
||||
sizeof (struct dwarf2_loclist_baton));
|
||||
baton->objfile = objfile;
|
||||
|
||||
/* We don't know how long the location list is, but make sure we
|
||||
don't run off the edge of the section. */
|
||||
baton->size = dwarf_loc_size - DW_UNSND (attr);
|
||||
baton->data = dwarf_loc_buffer + DW_UNSND (attr);
|
||||
baton->base_address = cu_header->base_address;
|
||||
if (cu_header->base_known == 0)
|
||||
complaint (&symfile_complaints,
|
||||
"Location list used without specifying the CU base address.");
|
||||
|
||||
SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_loclist_funcs;
|
||||
SYMBOL_LOCATION_BATON (sym) = baton;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct dwarf2_locexpr_baton *baton;
|
||||
|
||||
baton = obstack_alloc (&objfile->symbol_obstack,
|
||||
sizeof (struct dwarf2_locexpr_baton));
|
||||
baton->objfile = objfile;
|
||||
baton = obstack_alloc (&objfile->symbol_obstack,
|
||||
sizeof (struct dwarf2_locexpr_baton));
|
||||
baton->objfile = objfile;
|
||||
|
||||
/* Note that we're just copying the block's data pointer here, not
|
||||
the actual data. We're still pointing into the dwarf_info_buffer
|
||||
for SYM's objfile; right now we never release that buffer, but
|
||||
when we do clean up properly this may need to change. */
|
||||
baton->size = DW_BLOCK (attr)->size;
|
||||
baton->data = DW_BLOCK (attr)->data;
|
||||
|
||||
SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs;
|
||||
SYMBOL_LOCATION_BATON (sym) = baton;
|
||||
if (attr_form_is_block (attr))
|
||||
{
|
||||
/* Note that we're just copying the block's data pointer
|
||||
here, not the actual data. We're still pointing into the
|
||||
dwarf_info_buffer for SYM's objfile; right now we never
|
||||
release that buffer, but when we do clean up properly
|
||||
this may need to change. */
|
||||
baton->size = DW_BLOCK (attr)->size;
|
||||
baton->data = DW_BLOCK (attr)->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwarf2_invalid_attrib_class_complaint ("location description",
|
||||
SYMBOL_NATURAL_NAME (sym));
|
||||
baton->size = 0;
|
||||
baton->data = NULL;
|
||||
}
|
||||
|
||||
SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs;
|
||||
SYMBOL_LOCATION_BATON (sym) = baton;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue