如何编写链接描述文件将变量放置在共享对象的特定段中?

问题描述 投票:0回答:0

我有数千个 struct My_Str_A 类型的全局变量和另外数千个 struct My_Str_B 类型的全局变量。它们已部分初始化。我所说的“部分”是指对于结构变量的每个人,并非所有字段都被初始化。 目前所有这些变量都已编译并静态链接到主程序。

变量在汇编中定义,类似于:

    .section .SEG_A,"a",%progbits
    .align 1
    .global global_conf_xxx
global_conf_xxx:
    .short   1
    .byte    0x20
    .byte    0

    .section .SEG_RAM_PTR,"a",%nobits
ram_xxx:
    .space   4  

链接器脚本类似于:

SECTIONS
{
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x80000000)); . = SEGMENT_START("text-segment", 0x80000000) + SIZEOF_HEADERS;
  .interp         : { *(.interp) }
  .note.gnu.build-id  : { *(.note.gnu.build-id) }
  .hash           : { *(.hash) }
  .gnu.hash       : { *(.gnu.hash) }
  .dynsym         : { *(.dynsym) }
  .dynstr         : { *(.dynstr) }
  .gnu.version    : { *(.gnu.version) }
  .gnu.version_d  : { *(.gnu.version_d) }
  .gnu.version_r  : { *(.gnu.version_r) }
    .text           :
    {
        *(.text.unlikely .text.*_unlikely .text.unlikely.*)
        *(.text.exit .text.exit.*)
        *(.text.startup .text.startup.*)
        *(.text.hot .text.hot.*)
        *(.text .stub .text.* .gnu.linkonce.t.*)
        
        . = ALIGN(256);

        beginning_var_A = .;
        *(.SEG_A)
        ending_var_A = .;

        . = . + 64;

        . = ALIGN(4);
        beginning_var_B = .;
        *(.SEG_B)
        ending_var_A = .;
    }
      __bss_start = .;
      __bss_start__ = .;    
    .bss            :
    {
        *(.dynbss)
        *(.bss .bss.* .gnu.linkonce.b.*)
        *(COMMON)
        
        . = ALIGN(4);
        first_in_ram = .;
        *(.SEG_RAM_PTR)
    }
    _bss_end__ = .; __bss_end__ = .;
}

现在我想将所有这些变量打包到一个共享对象中,然后动态链接到我的主程序。我需要两个链接器脚本分别用于共享对象和主程序。以下是我的要求:

  1. 所有 struct My_Str_A 类型的变量都放在名为 SEG_A 的段中,所有 struct My_Str_B 类型的变量都放在名为 SEG_B 的段中;

  2. 共享库的链接描述文件中定义的 4 个定义变量表示 SEG_A 和 SEG_B 的开头和结尾,在 C 源代码中可以正常工作;

  3. 共享对象的 bss 部分中的变量(first_in_ram)表示用户定义部分 SEG_RAM_PTR 的 RAM 地址,在 C 源代码中可以正常工作。 我尝试了这样的方法: 在 libconf.lds 中:

    章节 { 。文本 : {
    。 =对齐(256);

         beginning_var_A = .;
         *(.SEG_A)
         ending_var_A = .;
    
         . = . + 64;
    
         . = ALIGN(4);
         beginning_var_B = .;
         *(.SEG_B)
         ending_var_A = .;
     }
       __bss_start = .;
       __bss_start__ = .;    
     .bss            :
     {       
         . = ALIGN(4);
         first_in_ram = .;
         *(.SEG_RAM_PTR)
     }
     _bss_end__ = .; __bss_end__ = .;
    

    }

在main.lds中:

SECTIONS
{
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x80000000)); . = SEGMENT_START("text-segment", 0x80000000) + SIZEOF_HEADERS;
  .interp         : { *(.interp) }
  .note.gnu.build-id  : { *(.note.gnu.build-id) }
  .hash           : { *(.hash) }
  .gnu.hash       : { *(.gnu.hash) }
  .dynsym         : { *(.dynsym) }
  .dynstr         : { *(.dynstr) }
  .gnu.version    : { *(.gnu.version) }
  .gnu.version_d  : { *(.gnu.version_d) }
  .gnu.version_r  : { *(.gnu.version_r) }
    .text           :
    {
        *(.text.unlikely .text.*_unlikely .text.unlikely.*)
        *(.text.exit .text.exit.*)
        *(.text.startup .text.startup.*)
        *(.text.hot .text.hot.*)
        *(.text .stub .text.* .gnu.linkonce.t.*)
    }
      __bss_start = .;
      __bss_start__ = .;    
    .bss            :
    {
        *(.dynbss)
        *(.bss .bss.* .gnu.linkonce.b.*)
        *(COMMON)
    }
    _bss_end__ = .; __bss_end__ = .;
}

结果:一些配置项按我想要的方式工作,但另一些则不然。 我检查了可工作项和不可工作项的地址,它们分别是0xf74a56c0和0x80845580。看来addr 0x80845580超出了数据段的范围,属于文本段。

我认为 libconf.lds 需要以某种方式进行更改。谁能帮我解决这个问题吗?

c linker embedded-linux cross-compiling
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.