Linux启动内核报错:init Not tainted

Linux启动内核报错:init Not tainted,第1张

如下图,启动的时候提示内核错误,关键词:init Not tainted 错误修改了 selinux 的配置文件,改回来即可 挂载系统镜像文件,这里我的机器是Vmware虚拟出来的,直接设置开机连接系统镜像ISO文件即可,然后从镜像启动,选择Rescue模式,启动机器,启动后,原来的系统文件被挂载到了 /mnt/sysimage 下面 参考下图,修改文件 /mnt/sysimage/selinux/conf 修改后,重启系统,问题解决

现象1: 提示gas gld 比识别

措施: gnu编译器发展到后来,越来越流行,更多使用别名为 as ld gcc等.

现象2: 提示字节对齐需要是 2的倍数

措施: 具体解决方法: 利用命令 sed -i 's/align 2/align 4/g' filename 替换align 2 为 align 4(align 3 替换为 align 8)

sed -i 's/align 2/align 4/g' boot/head.s

sed -i 's/align 3/align 8/g' boot/head.s

现象3: -fcombine-regs -mstring-insns选项不识别

措施: 此两个选项已经过时,直接去掉即可

现象4: warning 特别多

措施: 将-Wall 替换为 -w

现象5: __stack_chk_fail 未定义

措施: 去网上搜了一下,在Makefile中的$(CFLAGS)后面加上-fno-stack-protector,即不需要栈保护

现象6: main.c 中_syscall0重复定义

措施: main.c static inline _syscall0(int, fork) 去掉static即可

现象7: 提示内嵌汇编不符合语法限制

措施: 类似的问题在后面编译中出现好多,C内嵌汇编的格式 asm (汇编语句:输入寄存器:输出寄存器:可能被修改的寄存器),最新的GCC规定 输入或输出寄存器不能出现在可能被修改的寄存器中,目前看到网上的方法是把所有类似问题的可能被修改的寄存器全部删掉 解决方案:find -type f -exec sed -i 's/:"\w{2}"(,"\w{2}") )/:) /g' {} 其中's/:"\w{2}"(,"\w{2}") /:/g'

现象8: 在 control.c 中清楚定义了 static unsigned char attr = 0x70 ,而在链接 control.o 时,却爆出 attr未定义。

措施: nm -C control.o 查看其符号,发现attr确实处于未定义状态。故单独编译一个小程序定义静态变量,查看其 .o 文件中,发现静态变量定义正常。故考虑为编译选项差异导致,最终发现因为 -O 编译优化选项导致,目前处理方式是去掉该选项。

现象9: build.c:(.text+0xde): undefined reference to `MAJOR'

措施: 通过分析编译打印信息,发现编译时没有加入头文件路径 -Iinclude

现象10: fs/fs.o: In function check_disk_change':(.text+0x1b2f): undefined reference to invalidate_buffers'

措施: 查找发现此函数定义在buffer.c 中,且为内联函数, 故尝试将其更改为普通函数, 然后编译通过.

现象11: 编译 build.c 时报错:/usr/include/i386-linux -gnu/bits/stdio2.h:57:8: error: unknown type name ‘__gnuc_va_list’

措施: 分析发现时此系列错误均由 -Iinclude 选项导致, 而该选项在 想象9 中加入, 故考虑去掉该选项, 直接在build.c 中加入 MAJOR 宏定义.

1.1 Linux内核异常处理相关文件

Linux内核中,异常处理主要由两个文件完成,entry.S和traps.c,当然还有一些其它异常处理函数分布于fault.c, memory.c等等。entry.S包含异常的入口、进入异常处理C函数前的压栈、退出C函数前的出栈、一些fork函数相关的处理代码(暂不分析)、任务切换汇编处理过程(cpu_switch_to函数,暂不分析)。traps.c主要包含异常处理C函数。

本文主要分析entry.S,对于traps.c作简要介绍。

1.2 执行kernel_entry之前的栈

1.3 执行kernel_entry时的栈

1.4 执行kernel_exit 时的栈

1.5 entry.s代码分析

/*

* Low-level exception handling code

*

* Copyright (C) 2012 ARM Ltd.

* Authors: Catalin Marinas <catalin.marinas@arm.com>

* Will Deacon <will.deacon@arm.com>

*

* This program is free softwareyou can redistribute it and/or modify

* it under the terms of the GNU General Public License version 2 as

* published by the Free Software Foundation.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTYwithout even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program. If not, see <http://www.gnu.org/licenses/>.

*/

#include <linux/init.h>

#include <linux/linkage.h>

#include <asm/assembler.h>

#include <asm/asm-offsets.h>

#include <asm/errno.h>

#include <asm/thread_info.h>

#include <asm/unistd.h>

#include <asm/unistd32.h>

/*

* Bad Abort numbers

*-----------------

*/

#define BAD_SYNC 0

#define BAD_IRQ 1

#define BAD_FIQ 2

#define BAD_ERROR 3

//根据该结构体内容

/*

struct pt_regs {

union {

struct user_pt_regs user_regs//结构体user_pt_regs和结构体pt_regs内容一样

struct { //共用体存储31个通用寄存器,外加sp,pc,pstate三个特殊寄存器

//该结构体用于异常处理的压栈d栈 *** 作

u64 regs[31]

u64 sp

u64 pc

u64 pstate

}

}

u64 orig_x0

u64 syscallno

}

*/

//S_FRAME_SIZE定义在asm-offsets.c中,DEFINE(S_FRAME_SIZE,sizeof(struct pt_regs))

//即结构体pt_regs的大小,结构体pt_regs的定义见上面

//S_LR定义:DEFINE(S_LR,offsetof(struct pt_regs, regs[30]))

//即31号寄存器在结构体pt_regs中的偏移量

//阅读以下内容请参考图1 和图2

.macro kernel_entry, el, regsize = 64

sub sp, sp, #S_FRAME_SIZE - S_LR // room for LR, SP, SPSR, ELR,见图2中sp'指向的位置

.if \regsize == 32

mov w0, w0 // zero upper 32 bits of x0

.endif

/*

*.macro push, xreg1, xreg2 //压栈两个寄存器

*stp \xreg1, \xreg2, [sp, #-16]! //注意!!!push指令也改变sp的值!!!

*.endm

*/

push x28, x29 //进行压栈 *** 作,push也是一个宏定义,因为ARMv8没有push指令,用stp代替

push x26, x27

push x24, x25

push x22, x23

push x20, x21

push x18, x19

push x16, x17

push x14, x15

push x12, x13

push x10, x11

push x8, x9

push x6, x7

push x4, x5

push x2, x3

push x0, x1 //此时sp指向位置见图2中sp''

.if \el == 0 //如果异常级是el0,把el0的sp栈指针给x21寄存器

mrs x21, sp_el0

.else

add x21, sp, #S_FRAME_SIZE //如果异常级不是el0,把sp指针指向的地方加上pt_regs大小后的地址放入x21,

//即指向没进入kernel_entry函数钱的sp指向的位置,见图2中x21指向的地址

.endif

mrs x22, elr_el1 //把el1的lr寄存器给x22

mrs x23, spsr_el1 //把spsr给x23

stp lr, x21, [sp, #S_LR] //把lr,x21寄存器存入sp+S_LR指向的地方

stp x22, x23, [sp, #S_PC] //把lr,存入sp+s_PC指向的位置,用于异常返回

/*

* Set syscallno to -1 by default (overridden later if real syscall).

*/

.if \el == 0

mvn x21, xzr

str x21, [sp, #S_SYSCALLNO]

.endif

/*

* Registers that may be useful after this macro is invoked:

*

* x21 - aborted SP

* x22 - aborted PC

* x23 - aborted PSTATE

*/

.endm

.macro kernel_exit, el, ret = 0

//把此时sp(即图2中sp'')+S_PC位置处开始的16字节内容分别给x21,x22

//即把栈中存的x21和x22内容取出来

ldp x21, x22, [sp, #S_PC] // load ELR, SPSR

.if \el == 0

ldr x23, [sp, #S_SP] // load return stack pointer,取出

.endif

.if \ret

ldr x1, [sp, #S_X1] // preserve x0 (syscall return),如果ret=1,则保存x0,用于系统调用,暂不分析

add sp, sp, S_X2

.else

pop x0, x1 //如果ret=0,d出x0,x1

.endif

pop x2, x3 // load the rest of the registers

pop x4, x5

pop x6, x7

pop x8, x9

msr elr_el1, x21 // set up the return data,把前面d出的x21,x22分别赋值给elr_el1,spsr_el1

msr spsr_el1, x22

.if \el == 0

msr sp_el0, x23

.endif

pop x10, x11

pop x12, x13

pop x14, x15

pop x16, x17

pop x18, x19

pop x20, x21

pop x22, x23

pop x24, x25

pop x26, x27

pop x28, x29

ldr lr, [sp], #S_FRAME_SIZE - S_LR // load LR and restore SP,把lrd出

eret // return to kernel,异常返回,该指令会把lr给pc,完成跳转

.endm

.macro get_thread_info, rd

mov \rd, sp

and \rd, \rd, #~((1 <<13) - 1) // top of 8K stack

.endm

/*

* These are the registers used in the syscall handler, and allow us to

* have in theory up to 7 arguments to a function - x0 to x6.

*

* x7 is reserved for the system call number in 32-bit mode.

*/

sc_nr .req x25 // number of system calls

scno .req x26 // syscall number

stbl .req x27 // syscall table pointer

tsk .req x28 // current thread_info

/*

* Interrupt handling.

*/

.macro irq_handler

ldr x1, handle_arch_irq

mov x0, sp

blr x1

.endm

.text

/*

* Exception vectors.

*/

.macro ventry label //这里是2^7对齐,即对齐到内存地址的0x80

.align 7

b \label

.endm

.align 11

/* ENTRY也是一个宏,定义在include/linkage.h中

* #ifndef ENTRY

* #define ENTRY(name) \

* .globl name\

* ALIGN\

* name:

* #endif


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/8510531.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-17
下一篇2023-04-17

发表评论

登录后才能评论

评论列表(0条)

    保存