- 论坛徽章:
- 0
|
Apache Hook 结构分析(二)
杨学刚
2009-3-18
xuegangyang@eyou.com
一、简介 1
二、Hook array结构分析 2
三、Hook 函数分析 3
3.1 hook函数实现 3
3.2 Run函数实现 4
3.2.1 FIRST处理流程对应的run函数定义 4
3.2.2 ALL处理流程对应的run函数定义 5
3.2.3 VOID处理流程对应的run函数定义 5
3.3 get_hook函数实现 6
四、HOOK宏分析 6
4.1 HOOK_STRUCT宏分析 6
4.2 EXTERNAL_HOOK宏分析 7
4.3 VOID宏分析 7
4.4 RUN_ALL宏分析 8
4.5 RUN_FIRST宏分析 9
4.6 使用宏定义HOOK 10
五、HOOK定义扩展 10
六、小结和思考 11
四、HOOK宏分析
通过以上分析可以看出apache中HOOK实现需要编写一个Hook array和三个函数,为了简化实现hook的方法和提高代码开发效率,Apache定义了五个HOOK宏来实现HOOK:APR_HOOK_STRUCT、APR_DECLARE_EXTERNAL_HOOK、APR_IMPLEMENT_EXTERNAL_HOOK_VOID、APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL、APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST,为描述方便,以上五个宏按照其名字分别简称为:HOOK_STRUCT、EXTERNAL_HOOK、VOID、RUN_ALL和RUN_FIRST宏
4.1 HOOK_STRUCT宏分析
APR_HOOK_STRUCT主要用于定义hook对应的_hooks变量,该宏的代码为:
#define APR_HOOK_STRUCT(members) \
static struct { members } _hooks; |
但在apache源码中,该宏通常以以下形式使用:
APR_HOOK_STRUCT(
APR_HOOK_LINK(header_parser)
) |
以上使用涉及到APR_HOOK_LINK宏,其定义非常简单:
#define APR_HOOK_LINK(name) \
apr_array_header_t *link_##name; |
结合APR_HOOK_LINK和HOOK_STRUCT宏,便可以定义_hooks 变量。
4.2 EXTERNAL_HOOK宏分析
EXTERNAL_HOOK宏主要用于声明Hook对应的hook、run和get_hook函数(注意:仅仅是声明而不是实现),声明了hook array中对应的element类型,其源码如下:
/** macro to declare the hook correctly */
#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
typedef ret ns##_HOOK_##name##_t args; \
link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
const char * const *aszPre, \
const char * const *aszSucc, int nOrder); \
link##_DECLARE(ret) ns##_run_##name args; \
APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \
typedef struct ns##_LINK_##name##_t \
{ \
ns##_HOOK_##name##_t *pFunc; \
const char *szName; \
const char * const *aszPredecessors; \
const char * const *aszSuccessors; \
int nOrder; \
} ns##_LINK_##name##_t; |
从以上源码中可以看到涉及APR_IMPLEMENT_HOOK_GET_PROTO宏,其功能是用于声明HOOK的get_hook函数,其源码如下:
/** macro to return the prototype of the hook function */
#define APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
link##_DECLARE(apr_array_header_t *) ns##_hook_get_##name(void) |
4.3 VOID宏分析
VOID 宏主要用于实现处理流程为VOID时的run函数,其源码如下:
#define APR_IMPLEMENT_EXTERNAL_HOOK_VOID(ns,link,name,args_decl,args_use) \
APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
link##_DECLARE(void) ns##_run_##name args_decl \
{ \
ns##_LINK_##name##_t *pHook; \
int n; \
\
if(!_hooks.link_##name) \
return; \
\
pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \
for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \
pHook[n].pFunc args_use; \
} |
源码中用到了APR_IMPLEMENT_EXTERNAL_HOOK_BASE宏,该宏用于实现HOOK对应的hook和get_hook函数,其源码如下:
#define APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf,const char * const *aszPre, \
const char * const *aszSucc,int nOrder) \
{ \
ns##_LINK_##name##_t *pHook; \
if(!_hooks.link_##name) \
{ \
_hooks.link_##name=apr_array_make(apr_hook_global_pool,1,sizeof(ns##_LINK_##name##_t)); \
apr_hook_sort_register(#name,&_hooks.link_##name); \
} \
pHook=apr_array_push(_hooks.link_##name); \
pHook->pFunc=pf; \
pHook->aszPredecessors=aszPre; \
pHook->aszSuccessors=aszSucc; \
pHook->nOrder=nOrder; \
pHook->szName=apr_hook_debug_current; \
if(apr_hook_debug_enabled) \
apr_hook_debug_show(#name,aszPre,aszSucc); \
} \
APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
{ \
return _hooks.link_##name; \
}
|
|
|