[Lldb-commits] [PATCH] D62732: [RISCV] Add SystemV ABI

Jade via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Tue Apr 27 01:27:57 PDT 2021


jade added a comment.

In D62732#2707945 <https://reviews.llvm.org/D62732#2707945>, @jade wrote:

> In D62732#2306055 <https://reviews.llvm.org/D62732#2306055>, @labath wrote:
>
>> ABI plugins are one of the hardest things to test in lldb, particularly without actual hardware. That's why we've let them be added in the past without any accompanying tests. The situation is not ideal though, because we've accumulated various ABI plugins which are hard to change without breaking (or even to know if they work) because they only work with third-party (possibly proprietary) stubs.
>>
>> I'm not sure what's the state of risc-v hardware these days and how much resources do you have available, but if it's at all possible, I'd definitely recommend adding the lldb-server bits for risc-v and adding a builtbot for testing this configuration.
>>
>> Even if there's no hardware which could run the lldb test suite in a reasonable amount of time, the availability of an lldb-server implementation would enable anyone to test this via qemu -- that's the strategy we're pursuing for the ARM SVE stuff, and we're about to add instructions on how to run lldb+sve+qemu here: D82064 <https://reviews.llvm.org/D82064>.
>
> This is also testable with the gdbserver built into qemu, at least for kernel debugging. It seems to work, although for some reason, step-out is broken for me on a rust target (https://github.com/lf-/mu):
>
>   (lldb) fin
>   error: Could not create return address breakpoint.
>
> I have yet to debug this but I think I will do so when I get more time.

I have looked at this. On my bare metal target with the integrated qemu gdbserver, `bt`, in several instances, is thinking it is at level zero of the stack and thus can't find another frame to put a breakpoint at. I've made a simple bare metal project that hits this issue with the unwinder. You just need a qemu build with emulated architecture support enabled (package `qemu-arch-extra` in many distros) and a copy of clang/lld/lldb for this.

These files are also available as a gist, which can be grabbed with: `git clone https://gist.github.com/e2efac2f780ed820277dbaf608805f4e lldb-riscv-repro`

Makefile:

  QEMU = qemu-system-riscv64
  TARGETFLAGS = --target=riscv64-none-unknown-elf -march=rv64imac
  CFLAGS =  $(TARGETFLAGS) -mno-relax -fPIC -g
  QEMUOPTS = -machine virt -bios none -kernel kern -m 128M \
  		   			-nographic -s -S
  
  LINKFLAGS = $(TARGETFLAGS) -fuse-ld=lld -nostdlib -nodefaultlibs \
  			-Wl,-Tshoo.ld
  CC = clang
  
  kern: init.o start.o
  	$(CC) $(LINKFLAGS) $^ -o $@
  
  qemu: kern
  	$(QEMU) $(QEMUOPTS)
  %.o: %.s
  	$(CC) $(CFLAGS) -c $^
  
  .PHONY: clean qemu
  clean:
  	rm *.o kern

`shoo.ld`:

  OUTPUT_ARCH("riscv64")
  ENTRY(_entry)
  
  SECTIONS {
      /* VIRT_DRAM */
      . = 0x80000000;
  
      .text : {
          *(.text.first)
          *(.text .text.*)
          . = ALIGN(0x1000);
      }
  
      .rodata ALIGN(0x1000) : {
          . = ALIGN(16);
          PROVIDE(srodata = .);
          *(.srodata .srodata.*)
          . = ALIGN(16);
          *(.rodata .rodata.*)
          . = ALIGN(0x1000);
          PROVIDE(erodata = .);
      }
  
      .data ALIGN(0x1000) : {
          PROVIDE(srwdata = .);
          *(.sdata .sdata.*)
          . = ALIGN(16);
          *(.data .data.*)
      }
  
      .bss ALIGN(0x1000) : {
          . = ALIGN(16);
          *(.sbss .sbss.*)
          . = ALIGN(16);
          *(.bss .bss.*)
      }
  }

`init.s`:

  // kernel entry point
  // largely nicked from https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/entry.S
  .data
  .globl STACKS
  .text
  .section .text.first
  .globl start
  .globl _entry
  // _entry(mhartid: usize, dtb: *const u8)
  _entry:
      // we arrive here, in machine mode, once qemu jumps to the start of memory
  
      // set up a stack
      la sp, STACKS
      li t0, 16384     // use 16k stacks
  
      // we want to get the pointer to the top of the (descending) stack
      // thus we want 16k * (hartid + 1)
      addi t1, a0, 1
      mul t0, t0, t1
      add sp, sp, t0
  
      call startup
  spin:
      j spin // startup() will not return
  .text

`start.c`:

  char STACKS[4*4096];
  volatile int i1 = 0;
  volatile int i2 = 0;
  volatile int i3 = 0;
  
  void fn3(void) {
      i3 = 10;
  }
  
  void fn2(void) {
      i2 = 3;
      fn3();
  }
  
  void fn1(void) {
      fn2();
      fn2();
      i1 = 18;
  }
  
  void startup(void) {
      fn1();
      while (1) {}
  }

Reproduction:

  $ make qemu
  # (in a separate window)
  $ lldb -a riscv64
  (lldb) target create kern
  Current executable set to '/tmp/lldb-issue/kern' (riscv64).
  (lldb) gdb-remote 1234
  Process 1 stopped
  * thread #1, stop reason = signal SIGTRAP
      frame #0: 0x0000000000001000
  ->  0x1000: auipc  t0, 0
      0x1004: addi   a2, t0, 40
  (lldb) b fn3
  Breakpoint 1: where = kern`fn3 + 2 at start.c:7:8, address = 0x0000000080000022
  (lldb) c
  Process 1 resuming
  Process 1 stopped
  * thread #1, stop reason = breakpoint 1.1
      frame #0: 0x0000000080000022 kern`fn3 at start.c:7:8
     4   	volatile int i3 = 0;
     5   	
     6   	void fn3(void) {
  -> 7   	    i3 = 10;
     8   	}
     9   	
     10  	void fn2(void) {
  kern`fn3:
  ->  0x80000022 <+2>: sd     ra, 8(sp)
      0x80000024 <+4>: sd     s0, 0(sp)
  (lldb) bt
  * thread #1, stop reason = breakpoint 1.1
    * frame #0: 0x0000000080000022 kern`fn3 at start.c:7:8
  (lldb) fin
  error: Could not create return address breakpoint.

Expected result:

  (gdb) target remote :1234
  Remote debugging using :1234
  0x0000000000001000 in ?? ()
  => 0x0000000000001000:	97 02 00 00	auipc	t0,0x0
  (gdb) b fn3
  Breakpoint 1 at 0x80000022: file start.c, line 7.
  (gdb) c
  Continuing.
  
  Breakpoint 1, fn3 () at start.c:7
  7	    i3 = 10;
  (gdb) bt
  #0  fn3 () at start.c:7
  #1  0x0000000080000058 in fn2 () at start.c:12
  #2  0x0000000080000070 in fn1 () at start.c:16
  #3  0x000000008000009c in startup () at start.c:22
  #4  0x000000008000001c in _entry () at init.s:23
  Backtrace stopped: frame did not save the PC

Another thing I've noticed while testing this patch is that the ABI names for the registers are the only ones accessible via `reg read`: `reg read x1` does not work, for instance. `lldb` has an alternate register name mechanism in `RegisterInfo`, which is used for `arg1`, `arg2`, etc, on Arm, and probably some others. It would be useful to have this for the `xN` register names in riscv.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62732/new/

https://reviews.llvm.org/D62732



More information about the lldb-commits mailing list