¿Cómo eliminar símbolos C/C++ no utilizados con GCC y ld?
Necesito optimizar severamente el tamaño de mi ejecutable ( ARM
desarrollo) y noté que en mi esquema de compilación actual ( gcc
+ ld
) los símbolos no utilizados no se eliminan.
El uso de arm-strip --strip-unneeded
para los ejecutables/bibliotecas resultantes no cambia el tamaño de salida del ejecutable (no tengo idea de por qué, tal vez simplemente no pueda) .
¿Cuál sería la forma (si existe) de modificar mi canal de construcción, de modo que los símbolos no utilizados se eliminen del archivo resultante?
Ni siquiera pensaría en esto, pero mi entorno integrado actual no es muy "potente" y guardar incluso 500K
resultados 2M
en un aumento muy agradable del rendimiento de carga.
Actualizar:
Desafortunadamente, la gcc
versión actual que uso no tiene la -dead-strip
opción y -ffunction-sections... + --gc-sections
for ld
no ofrece ninguna diferencia significativa en el resultado resultante.
Me sorprende que esto se haya convertido en un problema, porque estaba seguro de que gcc + ld
debería eliminar automáticamente los símbolos no utilizados (¿por qué tienen que conservarlos?).
Para GCC, esto se logra en dos etapas:
Primero compile los datos, pero dígale al compilador que separe el código en secciones separadas dentro de la unidad de traducción. Esto se hará para funciones, clases y variables externas utilizando los dos indicadores del compilador siguientes:
-fdata-sections -ffunction-sections
Vincula las unidades de traducción usando el indicador de optimización del vinculador (esto hace que el vinculador descarte las secciones sin referencia):
-Wl,--gc-sections
Entonces, si tuviera un archivo llamado test.cpp que tuviera dos funciones declaradas, pero una de ellas no se usara, podría omitir la que no se usó con el siguiente comando para gcc(g++):
gcc -Os -fdata-sections -ffunction-sections test.cpp -o test -Wl,--gc-sections
(Tenga en cuenta que -Os es un indicador del compilador adicional que le indica a GCC que optimice el tamaño)
Si hay que creer en este hilo , debe proporcionar -ffunction-sections
y-fdata-sections
a gcc, que colocará cada función y objeto de datos en su propia sección. Luego le das y --gc-sections
a GNU ld para que elimine las secciones no utilizadas.
Querrá consultar sus documentos para conocer su versión de gcc y ld:
Sin embargo, para mí (OS X gcc 4.0.1) encuentro estos para ld
-dead_strip
Elimine funciones y datos a los que no se puede acceder mediante el punto de entrada o los símbolos exportados.
-dead_strip_dylibs
Elimine los dylibs a los que el punto de entrada o los símbolos exportados no puedan acceder. Es decir, suprime la generación de comandos de carga para dylibs que no proporcionaron símbolos durante el enlace. Esta opción no debe usarse cuando se vincula con un dylib que se requiere en tiempo de ejecución por alguna razón indirecta, como que el dylib tiene un inicializador importante.
Y esta útil opción
-why_live symbol_name
Registra una cadena de referencias a nombre_símbolo. Sólo aplicable con
-dead_strip
. Puede ayudar a depurar por qué algo que cree que debería eliminarse no se elimina.
También hay una nota en el manual gcc/g++ de que ciertos tipos de eliminación de código inactivo solo se realizan si la optimización está habilitada al compilar.
Si bien es posible que estas opciones/condiciones no sean válidas para su compilador, le sugiero que busque algo similar en sus documentos.
Los hábitos de programación también podrían ayudar; por ejemplo, agregar static
funciones a las que no se accede fuera de un archivo específico; use nombres más cortos para los símbolos (puede ayudar un poco, probablemente no demasiado); utilizar const char x[]
cuando sea posible; ... este documento , aunque habla de objetos compartidos dinámicos, puede contener sugerencias que, si se siguen, pueden ayudar a reducir el tamaño de salida binaria final (si su objetivo es ELF).