07 lds文件与自定义段

来源:互联网 发布:sql 删除表结构 编辑:程序博客网 时间:2024/06/10 21:32

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里的命令就是采用这样的方法.