美文网首页
C语言中如何获取动态库的调用方信息

C语言中如何获取动态库的调用方信息

作者: onmeiei | 来源:发表于2022-09-07 10:46 被阅读0次

在Java中,很方便可以通过Thread的StackTrackElement来获取到方法的调用方信息。那么在C中如何获取类似的信息呢?
答案是使用backtrace系列函数。

#include <execinfo.h>

//backtrace() 返回调用程序的回溯(跟踪)信息,存储在由
//buffer指向的数组中。
int backtrace(void **buffer, int size);

//backtrace() 返回一组地址,backtrace_symbols()象征性地
//翻译这些地址为一个描述地址的字符串数组。
char **backtrace_symbols(void *const *buffer, int size);

//backtrace_symbols_fd()的参数buffer、size同backtrace_symbos(),
//不同之处在于,backtrace_symbols_fd()并不会返回一个
//字符串数组给调用者,而是将字符串写入fd对应文件。
void backtrace_symbols_fd(void *const *buffer, int size, int fd);

示例:
准备三个源文件:libB.cpp,libA.cpp,main.cpp
关系如下:

调用关系展示
  • libB.cpp
    这个方法是最关键的方法,使用backtrace函数打印了调用关系。
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>

int funB(){
    printf("====>>>> in funB(), printing backtrace ...\n");
    void *buffer[100];
    char **strings;
    int nptrs = backtrace(buffer, 100);
    printf("\nbacktrace() returned %d addresses\n", nptrs);
    strings = backtrace_symbols(buffer, nptrs);
    int j;
    for (j = 0; j < nptrs; j++) {
      printf("%s\n", strings[j]);
    }
    free(strings);
    return 0;
}
  • libA.cpp
    这个方法只是为了验证调用关系的,没有什么实际的用处。
include <stdio.h>

int funB();

int funA(){
    printf("====>>>> in funA(), calling funB\n");
    funB();
    return 0;
}
  • main.cpp
    主函数,1:通过A间接调用B;2:直接调用B;
int funA();
int funB();

#include<stdio.h>

int main(){

    printf("====>>>> in main(), calling funA()\n");
    funA();

    printf("\n\n---------------------------------------------------------\n\n\n");

    printf("====>>>> in main(), calling funB()\n");
    funB();

    return 0;
}

编译运行

  1. 简单编译并运行
#!/bin/bash
# 清理
rm lib/*.so -f
rm main_* -f

# 编译
gcc libB.cpp -fPIC -shared -o lib/libB.so
gcc libA.cpp -fPIC -shared -o lib/libA.so -Wl,-rpath=./lib -L./lib -lB
gcc main.cpp -o main_plain -L./lib -Wl,--copy-dt-needed-entries -lA

# 运行
export LD_LIBRARY_PATH=./lib
./main_plain

输出为:


调用输出
  1. 使用-O3优化编译并运行
#!/bin/bash
# 清理
rm lib/*.so -f
rm main_* -f

# 编译
gcc libB.cpp -fPIC -shared -o lib/libB.so -O3
gcc libA.cpp -fPIC -shared -o lib/libA.so -Wl,-rpath=./lib -L./lib -lB -O3
gcc main.cpp -o main_o3 -L./lib -Wl,--copy-dt-needed-entries -lA -O3

# 运行
export LD_LIBRARY_PATH=./lib
./main_o3

输出为:


调用输出
  1. 使用-O3以及-fomit-frame-pointer进行编译

-fomit-frame-pointer

Don't keep the frame pointer in a register for functions that don't need one. This avoids the instructions to save, set up and restore frame pointers; it also makes an extra register
available in many functions. It also makes debugging impossible on some machines.

On some machines, such as the VAX, this flag has no effect, because the standard calling sequence automatically handles the frame pointer and nothing is saved by pretending it doesn't exist.
The machine-description macro "FRAME_POINTER_REQUIRED" controls whether a target machine supports this flag.

The default setting (when not optimizing for size) for 32-bit GNU/Linux x86 and 32-bit Darwin x86 targets is -fomit-frame-pointer. You can configure GCC with the --enable-frame-pointer
configure option to change the default.

Enabled at levels -O, -O2, -O3, -Os.

#!/bin/bash
# 清理
rm lib/*.so -f
rm main_* -f

# 编译
gcc -fomit-frame-pointer libB.cpp -fPIC -shared -o lib/libB.so -O3
gcc -fomit-frame-pointer libA.cpp -fPIC -shared -o lib/libA.so -Wl,-rpath=./lib -L./lib -lB -O3
gcc -fomit-frame-pointer main.cpp -o main_o3_fomit -L./lib -Wl,--copy-dt-needed-entries -lA -O3

# 运行
export LD_LIBRARY_PATH=./lib
./main_o3_fomit

输出为:


调用输出

结论:获取的信息还是挺清晰的

如果用来保障libB.so只能被认证过的程序调用,那么可以在libB中对上一层的程序进行校验。

相关文章

  • 动态调用动态库方法 c/c++ linux windows

    动态调用动态库方法c/c++linuxwindows 关于动态调用动态库方法说明 一、 动态库概述 1、 动态库的...

  • golang调用c动态库

    golang调用c动态库 简介 golang调用c语言动态库,动态方式调用,可指定动态库路径,无需系统目录下 核心...

  • Java反射

    定义 Java语言中一种动态(运行时)访问、检测、修改它本身的能力。 作用 动态的获取类的完整结构信息,调用对象的...

  • Fortran与C++交叉编程:Fortran如何调用C++动态

    Fortran程序中调用C++编写的动态库的问题分为两个子问题 Fortran调用c形式函数接口 为c++动态库编...

  • iOS 如何监测app的CPU使用率

    1、前言 2、如何监测CPU的使用率? 在C语言中提供了两个库可以获取当前app的运行任务及线程堆栈信息,从中我们...

  • 调用C动态库

    C 是程序世界的宝库,在我们面向的设备系统中,也内置了大量的 C 动态库帮助我们完成各种任务。因为 Objecti...

  • [iOS]libffi动态调用C函数

    前言:在iOS开发中可以使用Runtime动态调用OC方法,但是无法动态调用C函数,那么该如何动态调用C函数呢?值...

  • PY08-04:Python加载动态库

      Python加载动态库主要用于使用C/C++弥补Python的性能,这个主题解决了Python调用动态库中函数...

  • C和C++中动态链接库的创建和链接(原创,装载请注明原处)

    C和C++中动态链接库的创建和链接 1.创建DLL(动态链接库)-C++方式 1.创建DLL(动态链接库-C++方...

  • JNI入门大全

    简介 JNI是Java Native Interface的缩写,它的设计目的能让JAVA动态调用C/C++动态库。...

网友评论

      本文标题:C语言中如何获取动态库的调用方信息

      本文链接:https://www.haomeiwen.com/subject/maznnrtx.html