详细分析CONTAINING_RECORD宏

该宏的作用是:用结构成员中的ListEntry的地址(0x108)减去结构体成员ListEntry到首地址的距离(8)得到结构体首地址(0x100

 

 

pEntry 中的值就是结构成员中的ListEntry的地址。即:0x108

ListEntry

0x108 结构成员中的ListEntry的地址,也是RemoveHeadList函数函数的值

 

y

0x104

ListEntry在结构体中的开始位置是8

x

0x100 结构体首地址

 

第一个成员存在低地址上

内存的地址是由低往高

 

 

typedef struct _MYDATASTRUCT{

 

        Ulongx;

        Ulongy;

        LIST_ENTRYListEntry;//这里的ListEntry在结构体中的开始位置是8

        

}MYDATASTRUCT,*PMYDATASTRUCT;

 

PLIST_ENTRYpEntry = RemoveHeadList(&head);

PMYDATASTRUCTpMydata = CONTAINING_RECORD(pEntry,MYDATASTRUCT,ListEntry);//可以理解为:pEntry - &MYDATASTRUCT.ListEntry

 

【注释】

 

1、实参MYDATASTRUCTListEntry用于返回ListEntry在结构体中的开始位置8,之后用结构成员中的ListEntry的地址(保存在了pEntry中)减去它就得到了结构体首地址(0x100)

 

2、反汇编代码如下:

 

#define CONTAINING_RECORD(address, type, field) ((type*)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))

 

注释:

 

(type *)((PCHAR)(address) 就是pEntry中的值,就是0x108

 

(ULONG_PTR)(&((type *)0)->field))) 返回的是结构体成员ListEntry到首地址的距离

 

((type *)0)->field  转换为(*0).field = [EAX(eax=0) + field] 。& 会转换为LEA就返回8了  即:LEA [EAX(0)+8]

 

即:0x108- 8 = 0x100  指向了结构体的起始地址

 

3、若MYDATASTRUCT结构的第一个成员是ListEntry,就不存在这种问题了,因为100-0=100还是指向了结构体的第一个成员, CONTAINING_RECORD的作用就是指向结构体的第一个成员,若不指向结构体第一个成员就该报错了。

 

typedef struct _MYDATASTRUCT{

 

  LIST_ENTRY ListEntry;

        ULONG x;

        Ulong y;

                

}MYDATASTRUCT,*PMYDATASTRUCT;

 

 

 

 

 

y

0x108

 

x

0x104

pEntry 起初指向了这里-->

ListEntry

0x100

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值