diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2007-11-25 21:40:39 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2007-11-25 21:40:39 +0000 |
commit | 4303944388ea72f96de9b1b662e45ac8f86cc741 (patch) | |
tree | 845139ad3874684f606283cb62b74826276352a7 /gdb/dwarf2read.c | |
parent | a67d13cf51c964d13c60cbe9b59d6214ec5265a8 (diff) | |
download | gdb-4303944388ea72f96de9b1b662e45ac8f86cc741.zip gdb-4303944388ea72f96de9b1b662e45ac8f86cc741.tar.gz gdb-4303944388ea72f96de9b1b662e45ac8f86cc741.tar.bz2 |
gdb/
* dwarf2read.c (dwarf2_get_pc_bounds): Moved the `DW_AT_ranges' parsing
code with its variables OBJFILE, CU_HEADER and OBFD into ...
(dwarf2_ranges_read): ... a new function.
(read_partial_die): Implemented the parsing of `DW_AT_ranges'.
gdb/testsuite/
* gdb.dwarf2/dw2-ranges.S, gdb.dwarf2/dw2-ranges.exp: New files.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 227 |
1 files changed, 125 insertions, 102 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 1498d1f..d6178a7 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -3077,6 +3077,124 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) local_symbols = new->locals; } +/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. + Return 1 if the attributes are present and valid, otherwise, return 0. */ + +static int +dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, + CORE_ADDR *high_return, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct comp_unit_head *cu_header = &cu->header; + bfd *obfd = objfile->obfd; + unsigned int addr_size = cu_header->addr_size; + CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); + /* Base address selection entry. */ + CORE_ADDR base; + int found_base; + unsigned int dummy; + gdb_byte *buffer; + CORE_ADDR marker; + int low_set; + CORE_ADDR low = 0; + CORE_ADDR high = 0; + + found_base = cu_header->base_known; + base = cu_header->base_address; + + if (offset >= dwarf2_per_objfile->ranges_size) + { + complaint (&symfile_complaints, + _("Offset %d out of bounds for DW_AT_ranges attribute"), + offset); + return 0; + } + buffer = dwarf2_per_objfile->ranges_buffer + offset; + + /* Read in the largest possible address. */ + marker = read_address (obfd, buffer, cu, &dummy); + if ((marker & mask) == mask) + { + /* If we found the largest possible address, then + read the base address. */ + base = read_address (obfd, buffer + addr_size, cu, &dummy); + buffer += 2 * addr_size; + offset += 2 * addr_size; + found_base = 1; + } + + low_set = 0; + + while (1) + { + CORE_ADDR range_beginning, range_end; + + range_beginning = read_address (obfd, buffer, cu, &dummy); + buffer += addr_size; + range_end = read_address (obfd, buffer, cu, &dummy); + buffer += addr_size; + offset += 2 * addr_size; + + /* An end of list marker is a pair of zero addresses. */ + if (range_beginning == 0 && range_end == 0) + /* Found the end of list entry. */ + break; + + /* Each base address selection entry is a pair of 2 values. + The first is the largest possible address, the second is + the base address. Check for a base address here. */ + if ((range_beginning & mask) == mask) + { + /* If we found the largest possible address, then + read the base address. */ + base = read_address (obfd, buffer + addr_size, cu, &dummy); + found_base = 1; + continue; + } + + if (!found_base) + { + /* We have no valid base address for the ranges + data. */ + complaint (&symfile_complaints, + _("Invalid .debug_ranges data (no base address)")); + return 0; + } + + range_beginning += base; + range_end += base; + + /* FIXME: This is recording everything as a low-high + segment of consecutive addresses. We should have a + data structure for discontiguous block ranges + instead. */ + if (! low_set) + { + low = range_beginning; + high = range_end; + low_set = 1; + } + else + { + if (range_beginning < low) + low = range_beginning; + if (range_end > high) + high = range_end; + } + } + + if (! low_set) + /* If the first entry is an end-of-list marker, the range + describes an empty scope, i.e. no instructions. */ + return 0; + + if (low_return) + *low_return = low; + if (high_return) + *high_return = high; + return 1; +} + /* Get low and high pc attributes from a die. Return 1 if the attributes are present and valid, otherwise, return 0. Return -1 if the range is discontinuous, i.e. derived from DW_AT_ranges information. */ @@ -3084,10 +3202,7 @@ static int dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, struct dwarf2_cu *cu) { - struct objfile *objfile = cu->objfile; - struct comp_unit_head *cu_header = &cu->header; struct attribute *attr; - bfd *obfd = objfile->obfd; CORE_ADDR low = 0; CORE_ADDR high = 0; int ret = 0; @@ -3111,108 +3226,11 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, attr = dwarf2_attr (die, DW_AT_ranges, cu); if (attr != NULL) { - unsigned int addr_size = cu_header->addr_size; - CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); /* Value of the DW_AT_ranges attribute is the offset in the .debug_ranges section. */ - unsigned int offset = DW_UNSND (attr); - /* Base address selection entry. */ - CORE_ADDR base; - int found_base; - unsigned int dummy; - gdb_byte *buffer; - CORE_ADDR marker; - int low_set; - - found_base = cu_header->base_known; - base = cu_header->base_address; - - if (offset >= dwarf2_per_objfile->ranges_size) - { - complaint (&symfile_complaints, - _("Offset %d out of bounds for DW_AT_ranges attribute"), - offset); - return 0; - } - buffer = dwarf2_per_objfile->ranges_buffer + offset; - - /* Read in the largest possible address. */ - marker = read_address (obfd, buffer, cu, &dummy); - if ((marker & mask) == mask) - { - /* If we found the largest possible address, then - read the base address. */ - base = read_address (obfd, buffer + addr_size, cu, &dummy); - buffer += 2 * addr_size; - offset += 2 * addr_size; - found_base = 1; - } - - low_set = 0; - - while (1) - { - CORE_ADDR range_beginning, range_end; - - range_beginning = read_address (obfd, buffer, cu, &dummy); - buffer += addr_size; - range_end = read_address (obfd, buffer, cu, &dummy); - buffer += addr_size; - offset += 2 * addr_size; - - /* An end of list marker is a pair of zero addresses. */ - if (range_beginning == 0 && range_end == 0) - /* Found the end of list entry. */ - break; - - /* Each base address selection entry is a pair of 2 values. - The first is the largest possible address, the second is - the base address. Check for a base address here. */ - if ((range_beginning & mask) == mask) - { - /* If we found the largest possible address, then - read the base address. */ - base = read_address (obfd, buffer + addr_size, cu, &dummy); - found_base = 1; - continue; - } - - if (!found_base) - { - /* We have no valid base address for the ranges - data. */ - complaint (&symfile_complaints, - _("Invalid .debug_ranges data (no base address)")); - return 0; - } - - range_beginning += base; - range_end += base; - - /* FIXME: This is recording everything as a low-high - segment of consecutive addresses. We should have a - data structure for discontiguous block ranges - instead. */ - if (! low_set) - { - low = range_beginning; - high = range_end; - low_set = 1; - } - else - { - if (range_beginning < low) - low = range_beginning; - if (range_end > high) - high = range_end; - } - } - - if (! low_set) - /* If the first entry is an end-of-list marker, the range - describes an empty scope, i.e. no instructions. */ + if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu)) return 0; - + /* Found discontinuous range of addresses. */ ret = -1; } } @@ -5569,6 +5587,11 @@ read_partial_die (struct partial_die_info *part_die, has_high_pc_attr = 1; part_die->highpc = DW_ADDR (&attr); break; + case DW_AT_ranges: + if (dwarf2_ranges_read (DW_UNSND (&attr), &part_die->lowpc, + &part_die->highpc, cu)) + has_low_pc_attr = has_high_pc_attr = 1; + break; case DW_AT_location: /* Support the .debug_loc offsets */ if (attr_form_is_block (&attr)) |