GDB Debugging with JTAG on Ariane
#1
Hi,

I have problems using the JTAG debugging connection with GDB for the Ariane Softcore. The Genesys 2 Board is connected to my PC via JTAG. I have OpenOCD with RISC-V support  installed on my machine and it seems to connect just fine:

Code:
~/Desktop/ariane $ openocd -f fpga/ariane.cfg
Open On-Chip Debugger 0.10.0+dev-00828-gde00906eb (2019-11-25-14:04)
Licensed under GNU GPL v2
For bug reports, read
       http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : clock speed 1000 kHz
Info : JTAG tap: riscv.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)
Info : datacount=2 progbufsize=8
Info : Examined RISC-V core; found 1 harts
Info :  hart 0: XLEN=64, misa=0x800000000014112d
Info : Listening on port 3333 for gdb connections
Ready for Remote Connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : accepting 'gdb' connection on tcp/3333

This does look quite similar to the output in the Ariane git with the exception of this line:
Info : JTAG tap: riscv.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)

I don't know whether this causes the problem or not gdb seems to connect just fine.

Okay, now to the actual problem. If I connect gdb and load the binary (a simple hello world), the PC points to _start. Unfortunately, _start contains loads of unimp instructions and does not redirect the program flow to the main function. Thus, if I do a continue, nothing happens. Same goes for break main etc. as the main function is apparently never called. See the GDB output below:

Code:
Reading symbols from ./out...
(gdb) target extended-remote :3333
Remote debugging using :3333
0x000000000001071c in _vfprintf_r ()
(gdb) load
Loading section .text, size 0xbd2c lma 0x100b0
Loading section .rodata, size 0xd08 lma 0x1bde0
Loading section .eh_frame, size 0x4 lma 0x1dae8
Loading section .init_array, size 0x10 lma 0x1daf0
Loading section .fini_array, size 0x8 lma 0x1db00
Loading section .data, size 0x1100 lma 0x1db08
Loading section .sdata, size 0x58 lma 0x1ec08
Start address 0x100c6, load size 56232
Transfer rate: 47 KB/sec, 5623 bytes/write.
(gdb) where
#0  0x00000000000100c6 in _start ()
(gdb) x/5i $pc
=> 0x100c6 <_start>:    unimp
  0x100c8 <_start+2>:  unimp
  0x100ca <_start+4>:  unimp
  0x100cc <_start+6>:  unimp
  0x100ce <_start+8>:  unimp
(gdb) cont
Continuing.

Interestingly, if I disassemble the _start function in a local GDB Session, it looks like this: 
Code:
(gdb) disassemble _start
Dump of assembler code for function _start:
  0x00000000000100c6 <+0>:     auipc   gp,0xe
  0x00000000000100ca <+4>:     addi    gp,gp,1066 # 0x1e4f0 <__malloc_av_+248>
  0x00000000000100ce <+8>:     addi    a0,gp,1904
  0x00000000000100d2 <+12>:    auipc   a2,0xf
  0x00000000000100d6 <+16>:    addi    a2,a2,-994 # 0x1ecf0
  0x00000000000100da <+20>:    sub     a2,a2,a0
  0x00000000000100dc <+22>:    li      a1,0
  0x00000000000100de <+24>:    jal     ra,0x1020c <memset>
  0x00000000000100e2 <+28>:    auipc   a0,0x9
  0x00000000000100e6 <+32>:    addi    a0,a0,-1238 # 0x18c0c <atexit>
  0x00000000000100ea <+36>:    beqz    a0,0x100f8 <_start+50>
  0x00000000000100ec <+38>:    auipc   a0,0x2
  0x00000000000100f0 <+42>:    addi    a0,a0,1108 # 0x12540 <__libc_fini_array>
  0x00000000000100f4 <+46>:    jal     ra,0x18c0c <atexit>
  0x00000000000100f8 <+50>:    jal     ra,0x101a2 <__libc_init_array>
  0x00000000000100fc <+54>:    lw      a0,0(sp)
  0x00000000000100fe <+56>:    addi    a1,sp,8
  0x0000000000010100 <+58>:    li      a2,0
  0x0000000000010102 <+60>:    jal     ra,0x1015c <main>
  0x0000000000010106 <+64>:    j       0x10184 <exit>

Am I missing something here? Do I need an extra GDB command to load the _start funtion or does it have to be compiled in a specific way? I compiled the binary with riscv64-unknown-elf-gcc test.c -o out and also tried adding -ffreestanding.

Thank you!
- Jan
Reply
#2
You are loading your code into a physical address that is not writable. If you want to run bare-metal applications you should fix your binary to start at 0x8000000 or higher (DRAM range). The easiest way to do that is by providing a linker file (linker.lds) to the linker:
Code:
riscv64-unknown-elf-gcc main.c -Tlinker.lds -o main.o

The linker file could look like the file in fpga/src/bootrom/linker.lds:

Code:
ENTRY(main)

SECTIONS
{
   // I changed this to the DRAM start addr (0x80000000)
   ROM_BASE = 0x80000000; /* ... but actually position independent */

   . = ROM_BASE;

   .text.init : { *(.text.init) }

   .text : ALIGN(0x100) {
   _TEXT_START_ = .;
       *(.text)
   _TEXT_END_ = .;
   }

   .data : ALIGN(0x100) {
   _DATA_START_ = .;
       *(.data)
   _DATA_END_ = .;
   }

   PROVIDE(_data = ADDR(.data));
   PROVIDE(_data_lma = LOADADDR(.data));
   PROVIDE(_edata = .);

   .bss : ALIGN(0x100) {
   _BSS_START_ = .;
       *(.bss)
   _BSS_END_ = .;
   }

   .rodata : ALIGN(0x100) {
   _RODATA_START_ = .;
       *(.rodata)
       *(.dtb*)
       *(.rodata*)
   _RODATA_END_ = .;
   }
}
Reply
#3
Thank you for your quick reply! I tried adding a linker file which I had to modify a little

Code:
ENTRY(main)

SECTIONS
{
  ROM_BASE = 0x8000000; /* ... but actually position independent */

  . = ROM_BASE;

  .text.init : { *(.text.init) }

  .text : ALIGN(0x100) {
  _TEXT_START_ = .;
      *(.text)
  _TEXT_END_ = .;
  }

  PROVIDE( __global_pointer$ = . + (4K / 2) );    /* This is modified */
  .data : ALIGN(0x100) {
  _DATA_START_ = .;
      *(.data)
  _DATA_END_ = .;
  }


  PROVIDE(_data = ADDR(.data));
  PROVIDE(_data_lma = LOADADDR(.data));

  _edata = .;                                      /* This is modified */
  PROVIDE (edata = .);

  .bss : ALIGN(0x100) {
  _BSS_START_ = .;
      *(.bss)
  _BSS_END_ = .;
  }

  .rodata : ALIGN(0x100) {
  _RODATA_START_ = .;
      *(.rodata)
      *(.dtb*)
      *(.rodata*)
  _RODATA_END_ = .;
  }

  PROVIDE(_end = .);                             /* This is modified */
}

The lines annotated with /* This is modified */ indicate modifications from fpga/src/bootrom/linker.lds. GCC seems to require these sections (Otherwise compilation fails with undefined reference to _end / _edata / __global_pointer$). The compilation works with the linker file as posted above. Loading the binary in GDB unfortunately still doesn't work.


Code:
(gdb) load
Loading section .text, size 0xbea6 lma 0x8000000
Loading section .text.startup, size 0x18 lma 0x800bea6
Loading section .data, size 0x1100 lma 0x800bf00
Loading section .eh_frame, size 0x4 lma 0x800d000
Loading section .sdata, size 0x20 lma 0x800d008
Loading section .fini_array, size 0x8 lma 0x800d028
Loading section .init_array, size 0x8 lma 0x800d030
Loading section .init_array.00000, size 0x8 lma 0x800d038
Loading section .rodata, size 0xd10 lma 0x800d200
Loading section .srodata, size 0x8 lma 0x800df10
Loading section .srodata.cst8, size 0x30 lma 0x800df18
Start address 0x80000a6, load size 56642
Transfer rate: 40 KB/sec, 4045 bytes/write.
(gdb) disassemble main
Dump of assembler code for function main:
=> 0x00000000080000a6 <+0>:     beqz    a3,0x8000020 <_start+32>
  0x00000000080000a8 <+2>:     jal     t4,0x7fdb692
  0x00000000080000ac <+6>:     jal     t4,0x7fdb696
  0x00000000080000b0 <+10>:    jal     t4,0x7fdb69a
  0x00000000080000b4 <+14>:    jal     t4,0x7fdb69e
  0x00000000080000b8 <+18>:    jal     t4,0x7fdb6a2
  0x00000000080000bc <+22>:    jal     t4,0x7fdb6a6
  0x00000000080000c0 <+26>:    jal     t4,0x7fdb6aa
  0x00000000080000c4 <+30>:    jal     t4,0x7fdb6ae
  0x00000000080000c8 <+34>:    jal     t4,0x7fdb6b2
  0x00000000080000cc <+38>:    jal     t4,0x7fdb6b6
End of assembler dump.


It seems like the memory is still not writable in that area. Thus, I tried larger ROM_BASE offsets e.g. 800000000 which results in an error at compile time:

Code:
~/Desktop/jan/helloworld $ riscv64-unknown-elf-gcc -Tlinker.lds -ffreestanding test.c -o out
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/crtbegin.o: in function `__do_global_dtors_aux':
crtstuff.c:(.text+0x0): relocation truncated to fit: R_RISCV_HI20 against `completed.5527'
/tmp/ccgwp6EG.o: in function `main':
test.c:(.text+0x12): relocation truncated to fit: R_RISCV_HI20 against `.LC0'
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-exit.o): in function `exit':
exit.c:(.text+0xe): relocation truncated to fit: R_RISCV_HI20 against symbol `_global_impure_ptr' defined in .srodata section in /home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-impure.o)
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-printf.o): in function `_printf_r':
printf.c:(.text+0x22): relocation truncated to fit: R_RISCV_HI20 against symbol `_impure_ptr' defined in .sdata section in /home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-impure.o)
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-vfprintf.o): in function `.L3':
vfprintf.c:(.text+0xac): relocation truncated to fit: R_RISCV_HI20 against `.LC10'
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-wsetup.o): in function `__swsetup_r':
wsetup.c:(.text+0x0): relocation truncated to fit: R_RISCV_HI20 against symbol `_impure_ptr' defined in .sdata section in /home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-impure.o)
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-__call_atexit.o): in function `__call_exitprocs':
__call_atexit.c:(.text+0x2): relocation truncated to fit: R_RISCV_HI20 against symbol `_global_impure_ptr' defined in .srodata section in /home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-impure.o)
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-__call_atexit.o): in function `register_fini':
__call_atexit.c:(.text.startup+0xa): relocation truncated to fit: R_RISCV_HI20 against symbol `__libc_fini_array' defined in .text section in /home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-fini.o)
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-fflush.o): in function `.L60':
fflush.c:(.text+0x1d4): relocation truncated to fit: R_RISCV_HI20 against symbol `_impure_ptr' defined in .sdata section in /home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-impure.o)
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-findfp.o): in function `_cleanup_r':
findfp.c:(.text+0x4): relocation truncated to fit: R_RISCV_HI20 against symbol `_fclose_r' defined in .text section in /home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-fclose.o)
/home/pi/Desktop/compiler/lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-freer.o): in function `_malloc_trim_r':
mallocr.c:(.text+0x4): additional relocation overflows omitted from the output
collect2: error: ld returned 1 exit status

Do you have any idea what I am doing wrong?
Reply
#4
My bad. I forgot a 0 in the DRAM address. The base address should be 0x80000000 (that is one 8 followed by 3 + 4=7 zeroes)
Reply
#5
(11-27-2019, 01:32 PM)scmoritz Wrote: My bad. I forgot a 0 in the DRAM address. The base address should be 0x80000000 (that is one 8 followed by 3 + 4=7 zeroes)

Thanks alot, it is working now! Smile
Reply


Forum Jump: