2011-08-31 7 views
7

Estoy escribiendo un strcmp bash incorporado. Se compila bien, pero cuando intento para que pueda, me sale:Carga Bash Builtin

$ enable -f ./strcmp strcmp 
bash: enable: cannot open shared object ./strcmp: ./strcmp: only ET_DYN and ET_EXEC can be loaded 

Los grandes partes de mi orden interna:

strcmp_builtin (list) 
WORD_LIST *list; 

char *strcmp_doc[] = { 
    (char *)NULL 
}; 

struct builtin strcmp_struct = { 
    "strcmp", /* builtin name */ 
    strcmp_builtin, /* function implementing the builtin */ 
    BUILTIN_ENABLED, /* initial flags for builtin */ 
    strcmp_doc, /* array of long documentation strings. */ 
    "strcmp 'string 1' 'string 2'", /* usage synopsis; becomes short_doc */ 
    0 /* reserved for internal use */ 
}; 

La línea de compilación (desde el archivo make ampliado):

~/bash-4.2/examples/loadables $ gcc -fPIC -DHAVE_CONFIG_H -DSHELL \ 
-g -O2 -I. -I.. -I../.. -I../../lib -I../../builtins -I../../include \ 
-I~/bash-4.2 -I~/bash-4.2/lib -I~/bash-4.2/builtins -c \ 
-o strcmp strcmp.c 

He buscado ET_DYN y ET_EXEC, y solo he encontrado enlaces a preguntas como esta.

Respuesta

10

¿Notaste la bandera -c? Eso es evitar que se vincule. Reemplace eso con -shared, como @shr mencionó

+1

Tonta, confiando en el archivo make sin mirar siquiera. Sí, no me gustaba. ¡Gracias! –

2

No estoy seguro, pero ... Alguna vez intenté gcc -shared?

7

Un poco de seguimiento en una respuesta a mi pregunta específica (ET_DYN y ET_EXEC), así como una expansión en WHY @ la respuesta de stanparker es correcta.

ET_DYN y ET_EXEC son tipos ejecutables ELF. En el encabezado ELF, hay un campo Elf32_Half e_type o Elf64_Half e_type con varias encripciones posiblemente ET_ *. Supongo que ET es "Executable Type", EXEC ejecutable y DYN Dynamic. Esto debería ser suficiente para mostrar que el artefacto emitido no era, de hecho, un objeto ejecutable de ningún tipo, y debería haber alentado a mirar más de cerca las banderas del CCG. (Para más información sobre los encabezados ELF, http://www.sco.com/developers/gabi/1998-04-29/ch4.eheader.html)

Ahora que vemos que no estamos enlazando, eliminemos el distintivo -c. Entonces, obtendremos un segundo error (esta vez en algún lugar de la compilación),

$ gcc [...] -o strcmp.o strcmp.c 
/usr/lib/gcc/i686-redhat-linux/4.6.0/../../../crt1.o: In function `_start': 
(.text+0x18): undefined reference to `main' 
/tmp/ccaiMtdc.o: In function `strcmp_builtin': 
~/bash-4.2/examples/loadables/strcmp.c:32: undefined reference to `make_builtin_argv' 
collect2: ld returned 1 exit status 

En realidad, hay dos errores aquí. La primera es "referencia indefinida a` main '", la segunda es" referencia indefinida a `make_builtin_argv'" (una función interna de bash). La última línea es suficiente para mostrarnos que GCC está muriendo durante la vinculación. La función _start es un punto de entrada común definido por glibc, que en realidad llama main al programa. En este punto, duh, no estamos haciendo un ejecutable, sino una lib compartida. Agregar -shared a la línea de comandos nos hace compilar perfectamente.

Entonces, ¿por qué no se me dio la línea de comando "Correcto"? Makefile.in no prueba dinámicamente los archivos fuente, por lo que debería haber agregado los objetivos .c y .o a mano, y luego volver a ejecutar ./configure. Después de hacerlo, obtenemos

$ make strcmp 
gcc [...] -c -o strcmp.o strcmp.c 
gcc -shared -Wl,-soname,strcmp -L./lib/termcap -o strcmp strcmp.o 

Cómo funciona?

$ enable -f ./strcmp strcmp 
$ strcmp "hi" "ho" 
$ echo $? 
2 
$ strcmp "hi" "ha" 
$ echo $? 
1 
$ strcmp "hi" "hi" 
$ echo $? 
0 

Eso es lo que espero que haga, por lo que parece que funciona.

De todos modos, lo importante de mí escribir esto es que esta no es la primera vez que personalmente me he echado a perder en compilación de GCC y C en general. Esta no es la primera vez que veo a alguien tener estos problemas en general. Hay una enorme cantidad de trabajo que se dedica a obtener una compilación C exitosa, y cada fase es importante. Por lo tanto, estoy escribiendo esto para recordarme a mí mismo exactamente qué estaban haciendo GCC (cc, ld, y elfls libs), por qué el pequeño personaje aquí y allá es importante y el proceso general de descubrimiento. No lo he visto mecanografiado en ningún otro lado, así que aquí está lo que tengo.

PS.Para aquellos interesados ​​en este built-in, estará en mi sitio, http://davidsouther.com/2011/08/bash-strcmp-builtin/