2016-06-27 3 views
2

Я хочу идентифицировать неиспользуемые файлы объектов в большом приложении C со многими библиотеками. С течением времени проект значительно вырос, и теперь я хочу искать библиотеки, которые больше не используются, поэтому я могу удалить их из файла зависимостей. Возможно ли с помощью gcc-линкера идентифицировать любой объект, который не используется?gcc linker получить список неиспользуемых объектов

Например, если я скомпилирую приложение с gcc, и, скажем, ни один из символов/функций библиотеки2 не используется. Есть ли способ получить информацию о том, какие объекты не связаны?

gcc library1.o library2.o main.o -o main.elf 

Я знаю, что GCC имеет компилятор и компоновщика флаги для удаления неиспользуемых символов:

-fdata-sections -ffunction-sections -Wl,--gc-sections 

Однако этот способ я не знаю, какие объекты были удалены НКУ. Было бы идеально, если gcc имеет возможность получить список объектов, которые не были связаны с приложением.

Просто для того, чтобы упомянуть: мне нужно это на объектном файле, а не на основе функции/символа!

Кто-нибудь знает такой вариант для gcc?

+0

Таким образом, вы могли бы просто посмотреть, что '.o' файлы вы можете найти после компиляции и сравните с исходников,. Я не знаю точно, просто идея ... –

+1

Взгляните на [этот ответ SO] (http://stackoverflow.com/a/4449936/3436922). Это может помочь. – LPs

+0

@R. Ну, это так.Я уже использую флаги -fdata-sections -ffunction-sections -Wl, -gc-sections, которые удаляют неиспользуемый код. Однако таким образом я не могу идентифицировать объекты для удаления и их и убирать мою сборную систему – franz86

ответ

1

Посмотрите на callcatcher

Это компилирует программу в сборке и извлекает очевидные ссылки с выхода сборки. Я думаю, это именно то, что вы ищете. (Обратите внимание, что он анализирует выход ассемблера, он будет работать только на платформах x86)

Примечание callcatcher игнорирует виртуальные функции (по ряду причин), поэтому он не позволит напрямую проанализировать их.

+0

Спасибо за подсказку. Я не знал этого инструмента, но он выглядит интересным. Я дам ему попробовать. – franz86

2

Например, если я скомпилирую приложение с gcc, и, скажем, ни один из символов/функций библиотеки2 не используется. Есть ли способ получить информацию о том, какие объекты не связаны?

gcc library1.o library2.o main.o -o main.elf

С выше команды, library2.oбудет быть связаны, даже если ни один из кода от него не будет задействован. Чтобы понять, почему, прочитайте this или this.

Это правда, что если компиляции кода в library2.o с -ffunction-sections -fdata-sectionsи связи с -Wl,-gc-sections, то все кода и данных от library2.o будет GC'd, но это не команда, которую вы дали.

Предположительно, вы больше заинтересованы в том, что произойдет, если вы используете библиотеки как библиотеки:

gcc main.o -o main.elf -lrary1 -lrary2 

В том случае, если ни один из кодов из library2 не упоминается, компоновщик не тянуть его в ссылку ,

Там нет никакого способа, чтобы задать компоновщик список вещей, которые он не сделал использовать, но (если вы используете GNU-LD) есть способ, чтобы спросить его список объектов, которые он сделал используйте: -M или -Map вариант. Как только вы знаете, какие объекты используются, проще всего вычесть используемые объекты из всех объектов, используемых при связывании, чтобы получить список, который не используется.

Update:

Gold компоновщик поддерживает --print-symbol-counts FILENAME вариант, который также может быть полезным здесь. Он печатает определенные и используется количество символов. Для library2.a он должен напечатать $num_defined 0, 0, указав, что на самом деле не использовались ни один из объектов от library2.a.

+0

Вы правы, моя команда была неправа, извините, что это было неточно. Я также думал о том, чтобы делать разницу между построенными объектами и связанными объектами, я только думал, что у gcc уже есть встроенные флаги, помогающие мне это сделать. – franz86

1

В сочетании с опциями компилятора -fdata-sections -ffunction-sections и варианты сцепления --gc-sections --print-gc-sections, список superflous объектных файлов в связи может быть получена следующим образом: -

--print-gc-sections заставит линкер сообщать отбрасываются секциям цитируя объектный файл, который они пришли, как:

/usr/bin/ld: Removing unused section '.text.unused' in file 'unused.o' 

Таким образом, можно grep из имен объектных файлов из этих строк, получить уни набор этих имен файлов и фильтровать их через набор созданных объектных файлов .

Вот иллюстрация:

foo.c

#include <stdio.h> 

void foo() { 
    puts("foo"); 
} 

unused.c

#include <stdio.h> 
void unused(void) 
{ 
    puts("unused"); 
} 

main.c

extern void foo(); 

int main() { 
    foo(); 
    return 0; 
} 

Makefile

LDFLAGS := -Wl,--gc-sections,--print-gc-sections 
CFLAGS := -fdata-sections -ffunction-sections 
SRCS := main.c foo.c unused.c 
OBJS := $(SRCS:.c=.o) 
GREP_FILT := $(patsubst %,-e '%',$(OBJS)) 

.PHONY: all clean idle-objects 

all: prog 

idle-objects: idle-objects.txt 

clean: 
    rm -f prog $(OBJS) link-log idle-objects.txt 

prog link.log: $(OBJS) 
    gcc -o prog $^ $(LDFLAGS) $(LDLIBS) 2>&1 | tee link.log 

idle-objects.txt : link.log 
    sed -E 's/^.*Removing unused section \x27.*\x27 in file \x27(\w+\.o)\x27$$/\1/g' $^ \ 
    | sort | uniq | grep -F $(GREP_FILT) > [email protected] 

unused.o это, конечно, только праздны объектный файл в связи.

$ make idle-objects 
cc -fdata-sections -ffunction-sections -c -o main.o main.c 
cc -fdata-sections -ffunction-sections -c -o foo.o foo.c 
cc -fdata-sections -ffunction-sections -c -o unused.o unused.c 
gcc -o prog main.o foo.o unused.o -Wl,--gc-sections,--print-gc-sections 2>&1 | tee link.log 
/usr/bin/ld: Removing unused section '.rodata.cst4' in file '/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/Scrt1.o' 
/usr/bin/ld: Removing unused section '.data' in file '/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/Scrt1.o' 
/usr/bin/ld: Removing unused section '.rodata' in file 'unused.o' 
/usr/bin/ld: Removing unused section '.text.unused' in file 'unused.o' 
sed -E 's/^.*Removing unused section \x27.*\x27 in file \x27(\w+\.o)\x27$/\1/g' link.log \ 
| sort | uniq | grep -F -e 'main.o' -e 'foo.o' -e 'unused.o' > idle-objects.txt 

дает нам:

$ cat idle-objects.txt 
unused.o 

В качестве альтернативы:

$ make clean 
rm -f prog main.o foo.o unused.o link-log idle-objects.txt 
$ make 
cc -fdata-sections -ffunction-sections -c -o main.o main.c 
cc -fdata-sections -ffunction-sections -c -o foo.o foo.c 
cc -fdata-sections -ffunction-sections -c -o unused.o unused.c 
gcc -o prog main.o foo.o unused.o -Wl,--gc-sections,--print-gc-sections 2>&1 | tee link.log 
/usr/bin/ld: Removing unused section '.rodata.cst4' in file '/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/Scrt1.o' 
/usr/bin/ld: Removing unused section '.data' in file '/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/Scrt1.o' 
/usr/bin/ld: Removing unused section '.rodata' in file 'unused.o' 
/usr/bin/ld: Removing unused section '.text.unused' in file 'unused.o' 
$ make idle-objects 
sed -E 's/^.*Removing unused section \x27.*\x27 in file \x27(\w+\.o)\x27$/\1/g' link.log \ 
| sort | uniq | grep -F -e 'main.o' -e 'foo.o' -e 'unused.o' > idle-objects.txt 
$ cat idle-objects.txt 
unused.o