2021-2022-1 20212813《Linux内核原理与分析》第六周作业

一、实验过程和分析

1、给MenuOS增加chmod命令(上一周选择的系统调用),并使用 gdb 跟踪分析

打开menu文件下的test.c的文件,添加chmod函数代码并在主函数中添加以下代码:

MenuConfig("chmod","Modifying File Permissions",Chmod);

如下图所示:
在这里插入图片描述

重新编译后运行MenuOS,结果如下图所示:
在这里插入图片描述

对chmod命令所用到的系统调用内核函数进行调试跟踪,命令如下:

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s

同之前调试方法一样,启动gdb,加载内核,连接到target remote:1234,在start_kernelsys_chmod分别设置断点后继续运行,并在MenuOS启动后执行chmod命令,如下图所示:
在这里插入图片描述
可以发现程序停在sys_chmod(定义在fs/open.c中)处,用宏来实现。然后继续单步执行,会出现“Cannot find bounds of current function”,直到返回系统调用位置。按照视频教学,尝试在system_call处设置一个断点,但是还是停在了sys_chmod处,system_call 不是正常的函数,是一段特殊的汇编代码,gdb还不能进行跟踪。

2、分析从 system_call 开始到 iret 结束之间的整个过程

通过课本知识讲解明白了在 start_kernel 中的 trap_init()(定义在/arch/x86/kernel/traps.c中)里将中断向量0x80和system_call中断服务程序入口进行了绑定:

#ifdef CONFIG_X86_32
   set_system_trap_gate(SYSCALL_VECTOR, &system_call); //绑定中断向量0x80和system_call中断服务程序入口,其中SYSCALL_VECTOR定义为0x80
   set_bit(SYSCALL_VECTOR, used_vectors);
#endif

system_call中断服务程序入口代码如下:

ENTRY(system_call)
	RING0_INT_FRAME			#can't unwind into user space anyway
	ASM_CLAC
	pushl_cfi %eax			#保存系统调用号
	SAVE_ALL				#保存现场,将CPU寄存器保存在堆栈中
	GET_THREAD_INFO(%ebp)	#ebp用于存放当前进程thread_info结构的地址
	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
	jnz syscall_trace_entry
	cmpl $(NR_syscalls), %eax 	#检查系统调用号(系统调用号应小于NR_syscalls)
	jae syscall_badsys			#不合法,跳入到异常处理
syscall_call:
	call *sys_call_table(,%eax,4)	#合法,对照系统调用号在系统调用表中寻找相应服务例程
syscall_after_call:
	movl %eax,PT_EAX(%esp)			#保存返回值到栈中
syscall_exit:
	LOCKDEP_SYS_EXIT
	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
					# setting need_resched or sigpending
					# between sampling and the iret
	TRACE_IRQS_OFF
	movl TI_flags(%ebp), %ecx
	testl $_TIF_ALLWORK_MASK, %ecx	#检查是否有任务需要处理
	jne syscall_exit_work			#需要,进入 syscall_exit_work(最常见的进程调度时机)

restore_all:
	TRACE_IRQS_IRET			#恢复现场
restore_all_notrace:	
#ifdef CONFIG_X86_ESPFIX32
	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS, SS and CS
	# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
	# are returning to the kernel.
	# See comments in process.c:copy_thread() for details.
	movb PT_OLDSS(%esp), %ah
	movb PT_CS(%esp), %al
	andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
	CFI_REMEMBER_STATE
	je ldt_ss			# returning to user-space with LDT SS
#endif
restore_nocheck:
	RESTORE_REGS 4			# skip orig_eax/error_code
irq_return:
	INTERRUPT_RETURN		#iret

其大概流程图和分析如下所示:
在这里插入图片描述

二、问题

在本地虚拟机上进行内核跟踪调试加载不出调试信息(no debugging symbols found),如下图所示:
在这里插入图片描述解决方案:
linux-3.18.6中通过运行make menuconfig 来进行个别的调整,这里需要开启"Compile the kernel with debug info"选项:
进入linux-3.18.6/目录下,运行make menuconfig,选择Kernel hacking —>Compile-time checks and compiler options —> [ ] Compile the kernel with debug info
示意图如下,利用键盘选中debug选项,然后敲"Y"勾选:
在这里插入图片描述
在这里插入图片描述
之后再次进行编译make,便可以解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值