电脑技术学习

FreeBSD的Loader和内核初始化

dn001

  宏DATA_SET()展开成MAKE_SET(),宏MAKE_SET()指向所有隐含的

sysinit幻数:/usr/include/linker_set.h
#define MAKE_SET(set, sym)           
  static void const * const __set_##set##_sym_##sym = &sym; 
  __asm(".section .set." #set ","aw"");      
  __asm(".long " #sym);           
  __asm(".previous")
#endif
#define TEXT_SET(set, sym) MAKE_SET(set, sym)
#define DATA_SET(set, sym) MAKE_SET(set, sym)

  回到我们的例子中,经过宏的展开过程,将会产生如下声明:

static struct sysinit announce_sys_init = {
  SI_SUB_COPYRIGHT,
  SI_ORDER_FIRST,
  (sysinit_cfunc_t)(sysinit_nfunc_t) print_CADdr_t,
  (void *) copyright
};
static void const *const __set_sysinit_set_sym_announce_sys_init =
  &announce_sys_init;
__asm(".section .set.sysinit_set" ","aw"");
__asm(".long " "announce_sys_init");
__asm(".previous");

  第一个__asm指令在内核可执行文件中建立一个ELF节(section)。这发生在内核链接的时候。

  这一节将被命令为.set.sysinit_set。这一节的内容是一个32位值——announce_sys_init结构的地址,这个结构正是第二个__asm指令所定义的。第三个__asm指令标记节的结束。

  如果前面有名字相同的节定义语句,节的内容(那个32位值)将被填加到已存在的节里,这样就构造出了一个32位指针数组。用objdump察看一个内核二进制文件,也许你会注意到里面有这么几个小的节:% objdump -h /kernel

标签: