weak alias

__attribute__是gcc专有的,用来说明函数的属性

weak 和 alias 分别是两个属性。weak 使得 dram_init_banksize 这个符号在目标文件中作为 weak symbol 而不是 global symbol。用 nm 命令查看编译 生成的目标文件可用看到 dram_init_banksize 是一个weak symbol,它前面的标记是 W。
而 alias 则使 dram_init_banksize 是 __dram_init_banksize 的一个别名,__dram_init_banksize 和 dram_init_banksize 必须在同一个编译单元中定义,否则会编译出错。

给函数加上weak属性时,即使函数没定义,函数被调用也可以编译成功。
当有两个函数同名时,则使用强符号(也叫全局符号,即没有加weak的函数)来代替弱符号(加weak的函数)。


glibc定义的系统调用

最近有人问道,glibc 中对我们常见的那些系统调用的定义在哪里?比如write(2)recv(2)

这个问题我以前在看glibc的代码时注意到了。我们通常可以直接找到的所谓定义,比如下面这个:

[c]
ssize_t
libc_write (int fd, const void *buf, size_t nbytes)
{
if (nbytes == 0)
return 0;
if (fd < 0)
{
set_errno (EBADF);
return -1;
}
if (buf == NULL)
{
__set_errno (EINVAL);
return -1;
}

set_errno (ENOSYS);
return -1;
}
libc_hidden_def (
libc_write)
stub_warning (write)

weak_alias (libc_write, write)
libc_hidden_weak (write)
weak_alias (
libc_write, write)
[/c]

其实很明显,这并不是真正的定义,至少并不是你想找的那个。这个是什么呢?这个其实是write(2)的一个alias,而且还是weak alias,换句话说也就是,如果一个平台上没有定义自己的write(2),那么就用一个。而且从上面的代码也可以看得出来,这个函数仅仅是处理了一下errno,别的什么都不做。

那真正的定义究竟在哪里?说实话,我当初找到费了一番周折,找到它们并不容易,因为它们是编译时生成的!!可以从下面三个文件中看出来:

sysdeps/unix/make-syscalls.sh
sysdeps/unix/syscalls.list(sysdeps/unix/inet/syscalls.list)
sysdeps/unix/syscall-template.S

syscall-template.S顾名思义是个定义的模板,每个生成的系统调用都要参考这个模板,但是怎么用模板来“刻画”每一个系统调用呢?于是就有了syscalls.list,而make-syscalls.sh就是用模板和那个列表来构建生成系统调用定义的makefile,该makefile最终生成最后的定义。有兴趣的朋友应该仔细看看这几个文件。

现在再想想,这么做其实是有道理的,在Linux下,系统调用的真正定义有很多相似的地方,确实可以通过“模板”来生成对应的汇编,但是否真值得花时间去构建那么抽象的一个模板和框架?我说不清楚,本着“懒惰”的原则确实应该如此,不过看看模板本身似乎原因不仅仅是“懒惰”。

从这里我们也可以看出glibc的代码难读啊,比起Linux内核来,不仅仅是风格的问题,还有就是使用了太多的tricks,导致的结果也很显而易见,参与glibc开发的和参与linux内核开发的人明显不是一个数量级的。

/******************** (C) COPYRIGHT 2007 STMicroelectronics ******************** * File Name : stm32f10x_vector.c * Author : MCD Application Team * Version : V1.0 * Date : 10/08/2007 * Description : This file contains the vector table for STM32F10x. * After Reset the Cortex-M3 processor is in Thread mode, * priority is Privileged, and the Stack is set to Main. ******************************************************************************** * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. *******************************************************************************/ /* Includes ------------------------------------------------------------------*/ void NMIException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void HardFaultException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void MemManageException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void BusFaultException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void UsageFaultException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DebugMonitor(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void SVCHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void PendSVC(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void SysTickHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); /* Peripherals handlers */ void WWDG_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void PVD_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TAMPER_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void RTC_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void FLASH_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void RCC_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI0_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI3_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI4_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel3_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel4_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel5_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel6_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel7_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void ADC_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USB_HP_CAN_TX_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USB_LP_CAN_RX0_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void CAN_RX1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void CAN_SCE_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI9_5_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM1_BRK_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM1_UP_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM1_TRG_COM_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM1_CC_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM3_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM4_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void I2C1_EV_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void I2C1_ER_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void I2C2_EV_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void I2C2_ER_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void SPI1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void SPI2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USART1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USART2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USART3_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI15_10_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void RTCAlarm_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USBWakeUp_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ extern unsigned long _etext; extern unsigned long _sidata; /* start address for the initialization values of the .data section. defined in linker script */ extern unsigned long _sdata; /* start address for the .data section. defined in linker script */ extern unsigned long _edata; /* end address for the .data section. defined in linker script */ extern unsigned long _sbss; /* start address for the .bss section. defined in linker script */ extern unsigned long _ebss; /* end address for the .bss section. defined in linker script */ extern void _estack; /* init value for the stack pointer. defined in linker script */ /* Private typedef -----------------------------------------------------------*/ /* function prototypes -------------------------------------------------------*/ void Reset_Handler(void) __attribute__((__interrupt__)); extern int main(void); /******************************************************************************* * * The minimal vector table for a Cortex M3. Note that the proper constructs * must be placed on this to ensure that it ends up at physical address * 0x0000.0000. * *******************************************************************************/ __attribute__ ((section(".vectors"), used)) void (* const gVectors[])(void) = { (void (*)(void))((unsigned long)&_estack), // The initial stack pointer Reset_Handler, // The reset handler NMIException, HardFaultException, MemManageException, BusFaultException, UsageFaultException, 0, 0, 0, 0, /* Reserved */ SVCHandler, DebugMonitor, 0, /* Reserved */ PendSVC, SysTickHandler, WWDG_IRQHandler, PVD_IRQHandler, TAMPER_IRQHandler, RTC_IRQHandler, FLASH_IRQHandler, RCC_IRQHandler, EXTI0_IRQHandler, EXTI1_IRQHandler, EXTI2_IRQHandler, EXTI3_IRQHandler, EXTI4_IRQHandler, DMAChannel1_IRQHandler, DMAChannel2_IRQHandler, DMAChannel3_IRQHandler, DMAChannel4_IRQHandler, DMAChannel5_IRQHandler, DMAChannel6_IRQHandler, DMAChannel7_IRQHandler, ADC_IRQHandler, USB_HP_CAN_TX_IRQHandler, USB_LP_CAN_RX0_IRQHandler, CAN_RX1_IRQHandler, CAN_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, 0, 0, 0, 0, 0, 0, 0, (unsigned short)0xF108F85F //this is a workaround for boot in RAM mode. }; /******************************************************************************* * Function Name : Reset_Handler * Description : This is the code that gets called when the processor first * starts execution following a reset event. Only the absolutely * necessary set is performed, after which the application * supplied main() routine is called. * Input : * Output : * Return : *******************************************************************************/ void Reset_Handler(void) { unsigned long *pulSrc, *pulDest; // // Copy the data segment initializers from flash to SRAM. // pulSrc = &_sidata; for(pulDest = &_sdata; pulDest < &_edata; ) { *(pulDest++) = *(pulSrc++); } // // Zero fill the bss segment. // for(pulDest = &_sbss; pulDest < &_ebss; ) { *(pulDest++) = 0; } // // Call the application's entry point. // main(); } void IntDefaultHandler(void) { for(;;); } /****************** (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ 这段代码有什么作用
最新发布
11-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值