From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14916 invoked by alias); 8 May 2007 12:40:23 -0000 Received: (qmail 14907 invoked by uid 22791); 8 May 2007 12:40:21 -0000 X-Spam-Check-By: sourceware.org Received: from mtagate8.de.ibm.com (HELO mtagate8.de.ibm.com) (195.212.29.157) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 08 May 2007 12:40:16 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate8.de.ibm.com (8.13.8/8.13.8) with ESMTP id l48CeCkE056984 for ; Tue, 8 May 2007 12:40:12 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v8.3) with ESMTP id l48CeDCp3686522 for ; Tue, 8 May 2007 14:40:13 +0200 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id l48CeCjF003321 for ; Tue, 8 May 2007 14:40:12 +0200 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id l48CeCFu003316; Tue, 8 May 2007 14:40:12 +0200 Message-Id: <200705081240.l48CeCFu003316@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Tue, 8 May 2007 14:40:12 +0200 Subject: Re: [rfc] [2/4] SPU overlay support: The SPU target part To: emi-suzuki@tjsys.co.jp (Emi SUZUKI) Date: Tue, 08 May 2007 12:40:00 -0000 From: "Ulrich Weigand" Cc: gdb-patches@sourceware.org In-Reply-To: <20070508.171059.207583878.emi-suzuki@tjsys.co.jp> from "Emi SUZUKI" at May 08, 2007 05:10:59 PM X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-05/txt/msg00113.txt.bz2 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