分享
 
 
 

分析内核对gzip压缩文件进行解压的方法

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

作者:opera

概述

----

1) Linux的初始内核映象以gzip压缩文件的格式存放在zImage或bzImage之中, 内核的自举

代码将它解压到1M内存开始处. 在内核初始化时, 如果加载了压缩的initrd映象, 内核会将解压到内存盘中, 这两处解压过程都使用了lib/inflate.c文件.

2) inflate.c是从gzip源程序中分离出来的, 包含了一些对全局数据的直接引用, 在使用时

需要直接嵌入到代码中. gzip压缩文件时总是在前32K字节的范围内寻找重复的字符串进行

编码, 在解压时需要一个至少为32K字节的解压缓冲区, 它定义为window[WSIZE].

inflate.c使用get_byte()读取输入文件, 它被定义成宏来提高效率. 输入缓冲区指针必须

定义为inptr, inflate.c中对之有减量操作. inflate.c调用flush_window()来输出window

缓冲区中的解压出的字节串, 每次输出长度用outcnt变量表示. 在flush_window()中, 还必

须对输出字节串计算CRC并且刷新crc变量. 在调用gunzip()开始解压之前, 调用makecrc()

初始化CRC计算表. 最后gunzip()返回0表示解压成功.

3) zImage或bzImage由16位引导代码和32位内核自解压映象两个部分组成. 对于zImage, 内

核自解压映象被加载到物理地址0x1000, 内核被解压到1M的部位. 对于bzImage, 内核自解

压映象被加载到1M开始的地方, 内核被解压为两个片段, 一个起始于物理地址0x2000-0x90000,

另一个起始于高端解压映象之后, 离1M开始处不小于低端片段最大长度的区域. 解压完成后,

这两个片段被合并到1M的起始位置.

解压根内存盘映象文件的代码

--------------------------

代码:

; drivers/block/rd.c

#ifdef BUILD_CRAMDISK

/*

* gzip declarations

*/

#define OF(args) args ; 用于函数原型声明的宏

#ifndef memzero

#define memzero(s, n) memset ((s), 0, (n))

#endif

typedef unsigned char uch; 定义inflate.c所使用的3种数据类型

typedef unsigned short ush;

typedef unsigned long ulg;

#define INBUFSIZ 4096 用户输入缓冲区尺寸

#define WSIZE 0x8000 /* window size--must be a power of two, and */

/* at least 32K for zip's deflate method */

static uch *inbuf; 用户输入缓冲区,与inflate.c无关

static uch *window; 解压窗口

static unsigned insize; /* valid bytes in inbuf */

static unsigned inptr; /* index of next byte to be processed in inbuf */

static unsigned outcnt; /* bytes in output buffer */

static int exit_code;

static long bytes_out; 总解压输出长度,与inflate.c无关

static struct file *crd_infp, *crd_outfp;

#define get_byte() (inptr

/* Diagnostic functions (stubbed out) */ 一些调试宏

#define Assert(cond,msg)

#define Trace(x)

#define Tracev(x)

#define Tracevv(x)

#define Tracec(c,x)

#define Tracecv(c,x)

#define STATIC static

static int fill_inbuf(void);

static void flush_window(void);

static void *malloc(int size);

static void free(void *where);

static void error(char *m);

static void gzip_mark(void **);

static void gzip_release(void **);

#include "../../lib/inflate.c"

static void __init *malloc(int size)

{

return kmalloc(size, GFP_KERNEL);

}

static void __init free(void *where)

{

kfree(where);

}

static void __init gzip_mark(void **ptr)

{

; 读取用户一个标记

}

static void __init gzip_release(void **ptr)

{

; 归还用户标记

}

/* ===========================================================================

* Fill the input buffer. This is called only when the buffer is empty

* and at least one byte is really needed.

*/

static int __init fill_inbuf(void) 填充输入缓冲区

{

if (exit_code) return -1;

insize = crd_infp-f_op-read(crd_infp, inbuf, INBUFSIZ,

&crd_infp-f_pos);

if (insize == 0) return -1;

inptr = 1;

return inbuf[0];

}

/* ===========================================================================

* Write the output window window[0..outcnt-1] and update crc and bytes_out.

* (Used for the decompressed data only.)

*/

static void __init flush_window(void) 输出window缓冲区中outcnt个字节串

{

ulg c = crc; /* temporary variable */

unsigned n;

uch *in, ch;

crd_outfp-f_op-write(crd_outfp, window, outcnt, &crd_outfp-f_pos);

in = window;

for (n = 0; n

ch = *in++;

c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c 8); 计算输出串的CRC

}

crc = c;

bytes_out += (ulg)outcnt; 刷新总字节数

outcnt = 0;

}

static void __init error(char *x) 解压出错调用的函数

{

printk(KERN_ERR "%s", x);

exit_code = 1;

}

static int __init

crd_load(struct file * fp, struct file *outfp)

{

int result;

insize = 0; /* valid bytes in inbuf */

inptr = 0; /* index of next byte to be processed in inbuf */

outcnt = 0; /* bytes in output buffer */

exit_code = 0;

bytes_out = 0;

crc = (ulg)0xffffffffL; /* shift register contents */

crd_infp = fp;

crd_outfp = outfp;

inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);

if (inbuf == 0) {

printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");

return -1;

}

window = kmalloc(WSIZE, GFP_KERNEL);

if (window == 0) {

printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");

kfree(inbuf);

return -1;

}

makecrc();

result = gunzip();

kfree(inbuf);

kfree(window);

return result;

}

#endif /* BUILD_CRAMDISK */

32位内核自解压代码

------------------

; arch/i386/boot/compressed/head.S

.text

#include

#include

.globl startup_32 对于zImage该入口地址为0x1000; 对于bzImage为0x101000

startup_32:

cld

cli

movl $(__KERNEL_DS),%eax

movl %eax,%ds

movl %eax,%es

movl %eax,%fs

movl %eax,%gs

lss SYMBOL_NAME(stack_start),%esp # 自解压代码的堆栈为misc.c中定义的16K字节的数组

xorl %eax,%eax

1: incl %eax # check that A20 really IS enabled

movl %eax,0x000000 # loop forever if it isn't

cmpl %eax,0x100000

je 1b

/*

* Initialize eflags. Some BIOS's leave bits like NT set. This would

* confuse the debugger if this code is traced.

* XXX - best to initialize before switching to protected mode.

*/

pushl $0

popfl

/*

* Clear BSS 清除解压程序的BSS段

*/

xorl %eax,%eax

movl $ SYMBOL_NAME(_edata),%edi

movl $ SYMBOL_NAME(_end),%ecx

subl %edi,%ecx

cld

rep

stosb

/*

* Do the decompression, and jump to the new kernel..

*/

subl $16,%esp # place for structure on the stack

movl %esp,%eax

pushl %esi # real mode pointer as second arg

pushl %eax # address of structure as first arg

call SYMBOL_NAME(decompress_kernel)

orl %eax,%eax # 如果返回非零,则表示为内核解压为低端和高端的两个片断

jnz 3f

popl %esi # discard address

popl %esi # real mode pointer

xorl %ebx,%ebx

ljmp $(__KERNEL_CS), $0x100000 # 运行start_kernel

/*

* We come here, if we were loaded high.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有