当前位置: 首页 > 工具软件 > getbase > 使用案例 >

get_base(current->ldt[1])和get_base(current->ldt[2])

轩辕亮
2023-12-01

free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
首先看下他调用的参数。
1、get_base(current->ldt[1])和get_base(current->ldt[2])
A.get_base()函数的定义:
#define get_base(ldt) _get_base( ((char *)&(ldt)) );
 
_get_base的代码如下:
 
#define _get_base(addr) ({\
unsigned long __base; \
__asm__(
    //将基地址的24-31位保存在dh中
    "movb %3,%%dh\n\t" \
    //将基地址的16-23位保存在dl中
    "movb %2,%%dl\n\t" \
    //将edx的内容左移16位
    //也就是将基地址的16-31位保存在edx的高16位中
    "shll $16,%%edx\n\t" \
    //将基地址的0-15位保存在dx
    //也就是 edx的低16位中
    "movw %1,%%dx" \
    //将返回值保存在_base中
    :"=d" (__base) \
    //使用内存变量偏移2个字节作为%1
    //也就是基地址的0-15位
    :"m" (*((addr)+2)), \
    //使用内存变量偏移4个字节作为%2
    //也就是基地址的16-23位
     "m" (*((addr)+4)), \
    //使用内存变%E)��偏移7个字节作为%3
    //也就是基地址的24-31位
     "m" (*((addr)+7))); \
__base;})
因此get_base函数的作用就是取出段选择符指向的段描述符中的段基址。
B.current->ldt[1]
根据kernel/sched.c中的定义:struct task_struct *current=&(init_task,task);
而task_struct的定义:
struct task_struct {
    long state;   
    long counter;
    long priority;
    long signal;
    struct sigaction sigaction[32];
    long blocked;   
    int exit_code;
    unsigned long start_code,end_code,end_data,brk,start_stack;
    long pid,father,pgrp,session,leader;
    unsigned short uid,euid,suid;
  &nbs`; unsigned short gid,egid,sgid;
    long alarm;
    long utime,stime,cutime,cstime,start_time;
    unsigned short used_math;
    int tty;       
    unsigned short umask;
    struct m_inode * pwd;
    struct m_inode * root;
    struct m_inode * executable;
    unsigned long close_on_exec;
    struct file * filp[NR_OPEN];
    struct desc_struct ldt[3];
    struct tss_struct tss;
};
 
因此current->ldt[1]和current->ldt[2]分别指向当前任务的代码段CS局部表描述符和数据堆栈段DS&SS局部表描述符。
2、get_limit(0x0f)和get_limit(0x17)
#define get_limit(segment) ({ \
unsigned long __limit; \
__asm__(
//lsll为加载段界限的指令
//即把segment段描述符中的段界限字段装入寄存器
//这里指把segment所指的段选择符中的段限界字段装载到%0寄存器中
"lsll %1,%0\n\t"
//将段限界+1,因为0代表1B
"incl %0\n\t"
//将返回值存放在_limit中
:"=r" (__limit)
//将segment 作为参数
:"r" (segment));
__limit;})\
参数segment是段选择符,get_base函数的作用就是取得segment指向的段描述符中的Limit段限长。
而段选择符的结构前面已经看过。由三个部分组成Index(15-3)+TI(2)+RPL(1-0)。其中Index为段描述符在描述符表中的索引值,TI标志指向的描述符表,RPL标志优先级。
这里采用的两个参数0x0f即1111B,因此他指向的段优先级为3,存储在LDT表中,索引为1。也就是当前任务段的代码段描述符。
另外一个参数0x17即10111B,因此他指向的段优先级为3,存储在LDT表中,索引为2.也就是当前任务的数及堆栈段描述符。
这样,通过get_limit(0x0f)和get_limit(0x17)就得到了当前任务代码段和数据堆栈段的长度。
因此,
free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
free_page_tables(get_base(current->ldt[2]),get_limit(0x17));就释放了当前任务的代码段和数据堆栈段。
 类似资料: