将 rodata 与创建它的函数放在一起
Keep rodata located with the function that created it
我试图让 .rodata 部分位置与其关联的函数内存位置保持一致。我正在使用 GNU compiler/linker、裸机、纯简 c 和 STM32L4A6 微控制器。
我有一个使用 STM32L4A6 控制器和 1Meg 闪存的定制板,分为 512 - 2K 页。每个页面都可以通过 RAM 中的函数 运行 单独擦除和编程。我想利用这个细粒度的闪存组织来创建一个嵌入式固件应用程序,可以通过修改或添加代码中的单个功能来即时更新。我的方案是为可能需要更改或创建的每个功能专门提供一个单独的闪存页面。它非常浪费闪光灯,但我永远不会使用超过 10% 的闪光灯,所以我可以承受浪费。我在这方面取得了一些进展,现在可以通过上传非常小的二进制代码对我的应用程序的操作进行重大更改。这些 "Patches" 通常甚至不需要重新启动系统。
我遇到的问题是,当函数包含任何类型的常量数据(例如文字字符串)时,它会在 .rodata 部分结束。我需要给定函数的 rodata 与创建它的函数位于同一区域。有谁知道我如何能够强制在函数中创建的 .rodata 保持附加到闪存中的相同函数?就像那个函数中的 .rodata 可以紧跟在函数本身之后?也许我需要使用 -ffunction-sections 或类似的东西?我已经阅读了各种链接器手册,但仍然不知道如何执行此操作。下面是我的链接描述文件的开始。我不知道如何在各个页面部分中包含函数 .rodata。
示例函数:
#define P018 __attribute__((long_call, section(".txt018")))
P018 int Function18(int A, int B){int C = A*B; return C;}
下面是一个更好的例子来说明我的问题:
#define P152 __attribute__((long_call, section(".txt152")))
P152 void TestFunc(int A){printf("%d Squared Is: %d\r\n",A,A*A);}
在这种情况下,可以在 .rodata 中找到“%d Squared Is: %d\r\n”的二进制等效项以及我程序中的所有其他文字字符串。我希望它位于 .txt152 部分。
链接器脚本片段(主要由简单的控制台程序生成。)
MEMORY
{
p000 (rx) : ORIGIN = 0x08000000, LENGTH = 0x8000
p016 (rx) : ORIGIN = 0x08008000, LENGTH = 0x800
p017 (rx) : ORIGIN = 0x08008800, LENGTH = 0x800
p018 (rx) : ORIGIN = 0x08009000, LENGTH = 0x800
.
.
.
p509 (rx) : ORIGIN = 0x080fe800, LENGTH = 0x800
p510 (rx) : ORIGIN = 0x080ff000, LENGTH = 0x800
p511 (rx) : ORIGIN = 0x080ff800, LENGTH = 0x800
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
ram2 (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
SECTIONS
{
.vectors :
{
KEEP(*(.isr_vector .isr_vector.*))
} > p000
.txt016 : { *(.txt016) } > p016 /* first usable 2k page following 32k p000 */
.txt017 : { *(.txt017) } > p017
.txt018 : { *(.txt018) } > p018
.
.
.
.txt509 : { *(.txt509) } > p509
.txt510 : { *(.txt510) } > p510
.txt511 : { *(.txt511) } > p511
.text :
{
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
} > p000
.
.
.
如果有人感兴趣,这是我执行 erase/program 操作的 RAM 代码
__attribute__((long_call, section(".data")))
void CopyPatch
(
unsigned short Page,
unsigned int NumberOfBytesToFlash,
unsigned char *PatchBuf
)
{
unsigned int i;
unsigned long long int *Flash;
__ASM volatile ("cpsid i" : : : "memory"); //disable interrupts
Flash = (unsigned long long int *)(FLASH_BASE + Page*2048); //set flash memory pointer to Page address
GPIOE->BSRR = GPIO_BSRR_BS_1; //make PE1(LED) high
FLASH->KEYR = 0x45670123; //unlock the flash
FLASH->KEYR = 0xCDEF89AB; //unlock the flash
while(FLASH->SR & FLASH_SR_BSY){} //wait while flash memory operation is in progress
FLASH->CR = FLASH_CR_PER | (Page << 3); //set Page erase bit and the Page to erase
FLASH->CR |= FLASH_CR_STRT; //start erase of Page
while(FLASH->SR & FLASH_SR_BSY){} //wait while Flash memory operation is in progress
FLASH->CR = FLASH_CR_PG; //set flash programming bit
for(i=0;i<(NumberOfBytesToFlash/8+1);i++)
{
Flash[i] = ((unsigned long long int *)PatchBuf)[i]; //copy RAM to FLASH, 8 bytes at a time
while(FLASH->SR & FLASH_SR_BSY){} //wait while flash memory operation is in progress
}
FLASH->CR = FLASH_CR_LOCK; //lock the flash
GPIOE->BSRR = GPIO_BSRR_BR_1; //make PE1(LED) low
__ASM volatile ("cpsie i" : : : "memory"); //enable interrupts
}
好的...抱歉耽搁了,但我不得不考虑一下...
我不确定您是否可以单独使用链接描述文件 [完全] 完成此操作。它 可能 是可能的,但我认为有一个 easier/surer 方法 [需要一些额外的准备]
我之前用过的一个方法是用-S
编译得到一个.s
文件。 Change/mangle那个。然后,编译修改后的 .s
请注意,您可能会遇到一些全局问题,例如:
int B;
这将转到 asm 源代码中的 .comm
部分。这可能并不理想。
对于初始化数据:
int B = 23;
您可能想要添加一个部分属性以将其强制到一个特殊部分。否则,它将在 .data
部分结束
因此,我可能会避免使用 .comm
and/or .bss
部分,而 always 使用初始化数据。那是因为 .comm
与 .rodata
有相同的问题(即它最终变成一个大斑点)。
总之,下面是一个循序渐进的过程。
我将节名宏放在一个普通文件中(例如)sctname.h
:
#define _SCTJOIN(_pre,_sct) _pre #_sct
#define _TXTSCT(_sct) __attribute__((section(_SCTJOIN(".txt",_sct))))
#define _DATSCT(_sct) __attribute__((section(_SCTJOIN(".dat",_sct))))
#ifdef SCTNO
#define TXTSCT _TXTSCT(SCTNO)
#define DATSCT _DATSCT(SCTNO)
#endif
这里是您的 .c
文件的略微修改版本(例如 module.c
):
#include <stdio.h>
#ifndef SCTNO
#define SCTNO 152
#endif
#include "sctname.h"
int B DATSCT = 23;
TXTSCT void
TestFunc(int A)
{
printf("%d Squared Is: %d\r\n", A, A * A * B);
}
要创建 .s
文件,我们执行以下操作:
cc -S -Wall -Werror -O2 module.c
实际段name/number可以在命令行指定:
cc -S -Wall -Werror -O2 -DSCTNO=152 module.c
这给了我们 module.s
:
.file "module.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d Squared Is: %d\r\n"
.section .txt152,"ax",@progbits
.p2align 4,,15
.globl TestFunc
.type TestFunc, @function
TestFunc:
.LFB11:
.cfi_startproc
movl %edi, %edx
movl %edi, %esi
xorl %eax, %eax
imull %edi, %edx
movl $.LC0, %edi
imull B(%rip), %edx
jmp printf
.cfi_endproc
.LFE11:
.size TestFunc, .-TestFunc
.globl B
.section .dat152,"aw"
.align 4
.type B, @object
.size B, 4
B:
.long 23
.ident "GCC: (GNU) 8.3.1 20190223 (Red Hat 8.3.1-2)"
.section .note.GNU-stack,"",@progbits
现在,我们必须读入 .s
并修改它。我已经创建了一个执行此操作的 perl 脚本(例如 rofix
):
#!/usr/bin/perl
master(@ARGV);
exit(0);
sub master
{
my(@argv) = @_;
$root = shift(@argv);
$root =~ s/[.][^.]+$//;
$sfile = "$root.s";
$ofile = "$root.TMP";
open($xfsrc,"<$sfile") or
die("rofix: unable to open '$sfile' -- $!\n");
open($xfdst,">$ofile") or
die("rofix: unable to open '$sfile' -- $!\n");
$txtpre = "^[.]txt";
$datpre = "^[.]dat";
# find the text and data sections
seek($xfsrc,0,0);
while ($bf = <$xfsrc>) {
chomp($bf);
if ($bf =~ /^\s*[.]section\s(\S+)/) {
$sctcur = ;
sctget($txtpre);
sctget($datpre);
}
}
# modify the data sections
seek($xfsrc,0,0);
while ($bf = <$xfsrc>) {
chomp($bf);
if ($bf =~ /^\s*[.]section\s(\S+)/) {
$sctcur = ;
sctfix();
print($xfdst $bf,"\n");
next;
}
print($xfdst $bf,"\n");
}
close($xfsrc);
close($xfdst);
system("diff -u $sfile $ofile");
rename($ofile,$sfile) or
die("rofix: unable to rename '$ofile' to '$sfile' -- $!\n");
}
sub sctget
{
my($pre) = @_;
my($sctname,@sct);
{
last unless (defined($pre));
@sct = split(",",$sctcur);
$sctname = shift(@sct);
last unless ($sctname =~ /$pre/);
printf("sctget: FOUND %s\n",$sctname);
$sct_lookup{$pre} = $sctname;
}
}
sub sctfix
{
my($sctname,@sct);
my($sctnew);
{
last unless ($sctcur =~ /^[.]rodata/);
$sctnew = $sct_lookup{$txtpre};
last unless (defined($sctnew));
@sct = split(",",$sctcur);
$sctname = shift(@sct);
$sctname .= $sctnew;
unshift(@sct,$sctname);
$sctname = join(",",@sct);
$bf = sprintf("\t.section\t%s",$sctname);
}
}
新旧module.s
的区别是:
sctget: FOUND .txt152
sctget: FOUND .dat152
--- module.s 2020-04-20 19:02:23.777302484 -0400
+++ module.TMP 2020-04-20 19:06:33.631926065 -0400
@@ -1,6 +1,6 @@
.file "module.c"
.text
- .section .rodata.str1.1,"aMS",@progbits,1
+ .section .rodata.txt152,"aMS",@progbits,1
.LC0:
.string "%d Squared Is: %d\r\n"
.section .txt152,"ax",@progbits
所以,现在,创建 .o
具有:
cc -c module.s
对于 makefile,它可能类似于[带有一些通配符]:
module.o: module.c
cc -S -Wall -Werror -O2 module.c
./rofix module.s
cc -c module.s
现在,您可以在链接描述文件中为 [您的原始部分] .txt152
和新的 .rodata.txt152
.
添加适当的位置
并且,初始化数据部分.dat152
请注意,实际的命名约定是任意的。如果要更改它们,只需适当修改 rofix
[和链接描述文件]
这是 module.o
的 readelf -a
输出:
请注意,还有一个 .rela.txt152
部分!?!?
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 808 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 15
Section header string table index: 14
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
0000000000000000 0000000000000000 AX 0 0 1
[ 2] .data PROGBITS 0000000000000000 00000040
0000000000000000 0000000000000000 WA 0 0 1
[ 3] .bss NOBITS 0000000000000000 00000040
0000000000000000 0000000000000000 WA 0 0 1
[ 4] .rodata.txt152 PROGBITS 0000000000000000 00000040
0000000000000014 0000000000000001 AMS 0 0 1
[ 5] .txt152 PROGBITS 0000000000000000 00000060
000000000000001a 0000000000000000 AX 0 0 16
[ 6] .rela.txt152 RELA 0000000000000000 00000250
0000000000000048 0000000000000018 I 12 5 8
[ 7] .dat152 PROGBITS 0000000000000000 0000007c
0000000000000004 0000000000000000 WA 0 0 4
[ 8] .comment PROGBITS 0000000000000000 00000080
000000000000002d 0000000000000001 MS 0 0 1
[ 9] .note.GNU-stack PROGBITS 0000000000000000 000000ad
0000000000000000 0000000000000000 0 0 1
[10] .eh_frame PROGBITS 0000000000000000 000000b0
0000000000000030 0000000000000000 A 0 0 8
[11] .rela.eh_frame RELA 0000000000000000 00000298
0000000000000018 0000000000000018 I 12 10 8
[12] .symtab SYMTAB 0000000000000000 000000e0
0000000000000150 0000000000000018 13 11 8
[13] .strtab STRTAB 0000000000000000 00000230
000000000000001c 0000000000000000 0 0 1
[14] .shstrtab STRTAB 0000000000000000 000002b0
0000000000000078 0000000000000000 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),
l (large), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
There is no dynamic section in this file.
Relocation section '.rela.txt152' at offset 0x250 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
00000000000a 00050000000a R_X86_64_32 0000000000000000 .rodata.txt152 + 0
000000000011 000c00000002 R_X86_64_PC32 0000000000000000 B - 4
000000000016 000d00000004 R_X86_64_PLT32 0000000000000000 printf - 4
Relocation section '.rela.eh_frame' at offset 0x298 contains 1 entry:
Offset Info Type Sym. Value Sym. Name + Addend
000000000020 000600000002 R_X86_64_PC32 0000000000000000 .txt152 + 0
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Symbol table '.symtab' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS module.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 4
6: 0000000000000000 0 SECTION LOCAL DEFAULT 5
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 9
9: 0000000000000000 0 SECTION LOCAL DEFAULT 10
10: 0000000000000000 0 SECTION LOCAL DEFAULT 8
11: 0000000000000000 26 FUNC GLOBAL DEFAULT 5 TestFunc
12: 0000000000000000 4 OBJECT GLOBAL DEFAULT 7 B
13: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf
No version information found in this file.
我试图让 .rodata 部分位置与其关联的函数内存位置保持一致。我正在使用 GNU compiler/linker、裸机、纯简 c 和 STM32L4A6 微控制器。
我有一个使用 STM32L4A6 控制器和 1Meg 闪存的定制板,分为 512 - 2K 页。每个页面都可以通过 RAM 中的函数 运行 单独擦除和编程。我想利用这个细粒度的闪存组织来创建一个嵌入式固件应用程序,可以通过修改或添加代码中的单个功能来即时更新。我的方案是为可能需要更改或创建的每个功能专门提供一个单独的闪存页面。它非常浪费闪光灯,但我永远不会使用超过 10% 的闪光灯,所以我可以承受浪费。我在这方面取得了一些进展,现在可以通过上传非常小的二进制代码对我的应用程序的操作进行重大更改。这些 "Patches" 通常甚至不需要重新启动系统。
我遇到的问题是,当函数包含任何类型的常量数据(例如文字字符串)时,它会在 .rodata 部分结束。我需要给定函数的 rodata 与创建它的函数位于同一区域。有谁知道我如何能够强制在函数中创建的 .rodata 保持附加到闪存中的相同函数?就像那个函数中的 .rodata 可以紧跟在函数本身之后?也许我需要使用 -ffunction-sections 或类似的东西?我已经阅读了各种链接器手册,但仍然不知道如何执行此操作。下面是我的链接描述文件的开始。我不知道如何在各个页面部分中包含函数 .rodata。
示例函数:
#define P018 __attribute__((long_call, section(".txt018")))
P018 int Function18(int A, int B){int C = A*B; return C;}
下面是一个更好的例子来说明我的问题:
#define P152 __attribute__((long_call, section(".txt152")))
P152 void TestFunc(int A){printf("%d Squared Is: %d\r\n",A,A*A);}
在这种情况下,可以在 .rodata 中找到“%d Squared Is: %d\r\n”的二进制等效项以及我程序中的所有其他文字字符串。我希望它位于 .txt152 部分。
链接器脚本片段(主要由简单的控制台程序生成。)
MEMORY
{
p000 (rx) : ORIGIN = 0x08000000, LENGTH = 0x8000
p016 (rx) : ORIGIN = 0x08008000, LENGTH = 0x800
p017 (rx) : ORIGIN = 0x08008800, LENGTH = 0x800
p018 (rx) : ORIGIN = 0x08009000, LENGTH = 0x800
.
.
.
p509 (rx) : ORIGIN = 0x080fe800, LENGTH = 0x800
p510 (rx) : ORIGIN = 0x080ff000, LENGTH = 0x800
p511 (rx) : ORIGIN = 0x080ff800, LENGTH = 0x800
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
ram2 (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
SECTIONS
{
.vectors :
{
KEEP(*(.isr_vector .isr_vector.*))
} > p000
.txt016 : { *(.txt016) } > p016 /* first usable 2k page following 32k p000 */
.txt017 : { *(.txt017) } > p017
.txt018 : { *(.txt018) } > p018
.
.
.
.txt509 : { *(.txt509) } > p509
.txt510 : { *(.txt510) } > p510
.txt511 : { *(.txt511) } > p511
.text :
{
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
} > p000
.
.
.
如果有人感兴趣,这是我执行 erase/program 操作的 RAM 代码
__attribute__((long_call, section(".data")))
void CopyPatch
(
unsigned short Page,
unsigned int NumberOfBytesToFlash,
unsigned char *PatchBuf
)
{
unsigned int i;
unsigned long long int *Flash;
__ASM volatile ("cpsid i" : : : "memory"); //disable interrupts
Flash = (unsigned long long int *)(FLASH_BASE + Page*2048); //set flash memory pointer to Page address
GPIOE->BSRR = GPIO_BSRR_BS_1; //make PE1(LED) high
FLASH->KEYR = 0x45670123; //unlock the flash
FLASH->KEYR = 0xCDEF89AB; //unlock the flash
while(FLASH->SR & FLASH_SR_BSY){} //wait while flash memory operation is in progress
FLASH->CR = FLASH_CR_PER | (Page << 3); //set Page erase bit and the Page to erase
FLASH->CR |= FLASH_CR_STRT; //start erase of Page
while(FLASH->SR & FLASH_SR_BSY){} //wait while Flash memory operation is in progress
FLASH->CR = FLASH_CR_PG; //set flash programming bit
for(i=0;i<(NumberOfBytesToFlash/8+1);i++)
{
Flash[i] = ((unsigned long long int *)PatchBuf)[i]; //copy RAM to FLASH, 8 bytes at a time
while(FLASH->SR & FLASH_SR_BSY){} //wait while flash memory operation is in progress
}
FLASH->CR = FLASH_CR_LOCK; //lock the flash
GPIOE->BSRR = GPIO_BSRR_BR_1; //make PE1(LED) low
__ASM volatile ("cpsie i" : : : "memory"); //enable interrupts
}
好的...抱歉耽搁了,但我不得不考虑一下...
我不确定您是否可以单独使用链接描述文件 [完全] 完成此操作。它 可能 是可能的,但我认为有一个 easier/surer 方法 [需要一些额外的准备]
我之前用过的一个方法是用-S
编译得到一个.s
文件。 Change/mangle那个。然后,编译修改后的 .s
请注意,您可能会遇到一些全局问题,例如:
int B;
这将转到 asm 源代码中的 .comm
部分。这可能并不理想。
对于初始化数据:
int B = 23;
您可能想要添加一个部分属性以将其强制到一个特殊部分。否则,它将在 .data
部分结束
因此,我可能会避免使用 .comm
and/or .bss
部分,而 always 使用初始化数据。那是因为 .comm
与 .rodata
有相同的问题(即它最终变成一个大斑点)。
总之,下面是一个循序渐进的过程。
我将节名宏放在一个普通文件中(例如)sctname.h
:
#define _SCTJOIN(_pre,_sct) _pre #_sct
#define _TXTSCT(_sct) __attribute__((section(_SCTJOIN(".txt",_sct))))
#define _DATSCT(_sct) __attribute__((section(_SCTJOIN(".dat",_sct))))
#ifdef SCTNO
#define TXTSCT _TXTSCT(SCTNO)
#define DATSCT _DATSCT(SCTNO)
#endif
这里是您的 .c
文件的略微修改版本(例如 module.c
):
#include <stdio.h>
#ifndef SCTNO
#define SCTNO 152
#endif
#include "sctname.h"
int B DATSCT = 23;
TXTSCT void
TestFunc(int A)
{
printf("%d Squared Is: %d\r\n", A, A * A * B);
}
要创建 .s
文件,我们执行以下操作:
cc -S -Wall -Werror -O2 module.c
实际段name/number可以在命令行指定:
cc -S -Wall -Werror -O2 -DSCTNO=152 module.c
这给了我们 module.s
:
.file "module.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d Squared Is: %d\r\n"
.section .txt152,"ax",@progbits
.p2align 4,,15
.globl TestFunc
.type TestFunc, @function
TestFunc:
.LFB11:
.cfi_startproc
movl %edi, %edx
movl %edi, %esi
xorl %eax, %eax
imull %edi, %edx
movl $.LC0, %edi
imull B(%rip), %edx
jmp printf
.cfi_endproc
.LFE11:
.size TestFunc, .-TestFunc
.globl B
.section .dat152,"aw"
.align 4
.type B, @object
.size B, 4
B:
.long 23
.ident "GCC: (GNU) 8.3.1 20190223 (Red Hat 8.3.1-2)"
.section .note.GNU-stack,"",@progbits
现在,我们必须读入 .s
并修改它。我已经创建了一个执行此操作的 perl 脚本(例如 rofix
):
#!/usr/bin/perl
master(@ARGV);
exit(0);
sub master
{
my(@argv) = @_;
$root = shift(@argv);
$root =~ s/[.][^.]+$//;
$sfile = "$root.s";
$ofile = "$root.TMP";
open($xfsrc,"<$sfile") or
die("rofix: unable to open '$sfile' -- $!\n");
open($xfdst,">$ofile") or
die("rofix: unable to open '$sfile' -- $!\n");
$txtpre = "^[.]txt";
$datpre = "^[.]dat";
# find the text and data sections
seek($xfsrc,0,0);
while ($bf = <$xfsrc>) {
chomp($bf);
if ($bf =~ /^\s*[.]section\s(\S+)/) {
$sctcur = ;
sctget($txtpre);
sctget($datpre);
}
}
# modify the data sections
seek($xfsrc,0,0);
while ($bf = <$xfsrc>) {
chomp($bf);
if ($bf =~ /^\s*[.]section\s(\S+)/) {
$sctcur = ;
sctfix();
print($xfdst $bf,"\n");
next;
}
print($xfdst $bf,"\n");
}
close($xfsrc);
close($xfdst);
system("diff -u $sfile $ofile");
rename($ofile,$sfile) or
die("rofix: unable to rename '$ofile' to '$sfile' -- $!\n");
}
sub sctget
{
my($pre) = @_;
my($sctname,@sct);
{
last unless (defined($pre));
@sct = split(",",$sctcur);
$sctname = shift(@sct);
last unless ($sctname =~ /$pre/);
printf("sctget: FOUND %s\n",$sctname);
$sct_lookup{$pre} = $sctname;
}
}
sub sctfix
{
my($sctname,@sct);
my($sctnew);
{
last unless ($sctcur =~ /^[.]rodata/);
$sctnew = $sct_lookup{$txtpre};
last unless (defined($sctnew));
@sct = split(",",$sctcur);
$sctname = shift(@sct);
$sctname .= $sctnew;
unshift(@sct,$sctname);
$sctname = join(",",@sct);
$bf = sprintf("\t.section\t%s",$sctname);
}
}
新旧module.s
的区别是:
sctget: FOUND .txt152
sctget: FOUND .dat152
--- module.s 2020-04-20 19:02:23.777302484 -0400
+++ module.TMP 2020-04-20 19:06:33.631926065 -0400
@@ -1,6 +1,6 @@
.file "module.c"
.text
- .section .rodata.str1.1,"aMS",@progbits,1
+ .section .rodata.txt152,"aMS",@progbits,1
.LC0:
.string "%d Squared Is: %d\r\n"
.section .txt152,"ax",@progbits
所以,现在,创建 .o
具有:
cc -c module.s
对于 makefile,它可能类似于[带有一些通配符]:
module.o: module.c
cc -S -Wall -Werror -O2 module.c
./rofix module.s
cc -c module.s
现在,您可以在链接描述文件中为 [您的原始部分] .txt152
和新的 .rodata.txt152
.
并且,初始化数据部分.dat152
请注意,实际的命名约定是任意的。如果要更改它们,只需适当修改 rofix
[和链接描述文件]
这是 module.o
的 readelf -a
输出:
请注意,还有一个 .rela.txt152
部分!?!?
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 808 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 15
Section header string table index: 14
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
0000000000000000 0000000000000000 AX 0 0 1
[ 2] .data PROGBITS 0000000000000000 00000040
0000000000000000 0000000000000000 WA 0 0 1
[ 3] .bss NOBITS 0000000000000000 00000040
0000000000000000 0000000000000000 WA 0 0 1
[ 4] .rodata.txt152 PROGBITS 0000000000000000 00000040
0000000000000014 0000000000000001 AMS 0 0 1
[ 5] .txt152 PROGBITS 0000000000000000 00000060
000000000000001a 0000000000000000 AX 0 0 16
[ 6] .rela.txt152 RELA 0000000000000000 00000250
0000000000000048 0000000000000018 I 12 5 8
[ 7] .dat152 PROGBITS 0000000000000000 0000007c
0000000000000004 0000000000000000 WA 0 0 4
[ 8] .comment PROGBITS 0000000000000000 00000080
000000000000002d 0000000000000001 MS 0 0 1
[ 9] .note.GNU-stack PROGBITS 0000000000000000 000000ad
0000000000000000 0000000000000000 0 0 1
[10] .eh_frame PROGBITS 0000000000000000 000000b0
0000000000000030 0000000000000000 A 0 0 8
[11] .rela.eh_frame RELA 0000000000000000 00000298
0000000000000018 0000000000000018 I 12 10 8
[12] .symtab SYMTAB 0000000000000000 000000e0
0000000000000150 0000000000000018 13 11 8
[13] .strtab STRTAB 0000000000000000 00000230
000000000000001c 0000000000000000 0 0 1
[14] .shstrtab STRTAB 0000000000000000 000002b0
0000000000000078 0000000000000000 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),
l (large), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
There is no dynamic section in this file.
Relocation section '.rela.txt152' at offset 0x250 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
00000000000a 00050000000a R_X86_64_32 0000000000000000 .rodata.txt152 + 0
000000000011 000c00000002 R_X86_64_PC32 0000000000000000 B - 4
000000000016 000d00000004 R_X86_64_PLT32 0000000000000000 printf - 4
Relocation section '.rela.eh_frame' at offset 0x298 contains 1 entry:
Offset Info Type Sym. Value Sym. Name + Addend
000000000020 000600000002 R_X86_64_PC32 0000000000000000 .txt152 + 0
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Symbol table '.symtab' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS module.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 4
6: 0000000000000000 0 SECTION LOCAL DEFAULT 5
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 9
9: 0000000000000000 0 SECTION LOCAL DEFAULT 10
10: 0000000000000000 0 SECTION LOCAL DEFAULT 8
11: 0000000000000000 26 FUNC GLOBAL DEFAULT 5 TestFunc
12: 0000000000000000 4 OBJECT GLOBAL DEFAULT 7 B
13: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf
No version information found in this file.