riscv elf文件中插入section

对于一个elf文件,我们可以通过readelf命令,搭配-S选项,查看该elf的section。

一、源代码

比如对应如下的汇编文件,文件中定义了两个section。

.text
.global _start
_start:
lb x5, 0(sp)
lb x6, 0(sp)
lb x7, 0(sp)
lb x8, 0(sp)
lb x9, 0(sp)
lb x10, 0(sp)
lb x11, 0(sp)
 
.data
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555
.word 0x55555555

链接脚本

OUTPUT_ARCH("riscv")
ENTRY(_start)
SECTIONS
{
. = 0x80000000;
.text :
{
*(.text)
}
. = 0x90000000;
.data :
{
*(.data)
}
}

链接脚本

编译的命令:

riscv-nuclei-elf-gcc a.S -Ta.lds  -nostdlib -nostartfiles -o a.elf

对于得到的elf的文件,使用readelf -S 查看section信息,得到以下信息。

There are 7 section headers, starting at offset 0x20f8:

Section Headers:

[Nr] Name    Type            Addr     Off    Size   ES Flg Lk Inf Al

[ 0]          NULL            00000000 000000 000000 00      0   0  0

[ 1] .text      PROGBITS        80000000 001000 00001c 00  AX  0   0  2

[ 2] .data     PROGBITS         90000000 002000 000030 00  WA  0   0  1

[ 3] .riscv.attributes LOPROC+0x3  00000000 002030 000033 00      0   0  1

[ 4] .symtab     SYMTAB        00000000 002064 000050 10      5   4  4

[ 5] .strtab      STRTAB         00000000 0020b4 000008 00      0   0  1

[ 6] .shstrtab    STRTAB         00000000 0020bc 000039 00      0   0  1

Key to Flags:

W (write), A (alloc), X (execute), M (merge), S (strings), I (info),

L (link order), O (extra OS processing required), G (group), T (TLS),

C (compressed), x (unknown), o (OS specific), E (exclude),

p (processor specific)

通过readelf -l查看segment信息,得到如下:

Elf file type is EXEC (Executable file)

Entry point 0x80000000

There are 2 program headers, starting at offset 52

 

Program Headers:

Type    Offset   VirtAddr   PhysAddr   FileSiz   MemSiz  Flg  Align

LOAD   0x001000 0x80000000 0x80000000 0x0001c 0x0001c R E  0x1000

LOAD   0x002000 0x90000000 0x90000000 0x00030 0x00030 RW  0x1000

 

Section to Segment mapping:

Segment Sections...

00     .text

01     .data

现在我想往elf文件中,插入两个section,分别是:

  • text_1:该section内容和.text section内容一致

  • data_1:该section内容和.data section内容一致

     

此时,就要用到objcopy工具,对于gcc工具链,都会有一个objcopy工具。该工具,可以拷贝或者修改一个目标文件的内容到另一个目标文件中。

关于该工具的介绍,可以参考手册:

https://sourceware.org/binutils/docs/binutils/objcopy.html

 

此时,我们要用到该工具的如下选项:

  • --add-section:增加一个section

  • --set-section-flags:修改section的属性标志

  • --set-section-vma:修改section的vma

  • --change-section-lma:修改section的lma

     

二、--add-section

官方解释:

--add-section sectionname=filename

Add a new section named sectionname while copying the file. The contents of the new section are taken from the file filename. The size of the section will be the size of the file. This option only works on file formats which can support sections with arbitrary names. Note - it may be necessary to use the --set-section-flags option to set the attributes of the newly created section.

向elf文件中,增加一个section,sectionname指定加入section的名字,filename,指定该section内容的文件

 

三、--set-section-flags

官方解释:

--set-section-flags sectionpattern=flags

Set the flags for any sections matching sectionpattern. The flags argument is a comma separated string of flag names. The recognized names are 'alloc', 'contents', 'load', 'noload', 'readonly', 'code', 'data', 'rom', 'share', and 'debug'. You can set the 'contents' flag for a section which does not have contents, but it is not meaningful to clear the 'contents' flag of a section which does have contents–just remove the section instead. Not all flags are meaningful for all object file formats.

设置section的属性标志,sectionpattern是section名字的模式匹配,flags是属性标志,可以设置多个属性标志,之间使用逗号分隔。

四、--change-section-vma

官方解释:

--adjust-section-vma sectionpattern{=,+,-}val

Set or change both the VMA address and the LMA address of any section matching sectionpattern. If '=' is used, the section address is set to val. Otherwise, val is added to or subtracted from the section address. See the comments under --change-addresses, above. If sectionpattern does not match any sections in the input file, a warning will be issued, unless --no-change-warnings is used.

更改一个section的vma,可以设置vma绝对值,也可以修改偏移。

五、--change-section-lma

官方解释

--change-section-lma sectionpattern{=,+,-}val

Set or change the LMA address of any sections matching sectionpattern. The LMA address is the address where the section will be loaded into memory at program load time. Normally this is the same as the VMA address, which is the address of the section at program run time, but on some systems, especially those where a program is held in ROM, the two can be different. If '=' is used, the section address is set to val. Otherwise, val is added to or subtracted from the section address. See the comments under --change-addresses, above. If sectionpattern does not match any sections in the input file, a warning will be issued, unless --no-change-warnings is used.

更改一个section的lma,可以设置lma绝对值,也可以修改偏移。

六、elf中增加section

首先,我们先提取源elf文件,.text段和.data段的内容,得到bin文件。

使用objcopy的-j选项,可以从elf文件中,提取指定section的内容。

riscv-nuclei-elf-objcopy -O binary -j .text  a.elf text.bin
riscv-nuclei-elf-objcopy -O binary -j .data  a.elf data.bin

然后使用objcopy命令,将提取得到的bin文件,给加入到elf文件中。 

riscv-nuclei-elf-objcopy -O elf32-littleriscv --add-section text_1=text.bin --set-section-flags text_1=alloc,code --change-section-vma text_1=0xa0000000 --change-section-lma text_1=0xb0000000  --add-section data_1=data.bin --set-section-flags data_1=alloc,data --change-section-vma data_1=0xb0000000 --change-section-lma data_1=0xc0000000 a.elf b.elf

执行,会得到如下warning

riscv-nuclei-elf-objcopy: b.elf: warning: allocated section `data_1' not in segment

riscv-nuclei-elf-objcopy: b.elf: warning: allocated section `text_1' not in segment

提示,新增加的section data_1和text_1,并没有加入到segment中。

此时,我们使用readelf -S,查看b.elf的section内容:

There are 9 section headers, starting at offset 0x40dc:

Section Headers:

[Nr] Name        Type            Addr     Off    Size   ES Flg Lk Inf Al

[ 0]             NULL            00000000 000000 000000 00      0   0  0

[ 1] .text         PROGBITS        80000000 001000 00001c 00  AX  0   0  2

[ 2] .data        PROGBITS        90000000 002000 000030 00  WA  0   0  1

[ 3] .riscv.attributes LOPROC+0x3      00000000 002030 000033 00      0   0  1

[ 4] data_1        PROGBITS        b0000000 003000 000030 00  WA  0   0  1

[ 5] text_1        PROGBITS        a0000000 004000 00001c 00 WAX  0   0  1

[ 6] .symtab      SYMTAB          00000000 00401c 000070 10      7   6  4

[ 7] .strtab        STRTAB          00000000 00408c 000008 00      0   0  1

[ 8] .shstrtab      STRTAB          00000000 004094 000047 00      0   0  1

Key to Flags:

W (write), A (alloc), X (execute), M (merge), S (strings), I (info),

L (link order), O (extra OS processing required), G (group), T (TLS),

C (compressed), x (unknown), o (OS specific), E (exclude),

p (processor specific)

发现section加入到elf文件中了。

此时再查看segement。得到如下信息。

Elf file type is EXEC (Executable file)

Entry point 0x80000000

There are 2 program headers, starting at offset 52

 

Program Headers:

Type    Offset   VirtAddr   PhysAddr   FileSiz   MemSiz  Flg  Align

LOAD   0x001000 0x80000000 0x80000000 0x0001c 0x0001c R E  0x1000

LOAD   0x002000 0x90000000 0x90000000 0x00030 0x00030 RW  0x1000

 

Section to Segment mapping:

Segment Sections...

00     .text

01     .data

可以看出,新增加的section,并没有加入到segment中。

使用-add-section的方式,可以给elf增加section,但是该section,不能自动加入到segment中。这个是objcopy工具的局限。

此条目发表在RISCV分类目录,贴了标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。