summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Huang <jserv@0xlab.org>2010-08-16 13:18:55 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2010-08-16 13:18:55 -0700
commit83a9e97f988380cb719825bcb054aa64455d7207 (patch)
tree4cbfae42088c624fcbe0086036a13f0e9fbe4a6c
parent62c1bed1c4505369cac2e72fbe30452a598fb690 (diff)
parent84e352dca84000ff0c68b4c5bad657949a443901 (diff)
downloadelfcopy-master.tar.gz
am 84e352dc: elfcopy: support unordered .debug_info references to .debug_rangeHEADandroid-sdk-tools_r12android-sdk-adt_r12mastermain
Merge commit '84e352dca84000ff0c68b4c5bad657949a443901' into gingerbread-plus-aosp * commit '84e352dca84000ff0c68b4c5bad657949a443901': elfcopy: support unordered .debug_info references to .debug_range
-rw-r--r--dwarf.c209
1 files changed, 108 insertions, 101 deletions
diff --git a/dwarf.c b/dwarf.c
index 4092596..5ad1887 100644
--- a/dwarf.c
+++ b/dwarf.c
@@ -2764,6 +2764,29 @@ display_debug_aranges (struct dwarf_section *section,
return 1;
}
+/* Each debug_information[x].range_lists[y] gets this representation for
+ sorting purposes. */
+struct range_entry
+{
+ /* The debug_information[x].range_lists[y] value. */
+ unsigned long ranges_offset;
+
+ /* Original debug_information to find parameters of the data. */
+ debug_info *debug_info_p;
+};
+
+/* Sort struct range_entry in ascending order of its RANGES_OFFSET. */
+static int
+range_entry_compar (const void *ap, const void *bp)
+{
+ const struct range_entry *a_re = ap;
+ const struct range_entry *b_re = bp;
+ const unsigned long a = a_re->ranges_offset;
+ const unsigned long b = b_re->ranges_offset;
+
+ return (a > b) - (b > a);
+}
+
static int
display_debug_ranges (struct dwarf_section *section,
void *file ATTRIBUTE_UNUSED)
@@ -2772,14 +2795,8 @@ display_debug_ranges (struct dwarf_section *section,
unsigned char *section_end;
unsigned long bytes;
unsigned char *section_begin = start;
- unsigned int num_range_list = 0;
- unsigned long last_offset = 0;
- unsigned int first = 0;
- unsigned int i;
- unsigned int j;
- int seen_first_offset = 0;
- int use_debug_info = 1;
- unsigned char *next;
+ unsigned int num_range_list, i;
+ struct range_entry *range_entries, *range_entry_fill;
bytes = section->size;
section_end = start + bytes;
@@ -2792,130 +2809,120 @@ display_debug_ranges (struct dwarf_section *section,
load_debug_info (file);
- /* Check the order of range list in .debug_info section. If
- offsets of range lists are in the ascending order, we can
- use `debug_information' directly. */
+ num_range_list = 0;
for (i = 0; i < num_debug_info_entries; i++)
- {
- unsigned int num;
+ num_range_list += debug_information [i].num_range_lists;
- num = debug_information [i].num_range_lists;
- num_range_list += num;
+ if (num_range_list == 0)
+ error (_("No range lists in .debug_info section!\n"));
- /* Check if we can use `debug_information' directly. */
- if (use_debug_info && num != 0)
- {
- if (!seen_first_offset)
- {
- /* This is the first range list. */
- last_offset = debug_information [i].range_lists [0];
- first = i;
- seen_first_offset = 1;
- j = 1;
- }
- else
- j = 0;
+ range_entries = xmalloc (sizeof (*range_entries) * num_range_list);
+ range_entry_fill = range_entries;
- for (; j < num; j++)
- {
- if (last_offset >
- debug_information [i].range_lists [j])
- {
- use_debug_info = 0;
- break;
- }
- last_offset = debug_information [i].range_lists [j];
- }
+ for (i = 0; i < num_debug_info_entries; i++)
+ {
+ debug_info *debug_info_p = &debug_information[i];
+ unsigned int j;
+
+ for (j = 0; j < debug_info_p->num_range_lists; j++)
+ {
+ range_entry_fill->ranges_offset = debug_info_p->range_lists[j];
+ range_entry_fill->debug_info_p = debug_info_p;
+ range_entry_fill++;
}
}
- if (!use_debug_info)
- /* FIXME: Should we handle this case? */
- error (_("Range lists in .debug_info section aren't in ascending order!\n"));
-
- if (!seen_first_offset)
- error (_("No range lists in .debug_info section!\n"));
+ qsort (range_entries, num_range_list, sizeof (*range_entries),
+ range_entry_compar);
/* DWARF sections under Mach-O have non-zero addresses. */
- if (debug_information [first].range_lists [0] != section->address)
+ if (range_entries[0].ranges_offset != section->address)
warn (_("Range lists in %s section start at 0x%lx\n"),
- section->name, debug_information [first].range_lists [0]);
+ section->name, range_entries[0].ranges_offset);
printf (_("Contents of the %s section:\n\n"), section->name);
printf (_(" Offset Begin End\n"));
- seen_first_offset = 0;
- for (i = first; i < num_debug_info_entries; i++)
+ for (i = 0; i < num_range_list; i++)
{
- unsigned long begin;
- unsigned long end;
- unsigned long offset;
+ struct range_entry *range_entry = &range_entries[i];
+ debug_info *debug_info_p = range_entry->debug_info_p;
unsigned int pointer_size;
+ unsigned long offset;
+ unsigned char *next;
unsigned long base_address;
- pointer_size = debug_information [i].pointer_size;
+ pointer_size = debug_info_p->pointer_size;
+
+ /* DWARF sections under Mach-O have non-zero addresses. */
+ offset = range_entry->ranges_offset - section->address;
+ next = section_begin + offset;
+ base_address = debug_info_p->base_address;
- for (j = 0; j < debug_information [i].num_range_lists; j++)
+ if (i > 0)
{
- /* DWARF sections under Mach-O have non-zero addresses. */
- offset = debug_information [i].range_lists [j] - section->address;
- next = section_begin + offset;
- base_address = debug_information [i].base_address;
+/*
+ if (start < next)
+ warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
+ (unsigned long) (start - section_begin),
+ (unsigned long) (next - section_begin), section->name);
+ else if (start > next)
+ warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
+ (unsigned long) (start - section_begin),
+ (unsigned long) (next - section_begin), section->name);
+*/
+ }
+ start = next;
- if (!seen_first_offset)
- seen_first_offset = 1;
- else
+ while (1)
+ {
+ dwarf_vma begin;
+ dwarf_vma end;
+
+ /* Note: we use sign extension here in order to be sure
+ * that we can detect the -1 escape value.
+ * Sign extension into the top 32 bits of a 32-bit
+ * address will not affect the values that we display
+ * since we always show hex values, and always the
+ * bottom 32-bits. */
+ begin = byte_get_signed (start, pointer_size);
+ start += pointer_size;
+ end = byte_get_signed (start, pointer_size);
+ start += pointer_size;
+
+ if (begin == 0 && end == 0)
{
-/* if (start < next)
- warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
- (long)(start - section_begin),
- (long)(next - section_begin), section->name);
- else if (start > next)
- warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
- (long)(start - section_begin),
- (long)(next - section_begin), section->name);
-*/
+ printf (_(" %8.8lx <End of list>\n"), offset);
+ break;
}
- start = next;
- while (1)
+ /* Check base address specifiers. */
+ if (begin == (dwarf_vma) -1 && end != (dwarf_vma) -1)
{
- begin = byte_get (start, pointer_size);
- start += pointer_size;
- end = byte_get (start, pointer_size);
- start += pointer_size;
-
- if (begin == 0 && end == 0)
- {
- printf (_(" %8.8lx <End of list>\n"), offset);
- break;
- }
-
- /* Check base address specifiers. */
- if (begin == -1UL && end != -1UL)
- {
- base_address = end;
- printf (_(" %8.8lx %8.8lx %8.8lx (base address)\n"),
- offset, begin, end);
- continue;
- }
-
- base_value_pair_hook(start - 2*pointer_size, pointer_size,
- base_address, begin, end);
+ base_address = end;
+ printf (_(" %8.8lx %8.8lx %8.8lx (base address)\n"),
+ offset, begin, end);
+ printf ("(base address)\n");
+ continue;
+ }
+ base_value_pair_hook(start - 2*pointer_size, pointer_size,
+ base_address, begin, end);
- printf (_(" %8.8lx %8.8lx %8.8lx"),
- offset, begin + base_address, end + base_address);
+ printf (_(" %8.8lx %8.8lx %8.8lx"),
+ offset, begin + base_address, end + base_address);
- if (begin == end)
- printf (_(" (start == end)"));
- else if (begin > end)
- printf (_(" (start > end)"));
+ if (begin == end)
+ printf (_(" (start == end)"));
+ else if (begin > end)
+ printf (_(" (start > end)"));
- putchar ('\n');
- }
+ putchar ('\n');
}
}
putchar ('\n');
+
+ free (range_entries);
+
return 1;
}