私はこれに対するサポートをに追加することを探していましたpam_cap.so
、そしてこの質問を見つけました。@EmployedRussianが自分の投稿のフォローアップで述べているように、受け入れられた回答はある時点で機能しなくなりました。これを再び機能させる方法を理解するのに時間がかかったので、ここに実際の例があります。
この実例には、対応するいくつかのテストでどのように機能するかを示す5つのファイルが含まれています。
まず、この些細なプログラムを考えてみましょう(それを呼び出しますempty.c
):
int main(int argc, char **argv) { return 0; }
それをコンパイルすると、次のようにシステム上の動的シンボルがどのように解決されるかを確認できます。
$ gcc -o empty empty.c
$ objcopy --dump-section .interp=/dev/stdout empty ; echo
/lib64/ld-linux-x86-64.so.2
$ DL_LOADER=/lib64/ld-linux-x86-64.so.2
その最後の行は、後で使用するためのシェル変数を設定します。
これが私のサンプル共有ライブラリを構築する2つのファイルです:
/* multi.h */
void multi_main(void);
void multi(const char *caller);
と
/* multi.c */
#include <stdio.h>
#include <stdlib.h>
#include "multi.h"
void multi(const char *caller) {
printf("called from %s\n", caller);
}
__attribute__((force_align_arg_pointer))
void multi_main(void) {
multi(__FILE__);
exit(42);
}
const char dl_loader[] __attribute__((section(".interp"))) =
DL_LOADER ;
(更新2021-11-13:強制的な調整は、コードがSSEと互換性を持つようにするため__i386__
glibc
SIGSEGV
のものです。これがないと、クラッシュのデバッグが困難になります。)
次のようにコンパイルして実行できます。
$ gcc -fPIC -shared -o multi.so -DDL_LOADER="\"${DL_LOADER}\"" multi.c -Wl,-e,multi_main
$ ./multi.so
called from multi.c
$ echo $?
42
つまり、これは.so
スタンドアロンのバイナリとして実行できるものです。次に、共有オブジェクトとしてロードできることを検証します。
/* opener.c */
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
void *handle = dlopen("./multi.so", RTLD_NOW);
if (handle == NULL) {
perror("no multi.so load");
exit(1);
}
void (*multi)(const char *) = dlsym(handle, "multi");
multi(__FILE__);
}
つまり、共有オブジェクトを動的にロードし、そこから関数を実行します。
$ gcc -o opener opener.c -ldl
$ ./opener
called from opener.c
最後に、この共有オブジェクトに対してリンクします。
/* main.c */
#include "multi.h"
int main(int argc, char **argv) {
multi(__FILE__);
}
次のようにコンパイルして実行します。
$ gcc main.c -o main multi.so
$ LD_LIBRARY_PATH=./ ./main
called from main.c
(は標準のシステムライブラリの場所にないため、ランタイムが環境変数multi.so
を使用して共有オブジェクトファイルを検索する場所をオーバーライドする必要があることに注意してください。)LD_LIBRARY_PATH