Параметры компиляции -ffunction-sections -fdata-sections
и опция связывания --gc-sections
работают правильно в вашем примере.Ваша статическая библиотека лишняя, поэтому ее можно упростить до:
$ gcc -ffunction-sections -fdata-sections -c main.c getall.c
$ gcc -Wl,--gc-sections main.o getall.o -Wl,-Map=mapfile
, в которой я также запрашиваю файл компоновщика.
Неиспользуемые функции get2
и get3
отсутствуют в исполняемом файле:
$ nm a.out | grep get
0000000000000657 T get1
, и файл карты показывает, что неиспользуемые функциональные секции .text.get2
и .text.get3
, в которых определены get2
и get3
соответственно, были отброшены в связи:
mapfile (1)
...
Discarded input sections
...
.text.get2 0x0000000000000000 0xd getall.o
.text.get3 0x0000000000000000 0xd getall.o
...
Тем не менее, как вы обнаружили, все три строковых литерала "s97symmqdn-(1|2|3)"
находятся в программе:
$ strings a.out | egrep 's97symmqdn-(1|2|3)'
s97symmqdn-1
s97symmqdn-2
s97symmqdn-3
Это потому, что -fdata-sections
применяется только к тем же объектам данных, что __attribute__ ((__section__("name")))
применяется к 1 , то есть к определениям переменных , которыеиметь статическая продолжительность хранения .Он не применяется к анонимным строковым литералам, таким как "s97symmqdn-(1|2|3)"
.Все они просто помещаются в секцию .rodata
как обычно, и там мы находим их:
$ objdump -s -j .rodata a.out
a.out: file format elf64-x86-64
Contents of section .rodata:
06ed 73393773 796d6d71 646e2d31 00733937 s97symmqdn-1.s97
06fd 73796d6d 71646e2d 32007339 3773796d symmqdn-2.s97sym
070d 6d71646e 2d3300 mqdn-3.
--gc-sections
не позволяет компоновщику удалить .rodata
из программы, потому что он не являетсянеиспользуемый раздел: содержит "s97symmqdn-1"
, на который ссылается программа get1
, а также строки без ссылок "s97symmqdn-2"
и "s97symmqdn-3"
Fix
Toчтобы эти три строковых литерала были разделены на отдельные разделы данных, вам нужно назначить их различным именованным объектам, например,
getcall.c (2)
const char *get1()
{
static const char s[] = "s97symmqdn-1";
return s;
}
const char *get2()
{
static const char s[] = "s97symmqdn-2";
return s;
}
const char *get3()
{
static const char s[] = "s97symmqdn-3";
return s;
}
Еслимы перекомпилируем и перекомпилируем это изменение, мы видим:
mapfile (2)
...
Discarded input sections
...
.text.get2 0x0000000000000000 0xd getall.o
.text.get3 0x0000000000000000 0xd getall.o
.rodata.s.1797
0x0000000000000000 0xd getall.o
.rodata.s.1800
0x0000000000000000 0xd getall.o
...
Теперь есть два новых отброшенных раздела данных, которые содержат дваСтроковые литералы, которые нам не нужны, как мы видим в объектном файле:
$ objdump -s -j .rodata.s.1797 getall.o
getall.o: file format elf64-x86-64
Contents of section .rodata.s.1797:
0000 73393773 796d6d71 646e2d32 00 s97symmqdn-2.
и:
$ objdump -s -j .rodata.s.1800 getall.o
getall.o: file format elf64-x86-64
Contents of section .rodata.s.1800:
0000 73393773 796d6d71 646e2d33 00 s97symmqdn-3.
В любом месте программы теперь появляется только указанная строка "s97symmqdn-1"
:
$ strings a.out | egrep 's97symmqdn-(1|2|3)'
s97symmqdn-1
и это единственная строка в программе .rodata
:
$ objdump -s -j .rodata a.out
a.out: file format elf64-x86-64
Contents of section .rodata:
06f0 73393773 796d6d71 646e2d31 00 s97symmqdn-1.
[1]
-function-sections
имеет тот же эффект, что и определение каждой функции
foo
с
__attribute__ ((__section__(".text.foo")))