07 lds文件与自定义段

lds文件用于指定程序链接时的不同段内容的位置安排。linux内核镜像里就是利用lds文件,把不同的内容划分成很多不同的段.
uboot里的命令也就是利用此功能,把所有的命令统一到一个段里.

arm-linux-gnueabihf-ld –verbose > test.lds //把编译器默认的链接脚本输出到test.lds里

修改test.lds, 把最前的6行删除掉, 也要删除最后一行.
在84行加入自己的段:

  __mysection_start = . ;
  .mysection  :
  {
    *(.mysection);
  }
  .align = 4;
  __mysection_end = . ;

// __mysection_start 和 __mysection_end用于记录段的开始地址与结束地址.
*(.mysection) 表示所有的.o文件的.mysection段内容集中放起来

在代码里指定变量是分配在.mysection段:

    int num  __attribute__ ((section(".mysection"))) = 1;
    int num2 __attribute__ ((section(".mysection"))) = 2;
    int num3 __attribute__ ((section(".mysection"))) = 3;

编译时指定使用test.lds链接脚本:

arm-linux-gnueabihf-gcc test.c -Ttest.lds -o test

编译完成后,可以反汇编确认.mysection里的状况:

    arm-linux-gnueabihf-objdump -D test 
  查看到的输出:
    Disassembly of section .mysection:

    000083d4 <num>:
        83d4:       00000001        andeq   r0, r0, r1

    000083d8 <num2>:
        83d8:       00000002        andeq   r0, r0, r2

    000083dc <num3>:
        83dc:       00000003        andeq   r0, r0, r3


加进一个段后, 可以通过__mysection_start 和__mysection_end算出一个段的大小,及段里的变量个数.
也可以取出每个段里变量的值.

在代码里:
__mysection_start 相当于一个变量(类型不重要),它的地址就是段的开始地址
__mysection_end, 它的地址就是段的结束地址
实验代码:
test.c

    #include <stdio.h>

    int num __attribute__ ((section(".mysection"))) = 1;
    int num2 __attribute__ ((section(".mysection"))) = 2;
    int num3 __attribute__ ((section(".mysection"))) = 3;
    int num4 __attribute__ ((section(".mysection"))) = 55; 

    extern int __mysection_start; //这个变量是在链接脚本里声明的
    extern int __mysection_end;
    int main(void)
    {
        int *p = &__mysection_start;

        for (; p < &__mysection_end; p++)
        {   
        printf("%d\n", *p);
        }   

        return 0;
    }

以后再加变量到.mysection段里,main函数的代码可以不用修改都可以获取到相应的变量的值

实现命令的功能:

test.c

    #include <stdio.h>

    typedef struct {
        char *name;  //命令的名字
        char *help; // 命令的帮助信息
        void (*func)(void); //命令的功能函数
    }cmd_t;

    #define MySection  __attribute__ ((section(".mysection")))

    #define ADD_CMD(name, help, func) \
        cmd_t __cmd_##name MySection = {#name, help , func}  

    void do_cmd1(void)
    {
        printf("in %s\n", __func__);
    }
    ADD_CMD(cmd1, "help of cmd1", do_cmd1);


    extern cmd_t __mysection_start;
    extern cmd_t __mysection_end;
    int main(void)
    {
        cmd_t *p = &__mysection_start;      

        for (; p < &__mysection_end; p++)
        {
            printf("%s\n", p->name);
            p->func();
            printf("#################\n");
        }
        return 0;
    }

// 再增加命令时,只需实现命令的功能函数后, 调用ADD_CMD宏即可.
// 也可以把每个命令用一个源文件来实现,最后一起编译即可。uboot里的命令就是采用这样的方法.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值