可装载猛砸内建

可装载猛砸内建

问题描述:

我正在写一个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提到

+1

愚蠢的我,相信制造文件,甚至没有看。是的,它不喜欢。谢谢! –

我不知道,但是......试过gcc -shared

对我的具体问题(ET_DYN和ET_EXEC)的回答稍作跟踪,以及为什么@Stanparker的回答是正确的。

ET_DYN和ET_EXEC是ELF可执行类型。在ELF头,有一个字段Elf32_Half e_typeElf64_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/