简体   繁体   English

可装载的Bash内置

[英]Loadable Bash Builtin

I'm writing a strcmp bash builtin. 我正在写一个strcmp bash内置。 It compiles fine, but when I try to enable it, I get: 编译很好,但是当我尝试启用它时,我得到:

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

The big parts of my builtin: 我内置的重要部分:

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 */
};

The compile line (from the expanded make file): 编译行(来自扩展的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

I have googled ET_DYN and ET_EXEC, and only found links to questions like this. 我用Google搜索ET_DYN和ET_EXEC,只找到了这样的问题的链接。

Did you notice the -c flag? 你注意到-c标志了吗? That's keeping it from linking. 这使它无法链接。 Replace that with -shared , as @shr mentioned 更换与-shared ,如@shr提到

A little follow up on an answer to my specific question (ET_DYN and ET_EXEC), as well as an expansion on WHY @stanparker's answer is correct. 对我的具体问题(ET_DYN和ET_EXEC)的答案进行了一点跟进,以及为什么@stanparker的答案是正确的扩展。

ET_DYN and ET_EXEC are ELF Executable types. ET_DYN和ET_EXEC是ELF可执行类型。 In the ELF header, there is a field Elf32_Half e_type or Elf64_Half e_type with several possibly ET_* enums. 在ELF头中,有一个字段Elf32_Half e_typeElf64_Half e_type其中有几个可能的ET_ *枚举。 I'm guessing ET is "Executable Type", EXEC executable and DYN Dynamic. 我猜ET是“可执行类型”,EXEC可执行文件和DYN动态。 This should all be enough to show that the emitted artifact was not, in fact, an executable object of any kind, and should have encouraged looking closer at the GCC flags. 这应该足以表明发出的工件实际上不是任何类型的可执行对象,并且应该鼓励仔细观察GCC标志。 (For more on the ELF headers, http://www.sco.com/developers/gabi/1998-04-29/ch4.eheader.html ) (有关ELF标题的更多信息, 请访问http://www.sco.com/developers/gabi/1998-04-29/ch4.eheader.html

Now that we see we aren't linking, let's remove the -c flag. 现在我们看到我们没有链接,让我们删除-c标志。 Then, we'll get a second error (this time somewhere in the compile), 然后,我们将得到第二个错误(这次是编译中的某个地方),

$ 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

There are actually two errors here. 这里实际上有两个错误。 The first is "undefined reference to `main'", the second is "undefined reference to `make_builtin_argv'" (a bash internal function). 第一个是“对'main'的未定义引用”,第二个是“对`make_builtin_argv'的未定义引用”(bash内部函数)。 The last line is enough to show us GCC is dying during linking. 最后一行足以告诉我们GCC在链接期间正在死亡。 The function _start is a common entry point defined by glibc, which itself actually calls main in the program. 函数_start是由glibc定义的公共入口点,glibc本身实际上在程序中调用main。 At this point, duh, we aren't making an executable, but a shared lib. 在这一点上,呃,我们不是一个可执行文件,而是一个共享库。 Adding -shared to the command line gets us compiling perfectly. 在命令行中添加-shared可以让我们完美地编译。

So, why wasn't make giving me the "Correct" command line? 那么,为什么不给我“正确”的命令行呢? Makefile.in doesn't dynamically test for source files, so I should have added the .c and .o targets by hand, then rerunning ./configure. Makefile.in不会动态测试源文件,所以我应该手动添加.c和.o目标,然后重新运行./configure。 After doing so, we get 这样做之后,我们得到了

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

Does it work? 它有用吗?

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

That's what I expect it to do, so it seems it does work. 这就是我期望它做的,所以看起来确实有效。

Anyway, the point of me writing this up is that this is not the first time I've personally gotten messed up on GCC and C compiling in general. 无论如何,我写这篇文章的重点是,这不是我个人第一次搞砸GCC和C编译。 This is not the first time I've seen someone have these problems in general. 这不是我第一次看到有人遇到这些问题。 There is a tremendous amount of work that goes into getting a successful C compile, and each phase is important. 获得成功的C编译需要做大量的工作,每个阶段都很重要。 So, I'm writing this up to remind myself of exactly what GCC (cc, ld, and the elf libs) were doing, why the one little character here and there is important, and the overall discovery process. 所以,我写这篇文章是为了提醒自己GCC(cc,ld和elf libs)正在做什么,为什么这里和那里的一个小角色很重要,以及整个发现过程。 I haven't seen it typed up anywhere else, so here is what I have. 我还没有看到它在其他任何地方打字,所以这就是我所拥有的。

PS. PS。 For those interested in this builtin, it will be on my site, http://davidsouther.com/2011/08/bash-strcmp-builtin/ 对于那些对这个内置感兴趣的人,它将在我的网站上, http://davidsouther.com/2011/08/bash-strcmp-builtin/

我不确定,但是......曾经尝试过gcc -shared

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM