Libco Hook 机制浅析

之前的文章里我们提到过 Libco 有一套 Hook 机制,可以通过协程的让出(yield)原语将系统的阻塞系统调用改造为非阻塞的,这篇文章我们将深入解析 Hook 机制到底是怎么运作的

Hook 机制的核心有两点

  • 提供自己的实现覆盖标准库(libc.so)的实现
  • 在自己实现的代码里要有办法能够调用标准库的实现

也就是说,我们提供的实现其实是标准库实现的 wrapper

为了搞明白 Hook 机制,我们首先要了解 Linux 动态库究竟是怎么运作的

动态库的加载和符号表

动态库是在运行时链接的,这个工作是由动态链接器来完成的(Linux 下是 /lib/ld-linux.so.2 ),主要涉及到的步骤有

  • 搜索可执行文件依赖的所有动态库,并将它们加载到进程的虚拟地址空间中
  • 做符号解析和重定位
    • 动态库的符号会被加到全局符号表里
  • 执行共享对象的初始化代码

如果可执行文件依赖的多个动态库定义了同一个符号时,以先加载的动态库为准,那么如果想要覆盖掉动态库 A 里的符号,最简单的做法就是让我们的库在动态库 A 之前加载,通常使用环境变量 LD_PRELOAD 来实现这点

  • LD_PRELOAD 中列出的动态库会在所有其他动态库之前加载,包括 libc.so
  • 如果我们想要提供自己的 malloc 实现,只需要在自己的动态库里实现 malloc,然后将它加入 LD_PRELOAD 中,这样就会覆盖掉标准库的 malloc 实现

命令 LD_DEBUG=files ./a.out 可以查看动态库的加载顺序和初始化顺序,这些顺序是实现相关的

dlsym

解决了第一个问题,那么剩下的问题就是如何在我们的实现里调用标准库实现了,直接用函数名调用肯定是不行的,那么我们能想到的办法就是能否给标准库的实现改一个名字呢?

为了实现这点,我们需要用到 dlsym 函数, 它的函数原型为

void *dlsym(void *restrict handle, const char *restrict symbol);

dlsym 的原意是用来获得动态加载进来的动态库中的接口(Linux 中的动态库不仅可以在程序启动时加载,还可以在程序运行过程中加载和卸载),其中 handle 是动态库的句柄,symbol 是要搜索的符号

此外,dlsym 还支持两个伪 handle

  • RTLD_DEFAULT

    • 按默认搜索顺序搜索第一次出现的 symbol,搜索范围包含全局符号表里的所有符号

      • 程序可执行文件本身的符号
      • 动态链接器加载的动态库中的符号
      • 如果用 dlopen 加载动态库时,指定了 RTLD_GLOBAL选项,那么它的符号也会出现在全局符号表里
  • RTLD_NEXT
    • 从当前可执行文件或动态库开始,搜索下一次出现的 symbol

      • 假设搜索顺序是 A -> B -> C -> D,在动态库 B 里调这个接口搜索 symbol1,就会依次去 C 和 D 中搜索 symbol1,返回先找到的 symbol1 地址

利用 RTLD_NEXT 就可以实现我们想要的功能,假设说我们用 LD_PRELOAD 覆盖了标准库 malloc 实现,就可以通过 dlsym 拿到标准库的 malloc 地址(前提是在 libc.so 之前没有其他库定义了 malloc),给它的函数指针起一个其他的名字,就可以在我们的实现里调用标准库 malloc 了

可以看到 Libco 里就是用这种方法拿到所有标准库实现的函数指针

typedef ssize_t (*read_pfn_t)(int fildes, void *buf, size_t nbyte);
static read_pfn_t g_sys_read_func = (read_pfn_t)dlsym(RTLD_NEXT, "read");

Libco Hook 机制浅析的更多相关文章

  1. Linux模块机制浅析

    Linux模块机制浅析   Linux允许用户通过插入模块,实现干预内核的目的.一直以来,对linux的模块机制都不够清晰,因此本文对内核模块的加载机制进行简单地分析. 模块的Hello World! ...

  2. Hook机制里登场的角色

    稍有接触过 WordPress 主题或插件制作修改的朋友,对 WordPress 的Hook机制应该不陌生,但通常刚接触WordPress Hook 的新手,对其运作原理可能会有点混乱或模糊.本文针对 ...

  3. typecho流程原理和插件机制浅析(第二弹)

    typecho流程原理和插件机制浅析(第二弹) 兜兜 393 2014年04月02日 发布 推荐 1 推荐 收藏 14 收藏,3.7k 浏览 上一次说了 Typecho 大致的流程,今天简单说一下插件 ...

  4. typecho流程原理和插件机制浅析(第一弹)

    typecho流程原理和插件机制浅析(第一弹) 兜兜 393 2014年03月28日 发布 推荐 5 推荐 收藏 24 收藏,3.5k 浏览 虽然新版本0.9在多次跳票后终于发布了,在漫长的等待里始终 ...

  5. 黄聪:WordPress 的 Hook 机制与原理(add_action、add_filter)

    稍有接触过 WordPress 主题或插件制作修改的朋友,对 WordPress 的Hook机制应该不陌生,但通常刚接触WordPress Hook 的新手,对其运作原理可能会有点混乱或模糊.本文针对 ...

  6. oracle的resetlogs机制浅析

    oracle的resetlogs机制浅析 alter database open resetlogs 这个命令我想大家都很熟悉了,那有没有想过这个resetlogs选项为什么要用?什么时候用?它的原理 ...

  7. 【repost】JS中的hook机制

    hook机制也就是钩子机制,由表驱动实现,常用来处理多种特殊情况的处理.我们预定义了一些钩子,在常用的代码逻辑中去适配一些特殊的事件,这样可以让我们少些很多if else语句.举个高考加分的例子,比如 ...

  8. webpack模块机制浅析【一】

    webpack模块机制浅析[一] 今天看了看webpack打包后的代码,所以就去分析了下代码的运行机制. 下面这段代码是webpack打包后的最基本的形式,可以说是[骨架] (function(roo ...

  9. 插件开发之360 DroidPlugin源码分析(二)Hook机制

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52124397 前言:新插件的开发,可以说是为插件开发者带来了福音,虽然还很多坑要填补, ...

随机推荐

  1. Java Arrays.asList(0,1,2,3,4,5,6,7,8,9).parallelStream().forEach 进行循环获取HttpServletRequest的为Null的解决方案

    Arrays.asList(0,1,2,3,4,5,6,7,8,9).parallelStream().forEach() parallelStream是并行执行流的每个元素,也就是多线程执行,这样就 ...

  2. MySQL 根据JSON类型的字段进行过滤数据的方式

    第一种方式:JSON_CONTAINS 函数 : 执行相等形式的比较 注意:值的类型一定要相同,不然会报错 文档地址:https://dev.mysql.com/doc/refman/8.0/en/j ...

  3. SpringDataJdbc使用数据库默认值的解决方法

    SpringDataJdbc提供了 @ReadOnlyProperty 注解,这会造成由Repository保存的实体会忽略这个字段的值进行保存,进而采用数据库的默认值操作:而查询时这个字段也是能够查 ...

  4. memcached 是如何做身份验证的?

    没有身份认证机制!memcached 是运行在应用下层的软件(身份验证应该是应用 上层的职责).memcached 的客户端和服务器端之所以是轻量级的,部分原因就 是完全没有实现身份验证机制.这样,m ...

  5. Redis缓存穿透、缓存雪崩、缓存击穿

    缓存穿透: ​ 缓存穿透,是指查询一个数据库一定不存在的数据.正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存.如果 ...

  6. .NET面试经典三问:什么是.NET?什么是.NET Framework?什么是.NET Core?

    什么是.NET?什么是.NET Framework? 本文将从上往下,循序渐进的介绍一系列相关.NET的概念,先从类型系统开始讲起,我将通过跨语言操作这个例子来逐渐引入一系列.NET的相关概念,这主要 ...

  7. JS练习实例--编写经典小游戏俄罗斯方块

    最近在学习JavaScript,想编一些实例练练手,之前编了个贪吃蛇,但是实现时没有注意使用面向对象的思想,实现起来也比较简单所以就不总结了,今天就总结下俄罗斯方块小游戏的思路和实现吧(需要下载代码也 ...

  8. google fonts 国内使用解决方案

    由于众所周知的原因,国内使用google font库有很大的问题. 解决方案1:使用国内镜像如360网站卫士常用前端公共库CDN服务 优点:使用方便 缺点:目标用户包含国外的开发者,不清楚国外用户的加 ...

  9. 纯CSS实现扁平化风格开关按钮

    开关样式预览图 前言 最近在基于bootstrap框架开发一个网站,在填写表单一项需要用户填写是否选择某一选项,本来想引用bootstrap框架自带的一个按钮插件,结果在引用js的时候总是出错,就找了 ...

  10. 《每周一点canvas动画》——3D点线与水波动画

    <每周一点canvas动画>--差分函数的妙用 每周一点canvas动画代码文件 好像上次更新还是十一前,这唰唰唰的就过去大半个月了,现在才更新实在不好意思.这次我们不涉及canvas 3 ...