* [rfc] [2/4] SPU overlay support: The SPU target part
@ 2007-05-07 22:26 Ulrich Weigand
2007-05-08 8:10 ` Emi SUZUKI
0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2007-05-07 22:26 UTC (permalink / raw)
To: gdb-patches
Hello,
this is spu-tdep.c part of SPU overlay handling.
Tested on spu-elf.
I'll commit this together with the gdbarch change.
Bye,
Ulrich
ChangeLog:
* spu-tdep.c: Include "observer.h".
(spu_frame_unwind_cache): Unwind PC through overlay return stubs.
(spu_overlay_data): New variable.
(struct spu_overlay_table): New type.
(spu_get_overlay_table, spu_overlay_update_osect, spu_overlay_update,
spu_overlay_new_objfile): New functions.
(spu_gdbarch_init): Install spu_overlay_update.
(_initialize_spu_tdep): Register spu_overlay_new_objfile,
allocate spu_overlay_data objfile data.
diff -urNp gdb-orig/gdb/Makefile.in gdb-head/gdb/Makefile.in
--- gdb-orig/gdb/Makefile.in 2007-05-07 22:32:35.801737958 +0200
+++ gdb-head/gdb/Makefile.in 2007-05-07 23:18:00.069628011 +0200
@@ -2681,7 +2681,7 @@ spu-tdep.o: spu-tdep.c $(defs_h) $(arch_
$(frame_unwind_h) $(frame_base_h) $(trad_frame_h) $(symtab_h) \
$(symfile_h) $(value_h) $(inferior_h) $(dis_asm_h) $(objfiles_h) \
$(language_h) $(regcache_h) $(reggroups_h) $(floatformat_h) \
- $(spu_tdep_h)
+ $(observer_h) $(spu_tdep_h)
stabsread.o: stabsread.c $(defs_h) $(gdb_string_h) $(bfd_h) $(gdb_obstack_h) \
$(symtab_h) $(gdbtypes_h) $(expression_h) $(symfile_h) $(objfiles_h) \
$(aout_stab_gnu_h) $(libaout_h) $(aout_aout64_h) $(gdb_stabs_h) \
diff -urNp gdb-orig/gdb/spu-tdep.c gdb-head/gdb/spu-tdep.c
--- gdb-orig/gdb/spu-tdep.c 2007-05-07 23:17:34.332470446 +0200
+++ gdb-head/gdb/spu-tdep.c 2007-05-07 23:17:50.367559497 +0200
@@ -42,6 +42,7 @@
#include "regcache.h"
#include "reggroups.h"
#include "floatformat.h"
+#include "observer.h"
#include "spu-tdep.h"
@@ -671,6 +672,7 @@ spu_frame_unwind_cache (struct frame_inf
{
struct spu_unwind_cache *info;
struct spu_prologue_data data;
+ gdb_byte buf[16];
if (*this_prologue_cache)
return *this_prologue_cache;
@@ -698,7 +700,6 @@ spu_frame_unwind_cache (struct frame_inf
{
CORE_ADDR cfa;
int i;
- gdb_byte buf[16];
/* Determine CFA via unwound CFA_REG plus CFA_OFFSET. */
frame_unwind_register (next_frame, data.cfa_reg, buf);
@@ -711,15 +712,6 @@ spu_frame_unwind_cache (struct frame_inf
if (data.reg_offset[i] != -1)
info->saved_regs[i].addr = cfa - data.reg_offset[i];
- /* The previous PC comes from the link register. */
- if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
- info->saved_regs[SPU_PC_REGNUM] = info->saved_regs[SPU_LR_REGNUM];
- else
- info->saved_regs[SPU_PC_REGNUM].realreg = SPU_LR_REGNUM;
-
- /* The previous SP is equal to the CFA. */
- trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, cfa);
-
/* Frame bases. */
info->frame_base = cfa;
info->local_base = cfa - data.size;
@@ -742,20 +734,28 @@ spu_frame_unwind_cache (struct frame_inf
if (backchain + 16 < SPU_LS_SIZE)
info->saved_regs[SPU_LR_REGNUM].addr = backchain + 16;
- /* This will also be the previous PC. */
- if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
- info->saved_regs[SPU_PC_REGNUM] = info->saved_regs[SPU_LR_REGNUM];
- else
- info->saved_regs[SPU_PC_REGNUM].realreg = SPU_LR_REGNUM;
-
- /* The previous SP will equal the backchain value. */
- trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, backchain);
-
/* Frame bases. */
info->frame_base = backchain;
info->local_base = reg;
}
}
+
+ /* The previous SP is equal to the CFA. */
+ trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, info->frame_base);
+
+ /* The previous PC comes from the link register. In the case
+ of overlay return stubs, we unwind to the real return address. */
+ if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
+ target_read_memory (info->saved_regs[SPU_LR_REGNUM].addr, buf, 16);
+ else
+ frame_unwind_register (next_frame, SPU_LR_REGNUM, buf);
+
+ if (extract_unsigned_integer (buf + 8, 4) != 0)
+ trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
+ extract_unsigned_integer (buf + 8, 4));
+ else
+ trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
+ extract_unsigned_integer (buf, 4));
return info;
}
@@ -1124,6 +1124,189 @@ spu_software_single_step (struct regcach
return 1;
}
+/* Target overlays for the SPU overlay manager.
+
+ See the documentation of simple_overlay_update for how the
+ interface is supposed to work.
+
+ Data structures used by the overlay manager:
+
+ struct ovly_table
+ {
+ u32 vma;
+ u32 size;
+ u32 pos;
+ u32 buf;
+ } _ovly_table[]; -- one entry per overlay section
+
+ struct ovly_buf_table
+ {
+ u32 mapped;
+ } _ovly_buf_table[]; -- one entry per overlay buffer
+
+ _ovly_table should never change.
+
+ Both tables are aligned to a 16-byte boundary, the symbols _ovly_table
+ and _ovly_buf_table are of type STT_OBJECT and their size set to the size
+ of the respective array. buf in _ovly_table is an index into _ovly_buf_table.
+
+ mapped is an index into _ovly_table. Both the mapped and buf indices start
+ from one to reference the first entry in their respective tables. */
+
+/* Using the per-objfile private data mechanism, we store for each
+ objfile an array of "struct spu_overlay_table" structures, one
+ for each obj_section of the objfile. This structure holds two
+ fields, MAPPED_PTR and MAPPED_VAL. If MAPPED_PTR is zero, this
+ is *not* an overlay section. If it is non-zero, it represents
+ a target address. The overlay section is mapped iff the target
+ integer at this location equals MAPPED_VAL. */
+
+static const struct objfile_data *spu_overlay_data;
+
+struct spu_overlay_table
+ {
+ CORE_ADDR mapped_ptr;
+ CORE_ADDR mapped_val;
+ };
+
+/* Retrieve the overlay table for OBJFILE. If not already cached, read
+ the _ovly_table data structure from the target and initialize the
+ spu_overlay_table data structure from it. */
+static struct spu_overlay_table *
+spu_get_overlay_table (struct objfile *objfile)
+{
+ struct minimal_symbol *ovly_table_msym, *ovly_buf_table_msym;
+ CORE_ADDR ovly_table_base, ovly_buf_table_base;
+ unsigned ovly_table_size, ovly_buf_table_size;
+ struct spu_overlay_table *tbl;
+ struct obj_section *osect;
+ char *ovly_table;
+ int i;
+
+ tbl = objfile_data (objfile, spu_overlay_data);
+ if (tbl)
+ return tbl;
+
+ ovly_table_msym = lookup_minimal_symbol ("_ovly_table", NULL, objfile);
+ if (!ovly_table_msym)
+ return NULL;
+
+ ovly_buf_table_msym = lookup_minimal_symbol ("_ovly_buf_table", NULL, objfile);
+ if (!ovly_buf_table_msym)
+ return NULL;
+
+ ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym);
+ ovly_table_size = MSYMBOL_SIZE (ovly_table_msym);
+
+ ovly_buf_table_base = SYMBOL_VALUE_ADDRESS (ovly_buf_table_msym);
+ ovly_buf_table_size = MSYMBOL_SIZE (ovly_buf_table_msym);
+
+ ovly_table = xmalloc (ovly_table_size);
+ read_memory (ovly_table_base, ovly_table, ovly_table_size);
+
+ tbl = OBSTACK_CALLOC (&objfile->objfile_obstack,
+ objfile->sections_end - objfile->sections,
+ struct spu_overlay_table);
+
+ for (i = 0; i < ovly_table_size / 16; i++)
+ {
+ CORE_ADDR vma = extract_unsigned_integer (ovly_table + 16*i + 0, 4);
+ CORE_ADDR size = extract_unsigned_integer (ovly_table + 16*i + 4, 4);
+ CORE_ADDR pos = extract_unsigned_integer (ovly_table + 16*i + 8, 4);
+ CORE_ADDR buf = extract_unsigned_integer (ovly_table + 16*i + 12, 4);
+
+ if (buf == 0 || (buf - 1) * 4 >= ovly_buf_table_size)
+ continue;
+
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
+ if (vma == bfd_section_vma (objfile->obfd, osect->the_bfd_section)
+ && pos == osect->the_bfd_section->filepos)
+ {
+ int ndx = osect - objfile->sections;
+ tbl[ndx].mapped_ptr = ovly_buf_table_base + (buf - 1) * 4;
+ tbl[ndx].mapped_val = i + 1;
+ break;
+ }
+ }
+
+ xfree (ovly_table);
+ set_objfile_data (objfile, spu_overlay_data, tbl);
+ return tbl;
+}
+
+/* Read _ovly_buf_table entry from the target to dermine whether
+ OSECT is currently mapped, and update the mapped state. */
+static void
+spu_overlay_update_osect (struct obj_section *osect)
+{
+ struct spu_overlay_table *ovly_table;
+ CORE_ADDR val;
+
+ ovly_table = spu_get_overlay_table (osect->objfile);
+ if (!ovly_table)
+ return;
+
+ ovly_table += osect - osect->objfile->sections;
+ if (ovly_table->mapped_ptr == 0)
+ return;
+
+ val = read_memory_unsigned_integer (ovly_table->mapped_ptr, 4);
+ osect->ovly_mapped = (val == ovly_table->mapped_val);
+}
+
+/* If OSECT is NULL, then update all sections' mapped state.
+ If OSECT is non-NULL, then update only OSECT's mapped state. */
+static void
+spu_overlay_update (struct obj_section *osect)
+{
+ /* Just one section. */
+ if (osect)
+ spu_overlay_update_osect (osect);
+
+ /* All sections. */
+ else
+ {
+ struct objfile *objfile;
+
+ ALL_OBJSECTIONS (objfile, osect)
+ if (section_is_overlay (osect->the_bfd_section))
+ spu_overlay_update_osect (osect);
+ }
+}
+
+/* Whenever a new objfile is loaded, read the target's _ovly_table.
+ If there is one, go through all sections and make sure for non-
+ overlay sections LMA equals VMA, while for overlay sections LMA
+ is larger than local store size. */
+static void
+spu_overlay_new_objfile (struct objfile *objfile)
+{
+ struct spu_overlay_table *ovly_table;
+ bfd *obfd = objfile->obfd;
+ struct obj_section *osect;
+
+ /* If we've already touched this file, do nothing. */
+ if (!objfile || objfile_data (objfile, spu_overlay_data) != NULL)
+ return;
+
+ /* Check if this objfile has overlays. */
+ ovly_table = spu_get_overlay_table (objfile);
+ if (!ovly_table)
+ return;
+
+ /* Now go and fiddle with all the LMAs. */
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
+ {
+ asection *bsect = osect->the_bfd_section;
+ int ndx = osect - objfile->sections;
+
+ if (ovly_table[ndx].mapped_ptr == 0)
+ bfd_section_lma (obfd, bsect) = bfd_section_vma (obfd, bsect);
+ else
+ bfd_section_lma (obfd, bsect) = bsect->filepos + SPU_LS_SIZE;
+ }
+}
+
/* Set up gdbarch struct. */
@@ -1200,6 +1383,9 @@ spu_gdbarch_init (struct gdbarch_info in
set_gdbarch_cannot_step_breakpoint (gdbarch, 1);
set_gdbarch_software_single_step (gdbarch, spu_software_single_step);
+ /* Overlays. */
+ set_gdbarch_overlay_update (gdbarch, spu_overlay_update);
+
return gdbarch;
}
@@ -1230,4 +1416,8 @@ _initialize_spu_tdep (void)
register_gdbarch_init (bfd_arch_spu, spu_gdbarch_init);
spu_init_vector_type ();
+
+ /* Add ourselves to objfile event chain. */
+ observer_attach_new_objfile (spu_overlay_new_objfile);
+ spu_overlay_data = register_objfile_data ();
}
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] [2/4] SPU overlay support: The SPU target part
2007-05-07 22:26 [rfc] [2/4] SPU overlay support: The SPU target part Ulrich Weigand
@ 2007-05-08 8:10 ` Emi SUZUKI
2007-05-08 12:40 ` Ulrich Weigand
0 siblings, 1 reply; 8+ messages in thread
From: Emi SUZUKI @ 2007-05-08 8:10 UTC (permalink / raw)
To: uweigand; +Cc: gdb-patches
Hello Ulrich,
I know that the duscussion about the corresponding gdbarch changes is
going on (and I unfortunately have no alternative idea about it), but
just want to notice you something that I came across.
> +static void
> +spu_overlay_new_objfile (struct objfile *objfile)
> +{
> + struct spu_overlay_table *ovly_table;
> + bfd *obfd = objfile->obfd;
> + struct obj_section *osect;
It will cause SEGV if objfile is NULL.
That code seems to be optimized out by `-O2' option of GCC, though.
--
Emi SUZUKI / emi-suzuki at tjsys.co.jp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] [2/4] SPU overlay support: The SPU target part
2007-05-08 8:10 ` Emi SUZUKI
@ 2007-05-08 12:40 ` Ulrich Weigand
2007-05-10 21:55 ` Daniel Jacobowitz
0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2007-05-08 12:40 UTC (permalink / raw)
To: Emi SUZUKI; +Cc: gdb-patches
Emi Suzuki wrote:
> I know that the duscussion about the corresponding gdbarch changes is
> going on (and I unfortunately have no alternative idea about it), but
> just want to notice you something that I came across.
>
> > +static void
> > +spu_overlay_new_objfile (struct objfile *objfile)
> > +{
> > + struct spu_overlay_table *ovly_table;
> > + bfd *obfd = objfile->obfd;
> > + struct obj_section *osect;
>
> It will cause SEGV if objfile is NULL.
> That code seems to be optimized out by `-O2' option of GCC, though.
Ah, thanks for catching this! An updated patch is attached.
Bye,
Ulrich
ChangeLog:
* spu-tdep.c: Include "observer.h".
(spu_frame_unwind_cache): Unwind PC through overlay return stubs.
(spu_overlay_data): New variable.
(struct spu_overlay_table): New type.
(spu_get_overlay_table, spu_overlay_update_osect, spu_overlay_update,
spu_overlay_new_objfile): New functions.
(spu_gdbarch_init): Install spu_overlay_update.
(_initialize_spu_tdep): Register spu_overlay_new_objfile,
allocate spu_overlay_data objfile data.
diff -urNp gdb-orig/gdb/Makefile.in gdb-head/gdb/Makefile.in
--- gdb-orig/gdb/Makefile.in 2007-05-08 14:19:05.149146119 +0200
+++ gdb-head/gdb/Makefile.in 2007-05-07 23:18:00.000000000 +0200
@@ -2681,7 +2681,7 @@ spu-tdep.o: spu-tdep.c $(defs_h) $(arch_
$(frame_unwind_h) $(frame_base_h) $(trad_frame_h) $(symtab_h) \
$(symfile_h) $(value_h) $(inferior_h) $(dis_asm_h) $(objfiles_h) \
$(language_h) $(regcache_h) $(reggroups_h) $(floatformat_h) \
- $(spu_tdep_h)
+ $(observer_h) $(spu_tdep_h)
stabsread.o: stabsread.c $(defs_h) $(gdb_string_h) $(bfd_h) $(gdb_obstack_h) \
$(symtab_h) $(gdbtypes_h) $(expression_h) $(symfile_h) $(objfiles_h) \
$(aout_stab_gnu_h) $(libaout_h) $(aout_aout64_h) $(gdb_stabs_h) \
diff -urNp gdb-orig/gdb/spu-tdep.c gdb-head/gdb/spu-tdep.c
--- gdb-orig/gdb/spu-tdep.c 2007-05-08 14:19:05.187140671 +0200
+++ gdb-head/gdb/spu-tdep.c 2007-05-08 14:21:11.400194338 +0200
@@ -42,6 +42,7 @@
#include "regcache.h"
#include "reggroups.h"
#include "floatformat.h"
+#include "observer.h"
#include "spu-tdep.h"
@@ -671,6 +672,7 @@ spu_frame_unwind_cache (struct frame_inf
{
struct spu_unwind_cache *info;
struct spu_prologue_data data;
+ gdb_byte buf[16];
if (*this_prologue_cache)
return *this_prologue_cache;
@@ -698,7 +700,6 @@ spu_frame_unwind_cache (struct frame_inf
{
CORE_ADDR cfa;
int i;
- gdb_byte buf[16];
/* Determine CFA via unwound CFA_REG plus CFA_OFFSET. */
frame_unwind_register (next_frame, data.cfa_reg, buf);
@@ -711,15 +712,6 @@ spu_frame_unwind_cache (struct frame_inf
if (data.reg_offset[i] != -1)
info->saved_regs[i].addr = cfa - data.reg_offset[i];
- /* The previous PC comes from the link register. */
- if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
- info->saved_regs[SPU_PC_REGNUM] = info->saved_regs[SPU_LR_REGNUM];
- else
- info->saved_regs[SPU_PC_REGNUM].realreg = SPU_LR_REGNUM;
-
- /* The previous SP is equal to the CFA. */
- trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, cfa);
-
/* Frame bases. */
info->frame_base = cfa;
info->local_base = cfa - data.size;
@@ -742,20 +734,28 @@ spu_frame_unwind_cache (struct frame_inf
if (backchain + 16 < SPU_LS_SIZE)
info->saved_regs[SPU_LR_REGNUM].addr = backchain + 16;
- /* This will also be the previous PC. */
- if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
- info->saved_regs[SPU_PC_REGNUM] = info->saved_regs[SPU_LR_REGNUM];
- else
- info->saved_regs[SPU_PC_REGNUM].realreg = SPU_LR_REGNUM;
-
- /* The previous SP will equal the backchain value. */
- trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, backchain);
-
/* Frame bases. */
info->frame_base = backchain;
info->local_base = reg;
}
}
+
+ /* The previous SP is equal to the CFA. */
+ trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, info->frame_base);
+
+ /* The previous PC comes from the link register. In the case
+ of overlay return stubs, we unwind to the real return address. */
+ if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
+ target_read_memory (info->saved_regs[SPU_LR_REGNUM].addr, buf, 16);
+ else
+ frame_unwind_register (next_frame, SPU_LR_REGNUM, buf);
+
+ if (extract_unsigned_integer (buf + 8, 4) != 0)
+ trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
+ extract_unsigned_integer (buf + 8, 4));
+ else
+ trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
+ extract_unsigned_integer (buf, 4));
return info;
}
@@ -1124,6 +1124,189 @@ spu_software_single_step (struct regcach
return 1;
}
+/* Target overlays for the SPU overlay manager.
+
+ See the documentation of simple_overlay_update for how the
+ interface is supposed to work.
+
+ Data structures used by the overlay manager:
+
+ struct ovly_table
+ {
+ u32 vma;
+ u32 size;
+ u32 pos;
+ u32 buf;
+ } _ovly_table[]; -- one entry per overlay section
+
+ struct ovly_buf_table
+ {
+ u32 mapped;
+ } _ovly_buf_table[]; -- one entry per overlay buffer
+
+ _ovly_table should never change.
+
+ Both tables are aligned to a 16-byte boundary, the symbols _ovly_table
+ and _ovly_buf_table are of type STT_OBJECT and their size set to the size
+ of the respective array. buf in _ovly_table is an index into _ovly_buf_table.
+
+ mapped is an index into _ovly_table. Both the mapped and buf indices start
+ from one to reference the first entry in their respective tables. */
+
+/* Using the per-objfile private data mechanism, we store for each
+ objfile an array of "struct spu_overlay_table" structures, one
+ for each obj_section of the objfile. This structure holds two
+ fields, MAPPED_PTR and MAPPED_VAL. If MAPPED_PTR is zero, this
+ is *not* an overlay section. If it is non-zero, it represents
+ a target address. The overlay section is mapped iff the target
+ integer at this location equals MAPPED_VAL. */
+
+static const struct objfile_data *spu_overlay_data;
+
+struct spu_overlay_table
+ {
+ CORE_ADDR mapped_ptr;
+ CORE_ADDR mapped_val;
+ };
+
+/* Retrieve the overlay table for OBJFILE. If not already cached, read
+ the _ovly_table data structure from the target and initialize the
+ spu_overlay_table data structure from it. */
+static struct spu_overlay_table *
+spu_get_overlay_table (struct objfile *objfile)
+{
+ struct minimal_symbol *ovly_table_msym, *ovly_buf_table_msym;
+ CORE_ADDR ovly_table_base, ovly_buf_table_base;
+ unsigned ovly_table_size, ovly_buf_table_size;
+ struct spu_overlay_table *tbl;
+ struct obj_section *osect;
+ char *ovly_table;
+ int i;
+
+ tbl = objfile_data (objfile, spu_overlay_data);
+ if (tbl)
+ return tbl;
+
+ ovly_table_msym = lookup_minimal_symbol ("_ovly_table", NULL, objfile);
+ if (!ovly_table_msym)
+ return NULL;
+
+ ovly_buf_table_msym = lookup_minimal_symbol ("_ovly_buf_table", NULL, objfile);
+ if (!ovly_buf_table_msym)
+ return NULL;
+
+ ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym);
+ ovly_table_size = MSYMBOL_SIZE (ovly_table_msym);
+
+ ovly_buf_table_base = SYMBOL_VALUE_ADDRESS (ovly_buf_table_msym);
+ ovly_buf_table_size = MSYMBOL_SIZE (ovly_buf_table_msym);
+
+ ovly_table = xmalloc (ovly_table_size);
+ read_memory (ovly_table_base, ovly_table, ovly_table_size);
+
+ tbl = OBSTACK_CALLOC (&objfile->objfile_obstack,
+ objfile->sections_end - objfile->sections,
+ struct spu_overlay_table);
+
+ for (i = 0; i < ovly_table_size / 16; i++)
+ {
+ CORE_ADDR vma = extract_unsigned_integer (ovly_table + 16*i + 0, 4);
+ CORE_ADDR size = extract_unsigned_integer (ovly_table + 16*i + 4, 4);
+ CORE_ADDR pos = extract_unsigned_integer (ovly_table + 16*i + 8, 4);
+ CORE_ADDR buf = extract_unsigned_integer (ovly_table + 16*i + 12, 4);
+
+ if (buf == 0 || (buf - 1) * 4 >= ovly_buf_table_size)
+ continue;
+
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
+ if (vma == bfd_section_vma (objfile->obfd, osect->the_bfd_section)
+ && pos == osect->the_bfd_section->filepos)
+ {
+ int ndx = osect - objfile->sections;
+ tbl[ndx].mapped_ptr = ovly_buf_table_base + (buf - 1) * 4;
+ tbl[ndx].mapped_val = i + 1;
+ break;
+ }
+ }
+
+ xfree (ovly_table);
+ set_objfile_data (objfile, spu_overlay_data, tbl);
+ return tbl;
+}
+
+/* Read _ovly_buf_table entry from the target to dermine whether
+ OSECT is currently mapped, and update the mapped state. */
+static void
+spu_overlay_update_osect (struct obj_section *osect)
+{
+ struct spu_overlay_table *ovly_table;
+ CORE_ADDR val;
+
+ ovly_table = spu_get_overlay_table (osect->objfile);
+ if (!ovly_table)
+ return;
+
+ ovly_table += osect - osect->objfile->sections;
+ if (ovly_table->mapped_ptr == 0)
+ return;
+
+ val = read_memory_unsigned_integer (ovly_table->mapped_ptr, 4);
+ osect->ovly_mapped = (val == ovly_table->mapped_val);
+}
+
+/* If OSECT is NULL, then update all sections' mapped state.
+ If OSECT is non-NULL, then update only OSECT's mapped state. */
+static void
+spu_overlay_update (struct obj_section *osect)
+{
+ /* Just one section. */
+ if (osect)
+ spu_overlay_update_osect (osect);
+
+ /* All sections. */
+ else
+ {
+ struct objfile *objfile;
+
+ ALL_OBJSECTIONS (objfile, osect)
+ if (section_is_overlay (osect->the_bfd_section))
+ spu_overlay_update_osect (osect);
+ }
+}
+
+/* Whenever a new objfile is loaded, read the target's _ovly_table.
+ If there is one, go through all sections and make sure for non-
+ overlay sections LMA equals VMA, while for overlay sections LMA
+ is larger than local store size. */
+static void
+spu_overlay_new_objfile (struct objfile *objfile)
+{
+ struct spu_overlay_table *ovly_table;
+ struct obj_section *osect;
+
+ /* If we've already touched this file, do nothing. */
+ if (!objfile || objfile_data (objfile, spu_overlay_data) != NULL)
+ return;
+
+ /* Check if this objfile has overlays. */
+ ovly_table = spu_get_overlay_table (objfile);
+ if (!ovly_table)
+ return;
+
+ /* Now go and fiddle with all the LMAs. */
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
+ {
+ bfd *obfd = objfile->obfd;
+ asection *bsect = osect->the_bfd_section;
+ int ndx = osect - objfile->sections;
+
+ if (ovly_table[ndx].mapped_ptr == 0)
+ bfd_section_lma (obfd, bsect) = bfd_section_vma (obfd, bsect);
+ else
+ bfd_section_lma (obfd, bsect) = bsect->filepos + SPU_LS_SIZE;
+ }
+}
+
/* Set up gdbarch struct. */
@@ -1200,6 +1383,9 @@ spu_gdbarch_init (struct gdbarch_info in
set_gdbarch_cannot_step_breakpoint (gdbarch, 1);
set_gdbarch_software_single_step (gdbarch, spu_software_single_step);
+ /* Overlays. */
+ set_gdbarch_overlay_update (gdbarch, spu_overlay_update);
+
return gdbarch;
}
@@ -1230,4 +1416,8 @@ _initialize_spu_tdep (void)
register_gdbarch_init (bfd_arch_spu, spu_gdbarch_init);
spu_init_vector_type ();
+
+ /* Add ourselves to objfile event chain. */
+ observer_attach_new_objfile (spu_overlay_new_objfile);
+ spu_overlay_data = register_objfile_data ();
}
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] [2/4] SPU overlay support: The SPU target part
2007-05-08 12:40 ` Ulrich Weigand
@ 2007-05-10 21:55 ` Daniel Jacobowitz
2007-05-10 22:20 ` Ulrich Weigand
0 siblings, 1 reply; 8+ messages in thread
From: Daniel Jacobowitz @ 2007-05-10 21:55 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: Emi SUZUKI, gdb-patches
On Tue, May 08, 2007 at 02:40:12PM +0200, Ulrich Weigand wrote:
> + /* The previous SP is equal to the CFA. */
> + trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, info->frame_base);
> +
> + /* The previous PC comes from the link register. In the case
> + of overlay return stubs, we unwind to the real return address. */
> + if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
> + target_read_memory (info->saved_regs[SPU_LR_REGNUM].addr, buf, 16);
> + else
> + frame_unwind_register (next_frame, SPU_LR_REGNUM, buf);
> +
> + if (extract_unsigned_integer (buf + 8, 4) != 0)
> + trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
> + extract_unsigned_integer (buf + 8, 4));
> + else
> + trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
> + extract_unsigned_integer (buf, 4));
(I'm not sure how this ends up detecting an overlay return stub, but
I'll take your word for it.)
This is clever, but kind of sneaky. We show signal return trampolines
and dummy call trampolines, so I'm not sure why it's necessary to
hide overlay return stubs. Do you think this is more useful than
confusing?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] [2/4] SPU overlay support: The SPU target part
2007-05-10 21:55 ` Daniel Jacobowitz
@ 2007-05-10 22:20 ` Ulrich Weigand
2007-05-11 17:32 ` Daniel Jacobowitz
0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2007-05-10 22:20 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Emi SUZUKI, gdb-patches
Daniel Jacobowitz wrote:
> (I'm not sure how this ends up detecting an overlay return stub, but
> I'll take your word for it.)
On the SPU, every register is a 16-byte vector register, and that
includes the "link register" 0. As addresses are only 32 bit
(actually only 18 bit), only the first of four 32-bit slots in
the link register is used to hold the return address. However,
the whole 128-bit register is always saved/restored on the stack.
This makes it possible to use the remaining slots to hold additional
information needed to handle return jumps crossing an overlay
boundary. In those cases, the slots are set up to hold:
[0] Return stub entry point in the overlay manager
[1] Partition number of the overlay section to be returned to
[2] Actual return address in the (restored) overlay section
Thus, when the normal function return is executed, control will
"return" to the overlay manager, which can examine the remaining
slots to determine which overlay section to swap in, and then
transfer control to the actual return address.
What the PC unwinder code does when it sees an unwound link
register of that form is to set the PC to the value in slot 2
of the link register, instead of slot 0 as usual.
Note that there is no stack frame associated with the return
stub at all.
> This is clever, but kind of sneaky. We show signal return trampolines
> and dummy call trampolines, so I'm not sure why it's necessary to
> hide overlay return stubs. Do you think this is more useful than
> confusing?
Both signal return and dummy call trampolines are entities the
user actually knows about and wants to see. The overlay mechanism
is supposed to be fully transparent to the user; I'd compare the
overlay call and return stubs to things like PLT stubs in ELF
-- we don't show those either.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] [2/4] SPU overlay support: The SPU target part
2007-05-10 22:20 ` Ulrich Weigand
@ 2007-05-11 17:32 ` Daniel Jacobowitz
2007-05-11 19:09 ` Ulrich Weigand
0 siblings, 1 reply; 8+ messages in thread
From: Daniel Jacobowitz @ 2007-05-11 17:32 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: Emi SUZUKI, gdb-patches
On Fri, May 11, 2007 at 12:20:05AM +0200, Ulrich Weigand wrote:
> This makes it possible to use the remaining slots to hold additional
> information needed to handle return jumps crossing an overlay
> boundary. In those cases, the slots are set up to hold:
> [0] Return stub entry point in the overlay manager
> [1] Partition number of the overlay section to be returned to
> [2] Actual return address in the (restored) overlay section
Clever. Could we have a comment about this in GDB somewhere?
Apologies if there was one; I didn't see it.
> > This is clever, but kind of sneaky. We show signal return trampolines
> > and dummy call trampolines, so I'm not sure why it's necessary to
> > hide overlay return stubs. Do you think this is more useful than
> > confusing?
>
> Both signal return and dummy call trampolines are entities the
> user actually knows about and wants to see. The overlay mechanism
> is supposed to be fully transparent to the user; I'd compare the
> overlay call and return stubs to things like PLT stubs in ELF
> -- we don't show those either.
Well, they never end up on the stack. We would if they did. But this
isn't a big issue to me; I'd be very confused if I stepi'd a
return instruction and ended up somewhere other than the function
listed in the backtrace, but my use of GDB is probably not typical.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] [2/4] SPU overlay support: The SPU target part
2007-05-11 17:32 ` Daniel Jacobowitz
@ 2007-05-11 19:09 ` Ulrich Weigand
2007-05-11 19:33 ` Daniel Jacobowitz
0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2007-05-11 19:09 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Emi SUZUKI, gdb-patches
Daniel Jacobowitz wrote:
> On Fri, May 11, 2007 at 12:20:05AM +0200, Ulrich Weigand wrote:
> > This makes it possible to use the remaining slots to hold additional
> > information needed to handle return jumps crossing an overlay
> > boundary. In those cases, the slots are set up to hold:
> > [0] Return stub entry point in the overlay manager
> > [1] Partition number of the overlay section to be returned to
> > [2] Actual return address in the (restored) overlay section
>
> Clever. Could we have a comment about this in GDB somewhere?
> Apologies if there was one; I didn't see it.
Sure, I'll add a comment.
> > > This is clever, but kind of sneaky. We show signal return trampolines
> > > and dummy call trampolines, so I'm not sure why it's necessary to
> > > hide overlay return stubs. Do you think this is more useful than
> > > confusing?
> >
> > Both signal return and dummy call trampolines are entities the
> > user actually knows about and wants to see. The overlay mechanism
> > is supposed to be fully transparent to the user; I'd compare the
> > overlay call and return stubs to things like PLT stubs in ELF
> > -- we don't show those either.
>
> Well, they never end up on the stack. We would if they did. But this
> isn't a big issue to me; I'd be very confused if I stepi'd a
> return instruction and ended up somewhere other than the function
> listed in the backtrace, but my use of GDB is probably not typical.
The return stub isn't on the stack either. We'd have to manufacture
an extra zero-sized stack frame between caller and callee, with
special unwind rules to be able to continue the backtrace. I guess
this would be possible somehow, but I still don't see that this would
provide any benefit to most users ...
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] [2/4] SPU overlay support: The SPU target part
2007-05-11 19:09 ` Ulrich Weigand
@ 2007-05-11 19:33 ` Daniel Jacobowitz
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Jacobowitz @ 2007-05-11 19:33 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: Emi SUZUKI, gdb-patches
On Fri, May 11, 2007 at 09:09:28PM +0200, Ulrich Weigand wrote:
> The return stub isn't on the stack either. We'd have to manufacture
> an extra zero-sized stack frame between caller and callee, with
> special unwind rules to be able to continue the backtrace. I guess
> this would be possible somehow, but I still don't see that this would
> provide any benefit to most users ...
Oh... I see how it works now.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2007-05-11 19:33 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-05-07 22:26 [rfc] [2/4] SPU overlay support: The SPU target part Ulrich Weigand
2007-05-08 8:10 ` Emi SUZUKI
2007-05-08 12:40 ` Ulrich Weigand
2007-05-10 21:55 ` Daniel Jacobowitz
2007-05-10 22:20 ` Ulrich Weigand
2007-05-11 17:32 ` Daniel Jacobowitz
2007-05-11 19:09 ` Ulrich Weigand
2007-05-11 19:33 ` Daniel Jacobowitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox