在MDK中使用$Sub$$和$Super$$的記錄


在MDK開發環境下,對於某些無法被更改的函數,我們需要更改這些函數執行前后的邏輯,偏偏又無法更改到調用這些函數並已經被封裝的代碼,這真是讓人一籌莫展。

幸好MDK給我們留了一個后門,讓我們充分使用“$Sub$$”和“$Super$$”來完成這個目標。

 

比如某個函數

  extern void foo(void);

我們要在它執行的前后進行一段特定的處理,那么參考下面的代碼:

/*定義 foo 函數*/
void foo(void)
{
    printf("f()\n");
}

/*定義foo的補丁函數*/
void $Sub$$foo(void)
{
     /*需要在 foo() 之前執行的代碼塊*/
    printf("before_foo()\n");
  
    /*調用 foo(),要注意使用前綴"$Super$$"*/
    $Super$$foo();

     /*需要在 foo() 之后執行的代碼塊*/
    printf("execute_after_f()\n");
}

/*
疑問:我定義 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("\n execute \"foo();\" result:\n\n");
    /*
    直接寫作"foo();",理論上應該看到 
        <*> before_foo(), 
        <*> f(), 
        <*> after_foo()
    三行日志,實際上前面的“<*>”沒有輸出。
    也就是說,printf函數的補丁沒生效,foo的補丁生效了。
    為什么呢?
    */
    foo();
    /*采用 $Sub$$printf 的形式去調用的話就失去意義了。*/
    $Sub$$printf("i am printed by \"$Sub$$printf\".\n");
    
    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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM