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")