调试器工作原理(1):基础篇

原著原作 : 

本文是绕过挖掘调试器任务规律的文字的第一篇。我缺乏自信这篇文字遮盖了稍微文字和统治下的。,但我以为从字母表开端。。

说起本文

我企图在这篇文字中绍介说起Linux下的调试器走到预期的任务的次要组成党派——印痕零碎祈求救助。本文正中鹄的以信号告知是在一任一某一32位Ubuntu零碎上功绩的。。请坚持到底,在这点上的以信号告知与平台紧密相关性。,先前调动到别的平台上不太拮据。。

动机

相识的人笔者要做什么。,试设想象一下调试器是方式任务的。调试器可以启动若干课程,后来地调试它。,或许将本人用环衔接到现存的的课程。。它可以浸地运转以信号告知。,设置断点并运转顺序。,反省变量的值并拥护者祈求救助堆栈。。很多地调试器先前发生了稍许的较高的特点,譬如,在海报中治理脸色并祈求救助重大聚会。,您甚至可以直系的修正处置的以信号告知并调查所修正。。

虽然指印刷中所用的一种字体的调试器都是复杂的大型材顺序,但使成为一体惊奇的的是排列调试器的根底确是如许的复杂。调试器只用到了专有的由动手术零碎此外编辑者/用环衔接器提议的根底检修,剩的不管怎样训练成绩。。(翻阅维基百科对此条任务解说。),作者具有讽刺文学意味。

Linux下的调试

Linux下调试器发生一任一某一瑞士军刀般的器,这是pTrace零碎祈求救助。。这是一任一某一功用很多、功用比力复杂的器。,容许一任一某一课程把持另一任一某一课程的运转。,同时可以被监控和浸透到如此处置中。。印痕它本身必要一本中级的音长的书才干对其终止完整的的解说,这执意为什么我只企图经过诉讼把重音放在它的实践作用上。让笔者持续深刻根究。。

遍历处置的以信号告知

我要写一任一某一在拥护者典型下运转的处置的诉讼。,在这点上笔者要单步遍历如此课程的以信号告知——由CPU所治理的机器代码(缀编训令)。我会给你一任一某一诉讼以信号告知在在这点上。,解说每个党派,在本文的末了,您可以下载完整的的C顺序纵列。,你可以本人汇编和治理。。远远高于设计,笔者强制的汇编一任一某一顺序。,它发展一任一某一子处置来治理用户详述的命令。,父课程拥护者此子课程。。率先,次要功用是大约的。:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

intmain(intargc,char**argv)

{

    pid_t child_pid;

    if(argc<2){

        fprintf(stderr,“Expected a program name as argument\n”);

        return1;

    }

    child_pid=fork();

    if(child_pid==0)

        run_target(argv[1]);

    elseif(child_pid>0)

        run_debugger(child_pid);

    else{

        perror(“fork”);

        return1;

    }

    return0;

}

以信号告知相当复杂。,笔者经过叉子发展一任一某一新的子处置。。后续if结算单块处置子课程(在这点上称为TAR)。,而else if结算单块处置父课程(在这点上称为“调试器”)。以下是目的处置。:

1

2

3

4

5

6

7

8

9

10

11

12

13

voidrun_target(constchar*programname)

{

    procmsg(“target
起航。 will run ”%s”\n”
,programname);

    /*
Allow tracing of this process */

    if(印痕(PTRACE_TRACEME,0,0,0)<0){

        perror(“印痕”);

        return;

    }

    /*
Replace this 处置的 image with the given program */

    execl(programname,programname,0);

}

这党派最有意思的以一定间隔排列在印痕祈求救助。印痕的蓝本是(在sys/):

1

long印痕(enum__印痕_request request,  pid_t pid,void*addr,  void*data);

第一任一某一限制因素是回避。,它可以是一任一某一时刻表义的常数值,从p循迹开端。。第二份食物个限制因素详述课程ID。,第三和第四的限制因素是地址和要点录音的点明器。,用于动手术内存。。下面以信号告知段正中鹄的印痕祈求救助应用了PTRACE_TRACEME回避,这解释如此子处置必要动手术零碎内核。如此要价在手册中解说得很清楚的。:

点明该课程由其父课程拥护者。。发送到如此课程的无论哪个以信号告知(除非SIGKEY)大都会致使课程出错。,它的父课程将经过在其他人走后留下来警告。另一边,该课程以前一切对exec()的祈求救助都将使动手术零碎产生一任一某一SIGTRAP以信号告知发用无线电波发送它,这给父课程提议了把持子课程B的时机。。倘若您不相信被父课程拥护者,这个你不被期望应用如此回避。。(PID)、addr、录音被疏忽)

我图下说明文字了如此诉讼,笔者感兴趣。。坚持到底,run_target在印痕祈求救助以前接着做的是经过execl来祈求救助笔者详述的顺序。这将被解说为笔者凸党派的一党派。,动手术零碎的内核在子课程以前终止课程。,并向父课程发送一任一某一以信号告知。。

例如,是时分看一眼父课程必要做什么了。:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

voidrun_debugger(pid_t
child_pid)

{

    intwait_status;

    unsignedicounter=0;

    procmsg(“debugger
started\n”
);

    /*
Wait for child to stop on its first instruction */

    wait(&wait_status);

    while(WIFSTOPPED(wait_status)){

        icounter++;

        /*
Make the child execute another instruction */

        if(印痕(PTRACE_SINGLESTEP,child_pid,0,0)<0){

            perror(“印痕”);

            return;

        }

        /*
Wait for child to stop on its next instruction */

        wait(&wait_status);

    }

    procmsg(“the
child executed %u instructions\n”
,icounter);

}

笔者可以经过下面的以信号告知追忆一下。,子课程开端治理EXEC祈求救助后,它将终止并接纳SIGRAT以信号告知。。父课程正在其他人走后留下来经过初WEW产生此事变。。一旦子课程终止,倘若子课程终止运转,由于,WiFrue重现true),父课程反省事变。。

父课程接下来将做是什么如此AR最风趣的党派。。父课程经过PTRACE_SINGLESTEP此外子课程的id号来祈求救助印痕。这个做是通知动手术零碎——请重行促进者课程,先前当子课程治理下一任一某一训令时,它终止。。后来地父课程在其他人走后留下来该子再次终止。,全部弧形的持续治理。。当您从在其他人走后留下来中实现预期的结果利益或财富以信号告知时,它变动从而产生断层说起终止幼雏PRO的。,弧形的完毕。在如此拥护者顺序的正规的运转处置中,它将实现预期的结果利益或财富子课程正规的偿清的以信号告知(WIFFEXIT)。

icounter会统计资料子课程治理的训令等同。例如笔者如此复杂的诉讼实践上蒸馏器做了点可得到的东西的事实——经过在命令行上详述一任一某一顺序名,笔者的示例将治理详述的顺序。,后来地,顺序从B治理的CPU训令总额。。让笔者来看一眼实践动手术。。

实践结帐

我汇编了以下复杂的顺序。,后来地在笔者的拥护者顺序下治理。:

#include

intmain()

{

    printf(Hello,world!\n);

    return0;

}

令我突遇顶风而停止前进的是,,笔者的拥护者顺序运转了很长的工夫后来地报道显示一社会团体超越100000条训令实现预期的结果利益或财富了治理。这不管怎样一任一某一复杂的用誊写版印刷机印刷回避。,为什么会大约?答案很风趣。。默许局面下,Linux正中鹄的gcc编辑者会定态用环衔接到C运转时库。这残忍的无论哪个顺序运转的第一件事执意教育定态。。这必要大批的以信号告知走到预期的任务——记着,笔者的复杂拥护者顺序将对治理的每个训令终止计数。,这不仅仅是次要的功用。,但全部处置。。

例如,当我采取-static指明定态用环衔接如此结帐顺序时(坚持到底到可治理纵列例如补充部分了500KB的体积,由于它定态衔接C运转库。,笔者的拥护者顺序报道显示只7000条摆布的训令被治理了。这依然是很多。,先前倘若您识透LIBC的设定初值依然在EXE以前,洗涤动手术将在主控后终止。,嗯,这是合乎情理的。。同时,Primtf也一任一某一复重大聚会。。

笔者对此仍不满的人。,我相信能见稍许的东西。,譬如,我可以从完整的上见每个训令必要治理什么。。这可以经过缀编以信号告知走到预期的任务。。因而我把如此嘿。,尘世顺序缀编(GCC)) s)是下沉。:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

section    .text

    ;The
_start
symbol
must
be
declared
forthe
linker(ld)

    global_start

_start:

    ;Prepare
arguments
forthe
sys_write
system
call:

    ;  
eax:system
call
number(sys_write)

    ;  
ebx:file
descriptor(stdout)

    ;  
ecx:pointer
tostring

    ;  
edx:stringlength

    mov    edx,len

    mov    ecx,msg

    mov    ebx,1

    mov    eax,4

    ;Execute
the
sys_write
system
call

    int    0x80

    ;Execute
sys_exit

    mov    eax,1

    int    0x80

section  
.data

msg
db    嘿,
world!”
,0xa

len
equ    $msg

这就十足了。如今拥护者顺序将报道先前治理了7条训令。,我可以停止划桨地从缀编以信号告知中证实这点。。

深厚的训令流

缀编码顺序足以让我为极度的绍介印痕的另一任一某一令人敬畏的的功用——特点反省被拥护者课程的影响。在这点上是Run-Unjiggor重大聚会的另一任一某一版本。:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

voidrun_debugger(pid_t child_pid)

{

    intwait_status;

    unsignedicounter=0;

    procmsg(“debugger started\n”);

    /* Wait for child to stop on its first instruction */

    wait(&wait_status);

    while(WIFSTOPPED(wait_status)){

        icounter++;

        structuser_regs_struct regs;

        印痕(PTRACE_GETREGS,child_pid,0,®s);

        unsignedinstr=印痕(PTRACE_PEEKTEXT,child_pid,regs.eip,0);

        procmsg(“icounter = 美国一批备用药品 = 0x%08x.  instr = 0x%08x\n”,

                    icounter,regs.eip,instr);

        /* Make the child execute another instruction */

        if(印痕(PTRACE_SINGLESTEP,child_pid,0,0)<0){

            perror(“印痕”);

            return;

        }

        /* Wait for child to stop on its next instruction */

        wait(&wait_status);

    }

    procmsg(“the child executed %u instructions\n”,icounter);

}

与前一版本比拟,仅有的的分别是while弧形的的开端。。在这点上有两个新的印痕祈求救助。第一任一某一读取课程的表达值到一任一某一机构体中。零碎中清晰度了用户机构。这是一任一某一风趣的以一定间隔排列,倘若你翻开如此头纵列。,在纵列顶部大约的程度或者数量有大约的正文。:

1

/* 本纵列的仅有的任务是GDB。,同时只一致的GDB。。助动词=have这份纵列,不要看过于。。除非GDB,不然不要应用无论哪个别的作用。,除非你发生本人在做什么。。*/

如今,我不发生你在想什么。,但我觉得笔者是在得体的的轨道上。。无论方式,回到笔者的诉讼。。一旦笔者实现预期的结果一切表达值,,笔者就可以经过PTRACE_PEEKTEXT指明此外将(x86架构上的开发训令点明器)做限制因素传入印痕来祈求救助。笔者实现预期的结果利益或财富的是导演。。让笔者在缀编以信号告知上运转拥护者顺序的校订。。

$simple_tracer traced_helloworld

[5700]debugger started

[5701]target started.will run”traced_helloworld”

[5700]icounter=1.  EIP=0x08048080.  instr=0x00000eba

[5700]icounter=2.  EIP=0x08048085.  instr=0x0490a0b9

[5700]icounter=3.  EIP=0x0804808a.  instr=0x000001bb

[5700]icounter=4.  EIP=0x0804808f.  instr=0x000004b8

[5700]icounter=5.  EIP=0x08048094.  instr=0x01b880cd

Hello,world!

[5700]icounter=6.  EIP=0x08048096.  instr=0x000001b8

[5700]icounter=7.  EIP=0x0804809b.  instr=0x000080cd

[5700]the childexecuted7instructions

OK,因而如今除非IcOnter。,笔者也可以在每个举步中见训令和训令。。笔者方式证实这种得体的性?笔者可以在可治理FIL上治理ObjDIP D进行:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

$objdumpdtraced_helloworld

traced_helloworld:    
file
formatelf32i386

Disassembly
of
section.text:

08048080<.text>:

8048080:    
ba0e000000          mov    $0xe,%edx

8048085:    
b9
a0900408          mov    $0x80490a0,%ecx

804808a:    
bb01000000          mov    $0x1,%ebx

804808f:    
b804000000          mov    $0x4,%eax

8048094:    
cd80                  
int    $0x80

8048096:    
b801000000          mov    $0x1,%eax

804809b:    
cd80                  
int    $0x80

应用如此输入来比力笔者的拥护者顺序输入。,调查所同一任一某一以一定间隔排列被期望停止划桨。。

与运转处置关心

你先前发生了调试器也可以关系到先前有运转影响的课程上。见在这点上,你不被期望检测出惊奇的。,这也经过印痕来走到预期的任务的。这必要pTraceEnAsple回避。。我不熟练的给你一任一某一范本以信号告知在在这点上。,由于笔者先前看过以信号告知了。,这被期望停止划桨走到预期的任务。。由于教书的任务,在这点上的方式更附近的(由于笔者可以迅速地终止孩子)。。

以信号告知

本文提供的如此复杂的拥护者顺序的完整的以信号告知(更较高的短时间,你可以用誊写版印刷机印刷出详细的训令)你可以在在这点上找到它们。。经过Wall的顺序
–pedantic STD=C99汇编选择权是在GCC版本上汇编的。。

收场诗和下一步要做的。

固然,本文并没有遮盖过于的物质——笔者离一任一某一真正干的调试器还差的遥远的。先前,我相信这篇文字先前揭开了调试处置正中鹄的隐秘。。印痕是一任一某一发生很多地功用的零碎祈求救助,眼前,笔者只窗侧了这些功用正中鹄的专有的。。

可以逐级治理以信号告知是可得到的东西的。,但所有物有受限制的。。用嘿, 以尘世为例,走到次要功用,您必要经过数千条训令来设定初值C运转时。。这变动从而产生断层很附近的。。笔者打算的梦想receiver 收音机是在MAI使狂喜设置断点。,从断点治理单步治理。鄙人一篇文字中,我将绍介方式走到预期的任务断点机制。。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

`