Makefile for LD_PRELOAD __libc_start_main
Makefile for LD_PRELOAD __libc_start_main
我想做的很简单。当我启动猫鼬服务器时,我想创建一个额外的线程来做一些额外的工作。为此,我认为我需要LD_PRELOAD
服务器的__libc_start_main
。
/* This is spec_hooks.cpp */
typedef int (*main_type)(int, char**, char**);
struct arg_type
{
char **argv;
int (*main_func) (int, char **, char **);
};
main_type saved_init_func = NULL;
void tern_init_func(int argc, char **argv, char **env){
dprintf("%04d: __tern_init_func() called.n", (int) pthread_self());
if(saved_init_func)
saved_init_func(argc, argv, env);
__tern_prog_begin(); //create a new thread in this function
}
extern "C" int my_main(int argc, char **pt, char **aa)
{
int ret;
arg_type *args = (arg_type*)pt;
dprintf("%04d: __libc_start_main() called.n", (int) pthread_self());
ret = args->main_func(argc, args->argv, aa);
return ret;
}
extern "C" int __libc_start_main(
void *func_ptr,
int argc,
char* argv[],
void (*init_func)(void),
void (*fini_func)(void),
void (*rtld_fini_func)(void),
void *stack_end)
{
typedef void (*fnptr_type)(void);
typedef int (*orig_func_type)(void *, int, char *[], fnptr_type,
fnptr_type, fnptr_type, void*);
orig_func_type orig_func;
arg_type args;
void * handle;
int ret;
// Get lib path.
Dl_info dli;
dladdr((void *)dlsym, &dli);
std::string libPath = dli.dli_fname;
libPath = dli.dli_fname;
size_t lastSlash = libPath.find_last_of("/");
libPath = libPath.substr(0, lastSlash);
libPath += "/libc.so.6";
libPath = "/lib/x86_64-linux-gnu/libc.so.6";
if(!(handle=dlopen(libPath.c_str(), RTLD_LAZY))) {
puts("dlopen error");
abort();
}
orig_func = (orig_func_type) dlsym(handle, "__libc_start_main");
if(dlerror()) {
puts("dlerror");
abort();
}
dlclose(handle);
dprintf("%04d: __libc_start_main is hooked.n", (int) pthread_self());
args.argv = argv;
args.main_func = (main_type)func_ptr;
saved_init_func = (main_type)init_func;
saved_fini_func = (fini_type)rtld_fini_func;
ret = orig_func((void*)my_main, argc, (char**)(&args),
(fnptr_type)tern_init_func, (fnptr_type)fini_func,
rtld_fini_func, stack_end);
return ret;
}
但是,我不知道如何为此编写生成文件。有人可以给我任何帮助吗?有什么需要注意的吗?
关于makefiles问题的答案是,你想写这样的东西:
CFLAGS ?= -Wall -Wextra
all: mylib.so
mylib.so: mylib.o
gcc -o $@ -shared $(CFLAGS) $(LDFLAGS) $^
它使用隐式规则来生成共享对象所需的 .o 文件。(你还需要 -fPIC 在 CFLAGS 中用于x86_64,可能还需要 -pthread 以获得良好的度量,在 LDFLAGS 中使用 -ldl(。
问题的症结可以大大简化。要在初始化初期在LD_PRELOADed库中创建一个额外的线程,您只需执行以下操作:
static void start_my_thread() __attribute__((constructor));
static void start_my_thread() {
// Call pthread_create here and then return
}
它使用 gcc __attribute__
扩展来注册要在库加载期间自动调用的函数(即在main()
被命中之前(。
此外,即使您
想按照您展示的方式进行操作,您也可以通过使用伪库句柄RTLD_NEXT
来查找当前库之后的下一个符号出现,从而大大简化它。
所以当你写:
Dl_info dli; dladdr((void *)dlsym, &dli); std::string libPath = dli.dli_fname; libPath = dli.dli_fname; size_t lastSlash = libPath.find_last_of("/"); libPath = libPath.substr(0, lastSlash); libPath += "/libc.so.6"; libPath = "/lib/x86_64-linux-gnu/libc.so.6"; if(!(handle=dlopen(libPath.c_str(), RTLD_LAZY))) { puts("dlopen error"); abort(); } orig_func = (orig_func_type) dlsym(handle, "__libc_start_main");
这可以写成:
orig_func = (orig_func_type) dlsym(RTLD_NEXT, "__libc_start_main");
这也允许多个LD_PRELOAD库通过链接将它们插入相同的函数。
即使您确实出于某种原因明确地在libc上调用dlopen
(尽管RTLD_NEXT/RTLD_DEFAULT(,我也建议您在用于打开它的标志中添加RTLD_NOLOAD,这样您就不会在某些晦涩的配置上遇到奇怪的错误打开两个不同的libc副本!
相关文章:
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 代码在main()中运行,但在函数中出现错误
- 在Google Kick start中提交时出错
- 当我在main中声明了我的2d数组时,为什么我的程序会退出
- QML:修改在不同QML文件(而非main.QML)中定义的子对象的属性
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 函数是否可以访问传递给main()的参数
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 我的 int main() 中出现堆栈溢出错误
- C++变量名(可以将 main 声明为变量,但对于其他函数名称则不然)
- 当我尝试在 Main 中调用插入函数时,它不是取数字?
- File.cpp.o:OpenPose 标志 CMakeFiles/.. 的多重定义/main.cpp.o:首先在这里定
- 为什么类和 main() 函数中也有动态内存分配
- 在 main.cpp 的上下文中找不到目录(带有 CMake 的快板)
- 我想在 Main 中用 C++ 调用其他类中的一个类,但我做不到
- "main"函数堆栈中的对象在第一个任务运行时被覆盖 (FreeRTOS)
- 为什么 'main' 函数中的局部 int 变量会自动初始化?
- "Unable to start debugging. No process is associated with this object." - 在Visual Studio Code中使用GDB
- C++ assigment std::list:<typename>:itrator 在 main 中工作,但在方法中它不起作用
- C++生成文件错误"implicit entry/start for main executable"