可装载的Bash内置

时间:2011-08-31 04:27:57

标签: c bash strcmp built-in

我正在写一个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,只找到了这样的问题的链接。

3 个答案:

答案 0 :(得分:10)

你注意到-c标志了吗?这使它无法链接。将其替换为-shared,如@shr提到的

答案 1 :(得分:7)

对我的具体问题(ET_DYN和ET_EXEC)的答案进行了一些跟进,以及为什么@stanparker的答案是正确的扩展。

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