Home GCC issue in handling GP register in RISC-V
Post
Cancel

GCC issue in handling GP register in RISC-V

RISC-V GCC在处理GP寄存器时的问题

背景

BareMetal下需要在start.S中初始化bss段,不然里面的数值不一定为0(所有未初始化或初始化为0的全局变量会在bbs段中)

start.S

1
2
3
4
5
6
7
# zero-out bss
  la t0, _bss_start
  la t1, _bss_end
_bss_zero:
  SREG zero, (t0)
  add t0, t0, REGBYTES
  blt t0, t1, _bss_zero

link.ldS

1
2
3
4
5
6
7
8
9
10
# bss segment
  _bss_start = .;
  .sbss : {
    *(.sbss .sbss.* .gnu.linkonce.sb.*)
    *(.scommon)
  }
  .bss : {
    *(.bss)
  }
  _bss_end = .;

踩坑

1
2
  la t0, _bss_start  # 0x12c, 0x130 使用pc相对位置得到_bss_start
  la t1, _bss_end # 0x134 使用gp相对位置得到_bss_end

解决

start.S代码片段如下,可能此处有一个编译器的bug,如果gpt1之后加载,而0x134行中的t1相对gp的偏移-1944是从ldS脚本中的__global_pointer$计算得到的,那么t1就会加载到错误的地址(此时gp中的值并非__global_pointer$)。

BSS初始化放到gp初始化后面就一切正常,具体原因还要仔细再追。

1
2
3
4
5
6
7
8
9
10
11
12
13
# zero-out bss
  la t0, _bss_start
  la t1, _bss_end
_bss_zero:
  SREG zero, (t0)
  add t0, t0, REGBYTES
  blt t0, t1, _bss_zero

# initialize global pointer
.option push
.option norelax
  la gp, __global_pointer$
.option pop
This post is licensed under CC BY 4.0 by the author.

Debugging the linux kernel using thread-aware of gdb

Solution to local login busybox dropbear