2011-06-20 7 views
9

Actualmente estoy usando GCC 4.5.3, compilado para PowerPC 440, y estoy compilando código que no requiere libc. No tengo ninguna llamada directa a memcpy(), pero el compilador parece estar insertando uno durante la compilación.Obtención de GCC para compilar sin insertar la llamada a memcpy

Existen opciones de vinculador como -nostdlib, -nostartfiles, -nodefaultlibs pero no puedo usarlos ya que no estoy haciendo la fase de vinculación. Solo estoy compilando. Con algo como esto:

$ powerpc-440-eabi-gcc -O2 -g -c -o output.o input.c 

Si puedo comprobar el output.o con nm, veo una referencia al establecimiento de memoria:

$ powerpc-440-eabi-nm output.o | grep memcpy 
    U memcpy 
$ 

La página del CCG deja claro cómo quitar las llamadas al establecimiento de memoria y otras llamadas de libc con el enlazador, pero no quiero que el compilador las inserte en primer lugar, ya que estoy usando un enlazador completamente diferente (no el ld de GNU, y no sabe acerca de libc).

Gracias por cualquier ayuda que pueda proporcionar.

+0

Si nada de esto funciona, un byte byte por simples , La implementación basada en CPU de memcpy suficiente al menos para casos raramente utilizados es probablemente más corta que la mayoría de las respuestas po sted aquí. –

Respuesta

5

Necesita desactivar esa optimización con -fno-builtin. Tuve este problema una vez cuando intenté compilar memcpy para una biblioteca C. Se llamaba a sí mismo. Oops!

+1

¡Gracias por su respuesta! Después de leer todo el manual, parece que -fno-builtin o -ffreestanding debería hacer exactamente lo que necesito. Pero después de agregar esos modificadores de compilación, sigo recibiendo dos referencias a memcpy. ¿Cualquier otra sugerencia? – Brian

+0

@Brian: He acertado exactamente el mismo problema. ¿Es esto solo un error de GCC? –

+0

Sí, desafortunadamente, esta no es la respuesta correcta: hay casos en que las llamadas 'mem *' todavía están insertadas, sin importar qué. Ver la respuesta de Droopycom, ¡esa es la verdadera! –

3

También puede hacer que su binario de un "independiente" uno:

Los ISO C define estándar (en la cláusula 4) dos clases de conformidad aplicación. Una implementación alojada conforme admite todo el estándar [...]; solo se requiere una implementación independiente conforme para proporcionar ciertas instalaciones de biblioteca: las de,, y; desde AMD1, también aquellos en; y en C99, también aquellos en y. [...].

El estándar también define dos ambientes para los programas, un entorno independiente, se requieren de todas las implementaciones y que pueden no tener instalaciones de la biblioteca además de las requeridas de las implementaciones de Independiente, donde el manejo de inicio del programa y de terminación son definido por la implementación, y una entorno alojado, que no es obligatorio, en el que se proporcionan todas las instalaciones de la biblioteca y el inicio se realiza a través de una función int main (void) o int main (int, char * []).

Un núcleo del sistema operativo sería un entorno independiente; un programa que utiliza las instalaciones de un sistema operativo normalmente estaría en una implementación alojada.

(párrafo agregado por mí)

Más here. Y las opciones de gcc correspondientes (palabras clave -freestanding o -fno-builtin) pueden encontrarse en here.

5

Gcc emite llamadas a memcpy en algunas circunstancias, por ejemplo, si está copiando una estructura. No hay forma de cambiar el comportamiento de GCC, pero puede intentar evitarlo modificando su código para evitar dicha copia. La mejor apuesta es mirar el ensamblaje para descubrir por qué gcc emitió el memcpy y tratar de evitarlo. Esto va a ser molesto, ya que básicamente necesitas entender cómo funciona gcc.

Extracto de http://gcc.gnu.org/onlinedocs/gcc/Standards.html:

La mayor parte de las rutinas de soporte del compilador utilizado por GCC están presentes en libgcc, pero hay algunas excepciones. GCC requiere que el entorno independiente proporcione memcpy, memmove, memset y memcmp.Finalmente, si se usa __builtin_trap, y el objetivo no implementa el patrón de trampa, entonces GCC emitirá una llamada para abortar.

+0

Notamos que gcc recurría a memcpy cuando inicializamos una matriz local: int x [4] = {1,2,3,4}; Presumiblemente, gcc tuvo que copiar estos datos en la pila local cada vez que ingresamos a la función. Así que cambiarlo a una definición estática hizo que el problema desapareciera. estática const int x [4] = {1,2,3,4}; – phord

+1

Sí, pero también cambió el significado del código: es decir, si su función está cambiando x, entonces no será {1,2,3,4} al comienzo de la siguiente llamada ... – Droopycom

+0

Correcto, pero en este caso, prometemos no cambiar los datos. Aseguramos esa promesa al declararlo como 'const int' array. Y sí, podríamos dispararnos lanzando const, pero nos tomamos la seguridad de las armas muy en serio aquí y no tomamos esa tontería. El problema restante podría ser que nuestra matriz ahora está en .data en lugar de en la pila local. Pero esto tampoco es una preocupación para nuestro uso. YMMV. – phord

3

No hay necesidad de -fno-builtins o -ffreestanding ya que innecesariamente se desactivar muchas optimizaciones importantes

Esto es en realidad "optimizado" por el árbol-loop-distribuir los patrones de GCC, por lo que para deshabilitar el comportamiento no deseado mientras se mantiene la utilidad capacidades incorporadas, sólo puede utilizar:

-fno-tree-loop-distribute-patterns

MUSL-libc utiliza esta bandera para su construcción y tiene la siguiente nota en su script de configuración (miré a través de la fuente y no se encontró ninguna macro, por lo que este debe ser lo suficientemente)

# Compruebe si hay opciones que pueden ser necesarios para evitar que el compilador de
# generando versiones auto-referenciales de establecimiento de memoria ,, memmove, memcmp,
# y memset. En realidad, hay que añadir una comprobación para determinar si esto
# opción es suficiente, y si no, añadir una macro para paralizar estas
# funciones con volátil ...
# tryflag CFLAGS_MEMOPS -fno-árbol-loop-distribuir -patterns

también puede agregar esto como un atributo de las funciones individuales en gcc usando su atributo a optimizar, de manera que otras funciones se pueden beneficiar de llamar mem*()

Cuestiones relacionadas