[RFA] Location list support

Michal Ludvig
2003-02-21T11:06:39Z

[-- Attachment #1: Type: text/plain, Size: 1609 bytes --]

Hi,
attached is a patch that adds support for .debug_loc sections as
generated by newer versions of GCC (eg. from rtlopt-branch).

It works in this way:
- Parse .debug_loc into a list of new internal structures (struct
loclist_master, struct loclist_block). Each loclist_master belongs to
one variable and contains a pointer to a chain of loclist_blocks that
represent different locations where the given variable can be found
during it's life.
- Next the .debug_info is parsed and when a new symbol is being added,
the function new_symbol() first checks, if it's location is described by
a location list or not. If not, then the old method is used. If there is
a location list (in loclist_master) found for this variable, each one of
its loclist_blocks is parsed and added to symbol.loclist chain. The
structure symbol itself is filled up with the first loclist entry found
for this symbol (ie with the values for the lowest PC where the symbol
is valid).
- When the variable's value is to be read (in read_var_value()), it's
first checked if there is a non-null loclist pointer in variable's
'symbol' structure. If not, everything continued like it did until now.
If there is a loclist it's searched for a block valid for the actual PC
and if found, the variable is updated with description found there. If a
valid block is not found, it's assumed that a variable was already
optimized out on this PC and again the symbol structure is updated in an
appropriate way.

Comments? Approvals?

Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz

[-- Attachment #2: loclist-final-head-1.diff --]
[-- Type: text/plain, Size: 28577 bytes --]

2003-02-21 Michal Ludvig <mludvig@suse.cz>

* dwarf2read.c (struct comp_unit_head): Added lowpc, highpc.
(struct loclist_block, struct loclist_master)
(loclist_base, dwarf_loc_buffer): New variables.
(struct dwarf2_pinfo): Added dwarf_loc_buffer, dwarf_loc_size.
(DWARF_LOC_BUFFER, DWARF_LOC_SIZE): New macros.
(dwarf2_read_loclist, dwarf_alloc_loclist_block)
(dwarf_alloc_loclist_master): New functions.
(dwarf2_build_psymtabs): Init dwarf_loc_buffer.
(dwarf2_build_psymtabs_hard): Use dwarf_loc_{buffer,size}.
(psymtab_to_symtab_1): Use dwarf_loc_{buffer,size}.
Parse .debug_loc, fill lowpc/highpc.
(dwarf2_update_symbol_from_loclist): New function.
(update_symbol_class_function): New function type.
(update_external_symbol_class, update_variable_symbol_class)
(update_parameter_symbol_class, update_symbol_loclist_class):
New functions with code moved from new_symbol().
(create_location_list): New function.
(new_symbol): Add support for location lists, moved some
parts to separate functions.
(dwarf_alloc_loclist_block, dwarf_alloc_loclist_master):
New helper functions.
* findvar.c (read_var_value): Added searching in variable's
location list.
* symfile.h (dwarf2_update_symbol_from_loclist): New prototype.
* symtab.h (union symbol_info_value, union symbol_aux_value):
New unions cutted off struct general_symbol_info/struct symbol.
(struct symbol_loclist): New.
(struct symbol): New item loclist.
(SYMBOL_LOCLIST): New macro.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.86
diff -u -p -r1.86 dwarf2read.c
--- dwarf2read.c 14 Feb 2003 19:05:52 -0000 1.86
+++ dwarf2read.c 21 Feb 2003 09:53:13 -0000
@@ -221,6 +221,10 @@ struct comp_unit_head
/* Pointer to the DIE associated with the compilation unit. */

struct die_info *die;
+
+ /* PC bounds of this CU */
+
+ CORE_ADDR lowpc, highpc;
};

/* The line number information for a compilation unit (found in the
@@ -360,6 +364,24 @@ struct dwarf_block
char *data;
};

+struct loclist_block
+{
+ CORE_ADDR lowpc, highpc; /* Range where attribute is valid. */
+ struct dwarf_block blk;
+ struct loclist_block *next;
+ struct loclist_master *parent;
+};
+
+struct loclist_master
+{
+ unsigned int offset; /* Offset of this block in .debug_loc. */
+ CORE_ADDR baseaddr;
+ struct loclist_block *blocks;
+ struct loclist_master *next;
+};
+
+static struct loclist_master *loclist_base;
+
#ifndef ATTR_ALLOC_CHUNK
#define ATTR_ALLOC_CHUNK 4
#endif
@@ -394,6 +416,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;
@@ -510,6 +533,13 @@ struct dwarf2_pinfo

unsigned int dwarf_ranges_size;

+ /* Pointer to start of dwarf location list buffer for the objfile. */
+
+ char *dwarf_loc_buffer;
+
+ /* Size of dwarf location list section for the objfile. */
+
+ unsigned int dwarf_loc_size;
};

#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
@@ -525,6 +555,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
@@ -676,6 +708,8 @@ char *dwarf2_read_section (struct objfil

static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header);

+static void dwarf2_read_loclist (bfd *abfd, struct comp_unit_head *cu_header);
+
static void dwarf2_empty_abbrev_table (void *);

static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
@@ -901,6 +935,9 @@ static struct abbrev_info *dwarf_alloc_a

static struct die_info *dwarf_alloc_die (void);

+static struct loclist_block *dwarf_alloc_loclist_block (void);
+static struct loclist_master *dwarf_alloc_loclist_master (void);
+
static void initialize_cu_func_list (void);

static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
@@ -922,6 +959,7 @@ dwarf2_has_info (bfd *abfd)
dwarf_line_offset = 0;
dwarf_str_offset = 0;
dwarf_macinfo_offset = 0;
+ dwarf_loc_offset = 0;
dwarf_frame_offset = 0;
dwarf_eh_frame_offset = 0;
dwarf_ranges_offset = 0;
@@ -1061,6 +1099,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))
@@ -1287,6 +1333,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 */
@@ -1614,6 +1662,8 @@ psymtab_to_symtab_1 (struct partial_symt
struct symtab *symtab;
struct cleanup *back_to;

+ memset (&cu_header, 0, sizeof (cu_header));
+
/* Set local variables from the partial symbol table info. */
offset = DWARF_INFO_OFFSET (pst);
dwarf_info_buffer = DWARF_INFO_BUFFER (pst);
@@ -1627,6 +1677,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;
@@ -1644,13 +1696,13 @@ psymtab_to_symtab_1 (struct partial_symt
dwarf2_read_abbrevs (abfd, &cu_header);
make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);

+ dwarf2_read_loclist (abfd, &cu_header);
+
dies = read_comp_unit (info_ptr, abfd, &cu_header);

make_cleanup_free_die_list (dies);

- /* 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))
{
@@ -1677,6 +1729,13 @@ psymtab_to_symtab_1 (struct partial_symt
}
}
}
+
+ cu_header.lowpc = lowpc;
+ cu_header.highpc = highpc;
+
+ /* Do line number decoding in read_file_scope () */
+ process_die (dies, objfile, &cu_header);
+
symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));

/* Set symtab language to language from DW_AT_language.
@@ -3663,6 +3722,124 @@ dwarf2_read_section (struct objfile *obj
return buf;
}

+/* The following functions parse .debug_loc section and
+ store the contents to a list of lists. These lists are
+ then used when creating the actual "symbol" structures. */
+static struct loclist_block *
+dwarf2_loclist_lookup_block (unsigned int offset)
+{
+ /* .debug_loc goes here ... mludvig */
+ struct dwarf_block *blkp;
+ struct loclist_master *ll_ptr;
+
+ ll_ptr = loclist_base;
+
+ while (ll_ptr && ll_ptr->offset != offset)
+ ll_ptr = ll_ptr->next;
+
+ if (!ll_ptr)
+ {
+ warning ("Couldn't find appropriate location list for offset %u\n",
+ offset);
+ return NULL;
+ }
+
+ if (ll_ptr && !ll_ptr->blocks)
+ {
+ warning ("Loclist for off=%u doesn't have any blocks?\n", offset);
+ return NULL;
+ }
+
+ return ll_ptr->blocks;
+}
+
+static struct loclist_block *
+dwarf2_read_loclist_blocks (bfd *abfd, char **base, char *end,
+ unsigned int addr_size,
+ struct loclist_master *ll_master)
+{
+ char *ptr;
+ CORE_ADDR lowpc, highpc;
+ unsigned int data_size;
+ char *data_ptr;
+ struct loclist_block *llb_first = NULL, *llb_last = NULL;
+
+ ptr = *base;
+
+ while (ptr < end)
+ {
+ if (addr_size == 4)
+ {
+ lowpc = read_4_bytes (abfd, ptr);
+ ptr += 4;
+ highpc = read_4_bytes (abfd, ptr);
+ ptr += 4;
+ }
+ else if (addr_size == 8)
+ {
+ lowpc = read_8_bytes (abfd, ptr);
+ ptr += 8;
+ highpc = read_8_bytes (abfd, ptr);
+ ptr += 8;
+ }
+ else
+ error ("Address size == %d ... unsupported!", addr_size);
+
+ if (lowpc == 0 && highpc == 0)
+ break;
+
+ if (lowpc == (CORE_ADDR) -1L)
+ {
+ ll_master->baseaddr = highpc;
+ continue;
+ }
+
+ if (llb_last == NULL)
+ {
+ llb_last = dwarf_alloc_loclist_block ();
+ llb_first = llb_last;
+ }
+ else
+ {
+ llb_last->next = dwarf_alloc_loclist_block ();
+ llb_last = llb_last->next;
+ }
+
+ llb_last->parent = ll_master;
+ llb_last->lowpc = lowpc;
+ llb_last->highpc = highpc;
+
+ llb_last->blk.size = read_2_bytes (abfd, ptr);
+ ptr += 2;
+ llb_last->blk.data = ptr;
+ ptr += llb_last->blk.size;
+ }
+
+ *base = ptr;
+ return llb_first;
+}
+
+static void
+dwarf2_read_loclist (bfd *abfd, struct comp_unit_head *cu_header)
+{
+ char *loclist_ptr, *loclist_end;
+ struct loclist_master *ll_master;
+
+ loclist_ptr = dwarf_loc_buffer;
+ loclist_end = dwarf_loc_buffer + dwarf_loc_size;
+
+ while (loclist_ptr < loclist_end)
+ {
+ ll_master = dwarf_alloc_loclist_master ();
+ ll_master->next = loclist_base;
+ loclist_base = ll_master;
+
+ ll_master->offset = loclist_ptr - dwarf_loc_buffer;
+ ll_master->blocks = dwarf2_read_loclist_blocks
+ (abfd, &loclist_ptr, loclist_end, cu_header->addr_size, ll_master);
+ }
+}
+
/* In DWARF version 2, the description of the debugging information is
stored in a separate .debug_abbrev section. Before we read any
dies from a section we read in all abbreviations and install them
@@ -4952,6 +5129,173 @@ dwarf2_start_subfile (char *filename, ch
start_subfile (filename, dirname);
}

+void
+dwarf2_update_symbol_from_loclist (struct symbol *sym,
+ struct symbol_loclist *symll)
+{
+ SYMBOL_CLASS (sym) = SYMBOL_CLASS (symll);
+ memcpy ((void *) &sym->ginfo.value, (void *) &symll->ginfo.value,
+ sizeof (sym->ginfo.value));
+ memcpy ((void *) &sym->aux_value, (void *) &symll->aux_value,
+ sizeof (union symbol_aux_value));
+}
+
+typedef void (update_symbol_class_function) (struct symbol * sym,
+ struct objfile * objfile);
+
+static void
+update_external_symbol_class (struct symbol *sym, struct objfile *objfile)
+{
+ if (is_thread_local)
+ {
+ /* SYMBOL_VALUE_ADDRESS contains at this point the
+ offset of the variable within the thread local
+ storage. */
+ SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
+ SYMBOL_OBJFILE (sym) = objfile;
+ }
+ /* In shared libraries the address of the variable
+ in the location descriptor might still be relocatable,
+ so its value could be zero.
+ Enter the symbol as a LOC_UNRESOLVED symbol, if its
+ value is zero, the address of the variable will then
+ be determined from the minimal symbol table whenever
+ the variable is referenced. */
+ if (SYMBOL_VALUE_ADDRESS (sym))
+ {
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) +=
+ ANOFFSET (objfile->section_offsets, SYMBOL_SECTION (sym));
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ }
+ else
+ SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
+}
+
+static void
+update_variable_symbol_class (struct symbol *sym, struct objfile *objfile)
+{
+ if (optimized_out)
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ else if (isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) = DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
+ }
+ else if (offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
+ }
+ else if (islocal)
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ else if (is_thread_local)
+ {
+ SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
+ SYMBOL_OBJFILE (sym) = objfile;
+ }
+ else
+ {
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) +=
+ ANOFFSET (objfile->section_offsets, SYMBOL_SECTION (sym));
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ }
+}
+
+static void
+update_parameter_symbol_class (struct symbol *sym, struct objfile *objfile)
+{
+ if (isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) = DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
+ }
+ else if (offreg)
+ {
+ if (isderef)
+ {
+ if (basereg != frame_base_reg)
+ dwarf2_complex_location_expr_complaint ();
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
+ }
+ }
+ else
+ SYMBOL_CLASS (sym) = LOC_ARG;
+}
+
+static void
+update_symbol_loclist_class (struct symbol_loclist *symll,
+ struct objfile *objfile,
+ update_symbol_class_function * update_function)
+{
+ struct symbol *sym = alloca (sizeof (struct symbol));
+
+ SYMBOL_VALUE (sym) = SYMBOL_VALUE (symll);
+ SYMBOL_BASEREG (sym) = SYMBOL_BASEREG (symll);
+
+ (*update_function) (sym, objfile);
+
+ SYMBOL_VALUE (symll) = SYMBOL_VALUE (sym);
+ SYMBOL_BASEREG (symll) = SYMBOL_BASEREG (sym);
+ SYMBOL_CLASS (symll) = SYMBOL_CLASS (sym);
+}
+
+static void
+create_location_list (struct symbol *sym, struct objfile *objfile,
+ struct attribute *attr,
+ const struct comp_unit_head *cu_header,
+ update_symbol_class_function * update_function)
+{
+ struct dwarf_block *blkp = NULL;
+ struct loclist_block *llbp;
+ struct symbol_loclist *last_loclist_ptr = NULL;
+ CORE_ADDR baseaddr;
+
+ llbp = dwarf2_loclist_lookup_block ((unsigned int) DW_ADDR (attr));
+ gdb_assert (llbp != NULL);
+ blkp = &llbp->blk;
+ gdb_assert (blkp != NULL);
+
+ SYMBOL_VALUE_ADDRESS (sym) = decode_locdesc (blkp, objfile, cu_header);
+
+ (*update_function) (sym, objfile);
+
+ baseaddr = llbp->parent->baseaddr ?
+ llbp->parent->baseaddr : cu_header->lowpc;
+ baseaddr += ANOFFSET (objfile->section_offsets, objfile->sect_index_text);
+
+ /* Create location list. */
+ while (llbp)
+ {
+ struct symbol_loclist *symll;
+
+ blkp = &llbp->blk;
+ gdb_assert (blkp != NULL);
+
+ symll = xmalloc (sizeof (struct symbol_loclist));
+ symll->ginfo.value.address = decode_locdesc (blkp, objfile, cu_header);
+
+ symll->lowpc = llbp->lowpc + baseaddr;
+ symll->highpc = llbp->highpc + baseaddr;
+
+ if (last_loclist_ptr == NULL)
+ SYMBOL_LOCLIST (sym) = symll;
+ else
+ last_loclist_ptr->next = symll;
+ last_loclist_ptr = symll;
+
+ update_symbol_loclist_class (symll, objfile, update_function);
+
+ llbp = llbp->next;
+ }
+}
+
/* Given a pointer to a DWARF information entry, figure out if we need
to make a symbol table entry for it, and if so, create a new entry
and return a pointer to it.
@@ -5048,11 +5392,13 @@ new_symbol (struct die_info *die, struct
{
SYMBOL_VALUE_ADDRESS (sym) =
decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ update_external_symbol_class (sym, objfile);
}
else if (attr->form == DW_FORM_data4
|| attr->form == DW_FORM_data8)
{
- dwarf2_complex_location_expr_complaint ();
+ create_location_list (sym, objfile, attr, cu_header,
+ update_external_symbol_class);
}
else
{
@@ -5060,32 +5406,6 @@ new_symbol (struct die_info *die, struct
"external variable");
}
add_symbol_to_list (sym, &global_symbols);
- if (is_thread_local)
- {
- /* SYMBOL_VALUE_ADDRESS contains at this point the
- offset of the variable within the thread local
- storage. */
- SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
- SYMBOL_OBJFILE (sym) = objfile;
- }
-
- /* In shared libraries the address of the variable
- in the location descriptor might still be relocatable,
- so its value could be zero.
- Enter the symbol as a LOC_UNRESOLVED symbol, if its
- value is zero, the address of the variable will then
- be determined from the minimal symbol table whenever
- the variable is referenced. */
- else if (SYMBOL_VALUE_ADDRESS (sym))
- {
- fixup_symbol_section (sym, objfile);
- SYMBOL_VALUE_ADDRESS (sym) +=
- ANOFFSET (objfile->section_offsets,
- SYMBOL_SECTION (sym));
- SYMBOL_CLASS (sym) = LOC_STATIC;
- }
- else
- SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
}
else
{
@@ -5094,11 +5414,13 @@ new_symbol (struct die_info *die, struct
{
SYMBOL_VALUE (sym) = addr =
decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ update_variable_symbol_class (sym, objfile);
}
else if (attr->form == DW_FORM_data4
|| attr->form == DW_FORM_data8)
{
- dwarf2_complex_location_expr_complaint ();
+ create_location_list (sym, objfile, attr, cu_header,
+ update_variable_symbol_class);
}
else
{
@@ -5107,38 +5429,6 @@ new_symbol (struct die_info *die, struct
addr = 0;
}
add_symbol_to_list (sym, list_in_scope);
- if (optimized_out)
- {
- SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
- }
- else if (isreg)
- {
- SYMBOL_CLASS (sym) = LOC_REGISTER;
- SYMBOL_VALUE (sym) =
- DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
- }
- else if (offreg)
- {
- SYMBOL_CLASS (sym) = LOC_BASEREG;
- SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
- }
- else if (islocal)
- {
- SYMBOL_CLASS (sym) = LOC_LOCAL;
- }
- else if (is_thread_local)
- {
- SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
- SYMBOL_OBJFILE (sym) = objfile;
- }
- else
- {
- fixup_symbol_section (sym, objfile);
- SYMBOL_VALUE_ADDRESS (sym) =
- addr + ANOFFSET (objfile->section_offsets,
- SYMBOL_SECTION (sym));
- SYMBOL_CLASS (sym) = LOC_STATIC;
- }
}
}
else
@@ -5162,31 +5452,21 @@ new_symbol (struct die_info *die, struct
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
- SYMBOL_VALUE (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- if (isreg)
+ if (attr_form_is_block (attr))
{
- SYMBOL_CLASS (sym) = LOC_REGPARM;
SYMBOL_VALUE (sym) =
- DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ update_parameter_symbol_class (sym, objfile);
}
- else if (offreg)
+ else if (attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
{
- if (isderef)
- {
- if (basereg != frame_base_reg)
- dwarf2_complex_location_expr_complaint ();
- SYMBOL_CLASS (sym) = LOC_REF_ARG;
- }
- else
- {
- SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
- }
+ create_location_list (sym, objfile, attr, cu_header,
+ update_parameter_symbol_class);
}
else
{
- SYMBOL_CLASS (sym) = LOC_ARG;
+ dwarf2_complex_location_expr_complaint ();
}
}
attr = dwarf_attr (die, DW_AT_const_value);
@@ -6992,6 +7272,26 @@ dwarf_alloc_die (void)
memset (die, 0, sizeof (struct die_info));
return (die);
}
+
+static struct loclist_block *
+dwarf_alloc_loclist_block (void)
+{
+ struct loclist_block *llb;
+
+ llb = (struct loclist_block *) xmalloc (sizeof (struct loclist_block));
+ memset (llb, 0, sizeof (struct loclist_block));
+ return (llb);
+}
+
+static struct loclist_master *
+dwarf_alloc_loclist_master (void)
+{
+ struct loclist_master *llm;
+
+ llm = (struct loclist_master *) xmalloc (sizeof (struct loclist_master));
+ memset (llm, 0, sizeof (struct loclist_master));
+ return (llm);
+}
\f

/* Macro support. */
Index: findvar.c
===================================================================
RCS file: /cvs/src/src/gdb/findvar.c,v
retrieving revision 1.47
diff -u -p -r1.47 findvar.c
--- findvar.c 20 Feb 2003 17:17:23 -0000 1.47
+++ findvar.c 21 Feb 2003 09:53:13 -0000
@@ -415,12 +415,15 @@ symbol_read_needs_frame (struct symbol *
If FRAME is NULL, use the deprecated_selected_frame. */

struct value *
-read_var_value (register struct symbol *var, struct frame_info *frame)
+read_var_value (register struct symbol *varorig, struct frame_info *frame)
{
register struct value *v;
- struct type *type = SYMBOL_TYPE (var);
+ struct type *type = SYMBOL_TYPE (varorig);
CORE_ADDR addr;
register int len;
+ struct symbol *var = alloca (sizeof (struct symbol));
+
+ memcpy (var, varorig, sizeof (struct symbol));

v = allocate_value (type);
VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
@@ -431,6 +434,37 @@ read_var_value (register struct symbol *
if (frame == NULL)
frame = deprecated_selected_frame;

+ if (var->loclist)
+ {
+ struct symbol_loclist *llp = var->loclist;
+ int i = 0;
+
+ if (info_verbose)
+ printf (" (%s(%p) ", SYMBOL_NAME (var), (void *) frame->pc);
+ while (llp)
+ {
+ if (llp->lowpc <= frame->pc && llp->highpc > frame->pc)
+ break;
+ llp = llp->next;
+ }
+
+ if (llp)
+ {
+ dwarf2_update_symbol_from_loclist (var, llp);
+ if (info_verbose)
+ printf (" %p/%p ) ", (void *) llp->lowpc, (void *) llp->highpc);
+ }
+ else
+ {
+ SYMBOL_CLASS (var) = LOC_OPTIMIZED_OUT;
+ if (info_verbose)
+ printf_filtered
+ ("Variable '%s' has a location list but I couldn't\n"
+ "find an entry for pc=%p\n", SYMBOL_NAME (var),
+ (void *) frame->pc);
+ }
+ }
+
switch (SYMBOL_CLASS (var))
{
case LOC_CONST:
Index: symfile.h
===================================================================
RCS file: /cvs/src/src/gdb/symfile.h,v
retrieving revision 1.19
diff -u -p -r1.19 symfile.h
--- symfile.h 20 Feb 2003 00:01:06 -0000 1.19
+++ symfile.h 21 Feb 2003 09:53:14 -0000
@@ -317,6 +317,9 @@ extern int dwarf2_has_info (bfd * abfd);
extern void dwarf2_build_psymtabs (struct objfile *, int);
extern void dwarf2_build_frame_info (struct objfile *);

+extern void dwarf2_update_symbol_from_loclist (struct symbol *sym,
+ struct symbol_loclist *symll);
+
/* From mdebugread.c */

/* Hack to force structures to exist before use in parameter list. */
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.60
diff -u -p -r1.60 symtab.h
--- symtab.h 20 Feb 2003 17:17:25 -0000 1.60
+++ symtab.h 21 Feb 2003 09:53:14 -0000
@@ -42,29 +42,13 @@ struct blockvector;
#define BYTE_BITFIELD /*nothing */
#endif

-/* Define a structure for the information that is common to all symbol types,
- including minimal symbols, partial symbols, and full symbols. In a
- multilanguage environment, some language specific information may need to
- be recorded along with each symbol.
-
- These fields are ordered to encourage good packing, since we frequently
- have tens or hundreds of thousands of these. */
+/* Value of the symbol. Which member of this union to use, and what
+ it means, depends on what kind of symbol this is and its
+ SYMBOL_CLASS. See comments there for more details. All of these
+ are in host byte order (though what they point to might be in
+ target byte order, e.g. LOC_CONST_BYTES). */

-struct general_symbol_info
-{
- /* Name of the symbol. This is a required field. Storage for the name is
- allocated on the psymbol_obstack or symbol_obstack for the associated
- objfile. */
-
- char *name;
-
- /* Value of the symbol. Which member of this union to use, and what
- it means, depends on what kind of symbol this is and its
- SYMBOL_CLASS. See comments there for more details. All of these
- are in host byte order (though what they point to might be in
- target byte order, e.g. LOC_CONST_BYTES). */
-
- union
+union symbol_info_value
{
/* The fact that this is a long not a LONGEST mainly limits the
range of a LOC_CONST. Since LOC_CONST_BYTES exists, I'm not
@@ -80,8 +64,25 @@ struct general_symbol_info
/* for opaque typedef struct chain */

struct symbol *chain;
- }
- value;
+ };
+
+/* Define a structure for the information that is common to all symbol types,
+ including minimal symbols, partial symbols, and full symbols. In a
+ multilanguage environment, some language specific information may need to
+ be recorded along with each symbol.
+
+ These fields are ordered to encourage good packing, since we frequently
+ have tens or hundreds of thousands of these. */
+
+struct general_symbol_info
+{
+ /* Name of the symbol. This is a required field. Storage for the name is
+ allocated on the psymbol_obstack or symbol_obstack for the associated
+ objfile. */
+
+ char *name;
+
+ union symbol_info_value value;

/* Since one and only one language can apply, wrap the language specific
information inside a union. */
@@ -501,6 +502,27 @@ struct alias_list
struct alias_list *next;
};

+union symbol_aux_value
+{
+ /* Used by LOC_BASEREG and LOC_BASEREG_ARG. */
+ short basereg;
+
+ /* Used by LOC_THREAD_LOCAL_STATIC. The objfile in which this
+ symbol is defined. To find a thread-local variable (e.g., a
+ variable declared with the `__thread' storage class), we may
+ need to know which object file it's in. */
+ struct objfile *objfile;
+};
+
+struct symbol_loclist
+ {
+ CORE_ADDR lowpc, highpc;
+ enum address_class aclass BYTE_BITFIELD;
+ struct general_symbol_info ginfo;
+ union symbol_aux_value aux_value;
+ struct symbol_loclist *next;
+ };
+
struct symbol
{

@@ -534,19 +556,7 @@ struct symbol
/* Some symbols require an additional value to be recorded on a per-
symbol basis. Stash those values here. */

- union
- {
- /* Used by LOC_BASEREG and LOC_BASEREG_ARG. */
- short basereg;
-
- /* Used by LOC_THREAD_LOCAL_STATIC. The objfile in which this
- symbol is defined. To find a thread-local variable (e.g., a
- variable declared with the `__thread' storage class), we may
- need to know which object file it's in. */
- struct objfile *objfile;
- }
- aux_value;
-
+ union symbol_aux_value aux_value;

/* Link to a list of aliases for this symbol.
Only a "primary/main symbol may have aliases. */
@@ -557,6 +567,8 @@ struct symbol
struct range_list *ranges;

struct symbol *hash_next;
+
+ struct symbol_loclist *loclist;
};

@@ -568,6 +580,7 @@ struct symbol
#define SYMBOL_OBJFILE(symbol) (symbol)->aux_value.objfile
#define SYMBOL_ALIASES(symbol) (symbol)->aliases
#define SYMBOL_RANGES(symbol) (symbol)->ranges
+#define SYMBOL_LOCLIST(symbol) (symbol)->loclist
\f
/* A partial_symbol records the name, namespace, and address class of
symbols whose types we have not parsed yet. For functions, it also