¿Cómo eliminar los símbolos C / C ++ no utilizados con GCC y ld?

Necesito optimizar el tamaño de mi ejecutable severamente (desarrollo ARM ) y noté que en mi esquema de comstackción actual ( gcc + ld ) los símbolos que no se usan no se eliminan.

El uso de la arm-strip --strip-unneeded para los ejecutables / bibliotecas resultantes no cambia el tamaño de salida del ejecutable (no tengo ni idea de por qué, tal vez simplemente no puede) .

¿Cuál sería el camino (si existe) para modificar mi canalización 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 ahorra incluso 500K de los resultados de 2M en un impulso de carga muy agradable.

Actualizar:

Desafortunadamente, la versión actual de gcc que uso no tiene la opción -dead-strip y las -ffunction-sections... + --gc-sections para ld no da ninguna diferencia significativa para la salida resultante.

Estoy sorprendido de que esto incluso se haya convertido en un problema, porque estaba seguro de que gcc + ld debería quitar automáticamente los símbolos que no se usan (¿por qué incluso tienen que guardarlos?).

    Para GCC, esto se logra en dos etapas:

    Primero comstack los datos pero dile al comstackdor que separe el código en secciones separadas dentro de la unidad de traducción. Esto se hará para funciones, clases y variables externas mediante el uso de los siguientes dos indicadores del comstackdor:

     -fdata-sections -ffunction-sections 

    Vincule las unidades de traducción utilizando la bandera de optimización del enlazador (esto hace que el enlazador descarte las secciones sin referencia):

     -Wl,--gc-sections 

    Entonces, si tenía un archivo llamado test.cpp que tenía dos funciones declaradas, pero una de ellas no se utilizaba, podía omitir la que no se usa 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 de comstackción adicional que le dice a GCC que optimice para el tamaño)

    Si se quiere creer en este hilo , debe proporcionar las -ffunction-sections -fdata-sections a gcc, que colocarán cada función y objeto de datos en su propia sección. Luego, da y --gc-sections a GNU ld para eliminar las secciones no utilizadas.

    Deberá verificar sus documentos para su versión de gcc & ld:

    Sin embargo, para mí (OS X gcc 4.0.1) encuentro esto para ld

     -dead_strip 

    Elimine las funciones y los datos que son inalcanzables por el punto de entrada o los símbolos exportados.

     -dead_strip_dylibs 

    Elimina dylibs que no son alcanzables por el punto de entrada o símbolos exportados. Es decir, suprime la generación de comandos de comando de carga para dylibs que no suministraron símbolos durante el enlace. Esta opción no se debe utilizar cuando se realiza una vinculación con un archivo dylib que se requiere en el tiempo de ejecución por algún motivo indirecto, como que dylib tiene un inicializador importante.

    Y esta útil opción

     -why_live symbol_name 

    Registra una cadena de referencias a symbol_name. Solo aplicable con -dead_strip . Puede ayudar a depurar por qué no se elimina algo que crees que debería eliminarse.

    También hay una nota en el hombre de gcc / g ++ que dice que ciertos tipos de eliminación de código muerto solo se realizan si la optimización está habilitada al comstackr.

    Si bien estas opciones / condiciones pueden no ser válidas para su comstackdor, le sugiero que busque algo similar en sus documentos.

    Los hábitos de progtwigción también podrían ayudar; por ejemplo, agregar static a las 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); use const char x[] donde sea posible; … este documento , aunque se trata de objetos compartidos dynamics, puede contener sugerencias que, si se siguen, pueden ayudar a reducir el tamaño final de la salida binaria (si su objective es ELF).

    La respuesta es -flto . Tienes que pasarlo a tus pasos de comstackción y enlace, de lo contrario no hace nada.

    De hecho, funciona muy bien: ¡reduje el tamaño de un progtwig de microcontrolador que escribí a menos del 50% de su tamaño anterior!

    Desafortunadamente, parecía un poco defectuoso. Tuve casos de cosas que no se construyeron correctamente. Puede deberse al sistema de comstackción que estoy usando (QBS, es muy nuevo), pero en cualquier caso, le recomendaría que solo lo habilite para su comstackción final, si es posible, y pruebe esa comstackción a fondo.

    Me parece que la respuesta proporcionada por Nemo es la correcta. Si esas instrucciones no funcionan, el problema puede estar relacionado con la versión de gcc / ld que está utilizando, como ejercicio compilé un progtwig de ejemplo usando las instrucciones detalladas aquí.

     #include  void deadcode() { printf("This is d dead codez\n"); } int main(void) { printf("This is main\n"); return 0 ; } 

    Luego compilé el código usando interruptores de eliminación de código muerto progresivamente más agresivos:

     gcc -Os test.c -o test.elf gcc -Os -fdata-sections -ffunction-sections test.c -o test.elf -Wl,--gc-sections gcc -Os -fdata-sections -ffunction-sections test.c -o test.elf -Wl,--gc-sections -Wl,--strip-all 

    Estos parámetros de comstackción y enlace produjeron ejecutables de tamaño 8457, 8164 y 6160 bytes, respectivamente, la contribución más sustancial proveniente de la statement ‘strip-all’. Si no puede producir reducciones similares en su plataforma, entonces tal vez su versión de gcc no admita esta funcionalidad. Estoy usando gcc (4.5.2-8ubuntu4), ld (2.21.0.20110327) en Linux Mint 2.6.38-8-generic x86_64

    Si bien no se trata estrictamente de símbolos, si se trata de tamaños, comstackr siempre con -Os y -s flags. -Os optimiza el código resultante para el tamaño mínimo ejecutable y -s elimina la tabla de símbolos y la información de reubicación del ejecutable.

    A veces, si se desea un tamaño pequeño, jugar con distintas banderas de optimización puede tener significado o no. Por ejemplo, alternar -ffast-math y / o -fomit-frame-pointer a veces puede ahorrar incluso docenas de bytes.

    strip --strip-unneeded solo opera en la tabla de símbolos del ejecutable. En realidad, no elimina ningún código ejecutable.

    Las bibliotecas estándar obtienen el resultado que busca al dividir todas sus funciones en archivos de objetos separados, que se combinan utilizando ar . Si luego vincula el archivo resultante como una biblioteca (es decir, le da la opción -l your_library a ld) entonces ld solo incluirá los archivos objeto, y por lo tanto los símbolos, que realmente se usan.

    También puede encontrar algunas de las respuestas a esta pregunta similar de uso.

    No sé si esto ayudará con su situación actual, ya que esta es una característica reciente, pero puede especificar la visibilidad de los símbolos de forma global. Pasar -fvisibility=hidden -fvisibility-inlines-hidden en la comstackción puede ayudar al enlazador a eliminar más adelante los símbolos innecesarios. Si está produciendo un ejecutable (a diferencia de una biblioteca compartida) no hay nada más que hacer.

    Más información (y un enfoque detallado para, por ejemplo, bibliotecas) está disponible en la wiki de GCC .

    Del manual GCC 4.2.1, sección -fwhole-program :

    Supongamos que la unidad de comstackción actual representa el progtwig completo que se está comstackndo. Todas las funciones y variables públicas con la excepción de main y las fusionadas por atributo externally_visible convierten en funciones estáticas y en un efecto se optimiza de forma más agresiva mediante optimizadores interprocedimientos. Si bien esta opción es equivalente al uso adecuado de palabra clave static para progtwigs que constan de un solo archivo, en combinación con la opción --combine este indicador se puede usar para comstackr la mayoría de los progtwigs de C de menor escala ya que las funciones y variables se vuelven locales para toda la comstackción combinada unidad, no para el único archivo fuente en sí.

    Puede usar strip binary en el archivo de objeto (por ejemplo, ejecutable) para quitar todos los símbolos de él.

    Nota: cambia el archivo y no crea copia.