pthread_cond_broadcast 被 dlsym 破坏了?

2024-04-13

我正在尝试使用 LD_PRELOAD 机制插入对 pthread_cond_broadcast 的调用。我插入的 pthread_cond_broadcast 函数只是调用原始的 pthread_cond_broadcast 。然而,对于一个非常简单的 pthread 代码,其中 pthread_cond_wait 和 pthread_cond_broadcast 都被调用,我最终要么在 glibc 中出现段错误(对于 glibc 2.11.1),要么程序挂起(对于 glibc 2.15)。有任何线索吗?

插入代码(编译为共享库):

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <dlfcn.h>

static int (*orig_pthread_cond_broadcast)(pthread_cond_t *cond) = NULL;

__attribute__((constructor))
static void start() {
    orig_pthread_cond_broadcast =
        (int (*)()) dlsym(RTLD_NEXT, "pthread_cond_broadcast");
    if (orig_pthread_cond_broadcast == NULL) {
        printf("pthread_cond_broadcast not found!!!\n");
        exit(1);
    }
}

__attribute__((__visibility__("default")))
int pthread_cond_broadcast(pthread_cond_t *cond) {
    return orig_pthread_cond_broadcast(cond);
}

简单的pthread程序:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t cond_mutex;
pthread_cond_t cond_var;
int condition;

void *thread0_work(void *arg) {
    pthread_mutex_lock(&cond_mutex);
    printf("Signal\n");
    condition = 1;
    pthread_cond_broadcast(&cond_var);
    pthread_mutex_unlock(&cond_mutex);
    return NULL;
}

void *thread1_work(void *arg) {
    pthread_mutex_lock(&cond_mutex);
    while (condition == 0) {
        printf("Wait\n");
        pthread_cond_wait(&cond_var, &cond_mutex);
        printf("Done waiting\n");
    }
    pthread_mutex_unlock(&cond_mutex);
    return NULL;
}

int main() {
    pthread_t thread1;

    pthread_mutex_init(&cond_mutex, NULL);
    pthread_cond_init(&cond_var, NULL);

    pthread_create(&thread1, NULL, thread1_work, NULL);

    // Slowdown this thread, so the thread 1 does pthread_cond_wait.
    usleep(1000);

    thread0_work(NULL);

    pthread_join(thread1, NULL);

    return 0;
}

EDIT:

对于 glibc 2.11.1,gdb bt 给出:

(gdb) set environment LD_PRELOAD=./libintercept.so
(gdb) run
Starting program: /home/seguljac/intercept/main 
[Thread debugging using libthread_db enabled]
[New Thread 0x7ffff7436700 (LWP 19165)]
Wait
Signal
Before pthread_cond_broadcast

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff79ca0e7 in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib/libpthread.so.0
(gdb) bt
#0  0x00007ffff79ca0e7 in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib/libpthread.so.0
#1  0x00007ffff7bdb769 in pthread_cond_broadcast () from ./libintercept.so
#2  0x00000000004008e8 in thread0_work ()
#3  0x00000000004009a4 in main ()

EDIT 2:

(解决了) 正如 R.. 所建议的(谢谢!),问题是在我的平台上 pthread_cond_broadcast 是一个版本符号,而 dlsym 给出了错误的版本。这篇博客非常详细地解释了这种情况:http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/ http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/


通过您的函数的调用似乎最终以不同版本的函数结束:

With LD_PRELOAD:    __pthread_cond_broadcast_2_0 (cond=0x804a060) at old_pthread_cond_broadcast.c:37
Without LD_PRELOAD: pthread_cond_broadcast@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_broadcast.S:39

所以你的情况与这个问题类似,即你得到的 pthread 函数的版本不兼容:符号版本控制和 dlsym https://stackoverflow.com/questions/5587718/symbol-versioning-and-dlsym

本页提供了一种解决该问题的方法,尽管有点复杂:http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/ http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pthread_cond_broadcast 被 dlsym 破坏了? 的相关文章

  • 从 C# 调用非托管 dll。拿2

    我编写了一个 C 程序 它调用一个 C DLL 将命令行参数回显到文件中 当使用 rundll32 命令调用 c 时 它显示命令行参数没有问题 但是当从 c 内部调用它时 它不会显示 我问了这个问题 https stackoverflow
  • 如何拦截 .Net 中第三方库对非虚拟方法的调用?

    我认为我需要的是 net 人们称之为 透明动态代理 的东西 但到目前为止我所看到的所有实现 Castle DynamicProxy Spring NET AOP 等 都要求我至少执行以下操作之一 将拦截的方法声明为虚拟方法 包装类并创建包装
  • 即使我没有#include ,为什么仍然可以使用 std::max 和 std::min ?

    include
  • 类型转换 sockaddr 结构

    我正在尝试学习网络编程 并在这个过程中学习C 我对结构感到困惑sockaddr这是一个通用地址 并且sockaddr in 我的书里是这么说的 因此 我们可以填写 sockaddr in 的字段 然后强制转换 a 指向 它指向 指向 soc
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • 如何使用movntdqa避免缓存污染?

    我正在尝试编写一个 memcpy 函数 该函数不会将源内存加载到 CPU 缓存中 目的是避免缓存污染 下面的 memcpy 函数可以工作 但会像标准 memcpy 一样污染缓存 我正在使用带有 Visual C 2008 Express 的
  • 多个源文件中包含包含“const”的头文件

    Why does not包含定义的头文件const并被多个源文件包含会产生编译错误multiple definition const in header file h const int num 5 int x Error Multiple
  • 无法使用 ASP.NET Core 从 JWT 令牌获取声明

    我正在尝试使用 ASP NET Core 实现 JWT 持有者身份验证的非常简单的实现 我从控制器返回的响应有点像这样 var identity new ClaimsIdentity identity AddClaim new Claim
  • 为什么在 Linux 上字符串文字的内存地址与其他字符串文字的内存地址如此不同?

    我注意到字符串文字在内存中的地址与其他常量和变量 Linux 操作系统 非常不同 它们有许多前导零 未打印 Example const char h Hi int i 1 printf p n void h printf p n void
  • 尝试将元素推入向量

    在头文件 我没有编写 中 已经定义了一个结构体 如下所示 struct MemoryMessage public boost counted base public FastAlloc explicit MemoryMessage Memo
  • c#Registry to XML无效字符问题

    我在尝试从注册表创建 XML 文件时遇到问题 在我的笔记本电脑 W7 64b 上它工作正常 生成了 xml 文件 但在另一台计算机 Xp 32b 上抛出异常 System ArgumentException 十六进制值 0x00 是无效字符
  • 使用 cryptoapi CryptImportKey 导入公钥时出错

    我想将公钥 blob 导入到 CSP 但发生了错误 BYTE pbData 0xEB 0x2A 0x38 0x56 0x86 0x61 0x88 0x7F 0xA1 0x80 0xBD 0xDB 0x5C 0xAB 0xD5 0xF2 0x
  • 如何使用 Caliburn.Micro MVVM 将焦点设置到控件

    我有一个表单 我想在发生某些用户操作时将焦点设置到文本框 我知道 MVVM 的处理方式是绑定到 VM 属性 但是 TextBox 没有允许这种情况发生的属性 从虚拟机设置焦点的最佳方法是什么 我创建了一个 IResult 实现 可以很好地实
  • 读取所有进程内存以查找字符串变量c#的地址

    我有 2 个用 C 编写的程序 第一个名为 ScanMe 的程序包含一个包含值 FINDMEEEEEEE 的字符串变量 以及一个值为 1546 22915487 的双精度变量 另一个名为 MemoryScan 的程序读取第一个程序的所有内存
  • 专家 C#/.Net/WPF 开发人员应该了解哪些知识? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么 MISRA:2012 需要函数原型?

    我想知道为什么 MISRA 2012 需要函数原型 在下面的示例中 这两个原型并不是真正必要的 include
  • 如何带参数调用外部程序?

    我想在我的代码中调用一个 Windows 程序 并使用代码本身确定的参数 我不想调用外部函数或方法 而是调用 WinXP 环境中的实际 exe 或批处理 脚本文件 C 或 C 将是首选语言 但如果使用任何其他语言更容易完成此操作 请告诉我
  • 更新插入 MongoDB 时如何防止出现“_t”字段?

    我有一个应用程序 它使用 MongoDB 的 C 驱动程序将 Upsert 插入 MongoDB 数据库 当我打电话给Update函数 我无法指定我要更新的类型 然后 t字段插入元素的类型 这是我用来更新插入的代码 collection U
  • 什么是多重重继承?

    我将以下称为 多重重新继承 直接继承一个类一次 并通过继承其一个或多个后代来间接继承一次或多次 通过继承一个类的两个或多个后代来间接继承一个类两次或多次 我想知道它是否存在以及如何明确访问嵌入的子对象 1 Professional C 2n
  • lambda 表达式是多线程的吗?

    lambda 表达式是多线程的吗 假设当你将数学公式编写为 lambda 方法时 当你将其传递给另一个方法时 它会是多线程的吗 不是100 清楚你问的是什么 您是否想问 lambda 是否自然地在不同的线程上运行 如果是这样 则它们只是 S

随机推荐