zoukankan      html  css  js  c++  java
  • 了解动态链接(三)—— 共享模块的全局变量问题

    ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287

    假设 module.c 中引用了一个共享模块中定义的全局变量 global:

    1 extern int global;
    2 
    3 int foo() {
    4     global = 1;
    5 }

    编译器无法确定变量 global 的定义是在模块内部还是外部。假设 module.c 是可执行文件的一个源文件,可执行程序不是 PIC 的,不会进行重定位。链接器会在 .bss 段创建一个 global 变量的副本,这样造成同一个变量同时存在于多个位置。问题的解决办法是让所有对变量 global 的访问都指向可执行文件中的那个副本。

    ELF 共享库在编译时,默认把所有全局变量都当作是定义在其他模块中,通过 GOT 表实现外部访问。当共享模块被装载时,如果某个全局变量在可执行文件中拥有副本,动态链接器就把 GOT 表中的相应地址指向该副本。如果该变量在可执行文件中没有副本,那么 GOT 表中的相应地址就指向模块内部的该变量副本。

    假设 libx.so 中定义了一个全局变量 G,进程A和B都使用 libx.so。那么当 libx.so 被两个进程加载时,它的数据段在每个进程中都有独立的副本,所以进程 A 和 B 访问的都是自己进程中的那个全局变量 G 的副本,相互之间没有影响。但如果是同一个进程的线程 A 和 B,则他们访问的是同一个副本。

    而有时希望同一个进程中的不同线程,也访问全局变量的不同副本,这样可以避免线程之间对全局变量的干扰,或者避免做线程同步。这可以通过线程私有存储(Thread Local Storage, TLS) 来实现。在 Android 系统中,TLS是借助协处理器来实现的,在 Linker 和 getpid 等函数的实现中都能看到有关 TLS 的代码。

    有时也会希望多个进程共享同一个全局变量的副本,借此实现进程间通信。记得以前写 Windows DLL 时,有“共享数据段”的概念就是实现这个的。

    学习资料: 《程序员的自我修养——链接、装载和库》

  • 相关阅读:
    深度学习GPU集群管理软件 OpenPAI 简介
    图片加数字盲水印
    Kubernetes核心概念简介
    一文详解 Linux 系统常用监控工具(top,htop,iotop,iftop)
    【OfficeWebViewer】在线预览Word,Excel~
    【Java】大文本字符串滤重的简单方案
    Java应用集群下的定时任务处理方案(mysql)
    《将博客搬至CSDN》
    [转]Fiddler抓取Android真机上的HTTPS包
    [Java Collection]List分组之简单应用.
  • 原文地址:https://www.cnblogs.com/ilocker/p/4591787.html
Copyright © 2011-2022 走看看