OK6410A 开发板 (八) 8 linux-5.11 OK6410A 详细解析 start_kernel运行时的 栈

include/asm-generic/vmlinux.lds.h

 376 #define INIT_TASK_DATA(align)                       \                            
 377     . = ALIGN(align);                       \                                    
 378     __start_init_task = .;                      \                                
 379     init_thread_union = .;                      \                                
 380     init_stack = .;                         \                                    
 381     KEEP(*(.data..init_task))                   \                                
 382     KEEP(*(.data..init_thread_info))                \                            
 383     . = __start_init_task + THREAD_SIZE;                \                        
 384     __end_init_task = .;                                                         

include/asm-generic/vmlinux.lds.h


/*                                                                               
 * Writeable data.                                                               
 * All sections are combined in a single .data section.                          
 * The sections following CONSTRUCTORS are arranged so their                     
 * typical alignment matches.                                                    
 * A cacheline is typical/always less than a PAGE_SIZE so                        
 * the sections that has this restriction (or similar)                           
 * is located before the ones requiring PAGE_SIZE alignment.                     
 * NOSAVE_DATA starts and ends with a PAGE_SIZE alignment which                      
 * matches the requirement of PAGE_ALIGNED_DATA.                                     
 *                                                                                   
 * use 0 as page_align if page_aligned data is not used */                           
#define RW_DATA(cacheline, pagealigned, inittask)           \                        
    . = ALIGN(PAGE_SIZE);                       \                                    
    .data : AT(ADDR(.data) - LOAD_OFFSET) {             \                            
        INIT_TASK_DATA(inittask)                \                                    
        NOSAVE_DATA                     \                                            
        PAGE_ALIGNED_DATA(pagealigned)              \                                
        CACHELINE_ALIGNED_DATA(cacheline)           \                                
        READ_MOSTLY_DATA(cacheline)             \                                    
        DATA_DATA                       \                                            
        CONSTRUCTORS                        \                                        
    }                               \                                                
    BUG_TABLE                           \
arch/arm/kernel/vmlinux.lds.S

145     _sdata = .;                                                                  
146     RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)                              
147     _edata = .;

arch/arm/kernel/vmlinux.lds

_sdata = .;
. = ALIGN((1 << 12)); 
.data : 
AT(ADDR(.data) - 0) 
{ 
	. = ALIGN(((1 << 12) << 1)); 

	// 栈的底	
	__start_init_task = .; 
	init_thread_union = .; 
	init_stack = .; 
	KEEP(*(.data..init_task))  // KEEP 相当于告诉编译器,这部分不要被垃圾回收
	KEEP(*(.data..init_thread_info)) 
	. = __start_init_task + ((1 << 12) << 1);  
		// start_kernel 运行时的栈, 是 链接出来的,4KB大小 
		// #define THREAD_SIZE     (PAGE_SIZE << THREAD_SIZE_ORDER)
		// ((1 << 12) << 1)
	__end_init_task = .; 	// 栈顶
	// 栈的顶
 
	. = ALIGN((1 << 12));
	__nosave_begin = .; 
	*(.data..nosave) 
	. = ALIGN((1 << 12)); 
	__nosave_end = .; 
	. = ALIGN((1 << 12)); 
	*(.data..page_aligned) 
	. = ALIGN((1 << 12)); 
	. = ALIGN((1 << 6)); 
	*(.data..cacheline_aligned) 
	. = ALIGN((1 << 6)); 
	*(.data..read_mostly) 
	. = ALIGN((1 << 6)); 
	*(.xiptext) 
	*(.data) 
	*(.ref.data) 
	*(.data..shared_aligned) 
	*(.data.unlikely) 
	__start_once = .; 
	*(.data.once) 
	__end_once = .; 
	. = ALIGN(32); 
	*(__tracepoints) 
	. = ALIGN(8); 
	__start___dyndbg = .; 
	KEEP(*(__dyndbg)) __stop___dyndbg = .; 
	CONSTRUCTORS 
} 

. = ALIGN(8); 
__bug_table : 
AT(ADDR(__bug_table) - 0) 
{ 
	__start___bug_table = .; 
	KEEP(*(__bug_table)) 
	__stop___bug_table = .; 
}
_edata = .;

在 linux 链接时
将 init_thread_union 及 init_thread_union + THREAD_START_SP 这一段 放到了 数据段  // init_thread_union 只是链接脚本中的一个地址,被 extern 到了 一个变量union thread_union init_thread_union 中

在 linux 运行时
将 init_thread_union + THREAD_START_SP 放到了  sp 中,  // C0801FF8
并 b start_kernel
init/main.c,start_kernel,line = 851,addr of the fist variable(command_line):c0801fc4

arm 是满减栈 // 压栈的时候,先sp-4,再存值
地址从 C0801FF8 - C0800000
如果 往下一直增长,会首先覆盖 init_thread_info  // 此情况就是 栈溢出

其他
  • 1 C0801FFC - C0801FC8 存了什么(14个值)?
TOP
0e:c0801ffc:0
0d:c0801ff8:0
0c:c0801ff4:0
0b:c0801ff0:0
0a:c0801fec:c5387d				// 变量 cr_alignment 的值 // 即 cp15 Register 1: Control register
09:c0801fe8:410fb766			// processor_id 的值
08:c0801fe4:50000100			// atags 指针的 值
07:c0801fe0:65a					// board id
06:c0801fdc:c0387d 				// 变量 cr_alignment 的值
05:c0801fd8:51					// cp15 Register 3: Domain access control 的值 
04:c0801fd4:c0700330 			// 这个看样子是 __mmap_switched_data 中的 processor_id的地址
03:c0801fd0:0
02:c0801fcc:0
01:c0801fc8:0
00:c0801fc4:0
//c0801fc4 存了第一个变量 char * command_line;
BOTTOM
  • 2 C0801FF8 - C0800000 中的 KEEP((.data…init_task)) KEEP(
    (.data…init_thread_info)) 是什么?
先回答一下,该地址空间共 8KB左右
C0801FF8
	pt_regs 的值(18,最上面为r0-r15,cpsr,最下面为old_r0)
	stack()
	
	0x57AC6E9D  // set_task_stack_end_magic 在 此地址(init_thread_info的前面四字节)(栈底) 填充了一个32bit整数,用来标识栈底
	struct thread_info init_thread_info;
	struct task_struct init_task;
C0800000
  • current 与 task_struct (以 init_task为例)

include/asm-generic/current.h
7 #define get_current() (current_thread_info()->task)                              
8 #define current get_current()

arch/arm/include/asm/thread_info.h

91 static inline struct thread_info *current_thread_info(void)                      
92 {                                                                                
93     return (struct thread_info *)                                                
94         (current_stack_pointer & ~(THREAD_SIZE - 1));                            
95 }


arch/arm/include/asm/percpu.h
8 register unsigned long current_stack_pointer asm ("sp");

include/linux/init_task.h
43 #define __init_task_data __section(".data..init_task")

init/init_task.c
 60 /*                                                                               
 61  * Set up the first task table, touch at your own risk!. Base=0,                 
 62  * limit=0x1fffff (=2MB)                                                         
 63  */                                                                              
 64 struct task_struct init_task                                                     
 65 #ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK                                          
 66     __init_task_data                                                             
 67 #endif                                                                           
 68     __aligned(L1_CACHE_BYTES)                                                    
 69 = { 
...
 75     .stack      = init_stack,
...
 216 };                                                                               
 217 EXPORT_SYMBOL(init_task);

init/init_task.c
224 struct thread_info init_thread_info __init_thread_info = INIT_THREAD_INFO(init_task);

include/linux/init_task.h
49 #define __init_thread_info __section(".data..init_thread_info")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值