aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2read.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2003-04-13 15:43:35 +0000
committerDaniel Jacobowitz <drow@false.org>2003-04-13 15:43:35 +0000
commit0d53c4c49facfc7400795d0d4fc7489b296d743d (patch)
treef448041b3ca20debb7bbb7f2614ffd78abd7d3eb /gdb/dwarf2read.c
parent6aca59a35914f39148f06d4d43f56a56c3cc4e55 (diff)
downloadgdb-0d53c4c49facfc7400795d0d4fc7489b296d743d.zip
gdb-0d53c4c49facfc7400795d0d4fc7489b296d743d.tar.gz
gdb-0d53c4c49facfc7400795d0d4fc7489b296d743d.tar.bz2
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.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r--gdb/dwarf2read.c151
1 files changed, 104 insertions, 47 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index c77642d..b5fd389 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;
+ }
}