From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29954 invoked by alias); 8 Apr 2003 16:46:39 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 29908 invoked from network); 8 Apr 2003 16:46:36 -0000 Received: from unknown (HELO crack.them.org) (65.125.64.184) by sources.redhat.com with SMTP; 8 Apr 2003 16:46:36 -0000 Received: from nevyn.them.org ([66.93.61.169] ident=mail) by crack.them.org with asmtp (Exim 3.12 #1 (Debian)) id 192wF4-0007tC-00; Tue, 08 Apr 2003 11:46:38 -0500 Received: from drow by nevyn.them.org with local (Exim 3.36 #1 (Debian)) id 192wEw-0007Y7-00; Tue, 08 Apr 2003 12:46:30 -0400 Date: Tue, 08 Apr 2003 16:46:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Cc: Jim Blandy Subject: Re: RFA: Location list support for DWARF-2 Message-ID: <20030408164630.GA28986@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com, Jim Blandy References: <20030310160628.GA1988@nevyn.them.org> <20030312224043.GA8247@nevyn.them.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20030312224043.GA8247@nevyn.them.org> User-Agent: Mutt/1.5.1i X-SW-Source: 2003-04/txt/msg00130.txt.bz2 Ping? I never got any feedback on the updated patch. On Wed, Mar 12, 2003 at 05:40:44PM -0500, Daniel Jacobowitz wrote: > On Wed, Mar 12, 2003 at 04:37:20PM -0500, Jim Blandy wrote: > > > > Daniel Jacobowitz writes: > > > Here's initial support for location lists. I'd like to take a moment > > > to thank Jim Blandy and Daniel Berlin for hashing out the interface to > > > LOC_COMPUTED so thoroughly; it turned out that I didn't need to do > > > anything at all to the interface or to its clients in order to make > > > this work. > > > > > > To test this, you'll need a GCC CVS checkout from the "rtlopt-branch" > > > branch tag. This patch has no effect if location lists aren't used, > > > and is a strict improvement if they are, since otherwise we won't find > > > things at all. However, debug output from that branch is still a > > > little immature. One problem I've noticed so far is that we emit > > > incomplete location lists for global variables; see my post on the gcc@ > > > list for more details. So sometimes we can't find globals, which is a > > > regression in the debug info. > > > > > > This patch also does not support multiple overlapping location lists; > > > it simply uses the first match. The rest of GDB isn't ready for > > > multiple locations yet; that's down the list after DW_OP_piece I > > > think. > > > > > > I had to add the CU base address to each symbol's baton. Long term we > > > can get rid of it by making sure we can go from symbol to symtab and > > > storing it in the symtab; I think that's a good idea but it's a patch > > > for another day. > > > > > > Jim, is this OK? I'd appreciate another set of eyes on it. > > > > Rather than putting 'if (foo->is_list)' everywhere, why not just > > introduce a separate 'struct location_funcs' for location lists? > > Aside from just being cleaner, you'll save a word in each baton. > > Actually, it won't save any space to remove is_list: it goes into the > padding between size and the following CORE_ADDR/pointer. It does save > space for non-location-list variables though, because of the base > address, so I think it's a good idea. It requires introducing one > annoying hack in dwarf_expr_frame_base but I'm not terribly upset by > it. > > > > > > Index: dwarf2loc.c > > > =================================================================== > > > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2loc.c,v > > > retrieving revision 1.3 > > > diff -u -p -r1.3 dwarf2loc.c > > > --- dwarf2loc.c 5 Mar 2003 18:00:02 -0000 1.3 > > > +++ dwarf2loc.c 10 Mar 2003 15:22:17 -0000 > > > @@ -40,6 +40,68 @@ > > > #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_locexpr_baton *baton, > > > + int *locexpr_length, CORE_ADDR pc) > > > +{ > > > + CORE_ADDR base_address = baton->base_address; > > > + CORE_ADDR low, high; > > > + char *loc_ptr; > > > + unsigned int addr_size = TARGET_ADDR_BIT / TARGET_CHAR_BIT, length; > > > + CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); > > > > Why not just ~(~(CORE_ADDR)0 << (addr_size * 8))? > > Suppose that sizeof(CORE_ADDR) == 4 and addr_size == 4. That's a > left-shift by 32; very bad C mojo. > > By the way, Richard Henderson originally wrote this (although every > copy of it in GDB has my name on it, he submitted the original > DW_AT_ranges patch). So he gets credit for getting this right. I > always get it wrong :) > > > > + if (! baton->is_list) > > > + { > > > + *locexpr_length = baton->size; > > > + return baton->data; > > > + } > > > + > > > + loc_ptr = baton->data; > > > + > > > + while (1) > > > + { > > > + low = dwarf2_read_address (loc_ptr, loc_ptr + addr_size, &length); > > > + loc_ptr += length; > > > + high = dwarf2_read_address (loc_ptr, loc_ptr + addr_size, &length); > > > + loc_ptr += length; > > > > Shouldn't you pass baton->data + baton_size as the 'buf_end' argument? > > You're defeating the range-checking that function performs. > > Oops, this brings up a wart that I forgot to document. The size value > can't be trusted. You suggested a fix for this below; I like it, so > I'll use it :) > > > > > > Index: dwarf2read.c > > > =================================================================== > > > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2read.c,v > > > retrieving revision 1.88 > > > diff -u -p -r1.88 dwarf2read.c > > > --- dwarf2read.c 25 Feb 2003 21:36:17 -0000 1.88 > > > +++ dwarf2read.c 10 Mar 2003 05:01:11 -0000 > > > @@ -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; > > > + > > > + /* Flag representing whether base_address is accurate. */ > > > > You can be more concrete: "Non-zero if base_address has been set." > > Thanks. > > > > > > > @@ -1642,8 +1670,32 @@ psymtab_to_symtab_1 (struct partial_symt > > > > > > 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 = 0; > > > > Shouldn't this set it to 1, not zero? > > Uh, er, yes. Told you I needed more eyes. My tests all must have had > a low_pc. > > > > > > @@ -6481,6 +6511,7 @@ dump_die (struct die_info *die) > > > case DW_FORM_ref1: > > > case DW_FORM_ref2: > > > case DW_FORM_ref4: > > > + case DW_FORM_ref8: > > > case DW_FORM_udata: > > > case DW_FORM_sdata: > > > fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i])); > > > > This should be a separate patch (which you are welcome to commit). > > OK. > > > > > > @@ -7330,23 +7361,39 @@ dwarf2_symbol_mark_computed (struct attr > > > { > > > struct dwarf2_locexpr_baton *baton; > > > > > > - /* When support for location lists is added, this will go away. */ > > > - if (!attr_form_is_block (attr)) > > > - { > > > - dwarf2_complex_location_expr_complaint (); > > > - return; > > > - } > > > - > > > 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; > > > + /* When support for location lists is added, this will go away. */ > > > > This comment should go away, shouldn't it? > > Thought it had. Oopsie. > > > > > > + 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; > > > + baton->is_list = 0; > > > + } > > > + else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) > > > + { > > > + baton->size = 0; > > > > We don't have good information about the range list's extent > > available, but you should set this to 'dwarf_loc_size - DW_UNSND > > (attr)' or something like that. > > As above, sure. > > > > + baton->data = dwarf_loc_buffer + DW_UNSND (attr); > > > + baton->is_list = 1; > > > + baton->base_address = cu_header->base_address; > > > + if (cu_header->base_known == 0) > > > + complain (&symfile_complaints, > > > + "Location list used without specifying the CU base address."); > > 'complain' has been gone for a month and a half now. You'd probably > > better check this patch against more recent sources. > > Uhm... I was using the current development sources. My changelog > includes the deletion of complain. I apparently managed to change that > to a complain() without recompiling. I was shooting for complaint(). > Sorry 'bout that. > > Here's a revision. > > -- > Daniel Jacobowitz > MontaVista Software Debian GNU/Linux Developer > > 2003-03-10 Daniel Jacobowitz > > * 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_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. > (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. > > Index: dwarf2expr.c > =================================================================== > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2expr.c,v > retrieving revision 1.3 > diff -u -p -r1.3 dwarf2expr.c > --- dwarf2expr.c 5 Mar 2003 18:00:02 -0000 1.3 > +++ dwarf2expr.c 10 Mar 2003 00:30:18 -0000 > @@ -170,13 +170,13 @@ read_sleb128 (unsigned char *buf, unsign > 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_cont > 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; > > @@ -464,9 +464,10 @@ execute_stack_op (struct dwarf_expr_cont > > (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; > @@ -525,9 +526,10 @@ execute_stack_op (struct dwarf_expr_cont > > (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; > > @@ -537,9 +539,10 @@ execute_stack_op (struct dwarf_expr_cont > 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; > > Index: dwarf2expr.h > =================================================================== > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2expr.h,v > retrieving revision 1.2 > diff -u -p -r1.2 dwarf2expr.h > --- dwarf2expr.h 28 Feb 2003 20:03:18 -0000 1.2 > +++ dwarf2expr.h 10 Mar 2003 00:30:37 -0000 > @@ -99,5 +99,7 @@ unsigned char *read_uleb128 (unsigned ch > 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 > Index: dwarf2loc.c > =================================================================== > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2loc.c,v > retrieving revision 1.3 > diff -u -p -r1.3 dwarf2loc.c > --- dwarf2loc.c 5 Mar 2003 18:00:02 -0000 1.3 > +++ dwarf2loc.c 12 Mar 2003 22:37:23 -0000 > @@ -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 > @@ -88,12 +144,28 @@ static void > dwarf_expr_frame_base (void *baton, unsigned char **start, size_t * length) > { > 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 > @@ -238,8 +310,55 @@ dwarf2_loc_desc_needs_frame (unsigned ch > 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. */ > @@ -293,57 +412,13 @@ locexpr_describe_location (struct symbol > 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 > @@ -353,4 +428,76 @@ struct location_funcs dwarf2_locexpr_fun > locexpr_read_needs_frame, > 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 > }; > Index: dwarf2loc.h > =================================================================== > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2loc.h,v > retrieving revision 1.1 > diff -u -p -r1.1 dwarf2loc.h > --- dwarf2loc.h 21 Feb 2003 15:24:17 -0000 1.1 > +++ dwarf2loc.h 12 Mar 2003 22:03:18 -0000 > @@ -24,8 +24,11 @@ > /* 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 > { > @@ -34,6 +37,15 @@ struct dwarf2_locexpr_baton > struct objfile *objfile; > }; > > +struct dwarf2_loclist_baton > +{ > + CORE_ADDR base_address; > + unsigned char *data; > + unsigned short size; > + struct objfile *objfile; > +}; > + > extern struct location_funcs dwarf2_locexpr_funcs; > +extern struct location_funcs dwarf2_loclist_funcs; > > #endif > Index: dwarf2read.c > =================================================================== > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2read.c,v > retrieving revision 1.88 > diff -u -p -r1.88 dwarf2read.c > --- dwarf2read.c 25 Feb 2003 21:36:17 -0000 1.88 > +++ dwarf2read.c 12 Mar 2003 22:26:18 -0000 > @@ -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 *o > 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 objfi > 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_symt > 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_symt > 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_symt > > 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 *d > .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 attr > 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; > - > - /* 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; > + baton = obstack_alloc (&objfile->symbol_obstack, > + sizeof (struct dwarf2_locexpr_baton)); > + baton->objfile = objfile; > > - 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; > + } > } > -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer