[Cbe-oss-dev] SPU overlay DWARF DIE/CIE/FDE to program section/segment mapping?
John DelSignore
jdelsign at totalviewtech.com
Wed Mar 25 08:56:12 EST 2009
Hi Folks,
I'm not sure if this is the correct forum, but I'm not sure who else to ask, and I'm hoping that the Cell tool chain maintainers respond to this posting...
Question: Is there a way to determine the program segment to which a particular DWARF DIE or CIE/FDE belongs, when multiple program segments are linked at the same address due to SPU overlays?
Here is the problem, as seen with a simple SPU overlay example. Taken from the Cell SDK and changed slightly. The source code inside in the overlaid sections looks like this:
------------------------------cut-here------------------------------
% more olay*/test*.c
::::::::::::::
olay1/test1.c
::::::::::::::
/* --------------------------------------------------------------- */
/* (C)Copyright 2006 */
/* International Business Machines Corporation, */
/* All Rights Reserved. */
/* */
/* This program is made available under the terms of the */
/* Common Public License v1.0 which accompanies this distribution. */
/* --------------------------------------------------------------- */
/* PROLOG END TAG zYx */
#include <stdio.h>
int o1_test1(int p)
{
printf("o1_test1 prints %d\n", p);
return 1;
}
int o1_test2(int p)
{
printf("o1_test2 prints %d\n", p);
return 2;
}
::::::::::::::
olay2/test2.c
::::::::::::::
/* --------------------------------------------------------------- */
/* (C)Copyright 2006 */
/* International Business Machines Corporation, */
/* All Rights Reserved. */
/* */
/* This program is made available under the terms of the */
/* Common Public License v1.0 which accompanies this distribution. */
/* --------------------------------------------------------------- */
/* PROLOG END TAG zYx */
#include <stdio.h>
int o2_test1(int p)
{
printf("o2_test1 prints %d\n", p);
return 11;
}
int o2_test2(int p)
{
printf("o2_test2 prints %d\n", p);
return 12;
}
------------------------------cut-here------------------------------
When the above SPU code is linked, multiple program segments are linked at the same virtual address (overlaid). The program header for a sample program looks like this:
------------------------------cut-here------------------------------
% spu-readelf -lS spu_main
There are 26 section headers, starting at offset 0x792c:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .init PROGBITS 00000000 000100 000024 00 AX 0 0 4
[ 2] .text PROGBITS 00000030 000130 000ad0 00 WAX 0 0 16
[ 3] .segment1 PROGBITS 00000b00 000c00 000080 00 AX 0 0 16
[ 4] .segment2 PROGBITS 00000b00 000c80 000080 00 AX 0 0 16
[ 5] .fini PROGBITS 00000b80 000d00 00001c 00 AX 0 0 4
[ 6] .rodata PROGBITS 00000ba0 000d20 0000d0 00 A 0 0 16
[ 7] .ctors PROGBITS 00000c80 000e00 000008 00 WA 0 0 4
[ 8] .dtors PROGBITS 00000c88 000e08 000008 00 WA 0 0 4
[ 9] .jcr PROGBITS 00000c90 000e10 000004 00 WA 0 0 4
[10] .data PROGBITS 00000ca0 000e20 000454 00 WA 0 0 16
[11] .bss NOBITS 00001100 001274 000010 00 WA 0 0 16
[12] .comment PROGBITS 00000000 001274 0000fc 00 0 0 1
[13] .debug_aranges PROGBITS 00000000 001370 000190 00 0 0 1
[14] .debug_pubnames PROGBITS 00000000 001500 0001b0 00 0 0 1
[15] .debug_info PROGBITS 00000000 0016b0 003eb5 00 0 0 1
[16] .debug_abbrev PROGBITS 00000000 005565 000b79 00 0 0 1
[17] .debug_line PROGBITS 00000000 0060de 000954 00 0 0 1
[18] .debug_frame PROGBITS 00000000 006a34 0001f0 00 0 0 4
[19] .debug_str PROGBITS 00000000 006c24 0008a6 00 0 0 1
[20] .debug_loc PROGBITS 00000000 0074ca 000351 00 0 0 1
[21] .note.spu_name PROGBITS 00000000 007820 000020 00 0 0 16
[22] .toe NOBITS 00001180 001270 000010 00 WA 0 0 16
[23] .shstrtab STRTAB 00000000 007840 0000ec 00 0 0 1
[24] .symtab SYMTAB 00000000 007d3c 000670 10 25 66 4
[25] .strtab STRTAB 00000000 0083ac 000472 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Elf file type is EXEC (Executable file)
Entry point 0x30
There are 6 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000100 0x00000000 0x00000000 0x00b00 0x00b00 RWE 0x10
LOAD 0x000c00 0x00000b00 0x00000b00 0x00080 0x00080 R E 0x10
LOAD 0x000c80 0x00000b00 0x00000b80 0x00080 0x00080 R E 0x10
LOAD 0x000d00 0x00000b80 0x00000c00 0x00580 0x00590 RWE 0x10
LOAD 0x001270 0x00001180 0x00001200 0x00000 0x00010 RW 0x10
NOTE 0x007820 0x00000000 0x00000000 0x00020 0x00020 R 0x10
Section to Segment mapping:
Segment Sections...
00 .init .text
01 .segment1 .segment2
02 .segment1 .segment2
03 .fini .rodata .ctors .dtors .jcr .data .bss
04 .toe
05 .note.spu_name
------------------------------cut-here------------------------------
Notice that .segment1 and .segment2 are both at virtual address 0x00000b00, but their file offsets are different (0x000c00 and 0x000c80, respectively).
Loader symbols which are associated with a particular program segment are defined together in a single file section, and the file section header includes a "phoff" field, which, as we understand it, indicates
the offset within the executable file of the associated program segment. For example:
------------------------------cut-here------------------------------
% readelf -s spu_main | egrep Num\|_test
Num: Value Size Type Bind Vis Ndx Name
66: 00000b00 60 FUNC GLOBAL DEFAULT 3 o1_test1
70: 00000b40 60 FUNC GLOBAL DEFAULT 4 o2_test2
86: 00000b40 60 FUNC GLOBAL DEFAULT 3 o1_test2
92: 00000b00 60 FUNC GLOBAL DEFAULT 4 o2_test1
%
------------------------------cut-here------------------------------
We can take the section index (in the Ndx column), get the section file offset, and then lookup the program header. That makes it straightforward to determine the overlay to which a particular loader symbol belongs.
However, the DWARF information does not seem to contain any direct indication of the program segment to which a particular symbol belongs. Only the link address of the symbol is provided in the DWARF information, and when multiple segments are linked at the same address, that's ambiguous. That seems to make it impossible to determine which overlay a particular DWARF symbol belongs to. For example, here are some DWARF DIEs for the sample program functions o1_test1() and o2_test1(), both of which are at virtual address 0x00000b00:
------------------------------cut-here------------------------------
Compilation Unit @ offset 0x18d:
Length: 399
Version: 2
Abbrev Offset: 95
Pointer Size: 4
<0><198>: Abbrev Number: 1 (DW_TAG_compile_unit)
<199> DW_AT_stmt_list : 0x5c
<19d> DW_AT_high_pc : 0xb7c
<1a1> DW_AT_low_pc : 0xb00
<1a5> DW_AT_producer : GNU C 4.1.1
<1b1> DW_AT_language : 1 (ANSI C)
<1b2> DW_AT_name : test1.c
<1ba> DW_AT_comp_dir : /nfs/netapp0/user/home/slawrence/cell-sdk-copy2/prototype/src/samples/overlay/simple/spu_olay/olay1
...
<1><2c5>: Abbrev Number: 4 (DW_TAG_subprogram)
<2c6> DW_AT_sibling : <2f4>
<2ca> DW_AT_external : 1
<2cb> DW_AT_name : o1_test1
<2d4> DW_AT_decl_file : 1
<2d5> DW_AT_decl_line : 13
<2d6> DW_AT_prototyped : 1
<2d7> DW_AT_type : <23b>
<2db> DW_AT_low_pc : 0xb00
<2df> DW_AT_high_pc : 0xb3c
<2e3> DW_AT_frame_base : 0x20 (location list)
...
Compilation Unit @ offset 0x320:
Length: 399
Version: 2
Abbrev Offset: 200
Pointer Size: 4
<0><32b>: Abbrev Number: 1 (DW_TAG_compile_unit)
<32c> DW_AT_stmt_list : 0x9d
<330> DW_AT_high_pc : 0xb7c
<334> DW_AT_low_pc : 0xb00
<338> DW_AT_producer : GNU C 4.1.1
<344> DW_AT_language : 1 (ANSI C)
<345> DW_AT_name : test2.c
<34d> DW_AT_comp_dir : /nfs/netapp0/user/home/slawrence/cell-sdk-copy2/prototype/src/samples/overlay/simple/spu_olay/olay2
...
<1><458>: Abbrev Number: 4 (DW_TAG_subprogram)
<459> DW_AT_sibling : <487>
<45d> DW_AT_external : 1
<45e> DW_AT_name : o2_test1
<467> DW_AT_decl_file : 1
<468> DW_AT_decl_line : 13
<469> DW_AT_prototyped : 1
<46a> DW_AT_type : <3ce>
<46e> DW_AT_low_pc : 0xb00
<472> DW_AT_high_pc : 0xb3c
<476> DW_AT_frame_base : 0x5e (location list)
------------------------------cut-here------------------------------
The DWARF frame information has a similar problem:
------------------------------cut-here------------------------------
...
00000028 0000000c ffffffff CIE
Version: 1
Augmentation: ""
Code alignment factor: 1
Data alignment factor: -16
Return address column: 0
DW_CFA_def_cfa: r1 ofs 0
00000038 00000014 00000028 FDE cie=00000028 pc=00000b00..00000b3c
DW_CFA_advance_loc: 12 to 00000b0c
DW_CFA_def_cfa_offset: 48
DW_CFA_offset_extended_sf: r0 at cfa+16
DW_CFA_nop
DW_CFA_nop
00000050 00000014 00000028 FDE cie=00000028 pc=00000b40..00000b7c
DW_CFA_advance_loc: 12 to 00000b4c
DW_CFA_def_cfa_offset: 48
DW_CFA_offset_extended_sf: r0 at cfa+16
DW_CFA_nop
DW_CFA_nop
00000068 0000000c ffffffff CIE
Version: 1
Augmentation: ""
Code alignment factor: 1
Data alignment factor: -16
Return address column: 0
DW_CFA_def_cfa: r1 ofs 0
00000078 00000014 00000068 FDE cie=00000068 pc=00000b00..00000b3c
DW_CFA_advance_loc: 12 to 00000b0c
DW_CFA_def_cfa_offset: 48
DW_CFA_offset_extended_sf: r0 at cfa+16
DW_CFA_nop
DW_CFA_nop
00000090 00000014 00000068 FDE cie=00000068 pc=00000b40..00000b7c
DW_CFA_advance_loc: 12 to 00000b4c
DW_CFA_def_cfa_offset: 48
DW_CFA_offset_extended_sf: r0 at cfa+16
DW_CFA_nop
DW_CFA_nop
------------------------------cut-here------------------------------
Notice that the FDE pc ranges overlap
Without the connection between the DWARF symbol and the segment, it's difficult or impossible to manage breakpoints within and properly back trace out of code which is in an overlay. The reason for this is that we want to be able to take each link address in the executable file and relocate it into separate provisional address space. Each program object (subroutine, variable, etc.) lives at a unique location in the provisional address space, which allows a unique mapping between provisional addresses and symbols.
What we need is a way to map an address in a DWARF DIE or CIE/FDE to a particular section or program segment so that we can determine the proper provisional relocation value.
Does such a mapping exist?
Finally, as far as we can tell, breakpoint handling in overlaid SPU segments in ppu-gdb just flat out doesn't work:
------------------------------cut-here------------------------------
% ppu-gdb overlay_simple
GNU gdb 6.6.50.20070623-cvs
Copyright (C) 2007 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "powerpc64-linux"...
Using host libthread_db library "/lib64/libthread_db.so.1".
(gdb) set spu stop-on-load
(gdb) start
Breakpoint 1 at 0x180172c: file overlay_simple.c, line 23.
Starting program: /nfs/netapp0/user/home/slawrence/cell-sdk-copy2/prototype/src/samples/overlay/simple/overlay_simple
[Thread debugging using libthread_db enabled]
[New Thread 0xfff28a0 (LWP 22743)]
[Switching to Thread 0xfff28a0 (LWP 22743)]
main () at overlay_simple.c:23
23 unsigned int entry = SPE_DEFAULT_ENTRY;
(gdb) cont
Continuing.
Breakpoint 2 at 0x19c: file spu_main.c, line 33.
main (spuid=25296904, argp=0, envp=0) at spu_main.c:33
33 rc = o1_test1(101);
(gdb) b o2_test1
Breakpoint 3 at 0xb1c: file test2.c, line 14.
(gdb) b o2_test2
Breakpoint 4 at 0xb5c: file test2.c, line 20.
(gdb) cont
Continuing.
o1_test1 prints 101
o1_test2 prints 102
o2_test1 prints 201
o2_test2 prints 202
o1_test1 prints 301
o1_test2 prints 302
warning: Temporarily disabling breakpoints for unloaded shared library "spu_main at 0x1802000 <3>"
Program exited normally.
(gdb) start
Breakpoint 5 at 0x180172c: file overlay_simple.c, line 23.
Starting program: /nfs/netapp0/user/home/slawrence/cell-sdk-copy2/prototype/src/samples/overlay/simple/overlay_simple
Error in re-setting breakpoint 3:
Function "o2_test1" not defined.
Error in re-setting breakpoint 4:
Function "o2_test2" not defined.
Error in re-setting breakpoint 3:
Function "o2_test1" not defined.
Error in re-setting breakpoint 4:
Function "o2_test2" not defined.
Error in re-setting breakpoint 3:
Function "o2_test1" not defined.
Error in re-setting breakpoint 4:
Function "o2_test2" not defined.
Error in re-setting breakpoint 3:
Function "o2_test1" not defined.
Error in re-setting breakpoint 4:
Function "o2_test2" not defined.
[Thread debugging using libthread_db enabled]
[New Thread 0xfff28a0 (LWP 22840)]
Error in re-setting breakpoint 3:
Function "o2_test1" not defined.
Error in re-setting breakpoint 4:
Function "o2_test2" not defined.
Error in re-setting breakpoint 3:
Function "o2_test1" not defined.
Error in re-setting breakpoint 4:
Function "o2_test2" not defined.
Error in re-setting breakpoint 3:
Function "o2_test1" not defined.
Error in re-setting breakpoint 4:
Function "o2_test2" not defined.
[Switching to Thread 0xfff28a0 (LWP 22840)]
main () at overlay_simple.c:23
23 unsigned int entry = SPE_DEFAULT_ENTRY;
(gdb) cont
Continuing.
Breakpoint 6 at 0x19c: file spu_main.c, line 33.
main (spuid=25296904, argp=0, envp=0) at spu_main.c:33
33 rc = o1_test1(101);
(gdb) cont
Continuing.
o1_test1 prints 101
o1_test2 prints 102
o2_test1 prints 201
o2_test2 prints 202
o1_test1 prints 301
o1_test2 prints 302
warning: Temporarily disabling breakpoints for unloaded shared library "spu_main at 0x1802000 <3>"
Program exited normally.
(gdb)
------------------------------cut-here------------------------------
Notice that it didn't stop in o2_test1 or o2_test2, and it seems quite confused about when it should be plant breakpoint when the program is restarted.
Thanks much, and sorry for the long message!
Cheers, John D.
More information about the cbe-oss-dev
mailing list