libbfd
あー。
http://shinh.skr.jp/koneta/#shelang
シンボルが消された .so 内のロード、あっさりできた。 readelf とか見てたけどそんなこと以前に bfd_*dynamic_symtab* シリーズを使えばオッケー。これならシンボル情報を dynamic セクションから読むってことで、ローダが読んでる情報と同じになるはず。
先人偉い。 binutils 偉い。
mod_estraier-0.3.0
http://modestraier.sourceforge.net/
http://prdownloads.sourceforge.net/modestraier/mod_estraier-0.3.0.tar.gz?download
mod_estraier_cache を作ってみたがこの程度の再生能力ではわりとイマイチ。
http://shinh.skr.jp/tmp/mod_estraier_cache.html
後は Hyper Estraier 1.0.3 にあわせてちょこちょことか。
libffi
http://shinh.skr.jp/koneta/#shelang
更新しないと思ってたけど更新しました。
http://d.hatena.ne.jp/shinichiro_h/20051027#1130351251
の続きです。 libffi を紹介していただいたので使ってみました。生成されていた 7400行とかあった dispatch.c が完全にいらなくなってなんかハッピーチックです。
sayさん に指摘いただいたのですが、シンボルテーブルが無い .so ファイルだとダメです。 objdump やら ld やらはシンボルテーブル無くてもシンボル名からアドレス引いてやがるのでそのへん勉強してみようと思います。あと、どうやら libc のような最初っから読まれているシンボルは dlsym(RTLD_DEFAULT, "puts") などで取れるみたいなので見つからない場合はそれを使ってみました。
追記: シンボルテーブルの無い .so ファイルは elf.h とか使って .dynsym テーブルを読めばいい。実際のシンボル名はどう見ても .rodata にある。まぁちょっと調べりゃわかりそう… readelf -r がズバリっぽい。
以下 libffi について。
■
……面倒になったのでコードはって終わり。
#include <ffi.h>
ffi_type *get_ffi_type(reflection_type_t type) {
switch (type) {
case R_CHAR:
return &ffi_type_sint8;
case R_INT:
return &ffi_type_sint32;
case R_FLOAT:
return &ffi_type_float;
case R_PTR:
return &ffi_type_pointer;
default:
return &ffi_type_void;
}
}
int reflection_dispatch(
reflection_t* ref, const char* name, reflection_type_t rtype,
int arg_num, reflection_value_t* args, reflection_type_t* types,
reflection_value_t* ret)
{
reflection_sym_t** asym =
(reflection_sym_t**)htab_find_slot(ref->syms, name, NO_INSERT);
void* fp = NULL;
if (!asym) {
#ifdef __USE_GNU
fp = (void*)dlsym(RTLD_DEFAULT, name);
#endif
if (fp == 0) return 1;
}
else {
fp = (void*)((*asym)->fp);
}
{
ffi_cif cif;
ffi_type* as[32];
void* vs[32];
ffi_arg rv;
ffi_type* rt;
int i;
for (i = 0; i < arg_num; i++) {
as[i] = get_ffi_type(types[i]);
if (as[i] == &ffi_type_void) return 1;
vs[i] = &args[i];
}
rt = get_ffi_type(rtype);
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, arg_num, rt, as) != FFI_OK) {
return 1;
}
ffi_call(&cif, FFI_FN(fp), &rv, vs);
if (rtype != R_VOID) {
*ret = *(reflection_value_t*)&rv;
}
return 0;
}
}