链接器脚本中的MEMORY命令膨胀二进制大小

时间:2015-05-11 07:30:49

标签: gcc linker linker-scripts

我希望有一个图像加载到2个不同的内存位置,所有地址链接都在编译/链接时完成。

我想实现的总体目标

  1. 为文本和数据定义不同的加载区域
  2. 根据加载地址解析所有符号依赖关系
  3. 将文本和数据区域背靠背放入图像中(我的加载程序会在运行时将文本部分放到不同的地址)
  4. 所以我创建了以下脚本

    MEMORY
    {
        mem1 : ORIGIN = 0xfff00000, LENGTH = 100K
        mem2 : ORIGIN = 0xfff80000, LENGTH = 100K
    }
    
    SECTIONS
    {
        . = 0xfff00000;
    
        _image_base_origin = . - 0;
    
    
        ////////////////////////////////
        // TEXT
        ////////////////////////////////
        .text : {
             _text_origin = .;
             . = ALIGN(4); _text_offset = . - _image_base_origin;  *(.vectors)      *(.text) *(.eh_frame)
         } > mem2
         _text_size = . - _text_origin;
    
        ////////////////////////////////
        // DATA
        ////////////////////////////////
        .data : {
                _data_origin = .;
                . = ALIGN(8); _data_offset = . - _image_base_origin;  *(.data) *(.comment) *(.rodata*) *(.bss*)
         } > mem1
         _data_size = . - _data_origin;
    
    }
    

    我面临的问题当我将图像的文本部分放在mem2中时,二进制的大小会增加许多倍。

    如果我在我的文件上运行readelf

    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 5] .text             PROGBITS        fff80000 020000 0017a8 00  AX  0   0 32
      [ 6] .data             PROGBITS        fff00398 010398 0004f8 00  WA  0   0  8
    

    因此图像尺寸变为80000 + 17a8。它在图像中添加了mem2的偏移量并创建了二进制文件。它用零填充所有额外的内存。

    如果我只将文本部分放在mem1中,那我的图像尺寸非常小(它不会为我的图像添加偏移80000)。

    你能帮我吗?

1 个答案:

答案 0 :(得分:0)

较大的文件大小无疑是为了满足vma%pagesize == file_offset%pagesize的需求分页要求。如果您的系统未按需求分页,则可以使用-n进行链接。如果您的系统是按需求分页的,则ld默认页面大小可能不必要地大。 -z max-page-size选项可以解决这个问题。