为什么 .data.rel.ro 部分在我的可执行文件中占用如此多的空间?

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

我想在Linux上构建一个共享库,其中包含一个大的初始化数组,并在不同的可执行文件中使用该数组。 我希望这可以减少编译输出的大小,特别是如果多个程序使用此数据。 不幸的是,当共享对象中的数据被标记为只读时,情况似乎并非如此。

这是我在对象内的 4Mib 的“制表符”符号:

$ nm --print-size bigfile.o
0000000000000000 0000000000400000 R tab

我使用 ld 创建共享对象:

ld -o libbigfile.so -shared bigfile.o

当链接到时,这会产生 4M 的可执行文件

gcc -o bigfile main.o libbigfile.so

对此负责的似乎是.data.rel.ro

$ readelf --section-headers bigfile
[21] .data.rel.ro      PROGBITS         0000000000403dc0  00002dc0
0000000000400000       0000000000000000 WA       0     0     64

但是我可以用

readelf -x .data.rel.ro bigfile
检查 .data.rel.ro 充满了 0x00。 因此,如果共享对象的 .rodata 部分的内容仅在加载时复制,为什么它会占用可执行二进制文件中的该空间,而不是像 .bss 那样在加载时分配?

如何重现:

我有一个非常简单的主要内容:

#include <stdio.h>

extern char tab[];

int main() {
  puts(tab); 
  return 0;
}

我从 C 或汇编文件生成共享对象,但汇编文件较小(遗憾的是 C 中没有“times”前缀),所以这里是汇编版本:

global tab:data BYTESIZE

BYTESIZE equ (1 << 22)

section .rodata
align 64
tab:
    times (BYTESIZE - 2) db 'A'
    db 0xA
    db 0x0

构建它:

nasm -f elf64 bigfile.asm
ld -o libbigfile.so -shared bigfile.o
gcc -c main.c
gcc -o bigfile main.o libbigfile.so

注意:如果我将制表符放在 .data 部分中,大小问题就会消失。

c linux gcc ld elf
1个回答
0
投票

好吧,如果你用 -fPIC 链接,你会得到你想要的小 exe。

tab.h

#pragma once

extern const char tab[];

选项卡.c

#include "tab.h"

const char tab[1234567] = {255,255};

main.c

#include <stdio.h>

#include "tab.h"

int main() {
  puts((char*)tab);  
  return 0;
}

编译共享库

> gcc -shared -fPIC -o libtab.so tab.c

编译exe

> gcc -fPIC -o a main.c -L/home/user/CPP -ltab

我得到了 ls -l

15976   Dec  3 11:49 a
1247856 Dec  3 11:49 libtab.so
© www.soinside.com 2019 - 2024. All rights reserved.