解决《CPU设计实战》第四章实践交叉编译时报错mipsel-linux-ld: section .MIPS.abiflags LMA overlaps section .data LMA

最近在跟着《CPU设计实战》这本书学习MIPS指令集CPU的设计,在进行到4.3.1节快速上手CPU设计的开发环境的第4步,编译测试程序时,遇到了一个报错,网上也没找到方法,故记录一下自己的解决方法。

书上这一步的要求是:将一个有预先写好程序的func目录(此书的资源里已经提供)设置为一个已经安装了MIPS-GCC交叉编译工具的Linux虚拟机的共享目录,然后在虚拟机中进入soft/func目录,先运行make clean,再运行make进行编译。我采用的是openEuler20.03系统照着https://blog.csdn.net/alfiy/article/details/121653881https://blog.csdn.net/alfiy/article/details/121653881 这篇文章所描述的方法装了buildroot。但是如果用的是其他操作系统或其他编译工具,或者在进行其他项目时,如果遇到类似的问题,应该也能通过以下方式解决。

这是运行make时遇到的报错内容,部分无关的省略掉了:

[openeuler@test func]$ make
make compile
(--------------中间部分内容省略-----------------)
make[2]: Leaving directory '/mnt/hgfs/func/inst'
mipsel-linux-gcc -E -P -Umips -D_LOADER -U_MAIN -D_KERNEL -fno-builtin -mips1 -DMEMSTART=0x80000000 -DMEMSIZE=0x04000 -DCPU_COUNT_PER_US=1000 -I /mnt/hgfs/func/include  -fno-reorder-blocks -fno-reorder-functions -EL bin.lds.S -o bin.lds
mipsel-linux-ld -g -EL -T bin.lds  -o main.elf start.o -L . -linst
mipsel-linux-ld: section .MIPS.abiflags LMA [00000000bfcb0c48,00000000bfcb0c5f] overlaps section .data LMA [00000000bfcb0c48,00000000bfcb0c57]
make[1]: *** [Makefile:33: main.elf] Error 1
make[1]: Leaving directory '/mnt/hgfs/func'
make: *** [Makefile:13: all] Error 2
[openeuler@test func]$

执行mipsel-linux-ld -g -EL -T bin.lds  -o main.elf start.o -L . -linst这句时报section重叠。网上搜索了一圈发现,问题应该是这本书提供的源代码里没有给.data和.MIPS.abiflags的内容分配空间或是分配的不合理,导致了内容过多时存储会有重叠,导致报错。参考了另一篇有类似报错的文章,https://blog.csdn.net/weixin_39871788/article/details/78858791,尝试了以下方法,问题解决。

在文件夹中找到bin.lds文件(做完后发现改动bin.lds.S也可以,但是最后一步的操作有所不同)。因为这个文件夹是虚拟机和主机的共享文件夹,所以在主机上打开修改就行。

如果是在其他地方或项目里出现了这种问题,就去找项目里的以.ld或者.lds为后缀的文件打开修改。.ld文件里面的格式和不同语句分别代表什么意思网上都有,而且很详细。这里就不多介绍。

用任意文本编辑器打开后在第二行和第三行之间插入如下内容,给不同的内容分配不同的空间。如果已经存在MEMORY模块,就往里面加语句(也就是定义新空间)或者数字改大。

MEMORY
{
  RAM (xrw) : ORIGIN = 0x68000000, LENGTH = 1024K
  FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
}

加上上面的语句后就可以使用定义的空间了。在.data的大括号后面加上 >RAM,表示这块内容使用刚才的分配空间。

  .data : AT(rodata_end)
  {
    (中间部分省略,完整的代码会贴在后面)
} >RAM

这个报错是因为.MIPS.abiflags存在冲突,于是就在文件中另找一个地方插入如下几行,表示给.MIPS.abiflags使用刚才分配的另一个空间,避免冲突。在哪个位置插入似乎影响不大,我是插入到了.bss块的大括号后面的一行。如果是其他文件或项目的问题,对照插入或者找到相应的地方修改即可。

  .MIPS.abiflags : {
  . = ALIGN(4);
  *(.MIPS.abiflags*)
  . = ALIGN(4);
  } >FLASH

改好后完整的bin.lds文件如下:

OUTPUT_ARCH(mips)
ENTRY(_start)
MEMORY
{
  RAM (xrw) : ORIGIN = 0x68000000, LENGTH = 1024K
  FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
}
SECTIONS
{
  . = 0xbfc00000;
  .text :
  {
    _ftext = . ;
    *(.text)
    *(.rodata*)
    *(.reginfo)
    *(.init)
    *(.stub)
    *(.gnu.warning)
    rodata_end = .;
  } =0
  _etext = .;
  PROVIDE (etext = .);
  .fini : { *(.fini) } =0
  . = 0x80000000;
  .data : AT(rodata_end)
  {
    _fdata = . ;
    _stack = _fdata + 0x04000 -32;
    *(.data)
    *(.data*)
                __CTOR_LIST__ = .;
                LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
               *(.ctors)
                LONG(0)
                __CTOR_END__ = .;
                __DTOR_LIST__ = .;
                LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
               *(.dtors)
                LONG(0)
                __DTOR_END__ = .;
  _gp = ALIGN(16) + 0x7ff0;
    *(.got.plt) *(.got)
  *(.sdata)
   *(.lit8)
   *(.lit4)
} >RAM
  _edata = .;
  PROVIDE (edata = .);
  data_size = SIZEOF(.data);
  data_load_start = LOADADDR(.data);
  __bss_start = .;
  _fbss = .;
  .sbss : { *(.sbss) *(.scommon) }
  .bss :
  {
   *(.dynbss)
   *(.bss)
   *(COMMON)
  }
  .MIPS.abiflags : {
  . = ALIGN(4);
  *(.MIPS.abiflags*)
  . = ALIGN(4);
  } >FLASH
  . = ALIGN(8);
  _end = . ;
  PROVIDE (end = .);
   . = ALIGN(32);
  .bigdata : { *(.bigdata) }
   . = ALIGN(256);
  _heap = . ;
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .debug 0 : { *(.debug) }
  .debug_srcinfo 0 : { *(.debug_srcinfo) }
  .debug_aranges 0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  .debug_sfnames 0 : { *(.debug_sfnames) }
  .line 0 : { *(.line) }
  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
}

将改好的文件保存好即可。如果你是在bin.lds文件里改动的,则需要再打开相同目录下的Makefile文件,找到下面这一段,把其中第一行注释掉,避免重新编译时刚才所做的改动被覆盖。如果上面的内容是在bin.lds.S文件中改动,则可忽略这一步。

main.elf: start.o libinst.a 
    #把下面这行注释掉,避免重新编译时刚才所做的改动被覆盖
	#${CROSS_COMPILE}gcc -E -P -Umips -D_LOADER -U_MAIN $(CFLAGS) bin.lds.S -o bin.lds
	${CROSS_COMPILE}ld -g -EL -T bin.lds  -o $@ start.o -L . -linst
	${CROSS_COMPILE}objdump -alD $@ > test.s

改动完成,再次在Linux上重新运行make clean和make命令(如果是在bin.lds.S里做的改动,就运行make reset),成功编译。如果是其他工程或项目中报错,那就按照对应项目中的说明重新运行。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值