arch/arm/kernel/setup.c
static __maybe_unused unsigned long get_cpsr( void )
{
unsigned long reg_var;
//mrs r0, cpsr
asm volatile("mrs %0, cpsr" :"=r"(reg_var): :);
return reg_var;
}
__maybe_unused unsigned long get_spsr( void )
{
unsigned long reg_var;
//mrs r0, cpsr
asm volatile("mrs %0, spsr" :"=r"(reg_var): :);
return reg_var;
}
static __maybe_unused unsigned long get_pc( void )
{
unsigned long pc_var1;
asm volatile("mov %0, r15" :"=r"(pc_var1): :);
return pc_var1;
}
static __maybe_unused unsigned long get_lr( void )
{
unsigned long reg_var;
asm volatile("mov %0, lr" :"=r"(reg_var): :);
return reg_var;
}
static __maybe_unused ulong get_sp(void)
{
ulong ret;
asm("mov %0, sp" : "=r"(ret) : );
return ret;
}
static __maybe_unused ulong get_ip(void)
{
ulong ret;
asm("mov %0, ip" : "=r"(ret) : );
return ret;
}
static __maybe_unused ulong get_r12(void)
{
ulong ret;
asm("mov %0, r12" : "=r"(ret) : );
return ret;
}
static __maybe_unused ulong get_fp(void)
{
ulong ret;
asm("mov %0, fp" : "=r"(ret) : );
return ret;
}
static __maybe_unused ulong get_r11(void)
{
ulong ret;
asm("mov %0, r11" : "=r"(ret) : );
return ret;
}
void __init early_print_debug_info2(const char *str, ...)
{
extern void printascii(const char *);
char buf[256];
va_list ap;
va_start(ap, str);
vsnprintf(buf, sizeof(buf), str, ap);
va_end(ap);
printascii(buf);
}
//Role in the procedure call standard
//r15 PC The Program Counter.
//r14 LR The Link Register.
//r13 SP The Stack Pointer.
//r12 IP The Intra-Procedure-call scratch register. (可简单的认为暂存SP)
//实际上,还有一个r11是optional的,被称为FP,即frame pointer。
//dump_stack();
void __init early_print_debug_info(const char *str, ...)
{
extern void printascii(const char *);
__maybe_unused struct pt_regs *regs;
unsigned long reg;
unsigned long *reg_p;
int i;
char buf[256];
va_list ap;
va_start(ap, str);
vsnprintf(buf, sizeof(buf), str, ap);
va_end(ap);
printascii(buf);
printascii("hahaha:\n");
reg = get_sp();
early_print_debug_info2("sp = %lx\n", reg);
reg = get_pc();
early_print_debug_info2("pc = %lx\n", reg);
reg = get_ip();
early_print_debug_info2("ip = %lx\n", reg);
reg = get_r12();
early_print_debug_info2("r12 = %lx\n", reg);
reg = get_fp();
early_print_debug_info2("fp = %lx\n", reg);
reg = get_r11();
early_print_debug_info2("r11 = %lx\n", reg);
reg_p = (unsigned long *)reg;
for( i=0x00; i<5+13+1; i++ ){
early_print_debug_info2("reg[%08x] = 0x%lx\n", i, reg_p[i] );
}
regs = (struct pt_regs *)reg_p;
early_print_debug_info2("reg_p = 0x%p\n", reg_p );
//early_print_debug_info2("®s->ARM_pc = 0x%x\n", ®s->ARM_pc );
//early_print_debug_info2("®s->ARM_r0 = 0x%x\n", ®s->ARM_r0 );
}
#if 0
for test call c func:
hahaha:
sp = bacc0e40
pc = 40e04358
ip = bacc0cb8
r12 = bacc0cb8
fp = bacc0f64
r11 = bacc0f64
reg[00000000] = 0x40e0430c PC
reg[00000001] = 0x40008094 R0
reg[00000002] = 0xffffffff R1
reg[00000003] = 0x44000000 R2
reg[00000004] = 0x400080b4 R3
reg[00000005] = 0x0 R0
reg[00000006] = 0xffffffff R1
reg[00000007] = 0x44000000 R2
reg[00000008] = 0x400080b4 R3
reg[00000009] = 0x80000000 R4
reg[0000000a] = 0x409a0288 R5
reg[0000000b] = 0x409a03f4 R6
reg[0000000c] = 0xdfe278 R7
reg[0000000d] = 0x40000000 R8
reg[0000000e] = 0x410fc075 R9
reg[0000000f] = 0x409a0288 R10
reg[00000010] = 0x0 R11
reg[00000011] = 0x0 R12
reg[00000012] = 0x40008048 LR_CALL_IN
#endif
//sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET) 0x400080e0 - 0xc00080e0 = 0x80000000
//add r8, r8, r4 @ PHYS_OFFSET 0xc0000000 + 0x80000000 = 0x40000000
arch/arm/kernel/head.S
#ifndef CONFIG_XIP_KERNEL
adr r3, 2f
ldmia r3, {r4, r8}
sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET) 0x400080e0 - 0xc00080e0 = 0x80000000
add r8, r8, r4 @ PHYS_OFFSET 0xc0000000 + 0x80000000 = 0x40000000
@mov r12, r3
@bl dump_reg_n
@bl dump_new_line
stmfd sp!, {r0 - r12, lr}
adr r0, head_str_entry1
bl early_print_debug_info
ldmfd sp!, {r0 - r12, lr}
#else
//ldr r8, =PLAT_PHYS_OFFSET @ always constant in this case
#endif
......
head_str_entry1: .asciz "\n for test call c func: \n"
ENDPROC(stext)
early_print_debug_info 函数的反汇编:
.init.text:00000614 MOV R12, SP
.init.text:00000618 STMFD SP!, {R0-R3}
.init.text:0000061C STMFD SP!, {R4,R11,R12,LR,PC}
.init.text:00000620 SUB R11, R12, #0x14
R11在函数中不会改变 就是这个值 r11->PC
由R11的值可以反推堆栈中的内容
但是看有的函数 是 -4
get_spsr
.text:00000330
.text:00000330 var_10 = -0x10
.text:00000330
.text:00000330 MOV R12, SP
.text:00000334 STMFD SP!, {R11,R12,LR,PC}
.text:00000338 SUB R11, R12, #4
.text:0000033C STR LR, [SP,#0xC+var_10]!
.text:00000340
.text:00000340 loc_340 ; DATA XREF: __mcount_loc:00002794o
.text:00000340 BL __gnu_mcount_nc
.text:00000344 MRS R0, SPSR
.text:00000348 LDMFD SP, {R11,SP,PC}
.text:00000348 ; End of function get_spsr
这种情况 R11指向的还是PC,但是R0,R1,R2,R3没有入堆栈
.init.text:00000624 SUB SP, SP, #0x10C
.init.text:00000628 MOV R1, #0x100 ; maxlen
.init.text:0000062C LDR R4, =__stack_chk_guard