Windows GCC修改链接脚本文件实现section块存储函数
在单片机C语言中,常使用section定义函数块或变量块。
那么,在Windows系统上如何实现呢?有参考的文章,但是也踩了不少坑。
1、编写C代码
编写c文件,代码参考如下:
/* 将函数加入某一个section段内,并按顺序调用*/
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>typedef void (*myown_call)(void); // 定义函数指针类型extern myown_call _myown_start; // 函数块头
extern myown_call _myown_end; // 函数块尾// 定义.myown块
#define _init __attribute__((unused, section(".myown")))
#define func_init(func) myown_call _fn_##func _init = funcstatic void mspec1(void)
{printf("mspec1!\n");
}static void mspec2(void)
{printf("mspec2!\n");
}static void mspec3(void)
{printf("mspec3!\n");
}func_init(mspec1);
func_init(mspec2);
func_init(mspec3);/* func_init()作用相当于如下语句:
static myown_call mc1 __attribute__((unused, section(".myown"))) = mspec1;
static myown_call mc2 __attribute__((unused, section(".myown"))) = mspec2;
static myown_call mc3 __attribute__((unused, section(".myown"))) = mspec3;
*/void do_initcalls(void)
{myown_call *call_ptr = &_myown_start;do {fprintf (stderr, "call_ptr: %p\n", call_ptr);(*call_ptr)();++call_ptr;} while (call_ptr < &_myown_end);
}int main(void)
{do_initcalls();return 0;
}
2、修改GCC默认链接脚本
首先,将默认的链接脚本另存一个新文件,可在终端输入命令:
ld --verbose >test.lds
将会生成一个test.lds文件。
首先,要将lds转换为utf-8编码格式,否则会报告错误:
C:/Program Files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe:xx.lds:1: ignoring invalid character `\377' in expression
C:/Program Files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe:xx.lds:1: ignoring invalid character `\376' in expression
C:/Program Files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe:xx.lds:1: ignoring invalid character `\000' in expression
C:/Program Files/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe:xx.lds:1: syntax error
collect2.exe: error: ld returned 1 exit status
其次,要删除文件前后的“=======================”内容,
否则报告错误:lds:1: syntax error
最后,在“__bss_start__ = . ;”前面添加:
_myown_start = .;*(.myown)_myown_end = .;
最终如下图所示。
3、编译新的链接脚本
编译新的链接脚本,如:
gcc -T test.lds xxx.c -o xxx.exe
也可以修改VScode的tasks.json脚本:
到C文件界面,按F5开始调试,成功输出:
call_ptr: 0000000000407000
mspec1!
call_ptr: 0000000000407008
mspec2!
call_ptr: 0000000000407010
mspec3!
参考链接:GCC中初始化函数是怎样被处理的?-腾讯云开发者社区-腾讯云
gcc s.lds 使用方法_gcc lds-CSDN博客
Windows 中用 gcc 编译并引用链接脚本中定义的变量时的注意点_c链接脚本中定义变量-CSDN博客 .lds链接脚本以及编译流程分析_.lds文件编译-CSDN博客