可装载猛砸内建
我正在写一个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,只发现链接这样的问题。
你注意到-c
标志?这阻止了链接。替换为-shared
,因为@shr提到
我不知道,但是......试过gcc -shared
?
对我的具体问题(ET_DYN和ET_EXEC)的回答稍作跟踪,以及为什么@Stanparker的回答是正确的。
ET_DYN和ET_EXEC是ELF可执行类型。在ELF头,有一个字段Elf32_Half e_type
或Elf64_Half e_type
与几个可能ET_ *枚举。我猜ET是“Executable Type”,EXEC可执行文件和DYN Dynamic。这应该足以证明所发射的神器实际上不是任何类型的可执行对象,并且应该鼓励仔细观察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
这里实际存在两个错误。第一个是“未定义参考`主”,第二个是“未定义参考`make_builtin_argv'”(一个bash内部功能)。最后一行足以向我们展示GCC在链接期间正在死亡。函数_start是由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和精灵库)在做什么,为什么一个小角色我自己在这里和那里是非常重要的,整体的发现过程。我没有看到它在其他地方输入,所以这里是我的。
PS。对于那些对这个内建感兴趣的人,它会在我的网站上,http://davidsouther.com/2011/08/bash-strcmp-builtin/
愚蠢的我,相信制造文件,甚至没有看。是的,它不喜欢。谢谢! –