RTP之Hook

2022-06-30 18:59:21 浏览数 (2)

Task可以注册Hook,RTP也可以,只需在VIP中包含组件INCLUDE_RTP_HOOKS。每种Hook可以注册的数量为RTP_HOOK_TBL_SIZ

先看第一对Hook

代码语言:javascript复制
typedef STATUS (*RTP_PRE_CREATE_HOOK)
    (
    const char *rtpFileName, /* Null-terminated path to executable */
    const char *argv[],      /* pointer to NULL terminated argv array */
    const char *envp[],      /* pointer to NULL terminated envp array */
    int         priority,    /* priority of initial task */
    size_t      uStackSize,  /* User space stack size for intial task */
    int         options,     /* the options passed to RTP */
    int         taskOptions  /* Task options for RTP's initial task */
    );
STATUS rtpPreCreateHookAdd
    (
    RTP_PRE_CREATE_HOOK hook,
    BOOL                addToHead
    );
STATUS rtpPreCreateHookDelete
    (
    RTP_PRE_CREATE_HOOK hook
    );

rtpPreCreateHookAdd() 添加的Hook是在创建RTP之前调用。如果Hook的返回值不是OK,后续的RTP就不会被创建了。这种Hook可以用于RTP创建之前的验证。

参数<addToHead>用于指定同类Hook的调用顺序。如果使用FALSE,则将Hook加入列表尾部。如果使用TRUE,则加到列表头部,那么它就会被优先调用。

写个简单的RTP例子,例如main()直接返回,将编译的vxe文件复制两份

注册以下Hook

代码语言:javascript复制
#include <private/rtpLibP.h>

#if 0
/* options */
#define RTP_GLOBAL_SYMBOLS    0x01 /* register global symbols for RTP */
#define RTP_LOCAL_SYMBOLS     0x02 /* idem for local symbols */
#define RTP_ALL_SYMBOLS      (RTP_GLOBAL_SYMBOLS | RTP_LOCAL_SYMBOLS)
#define RTP_DEBUG             0x10 /* set RTP in debug mode when created */
#define RTP_BUFFER_VAL_OFF    0x20 /* disable buffer validation for all system calls issued from the RTP  */
#define RTP_LOADED_WAIT       0x40 /* Wait until the RTP is loaded */ 
#define RTP_CPU_AFFINITY_NONE 0x80 /* Remove any CPU affinity (SMP) */
#endif

#if 0
/* taskOptions */
#define VX_PRIVATE_ENV      0x00000080 /* private environment variables */
#define VX_NO_STACK_FILL    0x00000100 /* avoid stack fill of 0xee */
#define VX_TASK_NOACTIVATE  0x00002000 /* taskOpen() does not taskActivate() */
#define VX_NO_STACK_PROTECT 0x00004000 /* no over/underflow stack protection,*/

#define VX_COPROC1_TASK     0x01000000
#define VX_COPROC2_TASK     0x02000000

/* i86 */
#define VX_FP_TASK          VX_COPROC1_TASK
#endif

static STATUS rtpPreHook
    (
    const char *rtpFileName,
    const char *argv[],
    const char *envp[],
    int         priority,
    size_t      uStackSize,
    int         options,
    int         taskOptions
    )
{
    int i;

    if(strcmp("test.vxe", rtpFileName))
        {
        printf("%s should be loaded latern", rtpFileName);
        return ERROR;
        }

    if(argv != NULL)
        {
        i = -1;
        while(argv[  i] != NULL)
            {
            printf("argv[%d] = %sn", i, argv[i]);
            }
        }
    
    if(envp != NULL)
        {
        i = -1;
        while(envp[  i] != NULL)
            {
            printf("envp[%d]: %sn", i, envp[i]);
            }
        }

    printf("priority of main is %dn", priority);
    printf("stack size of main is %#xn", uStackSize);
    printf("options of RTP is %#xn", options);
    printf("options of main is %#xn", taskOptions);

    return OK;
    }

void testRtpHook()
{
    rtpPreCreateHookAdd(rtpPreHook, FALSE);
    }

看看执行效果

第二对Hook

代码语言:javascript复制
typedef STATUS (*RTP_POST_CREATE_HOOK)
    (
    const RTP_ID rtpId
    );
STATUS rtpPostCreateHookAdd
    (
    RTP_POST_CREATE_HOOK hook,
    BOOL                 addToHead
    );
STATUS rtpPostCreateHookDelete
    (
    RTP_POST_CREATE_HOOK hook
    );

rtpPostCreateHookAdd()添加的Hook是在RTP及其主任务已创建但未执行时调用。例如RTP A正在创建RTP B,这种Hook是在RTP A的上下文里执行。Hook创建的对象,属于RTP A。如果要改变对象的隶属关系,可以调用objOwnerSet():

objOwnerSet(createdObjId, rtpId)

这种Hook也是在rtpSpawn()里调用。如果返回值不是OK,已创建的RTP及其主任务都会被删除,然后rtpSpawn()返回ERROR。这种Hook可用于附加的资源分配。

参考上文的例子

代码语言:javascript复制

#include <private/rtpLibP.h>

static STATUS rtpPostHook
    (
    const RTP_ID rtpId
    )
{
    int i;
    WIND_TCB *pTcb;

    if(strcmp("test.vxe", rtpId->pPathName))
        {
        printf("%s should be loaded latern", rtpId->pPathName);
        return ERROR;
        }

    if(rtpId->pArgv != NULL)
        {
        i = -1;
        while(rtpId->pArgv[  i] != NULL)
            {
            printf("argv[%d] = %sn", i, rtpId->pArgv[i]);
            }
        }
    
    if(rtpId->pEnv != NULL)
        {
        i = -1;
        while(rtpId->pEnv[  i] != NULL)
            {
            printf("envp[%d]: %sn", i, rtpId->pEnv[i]);
            }
        }

    pTcb = taskTcb(rtpId->initTaskId);
    printf("priority of main is %dn", pTcb->priority);
    printf("stack size of main is %#xn", pTcb->pStackBase-pTcb->pStackEnd);
    printf("options of RTP is %#xn", rtpId->options);
    printf("options of main is %#xn", pTcb->options);

    return OK;
    }

void testRtpHook()
{
    rtpPostCreateHookAdd(rtpPostHook, FALSE);
    }

第三对Hook

代码语言:javascript复制
typedef void (*RTP_INIT_COMPLETE_HOOK)
    (
    const RTP_ID rtpId
    );
STATUS rtpInitCompleteHookAdd
    (
    RTP_INIT_COMPLETE_HOOK hook,
    BOOL                   addToHead
    );
STATUS rtpInitCompleteHookDelete
    (
    RTP_INIT_COMPLETE_HOOK hook
    );

rtpInitCompleteHookAdd()添加的Hook是在创建的RTP完全初始化之后调用 (其主任务执行之前)。这种Hook可用于通知Debugger或其它想访问新建RTP内存空间的工具。因此,它不应该再创建任何对象或执行对RTP有影响的操作。

最后一对

代码语言:javascript复制
typedef void (*RTP_DELETE_HOOK)
    (
    const RTP_ID rtpId
    const int    exitCode
    );
STATUS rtpDeleteHookAdd
    (
    RTP_DELETE_HOOK hook,
    BOOL            addToHead
    );
STATUS rtpDeleteHookDelete
    (
    RTP_DELETE_HOOK hook
    );

rtpDeleteHookAdd()添加的Hook在rtpDelete()删除RTP时调用。而且,这个时候,RTP内部的Task都已经被删除了

有个地方儿要注意:多个Hook之间可能有依赖关系。例如,某个Delete Hook使用的机制可能被其它Hook删除。因此,Hook的调用顺序就很重要。通常,Create Hook按照添加顺序来调用,Delete Hook的调用顺序则相反。即,Create Hook在注册时,参数 <addToHead> 使用FALSE;Delete Hook的,则使用TRUE。

这正是

RTP,多Hook, 可调试,可监测;

自己动手才解惑,多多练习更灵活

0 人点赞