我正在写一个strcmp bash内置。编译很好,但是当我尝试启用它时,我得到:
$ enable -f ./strcmp strcmp
bash: enable: cannot open shared object ./strcmp: ./strcmp: only ET_DYN and ET_EXEC can be loaded
我内置的重要部分:
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 */
};
编译行(来自扩展的make文件):
~/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
我用Google搜索ET_DYN和ET_EXEC,只找到了这样的问题的链接。
答案 0 :(得分:10)
你注意到-c
标志了吗?这使它无法链接。将其替换为-shared
,如@shr提到的
答案 1 :(得分:7)
对我的具体问题(ET_DYN和ET_EXEC)的答案进行了一些跟进,以及为什么@stanparker的答案是正确的扩展。
ET_DYN和ET_EXEC是ELF可执行类型。在ELF标头中,有一个字段Elf32_Half e_type
或Elf64_Half e_type
,其中包含几个可能的ET_ *枚举。我猜ET是“可执行类型”,EXEC可执行文件和DYN动态。这应该足以表明发出的工件实际上不是任何类型的可执行对象,并且应该鼓励仔细观察GCC标志。 (有关ELF标题的更多信息,http://www.sco.com/developers/gabi/1998-04-29/ch4.eheader.html)
现在我们发现我们没有链接,让我们删除-c标志。然后,我们将得到第二个错误(这次是编译中的某个地方),
$ 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
这里实际上有两个错误。第一个是“对'main'的未定义引用”,第二个是“对`make_builtin_argv'的未定义引用”(bash内部函数)。最后一行足以告诉我们GCC在链接期间正在死亡。函数_start是由glibc定义的公共入口点,glibc本身实际上在程序中调用main。在这一点上,呃,我们不是一个可执行文件,而是一个共享库。将-shared
添加到命令行可以让我们完美地编译。
那么,为什么不给我“正确”的命令行呢? Makefile.in不会动态测试源文件,所以我应该手动添加.c和.o目标,然后重新运行./configure。完成后,我们得到
$ make strcmp
gcc [...] -c -o strcmp.o strcmp.c
gcc -shared -Wl,-soname,strcmp -L./lib/termcap -o strcmp strcmp.o
有效吗?
$ enable -f ./strcmp strcmp
$ strcmp "hi" "ho"
$ echo $?
2
$ strcmp "hi" "ha"
$ echo $?
1
$ strcmp "hi" "hi"
$ echo $?
0
这就是我期望它做的,所以看起来确实有效。
无论如何,我写这篇文章的重点是,这不是我个人第一次搞砸GCC和C编译。这不是我第一次看到有人遇到这些问题。获得成功的C编译需要做大量的工作,每个阶段都很重要。所以,我写这篇文章是为了提醒自己GCC(cc,ld和elf libs)正在做什么,为什么这里和那里的一个小角色很重要,以及整个发现过程。我还没有看到它在其他任何地方打字,所以这就是我所拥有的。
PS。对于那些对此内置感兴趣的人,它将在我的网站http://davidsouther.com/2011/08/bash-strcmp-builtin/
上答案 2 :(得分:2)
我不确定,但是......曾经尝试gcc -shared
?