es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Descarte la función teóricamente utilizada pero técnicamente no utilizada.

¿Hay alguna forma de descartar una función/símbolo de un archivo de salida (.exe/.elf) aunque pueda ser llamado?

Supongamos que una biblioteca de terceros hace algo como esto:

int lib_func_get(int c) {
if (c < 5) {
return foo();
} else {
return bar()
}
}

Y sabes con certeza que c nunca es < 5, entonces me gustaría omitir/eliminar foo() de mi ejecutable para reducir el tamaño binario.

¿Cómo puedo hacer esto? ¿Quizás con la ayuda del script del enlazador y descartando .text.foo?

El enlazador de GCC tiene una sección similar para esto, /DISCARD/, pero la vinculación falla porque la función se usa:

refers [symbol], which is defined in a discarded section

El trasfondo de mi pregunta es reducir el tamaño binario de las aplicaciones empotradas, especialmente los cargadores de arranque, donde no se puede volver a compilar una biblioteca de terceros o la biblioteca forma parte de la cadena de herramientas (por ejemplo, libgcc) y no quieres modificar y reconstruir toda la cadena de herramientas.

Sé que esto puede ser un enfoque hacky pero me gustaría hacer esto.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible descartar una función/símbolo de un archivo de salida incluso si puede ser llamado. Una forma de hacer esto es usando la opción -gc-sections del enlazador. Esta opción le indica al enlazador que elimine secciones no utilizadas del archivo de salida.

    Para usar esta opción, necesita compilar y enlazar su programa con las opciones -ffunction-sections y -fdata-sections. Estas opciones le indican al compilador que coloque cada función y variable en su propia sección.

    Luego, cuando enlace su programa, puede agregar la opción -Wl,--gc-sections a la línea de comandos del enlazador. Esto le indicará al enlazador que elimine cualquier sección no utilizada del archivo de salida.

    Para descartar explícitamente una función/símbolo específico, puede usar la opción --undefined del enlazador. Esta opción le indica al enlazador que un símbolo no está definido, incluso si en realidad está definido en los archivos de entrada. Puede usar esta opción para “ocultar” una función/símbolo del enlazador para que no lo incluya en el archivo de salida.

    Por ejemplo, para descartar la función lib_func_get de su archivo de salida, podría usar la siguiente línea de comandos del enlazador:

    gcc main.o lib.o -Wl,--gc-sections -Wl,--undefined=lib_func_get -o myprogram
    

    Esto le indica al enlazador que descarte cualquier sección no utilizada y que trate la función lib_func_get como no definida. El enlazador entonces no incluirá la función foo() en el archivo de salida, ya que ya no se utiliza.

    Tenga en cuenta que este enfoque puede ser complicado y puede que no siempre funcione como se espera. Si una función/símbolo se llama indirectamente (a través de un puntero a función o una tabla de funciones virtuales, por ejemplo), puede que no sea posible eliminarlo por completo. Además, si la función/símbolo es necesaria para algún otro propósito (como el manejo de excepciones o la carga dinámica), eliminarlo podría romper su programa. Por lo tanto, generalmente es mejor confiar en técnicas de optimización estándar (como la eliminación de código muerto e inline de funciones) en lugar de intentar eliminar manualmente funciones/símbolos individuales.

Comments are closed.