2011-08-31 19 views
7

私はstrcmp bashビルトインを書いています。それは罰金コンパイルが、私はそれを有効にしようとすると、私が手:私の組み込みのロード可能な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 

私はET_DYNとET_EXECをグーグルで見つけましたが、このような質問へのリンクしか見つかりませんでした。

答えて

10

-cフラグに気付きましたか?それはリンクを維持しています。それを-sharedと置き換えてください@@と書いてあります。

+1

見ていなくてもmakeファイルを信頼してください。うん、好きではなかった。ありがとう! –

2

私はよく分かりませんが、これまでに試したことがありますgcc -shared

7

私の特定の質問(ET_DYNとET_EXEC)に対する回答と、WHY @ 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フラグを削除してみましょう。次に、2番目のエラー(今度はコンパイルのどこか)を取得します。

$ 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 

実際には2つのエラーがあります。最初は "main"への未定義参照で、2番目は "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、elf libs)がやっていたこと、ここの小さなキャラクターがなぜ重要か、全体的な発見プロセスを思い出させるために、これを書いています。私はそれがどこにでも入力されて見たことがないので、ここに私が持っているものです。

PS。この組み込みに興味がある人は、私のサイトにあります。http://davidsouther.com/2011/08/bash-strcmp-builtin/

関連する問題