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 = func

static 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博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

will.hu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值