diff options
author | Daniel Jacobowitz <dan@debian.org> | 2003-04-13 15:43:35 +0000 |
---|---|---|
committer | Daniel Jacobowitz <dan@debian.org> | 2003-04-13 15:43:35 +0000 |
commit | 8b0c482001a8edf1fde7466959b7767e15687d7c (patch) | |
tree | 809c27d50ca21098281cbeaa652587e0e80f05a9 | |
parent | a9127c2a4e7afdcca28fab319732ea0dfbac2fe8 (diff) | |
download | gdb-8b0c482001a8edf1fde7466959b7767e15687d7c.tar.gz |
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.
-rw-r--r-- | gdb/ChangeLog | 35 | ||||
-rw-r--r-- | gdb/dwarf2expr.c | 29 | ||||
-rw-r--r-- | gdb/dwarf2expr.h | 2 | ||||
-rw-r--r-- | gdb/dwarf2loc.c | 254 | ||||
-rw-r--r-- | gdb/dwarf2loc.h | 29 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 151 |
6 files changed, 388 insertions, 112 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7d6f504e4be..502514aad4c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,40 @@ 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 if the linkage name demangled successfully. diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index be965abd528..a87dfc6fb85 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -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; diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index 3d0fcb33e7b..599800ce482 100644 --- a/gdb/dwarf2expr.h +++ b/gdb/dwarf2expr.h @@ -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 diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 7073549bf02..2f5cce5f0da 100644 --- a/gdb/dwarf2loc.c +++ b/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 +}; diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index fde132922ac..b6b4d3325e1 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -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 diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index c77642d239a..b5fd38982f3 100644 --- a/gdb/dwarf2read.c +++ b/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_locexpr_baton)); - baton->objfile = objfile; + baton = obstack_alloc (&objfile->symbol_obstack, + sizeof (struct dwarf2_loclist_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; + /* 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_locexpr_funcs; - SYMBOL_LOCATION_BATON (sym) = baton; + 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; + + 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; + } } |