zoukankan      html  css  js  c++  java
  • 在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/
  • 相关阅读:
    JAVA常用运算符
    JAVA基本语义简介
    JAVA常用关键字
    记事本写JAVA程序
    JAVA开发环境搭建
    PROTEL DXP原理图编译 常见错误与处理方法
    关于光耦的认识
    十六进制转十进制函数_C编程
    Protues记录文档_1
    SR触发器和JK触发器
  • 原文地址:https://www.cnblogs.com/ssdq/p/13439299.html
Copyright © 2011-2022 走看看