需要跳过库内的命令参数

需要跳过库内的命令参数

我想跳过库的初始化部分中的命令参数。库的初始化部分是:

static void pa_init_services (void) __attribute__((constructor (102)));
static void pa_init_services()

IE,它在程序内的 main() 调用之前执行。我想实现我所说的“撕掉”参数,也就是说我想查看参数的前面,检查参数是否属于我的库,然后仅为我的库解析这些选项,然后删除在 main() 获取它们之前从列表中取出它们。我不控制哪个程序包含 main(),这是用于链接到客户端程序的通用库。

例如,如果我实际上可以访问 argv POINTER 和实际的 argc 位置,那么我可以简单地执行解析和跳过过程。

GTK 文档中提到(例如)此过程,GTK 解析特定于它的选项,并在客户端程序获取它们之前跳过它们。

答案1

在 Linux[1] 上,您可以覆盖库中的__libc_start_main()函数(调用该函数的包装器)。main()您可以多次这样做。

例子:

#define _GNU_SOURCE     /* for RTLD_NEXT */
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <err.h>
#ifdef __UCLIBC__
#define __libc_start_main       __uClibc_main
#endif
#define STR_(s) #s
#define STR(s)  STR_(s)
int __libc_start_main(
        int (*main)(int,char**,char**), int ac, char **av,
        int (*init)(int,char**,char**), void (*fini)(void),
        void (*rtld_fini)(void), void *stack_end)
{
        typeof(__libc_start_main) *real_lsm;
        if(*(void**)&real_lsm = dlsym(RTLD_NEXT, STR(__libc_start_main)))
                return real_lsm(main, ac - 1, av + 1, init, fini, rtld_fini, stack_end);
        else
                errx(1, "BUG: dlsym: %s", dlerror());
}
$ cc -fPIC -shared -Wall -W -Wno-parentheses skip.c -o skip1.so -ldl
$ cc -fPIC -shared -Wall -W -Wno-parentheses skip.c -o skip2.so -ldl
$ LD_PRELOAD="./skip1.so ./skip2.so" /bin/echo a b c d
c d

如果您显式地将程序链接到skip1.so等库,这也适用。您甚至可以execve()使用完全不同的参数来创建一个完全不同的程序。

[1] 这也适用于musl,尽管它__libc_start_main不需要参数rtld_fini。在 uclibc 中,等效函数是__uClibc_main.

答案2

可能已经找到了我自己的答案:

https://stackoverflow.com/questions/36998143/alternative-way-to-obtain-argc-and-argv-of-a-process

__attribute__((constructor)) void stuff(int argc, char **argv)
{
    for (int i=0; i<argc; i++) {
        printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
    }
}

当然,问题仍然是跳过参数,即,您可以查看参数,但是当 main() 程序发现您的 lib 参数与它自己的参数混合时,它将会失败。

相关内容