libffi浅析

本文介绍了libffi在ARM处理器上用于高级语言间互调的原理,特别是32位软浮点的SYSV ABI。内容涵盖ffi_type结构体的使用、函数调用的初始化步骤,包括ffi_cif结构体的初始化,以及参数如何按照SYSV ABI规则传递。重点解析了参数对齐、返回值处理和结构体返回的特殊情况。
摘要由CSDN通过智能技术生成

最近调试了weston的一个coredump,对libffi有了一些了解,在此记录下,使用的是arm处理器,32位,soft float,libffi3.1,使用的abi是SYSV。


libffi简介和使用示例:http://www.atmark-techno.com/~yashi/libffi.html,建议先看完,有所了解再继续看本文。大体意思就是libffi用于高级语言之间的相互调用。由于函数指针,参数类型,参数个数,参数的值都可以在运行时指定,所以在脚本语言调用c里面用的比较多,比如python 的ctypes;也可以调用不同abi(应用程序二进制接口)编译的程序,这个了解的不多。


数据类型

libffi定义了ffi_type结构体,用于描述对应的c语言中的uint32, sint32, floate, void *, struct等类型:

typedef struct _ffi_type
{
  size_t size;
  unsigned short alignment;
  unsigned short type;
  struct _ffi_type **elements;
} ffi_type;
比如变量ffi_type_uint32用于描述c语言的uint32类型,它所占大小是4;对齐大小是4;在libffi中用于标记类型的数字是FFI_TYPE_UINT32,也就是9;elements在c语言基本类型中没有用到,固定为NULL,elements在结构体中才会用到,为结构体中的元素。


ffi_type_uint32变量是通过FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32)得到的

#define FFI_TYPEDEF(name, type, id)       \
struct struct_align_##name {          \
  char c;                 \
  type x;                 \
};                        \
const ffi_type ffi_type_##name = {        \
  sizeof(type),                   \
  offsetof(struct struct_align_##name, x),    \
  id, NULL                    \
}

#define FFI_NONCONST_TYPEDEF(name, type, id)  \
struct struct_align_##name {          \
  char c;                 \
  type x;                 \
};                        \
ffi_type ffi_type_##name = {          \
  sizeof(type),                   \
  offsetof(struct struct_align_##name, x),    \
  id, NULL                    \
}
定义了struct_align_uint32结构体,这一系列结构体的第一个元素都是char,第二个是具体的uint32,sint32,void *等,用于之后求取对齐字节数。

ffi_type_uint32为ffi_type类型的const变量,sizeof(uint32)得到uint32的大小;offsetof类似于内核里面著名的container_of函数中求取结构体中元素偏移字节数的代码,可以得到uint32在struct_align_uint32中的偏移为4,表示uint32是4字节对齐的;id是FFI_TYPE_UINT32,值为9;elements为NULL。


函数调用

有了类型,下面就看函数调用,分为两步:

一、初始化ffi_cif结构体

ffi_cif结构体定义为:

typedef struct {
  ffi_abi abi;
  unsigned nargs;
  ffi_type **arg_types;
  ffi_type *rtype;
  unsigned bytes;
  unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
  FFI_EXTRA_CIF_FIELDS;
#endif
} ffi_cif;
表示了函数调用中的一些信息,比如abi;输入参数个数;输入参数类型(ffi_type_uint32之类的);返回值类型;输入参数占用空间的大小(aapcs要求进入arm函数时堆栈是8字节对齐的。由于
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
如果您想使用pip安装libffi库,可以使用以下命令: pip install libffi 但是,如果您需要下载libffi以及其他依赖库的离线安装包,可以按照以下步骤进行操作: 1. 确保您已经安装了pip,并将其升级到最新版本。 2. 使用以下命令下载所需的依赖库以及libffi库: pip3 download -r requirements.txt -d /tmp/packages/ 这将会将requirements.txt中列出的所有依赖库下载到/tmp/packages/目录中。如果requirements.txt中没有列出libffi库,您可以手动下载该库并将其放入/tmp/packages/目录中。 3. 然后,您可以使用以下命令安装libffi库: pip3 install --no-index --find-links=/tmp/packages/ libffi 这将会从/tmp/packages/目录中安装libffi库,而不是从默认的PyPI源安装。确保替换"/tmp/packages/"为您实际下载的离线安装包的目录路径。 请注意,在安装离线包时,可能会涉及到其他依赖库的安装。如果遇到缺少其他依赖库的情况,您可以手动下载并安装这些依赖库,或者将它们添加到requirements.txt文件中,然后再次运行下载命令。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [离线安装Python3和离线安装第三方模块](https://blog.csdn.net/qq_32613771/article/details/122160440)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值