Table of Contents

第一种方法void *dlsym(void *handle, const char *symbol);

main.c

dll.h

module1.c

module2.c

makefile

运行

第二种方法objdump

分析

首先,我们查看以下动态库的符号表

删掉符号表


简单来讲,就是获取二进制文件中的地址嘛!!

第一种方法void *dlsym(void *handle, const char *symbol);

大家可以自己查用户手册。

NAME
       dlsym, dlvsym - obtain address of a symbol in a shared object or executable

SYNOPSIS
       #include <dlfcn.h>

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

#define _GNU_SOURCE
       #include <dlfcn.h>

void *dlvsym(void *handle, char *symbol, char *version);

Link with -ldl.

NAME
       dlclose, dlopen, dlmopen - open and close a shared object

SYNOPSIS
       #include <dlfcn.h>

void *dlopen(const char *filename, int flags);

int dlclose(void *handle);

#define _GNU_SOURCE
       #include <dlfcn.h>

void *dlmopen (Lmid_t lmid, const char *filename, int flags);

Link with -ldl.

以下代码来源:https://blog.csdn.net/reage11/article/details/8606125(进行过修改)

main.c

#include <stdio.h>
#include <dlfcn.h>
#include "dll.h"#define debug() printf("%s:%d\n", __func__, __LINE__);int main(){void *dp;char *err;char fname[20];dll p;debug();void (*init)(dll *p);void (*Done)();printf("module1.so or moduel2.so");char tmp[20];scanf("%s", tmp);debug();printf("Open file: %s\n", tmp);sprintf(fname, "./%s", tmp);dp = dlopen(fname, RTLD_LAZY);//打开动态库。printf("Open file: %s\n", fname);if( NULL == dp) {printf("%s\n", dlerror());exit(1);}debug();init = dlsym(dp, "init");//找到init函数的地址。init(&p);Done = dlsym(dp, "Done");Done();printf("%s\n", p.name);return 0;
}

dll.h

typedef struct dll{char * name;void (*Done)() ;
}dll;

module1.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dll.h"void Done(){printf("This is test module 1!\n");
}void init(dll *p){p->name = (char *)calloc(3, sizeof(char));strcpy(p->name, "module1.so init");p->Done = Done;
}

module2.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dll.h"void Done(){printf("This is test module 2!\n");
}void init(dll *p){p->name = (char *)calloc(3, sizeof(char));strcpy(p->name, "module2.so");p->Done = Done;
}

makefile

ALL:gcc -rdynamic -o main main.c dll.h -ldl  #-ldl (指定dl库)因为dlopen和dlsym在dl库中gcc -shared -o module1.so  module1.c dll.h -fpicgcc -shared -o module2.so module2.c dll.h -fpic

运行

$ ./main
main:13
Input module1.so or moduel2.so: module1.so
main:20
Open file: module1.so
Open file: ./module1.so
main:34
This is test module 1!
module1.so init

第二种方法objdump

未完待续。。。

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>#include "dll.h"typedef void (*funcp)(dll *p);#define debug() printf("%s:%d\n", __func__, __LINE__);int main()
{FILE *fp = popen("objdump -T module1.so | grep init | awk '{print $1}'", "r");uint64_t func_addr;char ptr[20];memset(ptr, 0, 20);fgets(ptr, 20, fp);printf("Ptr: %s\n", ptr);func_addr = strtoul(ptr, NULL, 16);printf("%lx\n", func_addr);funcp init;debug();init = (funcp)func_addr;debug();dll p;debug();init(&p); debug();pclose(fp);return 0;
}

分析

init = dlsym(dp, "init");

是根据二进制文件中的符号表查询得出的函数地址吗?

首先,我们查看以下动态库的符号表

$ nm module1.so
0000000000201030 B __bss_startU calloc@@GLIBC_2.2.5
0000000000201030 b completed.7696w __cxa_finalize@@GLIBC_2.2.5
00000000000005b0 t deregister_tm_clones
0000000000000640 t __do_global_dtors_aux
0000000000200e10 t __do_global_dtors_aux_fini_array_entry
000000000000068a T Done
0000000000201028 d __dso_handle
0000000000200e18 d _DYNAMIC
0000000000201030 D _edata
0000000000201038 B _end
00000000000006f8 T _fini
0000000000000680 t frame_dummy
0000000000200e08 t __frame_dummy_init_array_entry
00000000000007e0 r __FRAME_END__
0000000000201000 d _GLOBAL_OFFSET_TABLE_w __gmon_start__
0000000000000718 r __GNU_EH_FRAME_HDR
000000000000069d T init
0000000000000550 T _initw _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTableU puts@@GLIBC_2.2.5
00000000000005f0 t register_tm_clones
0000000000201030 d __TMC_END__

可以看到init的地址为000000000000069d, 那么dlsym是否根据这个符号找到他的函数地址的呢?

删掉符号表

$ strip module1.so
$ nm module1.so
nm: module1.so: no symbols

再次运行,发现仍然可以。

$ strip module1.so
$ nm module1.so
nm: module1.so: no symbols
$ ./main
main:13
Input module1.so or moduel2.so: module1.so
main:20
Open file: module1.so
Open file: ./module1.so
main:34
This is test module 1!
module1.so init

行吧,就先这样吧。

C语言插件开发模式与分析相关推荐

  1. c语言窗口插件,C语言插件开发形式

    C语言插件开发模式 以前总是不明白为什么不同的模块是相互独立的编译,相互之间不存在的调用关系, 怎么做到在使用的时候加载不使用的时候卸载掉? 现在总算是明白了.其实就是将一个功能做成一个动态库,在wi ...

  2. 《C++应用程序性能优化::第二章C++语言特性的性能分析》学习和理解

    <C++应用程序性能优化::第二章C++语言特性的性能分析>学习和理解 说明:<C++应用程序性能优化> 作者:冯宏华等 2007年版.最近出了新版,看了目录,在前面增加了一章 ...

  3. 面向模式的分析和设计(POAD)

    <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 设计模式的作用 ...

  4. C语言教学模式 教学方法改革,C语言教学模式改革探究.docx

    C语言教学模式改革探究 摘 要: C 语言作为编程语言的基础课程, 是高等院校 计算机相关专业的必修课,其目标是培养学生的计算机思维 能力以及解决问题的能力 [1] .但在传统教学模式下,学生缺 乏练 ...

  5. 微服务架构通讯模式架构分析

    微服务架构通讯模式架构分析) 目录 概 述 小结 参考资料和推荐阅读 LD is tigger forever,CG are not brothers forever, throw the pot a ...

  6. 【Golang第8章:面向对象编程】Go语言的结构体是什么,怎么声明;Golang方法的调用和声明;go语言面向对象实例,go语言工厂模式;golang面向对象的三大特性:继承、封装、多态

    介绍 这个是在B站上看边看视频边做的笔记,这一章是Glang面向对象编程 这一章内容较多,内容有Go语言的结构体是什么,怎么声明:Golang方法的调用和声明:go语言面向对象实例,go语言工厂模式: ...

  7. 2022-2027年中国在线语言教育行业市场深度分析及投资战略规划报告

    [报告格式]电子版.纸介版 [出品单位]华经产业研究院 本报告由华经产业研究院出品,对中国在线语言教育行业的发展现状.竞争格局及市场供需形势进行了具体分析,并从行业的政策环境.经济环境.社会环境及技术 ...

  8. c语言读取文件函数,C语言文件操作详细分析:读取文件(fread函数使用)

    C语言文件操作详细分析:读取文件(fread函数使用) 这里详细介绍了C语言读取文件的函数fread的使用说明,参照了MSDN的说明,同时加入自己的经验让大家学的更加明白. C语言读取文件函数frea ...

  9. 2022-2028年中国交通建设PPP模式深度分析及发展战略研究报告(全卷)

    [报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了PPP模式行业相关概述.中国PPP模式行业运行环境.分析了中国PPP ...

最新文章

  1. React Native —— App
  2. sqlserver往oracle写数据,Sqlserver连接oracle进行读写数据库
  3. centos7 harbor 单机搭建
  4. WinSocket简单编程实验
  5. w,vmstat,top,sar
  6. 一元享移动怎么样_中国移动放大招!月租9元享200GB流量,网友:这套路谁敢用?...
  7. webrtc 渲染_[WebRTC架构分析]采样率转换
  8. python装饰器模式带参数_Python装饰器使用实例:验证参数合法性 请教Python 使用装饰器实现单例模式的原理...
  9. Hive MapJoin OOM
  10. FLASH AS3 TextField
  11. 面向对象的数据库开发--再论ORM
  12. H264 SPS分析
  13. 车牌识别——合成车牌数据
  14. Win7平台上通过QQ查询对方IP地址
  15. Excel时间段计算的相关公式
  16. 无线共享打印机无法连接服务器,“不能连接网络共享打印机”常见原因及处理方法:...
  17. 伺服驱动器的工作原理及伺服驱动器的常见接线方法
  18. C语言程序设计笔记(浙大翁恺版) 第五周:循环控制
  19. input输入框按照字符数限制输入
  20. slua 是c语言开发的吗,初学者必备文档:LUA新手快速学习笔记

热门文章

  1. IDEA 重置try catch的自动生成格式
  2. 在Docker官网上浏览版本号
  3. Java并发编程-八锁问题带你彻底理解对象锁和类锁
  4. Mac Docker安装MySQL5.7
  5. 对生信与计算生物的一点认识[转载]
  6. MySQL数据分析-(1) 数据库前言
  7. 5-35 有理数均值 (20分)
  8. Oracle锁庞大介绍
  9. linux中的echo%3e文件,Linux学习笔记-shell脚本中${}的使用方法
  10. synchronized原理_浅谈synchronized的实现原理