Linux源码与编译出的目标文件汇编代码的一致性问题
start_kernel是内核启动时比较重要的一个函数,然而我发现一个问题,我编译出来的目标文件中的汇编代码与C源码并不完全对应,这是怎么一回事呢?
asmlinkage void __init start_kernel(void) { char * command_line; extern const struct kernel_param __start___param[], __stop___param[]; /* * Need to run as early as possible, to initialize the * lockdep hash: */ lockdep_init(); smp_setup_processor_id(); debug_objects_early_init(); /* * Set up the the initial canary ASAP: */ boot_init_stack_canary(); cgroup_init_early(); local_irq_disable(); early_boot_irqs_disabled = true;
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
boot_cpu_init();
page_address_init();
pr_notice("%s", linux_banner);
setup_arch(&command_line);
mm_init_owner(&init_mm, &init_task);
mm_init_cpumask(&init_mm);
setup_command_line(command_line);
setup_nr_cpu_ids();
setup_per_cpu_areas();
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
objdump -d main.o
00000337 <start_kernel>: 337: 55 push %ebp 338: 89 e5 mov %esp,%ebp 33a: 53 push %ebx 33b: 83 ec 14 sub $0x14,%esp 33e: e8 fc ff ff ff call 33f <start_kernel+0x8> 343: e8 fc ff ff ff call 344 <start_kernel+0xd> 348: ff 15 08 00 00 00 call *0x8 34e: 64 8b 1d 00 00 00 00 mov %fs:0x0,%ebx 355: ba 01 00 00 00 mov $0x1,%edx 35a: 89 d8 mov %ebx,%eax 35c: c6 05 00 00 00 00 01 movb $0x1,0x0 363: e8 fc ff ff ff call 364 <start_kernel+0x2d> 368: 89 d8 mov %ebx,%eax 36a: ba 01 00 00 00 mov $0x1,%edx 36f: e8 fc ff ff ff call 370 <start_kernel+0x39> 374: 89 d8 mov %ebx,%eax 376: ba 01 00 00 00 mov $0x1,%edx 37b: e8 fc ff ff ff call 37c <start_kernel+0x45> 380: ba 01 00 00 00 mov $0x1,%edx 385: 89 d8 mov %ebx,%eax 387: e8 fc ff ff ff call 388 <start_kernel+0x51> 38c: e8 fc ff ff ff call 38d <start_kernel+0x56> 391: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
objdump -r main.o
00000309 R_386_32 boot_command_line 0000030e R_386_32 .init.data 00000313 R_386_PC32 strlcpy 00000318 R_386_32 .init.data 0000031d R_386_PC32 parse_early_options 00000324 R_386_32 .init.data 0000033f R_386_PC32 smp_setup_processor_id 00000344 R_386_PC32 cgroup_init_early 0000034a R_386_32 pv_irq_ops 00000351 R_386_32 cpu_number 0000035e R_386_32 early_boot_irqs_disabled 00000364 R_386_PC32 set_cpu_online 00000370 R_386_PC32 set_cpu_active 0000037c R_386_PC32 set_cpu_present 00000388 R_386_PC32 set_cpu_possible 0000038d R_386_PC32 page_address_init 00000395 R_386_32 linux_banner 0000039c R_386_32 .rodata.str1.1 000003a1 R_386_PC32 printk 000003a9 R_386_PC32 setup_arch 000003ae R_386_32 init_task 000003b3 R_386_32 init_mm 000003b8 R_386_PC32 mm_init_owner 000003bd R_386_32 boot_command_line
那么,lockdep_init函数哪里去了呢,start_kernel究竟有没有调用到它呢。
首先可以肯定的是,lockdep_init没有被内核导出,因为在System.map中找不到它。
然后,在重定位信息中也找不到lockdep_init。
lockdep_init是在哪个文件中定义的?
kernel/locking/lockdep.c
但是在kernel/locking目录下并没有生成lockdep.o,这又是为什么?
void lockdep_init(void) { int i; /* * Some architectures have their own start_kernel() * code which calls lockdep_init(), while we also * call lockdep_init() from the start_kernel() itself, * and we want to initialize the hashes only once: */ if (lockdep_initialized) return; for (i = 0; i < CLASSHASH_SIZE; i++) INIT_LIST_HEAD(classhash_table + i); for (i = 0; i < CHAINHASH_SIZE; i++) INIT_LIST_HEAD(chainhash_table + i); lockdep_initialized = 1; }