在MDK中使用$Sub$$和$Super$$的记录

在MDK开发环境下,对于某些无法被更改的函数,我们需要更改这些函数执行前后的逻辑,偏偏又无法更改到调用这些函数并已经被封装的代码,这真是让人一筹莫展。

幸好MDK给我们留了一个后门,让我们充分使用“$Sub$$”和“$Super$$”来完成这个目标。

比如某个函数

  extern void foo(void);

我们要在它执行的前后进行一段特定的处理,那么参考下面的代码:

/*定义 foo 函数*/
void foo(void)
{
    printf("f()
");
}

/*定义foo的补丁函数*/
void $Sub$$foo(void)
{
     /*需要在 foo() 之前执行的代码块*/
    printf("before_foo()
");
  
    /*调用 foo(),要注意使用前缀"$Super$$"*/
    $Super$$foo();

     /*需要在 foo() 之后执行的代码块*/
    printf("execute_after_f()
");
}

/*
疑问:我定义 printf 的补丁函数 $Sub$$printf,
实际调用 printf 的时候,并没有进入 $Sub$$printf,
这是为何?
*/
int $Sub$$printf(const char *fmt, ...)
{
    $Super$$printf("<*> ");
    return $Super$$printf(fmt);
}

int main(void)
{
    uint32_t limitedTick;
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    tick_initialize();
    trace_initialize(user_command_deal);

    printf("
 execute "foo();" result:

");
    /*
    直接写作"foo();",理论上应该看到 
        <*> before_foo(), 
        <*> f(), 
        <*> after_foo()
    三行日志,实际上前面的“<*>”没有输出。
    也就是说,printf函数的补丁没生效,foo的补丁生效了。
    为什么呢?
    */
    foo();
    /*采用 $Sub$$printf 的形式去调用的话就失去意义了。*/
    $Sub$$printf("i am printed by "$Sub$$printf".
");
    
    while(1);
    return 0;
}

 

注意:

1、必须定义一个新的以“$Sub$$”作为前缀,后面紧跟“欲被处理的函数名”的函数,例如 “$Sub$$foo()”.

2、在补丁函数里面需要以 “$Super$$foo()” 的方式去调用原始的 foo 函数,而不应该直接写作 “foo()”去调用。

不要“$Super$$”前缀也能调用到,不建议这么做。感觉要是不加前缀,就好像进入无限嵌套一样的,不断的调用自己。

3、这个特性仅在ARM CC编译器内被支持,所以一般都会使用宏“#if defined(__CC_ARM)”来囊括处理。

4、既然是针对 foo 的补丁,在调用的地方自然就应该写作 "foo();",而不是 "$Sub$$foo();",要不然补丁有何意义呢?

疑问:

为什么我针对printf的补丁不生效呢?

经过调试,发现printf被替换成了 __2printf,如果针对  printf 这个“词”进行 $Sub$$ 前缀化,是达不到目标的,改成 $Sub$$__2printf 之后,再使用 printf 的时候就实际执行了 $Sub$$__2printf 。

搞不懂为什么 printf 会变成 __2printf。

参考:

https://developer.arm.com/documentation/dui0377/g/accessing-and-managing-symbols-with-armlink/use-of--super---and--sub---to-patch-symbol-definitions

https://www.cnblogs.com/raswin/p/10031117.html

https://blog.csdn.net/qq_42860728/article/details/89495882

如果转载,请注明出处。https://www.cnblogs.com/ssdq/
原文地址:https://www.cnblogs.com/ssdq/p/13439299.html