一、简介
官方说明链接:https://developer.arm.com/documentation/dui0377/g/pge1362065967698
ARM链接器提供$Super$$
和$Sub$$
关键字用来为一些无法修改的函数打补丁。
这是一种特殊模式:用于有一个已经存在且不能被改变的函数的情况(比如不能更改的库函数);使用这两个模式可以帮原函数打补丁,如存在一个函数foo()
;
$Sub$$foo
:定义的新功能函数,在foo()
函数之前/后使用$Sub$$foo
可以添加一些新的程序代码。
$Super$$foo
:就是原始的未修补的foo函数,使用这个$Super$$foo
函数将直接跳转到foo()
函数。
二、测试
1、创建一个工程,使用串口发送"$Super$$foo(void)\r\n"
字符串。
void foo(void){
HAL_UART_Transmit(&huart1,(uint8_t*)"-----------------\r\n",19,100);
HAL_UART_Transmit(&huart1,(uint8_t*)"$Super$$foo(void)\r\n",19,100);
HAL_UART_Transmit(&huart1,(uint8_t*)"-----------------\r\n",19,100);
}
2、在main
函数中调用
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
foo();
while (1)
{
}
}
3、编译、烧录、启动,在串口输出信息如下
4、在main
函数外添加补丁函数,main
函数调用foo
函数
void $Sub$$foo(void)
{
HAL_UART_Transmit(&huart1,(uint8_t*)"====================\r\n",22,100);
HAL_UART_Transmit(&huart1,(uint8_t*)"void $Sub$$foo(void)\r\n",22,100);
HAL_UART_Transmit(&huart1,(uint8_t*)"====================\r\n",22,100);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
foo();
while (1)
{
}
}
5、串口输入信息如下
通过以上输出发现,只执行补丁函数,而未执行原来foo函数。
6、在补丁函数中调用原来函数,在代码中添加如下信息
extern void $Super$$foo(void);
void $Sub$$foo(void)
{
HAL_UART_Transmit(&huart1,(uint8_t*)"====================\r\n",22,100);
HAL_UART_Transmit(&huart1,(uint8_t*)"void $Sub$$foo(void)\r\n",22,100);
$Super$$foo();
HAL_UART_Transmit(&huart1,(uint8_t*)"====================\r\n",22,100);
}
7、串口输出信息如下
通过以上输出信息,可以看出先执行foo补丁函数,再执行foo函数,执行完foo函数后再次执行补丁函数。
8、调整补丁函数执行顺序
extern void $Super$$foo(void);
void $Sub$$foo(void)
{
HAL_UART_Transmit(&huart1,(uint8_t*)"====================\r\n",22,100);
HAL_UART_Transmit(&huart1,(uint8_t*)"void $Sub$$foo(void)\r\n",22,100);
HAL_UART_Transmit(&huart1,(uint8_t*)"====================\r\n",22,100);
$Super$$foo();
}
9、串口输出信息如下
三、总结
通过以上分析,可以通过ARM链接器提供$Super$$
和$Sub$$
功能在原有函数前或后插入其他代码,对原有函数打补丁。