summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@debian.org>2006-04-17 14:21:14 +0000
committerDaniel Jacobowitz <dan@debian.org>2006-04-17 14:21:14 +0000
commite4267f758539c0140fe0b62dfa6a84f462f1b1c6 (patch)
treefc2b2263a74968d4b7494dae28ed28e47a5ff60a
parent973afa5c31fe8ce1e73258db8abc828dcb731e7d (diff)
downloadgdb-e4267f758539c0140fe0b62dfa6a84f462f1b1c6.tar.gz
* buildsym.c (start_subfile): Handle producer.
(record_producer): New function. * buildsym.h (struct subfile): Include producer. (record_producer): New prototype. * dwarf2-frame.c (struct dwarf2_cie): Add version. (struct dwarf2_frame_state): Add armcc_cfa_offsets_sf and armcc_cfa_offsets_reversed. (execute_cfa_program): Handle armcc_cfa_offsets_sf. (dwarf2_frame_find_quirks): New function. (dwarf2_frame_cache): Call it. Handle armcc_cfa_offsets_reversed. (decode_frame_entry_1): Record the CIE version. * dwarf2read.c (read_file_scope): Save the producer. * symtab.h (struct symtab): Rename unused version member to producer.
-rw-r--r--ChangeLog.csl17
-rw-r--r--gdb/buildsym.c17
-rw-r--r--gdb/buildsym.h3
-rw-r--r--gdb/dwarf2-frame.c60
-rw-r--r--gdb/dwarf2read.c10
-rw-r--r--gdb/symtab.h4
6 files changed, 100 insertions, 11 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index 3dfc1b32735..157182f9fcc 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,3 +1,20 @@
+2006-04-17 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * gdb/buildsym.c (start_subfile): Handle producer.
+ (record_producer): New function.
+ * gdb/buildsym.h (struct subfile): Include producer.
+ (record_producer): New prototype.
+ * gdb/dwarf2-frame.c (struct dwarf2_cie): Add version.
+ (struct dwarf2_frame_state): Add armcc_cfa_offsets_sf and
+ armcc_cfa_offsets_reversed.
+ (execute_cfa_program): Handle armcc_cfa_offsets_sf.
+ (dwarf2_frame_find_quirks): New function.
+ (dwarf2_frame_cache): Call it. Handle armcc_cfa_offsets_reversed.
+ (decode_frame_entry_1): Record the CIE version.
+ * gdb/dwarf2read.c (read_file_scope): Save the producer.
+ * gdb/symtab.h (struct symtab): Rename unused version member to
+ producer.
+
2006-04-12 Daniel Jacobowitz <dan@codesourcery.com>
* gdb/Makefile.in (ALLDEPFILES): Add solib-target.c.
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index d0143bc3f24..7908773708d 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -591,6 +591,9 @@ start_subfile (char *name, char *dirname)
later via a call to record_debugformat. */
subfile->debugformat = NULL;
+ /* Similarly for the producer. */
+ subfile->producer = NULL;
+
/* If the filename of this subfile ends in .C, then change the
language of any pending subfiles from C to C++. We also accept
any other C++ suffixes accepted by deduce_language_from_filename. */
@@ -999,6 +1002,12 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
&objfile->objfile_obstack);
}
+ /* Similarly for the producer. */
+ if (subfile->producer != NULL)
+ symtab->producer = obsavestring (subfile->producer,
+ strlen (subfile->producer),
+ &objfile->objfile_obstack);
+
/* All symtabs for the main file and the subfiles share a
blockvector, so we need to clear primary for everything
but the main file. */
@@ -1021,6 +1030,8 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
{
xfree ((void *) subfile->debugformat);
}
+ if (subfile->producer != NULL)
+ xfree (subfile->producer);
nextsub = subfile->next;
xfree ((void *) subfile);
@@ -1097,6 +1108,12 @@ record_debugformat (char *format)
current_subfile->debugformat = savestring (format, strlen (format));
}
+void
+record_producer (const char *producer)
+{
+ current_subfile->producer = savestring (producer, strlen (producer));
+}
+
/* Merge the first symbol list SRCLIST into the second symbol list
TARGETLIST by repeated calls to add_symbol_to_list(). This
procedure "frees" each link of SRCLIST by adding it to the
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index 8b8ee89d22b..3b4fee68c3a 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -68,6 +68,7 @@ struct subfile
struct linetable *line_vector;
int line_vector_length;
enum language language;
+ char *producer;
char *debugformat;
};
@@ -281,6 +282,8 @@ extern void record_pending_block (struct objfile *objfile,
extern void record_debugformat (char *format);
+extern void record_producer (const char *producer);
+
extern void merge_symbol_lists (struct pending **srclist,
struct pending **targetlist);
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 668500d26c9..4301dac5fb5 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -69,6 +69,9 @@ struct dwarf2_cie
/* True if a 'z' augmentation existed. */
unsigned char saw_z_augmentation;
+ /* The version recorded in the CIE. */
+ unsigned char version;
+
struct dwarf2_cie *next;
};
@@ -130,6 +133,16 @@ struct dwarf2_frame_state
LONGEST data_align;
ULONGEST code_align;
ULONGEST retaddr_column;
+
+ /* Flags for known producer quirks. */
+
+ /* The ARM compilers, in DWARF2 mode, assume that DW_CFA_def_cfa
+ and DW_CFA_def_cfa_offset takes a factored offset. */
+ int armcc_cfa_offsets_sf;
+
+ /* The ARM compilers, in DWARF2 or DWARF3 mode, assume that
+ the CFA is defined as REG - OFFSET rather than REG + OFFSET. */
+ int armcc_cfa_offsets_reversed;
};
/* Store the length the expression for the CFA in the `cfa_reg' field,
@@ -399,6 +412,10 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
case DW_CFA_def_cfa:
insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+
+ if (fs->armcc_cfa_offsets_sf)
+ utmp *= fs->data_align;
+
fs->cfa_offset = utmp;
fs->cfa_how = CFA_REG_OFFSET;
break;
@@ -410,6 +427,10 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
case DW_CFA_def_cfa_offset:
insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+
+ if (fs->armcc_cfa_offsets_sf)
+ utmp *= fs->data_align;
+
fs->cfa_offset = utmp;
/* cfa_how deliberately not set. */
break;
@@ -614,6 +635,36 @@ dwarf2_frame_signal_frame_p (struct gdbarch *gdbarch,
return 0;
return ops->signal_frame_p (gdbarch, next_frame);
}
+
+static void
+dwarf2_frame_find_quirks (struct dwarf2_frame_state *fs,
+ struct dwarf2_fde *fde)
+{
+ static const char *arm_idents[] = {
+ "ARM C Compiler, ADS",
+ "Thumb C Compiler, ADS",
+ "ARM C++ Compiler, ADS",
+ "Thumb C++ Compiler, ADS",
+ "ARM/Thumb C/C++ Compiler, RVCT"
+ };
+ int i;
+
+ struct symtab *s;
+
+ s = find_pc_symtab (fs->pc);
+ if (s == NULL || s->producer == NULL)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE (arm_idents); i++)
+ if (strncmp (s->producer, arm_idents[i], strlen (arm_idents[i])) == 0)
+ {
+ if (fde->cie->version == 1)
+ fs->armcc_cfa_offsets_sf = 1;
+
+ if (fde->cie->version == 1 || fde->cie->version == 3)
+ fs->armcc_cfa_offsets_reversed = 1;
+ }
+}
struct dwarf2_frame_cache
@@ -680,6 +731,9 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
fs->code_align = fde->cie->code_alignment_factor;
fs->retaddr_column = fde->cie->return_address_register;
+ /* Check for "quirks" - known bugs in producers. */
+ dwarf2_frame_find_quirks (fs, fde);
+
/* First decode all the insns in the CIE. */
execute_cfa_program (fde->cie->initial_instructions,
fde->cie->end, next_frame, fs);
@@ -696,7 +750,10 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
{
case CFA_REG_OFFSET:
cache->cfa = read_reg (next_frame, fs->cfa_reg);
- cache->cfa += fs->cfa_offset;
+ if (fs->armcc_cfa_offsets_reversed)
+ cache->cfa -= fs->cfa_offset;
+ else
+ cache->cfa += fs->cfa_offset;
break;
case CFA_EXP:
@@ -1454,6 +1511,7 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p)
cie_version = read_1_byte (unit->abfd, buf);
if (cie_version != 1 && cie_version != 3)
return NULL;
+ cie->version = cie_version;
buf += 1;
/* Interpret the interesting bits of the augmentation. */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 6fe9245f4a2..4bdf5e480cd 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2779,16 +2779,9 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_producer, cu);
if (attr)
cu->producer = DW_STRING (attr);
-
+
/* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
-#if 0
- /* FIXME:Do something here. */
- if (dip->at_producer != NULL)
- {
- handle_producer (dip->at_producer);
- }
-#endif
/* The compilation unit may be in a different language or objfile,
zero out all remembered fundamental types. */
@@ -2796,6 +2789,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
start_symtab (name, comp_dir, lowpc);
record_debugformat ("DWARF 2");
+ record_producer (cu->producer);
initialize_cu_func_list (cu);
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 840478ad5db..763d61ee27d 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -846,9 +846,9 @@ struct symtab
char *debugformat;
- /* String of version information. May be zero. */
+ /* String of producer version information. May be zero. */
- char *version;
+ char *producer;
/* Full name of file as found by searching the source path.
NULL if not yet known. */