Cell GDB

Toolchain-ul GNU pentru arhitectura Cell BE conține, pe lângă o versiune a compilatorului GCC specifică acestei arhitecuri, și o versiune a GDB care poate fi folosită pentru a depana programe scrise pentru Cell BE. Toate funcțiile GDB sunt disponibile și pe arhitectura Cell BE.

Această pagină presupune familiaritate cu utilizarea GDB. Pentru o introducere în utilizarea GDB puteți folosi pagina dedicată din cadrul cursului de SO.

Rulare

GDB este disponibil sub numele de ppu-gdb. Contrar numelui executabilului, se poate depana atât cod PPU cât și cod SPU.

Pentru exemplificare vom folosi următorul program, care conține mai multe bug-uri. Compilarea este făcută cu ajutorul makefile-urilor puse la dispoziție de SDK-ul Cell BE. Arhiva completă poate fi descărcată de aici.

Cod PPU Cod SPU
ppu/ppu_bugs.c
/*
 * Computer System Architecture - Cell GDB tutorial
 * PPU code
 */
 
#include <libspe2.h>
 
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
 
 
extern spe_program_handle_t spu_bugs;
 
 
int main(void)
{
  spe_context_ptr_t ctx;
 
  if((ctx = spe_context_create(0, NULL)) == NULL)
  {
    perror ("Failed creating context");
    exit(1);
  }
 
  if(spe_program_load(ctx, &spu_bugs))
  {
    perror ("Failed loading program");
    exit(1);
  }
 
  unsigned int entry = SPE_DEFAULT_ENTRY;
  if(spe_context_run(ctx, &entry, 0, 0, 0, 0) < 0)
  {
    perror ("Failed running context");
    exit(1);
  }
 
  if(spe_context_destroy(ctx) != 0)
  {
    perror("Failed destroying context");
    exit(1);
  }
 
  return 0;
}
spu/spu_bugs.c
/*
 * Computer System Architecture - Cell GDB tutorial
 * SPU code
 */
 
#include <spu_mfcio.h>
 
#include <stdio.h>
#include <string.h>
 
 
#define mfc_waittag(t) do {     \
  mfc_write_tag_mask(1 << (t)); \
  mfc_read_tag_status_all();    \
  } while(0)
 
 
int main(unsigned long long speid,
  unsigned long long argp)
{
  char msg[16];
 
  sprintf(msg, "Cell GDB tutorial: hello from SPU "
    "with ID %llx\n", speid);
 
  mfc_put(msg, argp, sizeof(msg), 0, 0, 0);
  mfc_waittag(0);
 
  return 0;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Compilând, observăm ca în mod implicit este generat un program optimizat și fără debug symbols (-O3). După cum se poate observa, acest program nu este foarte util pentru depanare, lipsind numele funcției, numărul liniei, valoarea parametrilor etc. din momentul producerii erorii.

[dan.dragomir@cell-qs22-1 gdb]$ make
[...]
/usr/bin/spu-gcc        -W -Wall -Winline  -I.  -I /opt/cell/sdk/usr/spu/include  -O3 -c spu_bugs.c
[...]
/usr/bin/ppu32-gcc        -W -Wall -Winline -m32  -I.  -I /opt/cell/sdk/usr/include -mabi=altivec -maltivec -O3 -c ppu_bugs.c
[...]
[dan.dragomir@cell-qs22-1 gdb]$ ppu-gdb ppu/ppu_bugs
[...]
(gdb) run
Starting program: /export/home/acs/external/dan.dragomir/gdb/ppu/ppu_bugs 
[Thread debugging using libthread_db enabled]
 
Program received signal SIGSEGV, Segmentation fault.
0x000001d8 in main () from spu_bugs@0x1801c00 <5>

În cazul folosirii makefile-urilor de compilare din SDK-ul Cell se poate defini variabila de mediu CC_OPT_LEVEL pentru a modifica nivelul de optimizare. Vom atribui aceastei variabile flag-urile necesare pentru a genera un program neoptimizat (-O0) și cu debug symbols (-g). În cazul în care compilarea nu se face cu makefile-urile din SDK, aceleași flag-uri trebuie pasate totuși compilatorului prin mecanismul specific metodei de compilare folosite.

[dan.dragomir@cell-qs22-1 gdb]$ make clean
[...]
[dan.dragomir@cell-qs22-1 gdb]$ make CC_OPT_LEVEL="-O0 -g"
[...]
/usr/bin/spu-gcc        -W -Wall -Winline  -I.  -I /opt/cell/sdk/usr/spu/include  -O0 -g -c spu_bugs.c
[...]
/usr/bin/ppu32-gcc        -W -Wall -Winline -m32  -I.  -I /opt/cell/sdk/usr/include -mabi=altivec -maltivec -O0 -g -c ppu_bugs.c
[dan.dragomir@cell-qs22-1 gdb]$ ppu-gdb ppu/ppu_bugs
[...]
(gdb) run
Starting program: /export/home/acs/external/dan.dragomir/gdb/ppu/ppu_bugs 
[Thread debugging using libthread_db enabled]
 
Program received signal SIGBUS, Bus error.
0x00000278 in main (speid=7798581337495727215, argp=6134033987286868041) at spu_bugs.c:26
26	  mfc_waittag(0);

Comenzi generice

În momentul opririi programului putem folosi comenzile cunoscute pentru a inspecta starea acestuia:

  • backtrace-ul
(gdb) backtrace
#0  0x00000278 in main (speid=7798581337495727215, argp=6134033987286868041) at spu_bugs.c:26
#1  0x00000094 in _start () from spu_bugs@0x1801c80 <5>
  • codul sursă
(gdb) list
21	
22	  sprintf(msg, "Cell GDB tutorial: hello from SPU "
23	    "with ID %llx\n", speid);
24	
25	  mfc_put(msg, argp, sizeof(msg), 0, 0, 0);
26	  mfc_waittag(0);
27	
28	  return 0;
29	}
30	
  • valorile variabilelor de interes din scope-ul curent
(gdb) print argp
$1 = 6134033987286868041
(gdb) print sizeof(msg)
$2 = 16
  • alte frame-uri din stiva
(gdb) up
#1  0x00000094 in _start () from spu_bugs@0x1801c80 <5>
(gdb) down
#0  0x00000278 in main (speid=7798581337495727215, argp=6134033987286868041) at spu_bugs.c:26
26	  mfc_waittag(0);
(gdb) frame 1
#1  0x00000094 in _start () from spu_bugs@0x1801c80 <5>
(gdb) frame 0
#0  0x00000278 in main (speid=7798581337495727215, argp=6134033987286868041) at spu_bugs.c:26
26	  mfc_waittag(0);
Comanda watch, folosită de obicei pentru a cauza oprirea programului la modificarea unei variabile, nu folosește watchpoint-uri hardware în versiunea de GDB disponibilă curent. Din acest motiv funcționarea nu este neaparat cea așteptată. Ea realizează oprirea programului la modificarea variabilei, însă locația în care acesta este oprit nu corespunde instrucțiunii care a modificat-o.

Comenzi specifice Cell BE

Oprirea programului la prima instrucțiune din codul SPU se poate face cu set spu stop-on-load on.

(gdb) set spu stop-on-load on
(gdb) run
Starting program: /export/home/acs/external/dan.dragomir/gdb/ppu/ppu_bugs 
[Thread debugging using libthread_db enabled]
Temporary breakpoint 1 at 0x194: file spu_bugs.c, line 23.
 
Temporary breakpoint 1, main (speid=25296904, argp=0) at spu_bugs.c:23
23	  sprintf(msg, "Cell GDB tutorial: hello from SPU "

De asemenea este posibilă activarea unui breakpoint la orice funcție/linie din codul SPU. În cazul unei întrebări legate de lipsa fișierului sursă al codului SPU se răspunde cu y.

(gdb) break spu_bugs.c:main
No source file named spu_bugs.c.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (spu_bugs.c:main) pending.
(gdb) run
Starting program: /export/home/acs/external/dan.dragomir/gdb/ppu/ppu_bugs 
[Thread debugging using libthread_db enabled]
 
Breakpoint 1, main (speid=25296904, argp=0) at spu_bugs.c:23
23	  sprintf(msg, "Cell GDB tutorial: hello from SPU "
(gdb) break spu_bugs.c:26
No source file named spu_bugs.c.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (spu_bugs.c:26) pending.
(gdb) run
Starting program: /export/home/acs/external/dan.dragomir/gdb/ppu/ppu_bugs 
[Thread debugging using libthread_db enabled]
 
Breakpoint 1, main (speid=7798581337495727215, argp=6134033987286868041) at spu_bugs.c:26
26	  mfc_put(msg, argp, sizeof(msg), 0, 0, 0);

Resurse

asc/cellcookbook/gdb.txt · Last modified: 2015/03/30 05:46 by dan.dragomir
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0