[ARM]__weak 的用法

本文探讨了__weak关键字在ARM架构下的作用。__weak允许函数或变量声明为弱引用,即使没有具体实现,链接器也不会报错。如果没有定义,弱引用的函数会被处理为NOP指令或跳转到下一条指令。这种机制在某些场景下提供了灵活性,例如库函数的选择性调用。总结了__weak的两个关键点:1. 弱引用函数不必有实现,未解析的弱引用不会导致链接错误;2. 未解析的弱函数调用会被替换为NOP或BL到下一条指令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

debug的时候,忽然发现这个函数没有函数实现的地方,只有函数的调用和声明。

仔细看了看这个函数的定义,前面居然有一个__weak,得,查查看看__weak是干什么的吧。

走后面是从ARM网站搜到的,偶也!

读完之后呢,大概总结两点:

1. 带__weak的函数,不一定非得有函数实现。有就最好了,当non-weak一样处理。如果没有函数实现,请看第二点。

2. 如果没有函数实现体,linker会把这个函数处理成nop或者BL到下一条语句。

 

真的是这样吗?得自己动手看看才行,实践出真知嘛!罗德巴赫伺候!!!

看到了吧,那个高亮的2039行有两个nop出现,到底是不是我们那个函数呢?去代码看看喽!

果然,2039行正是我们那个朝思暮想的函数。

好啦,到此为止,休息一会!

------------------------------------------------------------------------------------------------------------------------------

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

How does __weak work?

Applies to: DS-5, RealView Development Suite (RVDS)

Answer

The ARM compilation tools support the concept of "weak" references and definitions.  These can provide additional flexibility in the way the linker includes various (typically library) functions and variables in a build.

Weak references

If the linker can not resolve normal (non-weak) references to symbols included in the link, it will attempt to do so by finding the symbol in a library, and report an error if it can not.  Once such a reference has been resolved, the section it is resolved to is marked as used, so will not later be removed by the linker as an unused section.  Each non-weak reference must be resolved by exactly one definition (if there are multiple definitions, the linker will also report an error). 

Function or variable declarations in C source files can be marked with the__weak qualifier.  As with extern, this qualifier tells the compiler that a function or variable is declared in another compilation unit (source file).  As the definition of this function/variable may not be available to compiler, it creates a (weak) reference to be resolved by the linker.

The compiler will not load an object from a library in order to resolve a weak reference.  It will only be able to resolve the weak reference if the definition will be included in the image for other reasons.  The weak reference will not cause the linker to mark the section containing the definition as used, so it may be removed by the linker as unused.  The definition may already exist in the image for several reasons:

  1. The symbol is strongly referenced somewhere else in the code.
  2. The symbol definition exists in the same ELF section as a symbol definition that is included for any of these reasons*.
  3. The symbol definition is in a section that has been specified using --keep, or contains an ENTRY point.
  4. The symbol definition is in an object file included in the link (not a libary unless the object within the library has been explicitly included on the link line), and the--no_remove option is used.

In summary, a weak reference will be resolved if the definition is already included in the image, but will not affect whether or not that definition is included.

An unresolved weak function call will be replaced either with a NOP (no-operation instruction), or a BL (Branch with link instruction) to the following instruction - effectively the function call just does not happen.

Example usage:

A library contains a function foo(), that will be called in some builds of an application but not in others.  If it is used,init_foo() must be called first.  Weak references can be used to "automate" the call toinit_foo().

The library can define init_foo() and foo() in the the same ELF section*.  The application initialisation code should call init_foo()weakly.  Now if the application includes foo() for any reason, it will also includeinit_foo() and this will be called from the initialisation code.  In any builds that do not includefoo(), the call to init_foo()will be removed by the linker.

In this scenario, there is no need to rebuild the initialisation code between builds that includefoo() and don't include foo().  There is also no possibility of accidentally building an application with a version of the initialisation code that does not callinit_foo(), and other parts of the application that callfoo().

foo.c (typically built into a library):

void init_foo()
{
  // Some initialisation code
}

void foo()
{
  // A function that is included in some builds
  // and requires init_foo() to be called first.
}

init.c:

__weak void init_foo(void);

int main(void)
{
  init_foo();
  // Rest of code that may make calls foo() directly or indirectly.
}


Weak references can also be generated by the assembler:

init.s:

      IMPORT init_foo WEAK

      AREA init, CODE, readonly

      BL init_foo

      ;Rest of code

      END

Weak Definitions

A function definition (or EXPORTed label in assembler) can also be marked as weak, as can a variable definition.  In this case, a weak symbol definition is created in the object file.

A weak definition can be used to resolve any reference to that symbol in the same way as a normal definition.  However, if another (non-weak) definition of that symbol exists in the build, the linker will use that definition instead of the weak definition, and not produce an error due to multiply-defined symbols.

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

------------------------------------------------------------------------------------------------------------------------------

 

 

Default_Handler PROC EXPORT WWDG_IRQHandler [WEAK] EXPORT PVD_IRQHandler [WEAK] EXPORT TAMPER_IRQHandler [WEAK] EXPORT RTC_IRQHandler [WEAK] EXPORT FLASH_IRQHandler [WEAK] EXPORT RCC_IRQHandler [WEAK] EXPORT EXTI0_IRQHandler [WEAK] EXPORT EXTI1_IRQHandler [WEAK] EXPORT EXTI2_IRQHandler [WEAK] EXPORT EXTI3_IRQHandler [WEAK] EXPORT EXTI4_IRQHandler [WEAK] EXPORT DMA1_Channel1_IRQHandler [WEAK] EXPORT DMA1_Channel2_IRQHandler [WEAK] EXPORT DMA1_Channel3_IRQHandler [WEAK] EXPORT DMA1_Channel4_IRQHandler [WEAK] EXPORT DMA1_Channel5_IRQHandler [WEAK] EXPORT DMA1_Channel6_IRQHandler [WEAK] EXPORT DMA1_Channel7_IRQHandler [WEAK] EXPORT ADC1_2_IRQHandler [WEAK] EXPORT USB_HP_CAN1_TX_IRQHandler [WEAK] EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK] EXPORT CAN1_RX1_IRQHandler [WEAK] EXPORT CAN1_SCE_IRQHandler [WEAK] EXPORT EXTI9_5_IRQHandler [WEAK] EXPORT TIM1_BRK_IRQHandler [WEAK] EXPORT TIM1_UP_IRQHandler [WEAK] EXPORT TIM1_TRG_COM_IRQHandler [WEAK] EXPORT TIM1_CC_IRQHandler [WEAK] EXPORT TIM2_IRQHandler [WEAK] EXPORT TIM3_IRQHandler [WEAK] EXPORT TIM4_IRQHandler [WEAK] EXPORT I2C1_EV_IRQHandler [WEAK] EXPORT I2C1_ER_IRQHandler [WEAK] EXPORT I2C2_EV_IRQHandler [WEAK] EXPORT I2C2_ER_IRQHandler [WEAK] EXPORT SPI1_IRQHandler [WEAK] EXPORT SPI2_IRQHandler [WEAK] EXPORT USART1_IRQHandler [WEAK] EXPORT USART2_IRQHandler [WEAK] EXPORT USART3_IRQHandler [WEAK] EXPORT EXTI15_10_IRQHandler [WEAK] EXPORT RTCAlarm_IRQHandler [WEAK] EXPORT USBWakeUp_IRQHandler [WEAK] EXPORT TIM8_BRK_IRQHandler [WEAK] EXPORT TIM8_UP_IRQHandler [WEAK] EXPORT TIM8_TRG_COM_IRQHandler [WEAK] EXPORT TIM8_CC_IRQHandler [WEAK] EXPORT ADC3_IRQHandler [WEAK] EXPORT FSMC_IRQHandler [WEAK] EXPORT SDIO_IRQHandler [WEAK] EXPORT TIM5_IRQHandler [WEAK] EXPORT SPI3_IRQHandler [WEAK] EXPORT UART4_IRQHandler [WEAK] EXPORT UART5_IRQHandler [WEAK] EXPORT TIM6_IRQHandler [WEAK] EXPORT TIM7_IRQHandler [WEAK] EXPORT DMA2_Channel1_IRQHandler [WEAK] EXPORT DMA2_Channel2_IRQHandler [WEAK] EXPORT DMA2_Channel3_IRQHandler [WEAK] EXPORT DMA2_Channel4_5_IRQHandler [WEAK] WWDG_IRQHandler PVD_IRQHandler TAMPER_IRQHandler RTC_IRQHandler FLASH_IRQHandler RCC_IRQHandler EXTI0_IRQHandler EXTI1_IRQHandler EXTI2_IRQHandler EXTI3_IRQHandler EXTI4_IRQHandler DMA1_Channel1_IRQHandler DMA1_Channel2_IRQHandler DMA1_Channel3_IRQHandler DMA1_Channel4_IRQHandler DMA1_Channel5_IRQHandler DMA1_Channel6_IRQHandler DMA1_Channel7_IRQHandler ADC1_2_IRQHandler USB_HP_CAN1_TX_IRQHandler USB_LP_CAN1_RX0_IRQHandler CAN1_RX1_IRQHandler CAN1_SCE_IRQHandler EXTI9_5_IRQHandler TIM1_BRK_IRQHandler TIM1_UP_IRQHandler TIM1_TRG_COM_IRQHandler TIM1_CC_IRQHandler TIM2_IRQHandler TIM3_IRQHandler TIM4_IRQHandler I2C1_EV_IRQHandler I2C1_ER_IRQHandler I2C2_EV_IRQHandler I2C2_ER_IRQHandler SPI1_IRQHandler SPI2_IRQHandler USART1_IRQHandler USART2_IRQHandler USART3_IRQHandler EXTI15_10_IRQHandler RTCAlarm_IRQHandler USBWakeUp_IRQHandler TIM8_BRK_IRQHandler TIM8_UP_IRQHandler TIM8_TRG_COM_IRQHandler TIM8_CC_IRQHandler ADC3_IRQHandler FSMC_IRQHandler SDIO_IRQHandler TIM5_IRQHandler SPI3_IRQHandler UART4_IRQHandler UART5_IRQHandler TIM6_IRQHandler TIM7_IRQHandler DMA2_Channel1_IRQHandler DMA2_Channel2_IRQHandler DMA2_Channel3_IRQHandler DMA2_Channel4_5_IRQHandler B . ENDP ALIGN继续逐条指令进行分析
最新发布
08-03
DESCEND objtool HOSTCC scripts/mod/modpost.o INSTALL libsubcmd_headers CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/exec-cmd.o scripts/mod/modpost.c: In function ‘addend_arm_rel’: scripts/mod/modpost.c:1178:7: error: ‘R_ARM_MOVW_ABS_NC’ undeclared (first use in this function); did you mean ‘R_ARM_THM_ABS5’? case R_ARM_MOVW_ABS_NC: ^~~~~~~~~~~~~~~~~ R_ARM_THM_ABS5 scripts/mod/modpost.c:1178:7: note: each undeclared identifier is reported only once for each function it appears in scripts/mod/modpost.c:1179:7: error: ‘R_ARM_MOVT_ABS’ undeclared (first use in this function); did you mean ‘R_ARM_THM_ABS5’? case R_ARM_MOVT_ABS: ^~~~~~~~~~~~~~ R_ARM_THM_ABS5 scripts/mod/modpost.c:1185:7: error: ‘R_ARM_CALL’ undeclared (first use in this function); did you mean ‘R_ARM_COPY’? case R_ARM_CALL: ^~~~~~~~~~ R_ARM_COPY scripts/mod/modpost.c:1186:7: error: ‘R_ARM_JUMP24’ undeclared (first use in this function); did you mean ‘R_ARM_PC24’? case R_ARM_JUMP24: ^~~~~~~~~~~~ R_ARM_PC24 scripts/mod/modpost.c:1190:7: error: ‘R_ARM_THM_MOVW_ABS_NC’ undeclared (first use in this function); did you mean ‘R_ARM_THM_ABS5’? case R_ARM_THM_MOVW_ABS_NC: ^~~~~~~~~~~~~~~~~~~~~ R_ARM_THM_ABS5 scripts/mod/modpost.c:1191:7: error: ‘R_ARM_THM_MOVT_ABS’ undeclared (first use in this function); did you mean ‘R_ARM_THM_ABS5’? case R_ARM_THM_MOVT_ABS: ^~~~~~~~~~~~~~~~~~ R_ARM_THM_ABS5 scripts/mod/modpost.c:1200:7: error: ‘R_ARM_THM_JUMP19’ undeclared (first use in this function); did you mean ‘R_ARM_THM_PC9’? case R_ARM_THM_JUMP19: ^~~~~~~~~~~~~~~~ R_ARM_THM_PC9 scripts/mod/modpost.c:1222:7: error: ‘R_ARM_THM_JUMP24’ undeclared (first use in this function); did you mean ‘R_ARM_THM_PC8’? case R_ARM_THM_JUMP24: ^~~~~~~~~~~~~~~~ R_ARM_THM_PC8 make[2]: *** [scripts/Makefile.host:133: scripts/mod/modpost.o] Error 1 make[1]: *** [/usr/src/kernels/linux-6.12.33/Makefile:1216: prepare0] Error 2 make[1]: *** 正在等待未完成的任务.... CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/help.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/pager.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/parse-options.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/run-command.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/sigchain.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/subcmd-config.o LD /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/libsubcmd-in.o AR /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/libsubcmd.a CC /usr/src/kernels/linux-6.12.33/tools/objtool/weak.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/arch/x86/special.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/arch/x86/decode.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/arch/x86/orc.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/check.o LD /usr/src/kernels/linux-6.12.33/tools/objtool/arch/x86/objtool-in.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/special.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/builtin-check.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/elf.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/objtool.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/orc_gen.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/orc_dump.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libstring.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libctype.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/str_error_r.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/librbtree.o LD /usr/src/kernels/linux-6.12.33/tools/objtool/objtool-in.o LINK /usr/src/kernels/linux-6.12.33/tools/objtool/objtool make: *** [Makefile:224: __sub-make] Error 2 是什么意思,该怎么解决
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值