2016-06-27 6 views
2

Ich möchte unbenutzte Objektdateien in einer großen C-Anwendung mit vielen Bibliotheken identifizieren. Das Projekt ist im Laufe der Zeit sehr gewachsen und ich möchte nun nach Bibliotheken suchen, die nicht mehr benutzt werden, damit ich sie aus der Abhängigkeitsdatei entfernen kann. Ist es mit dem GCC-Linker möglich, ein Objekt zu identifizieren, das nicht verwendet wird?gcc Linker Liste der unbenutzten Objekte

Zum Beispiel, wenn ich eine Anwendung mit gcc kompiliere und sagen wir, keines der Symbole/Funktionen von library2 wird verwendet. Gibt es eine Möglichkeit, Informationen darüber zu erhalten, welche Objekte nicht verknüpft sind?

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

Ich weiß, dass gcc die Compiler und Linker-Flags nicht verwendete Symbole zu entfernen hat:

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

Doch diese Art und Weise Ich weiß nicht, welche Objekte von gcc entfernt wurden. Es wäre perfekt, wenn gcc eine Option hat, um eine Liste von Objekten zu erhalten, die nicht mit der Anwendung verknüpft sind.

Nur um zu erwähnen: Ich brauche es auf Objektdateibasis nicht auf Funktion/Symbolbasis!

Kennt jemand eine solche Option für gcc?

+0

So konnte man nur schauen, was '.o' Dateien, die Sie nach dem Kompilieren und zu vergleichen, um Ihre Quelldateien finden. Ich weiß es nicht sicher, nur eine Idee ... –

+1

Werfen Sie einen Blick auf [diese SO-Antwort] (http://stackoverflow.com/a/4449936/3436922). Es könnte helfen. – LPs

+0

@R. Joiny Ja das ist es.Ich verwende bereits die Flags -fdata-sections -ffunction-sections -Wl, - gc-sections, die nicht verwendeten Code entfernen. Aber auf diese Weise kann ich nicht identifizieren, die Objekte zu entfernen und sie und aufräumen mein Buildsystem – franz86

Antwort

1

Werfen Sie einen Blick auf callcatcher

Dies kompiliert Ihr Programm in Montage und extrahiert offensichtlich Referenzen aus der Baugruppe ausgegeben. Ich denke, das ist genau das, wonach du suchst. (Anmerkung aufgrund der Tatsache, dass es Assembler-Ausgabe analysiert nur auf x86-Plattformen funktioniert)

Hinweis Callcatcher ignoriert virtuelle Funktionen (aus einigen guten Gründen), so wird es nicht direkt erlauben Ihnen, diese zu analysieren.

+0

Danke für den Hinweis. Ich kannte dieses Tool nicht, aber es sieht interessant aus. Ich werde es versuchen. – franz86

2

Zum Beispiel, wenn ich eine Anwendung mit gcc kompiliere und sagen wir, keines der Symbole/Funktionen von library2 wird verwendet. Gibt es eine Möglichkeit, Informationen darüber zu erhalten, welche Objekte nicht verknüpft sind?

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

Mit obigem Befehl library2.owird in selbst verknüpft werden, wenn kein Code von ihm jemals verwendet wird. Um zu verstehen, warum, lesen Sie this oder this.

Es stimmt, dass wenn Sie Code in library2.o mit -ffunction-sections -fdata-sectionsund Verbindung mit -Wl,-gc-sections kompilieren, dann den gesamten Code und Daten von library2.o wird GC'd geführt werden, aber das ist nicht der Befehl, den Sie gab.

Vermutlich sind Sie mehr daran interessiert, was passiert, wenn Sie Bibliotheken als Bibliotheken verwenden:

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

In diesem Fall, wenn kein Code von library2 Bezug genommen wird, wird der Linker nicht in die Verbindung ziehen .

Es gibt keine Möglichkeit, den Linker für die Liste der Dinge, die es tat nicht Gebrauch zu fragen, aber (wenn Sie GNU-ld verwenden) gibt es eine Möglichkeit, es für eine Liste von Objekten zu fragen es tat Verwenden Sie: -M oder -Map Option. Sobald Sie wissen, welche Objekte verwendet werden, ist es eine einfache Sache, die verwendeten Objekte von allen Objekten zu entfernen, die beim Verknüpfen verwendet werden, um die Liste zu erhalten, die nicht verwendet wird.

Update:

Gold-Linker unterstützt --print-symbol-counts FILENAME Option, die auch hier hilfreich sein kann. Es druckt definierte und verwendete Symbolzählungen. Für library2.a sollte es $num_defined 0, die 0 drucken, die angibt, dass keines der Objekte von library2.a tatsächlich verwandt wurde.

+0

Sie haben Recht, mein Befehl war falsch, tut mir leid, dass es nicht korrekt war. Ich dachte auch daran, einen Unterschied zwischen den gebauten Objekten und den verknüpften Objekten zu machen, ich dachte nur, dass gcc bereits eingebaute Flaggen hat, die mir dabei helfen. – franz86

1

In Verbindung mit Compiler-Optionen -fdata-sections -ffunction-sections und Verknüpfung Optionen --gc-sections --print-gc-sections, eine Liste der superflous Objektdateien in der Verknüpfung kann wie folgt hergestellt werden: -

--print-gc-sections der Linker unter Berufung auf dem verworfenen Abschnitte berichten verursachen Objekt-Datei, die sie kommen, wie:

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

So kann man die Objektdateinamen aus diesen Zeilen grep aus, erhalten die uni que-Satz dieser Dateinamen, und filtern Sie sie durch den Satz von Objektdateien, die erstellt werden. Hier

ist eine Darstellung:

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 ist, natürlich, die nur im Leerlauf Objektdatei in der Verknüpfung.

$ 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 

gibt uns:

$ cat idle-objects.txt 
unused.o 

Alternativ:

$ 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