Example 1: Test the Patch

สมมติมันมีโปรแกรมรันอยู่แล้ว และคุณไม่อยาก shutdown มันเพราะอยากได้รางวัลชนะเลิศ 0-downtime ปีที่ 10 การ patch โดยใช้ GDB เสียบแล้วเปลี่ยน flow program สามารถทำได้ครับ ทำได้ แต่ไม่ควรทำครับ ผมล้อเล่นนะเรื่องเอาไป patch เนี่ย แต่จะทำให้ดูว่ามัน powerful มาก และมากพอที่บางครั้งเราเขียนลองเขียนโปรแกรมอะไรบางอย่างเพื่อ confirm ความคิดของเราได้ โดยไม่ต้องไปนั่งแก้ source + compile ใหม่ก่อนเลย

มีโปรแกรมรันอยู่ก่อนแล้ว ผมก็เปิดอีก terminal นึงแล้วเอา GDB เสียบไปที่ process id ที่รันอยู่

$ ./example.o
Put string to split: hello world
First str: Hello
Second str: World

Put string to split:
$ sudo gdb ./example.o -p `pgrep example.o`
0x00007f474d3a8081 in __GI___libc_read (fd=0, buf=0x55beb275a670, nbytes=1024)
    at ../sysdeps/unix/sysv/linux/read.c:27
27    ../sysdeps/unix/sysv/linux/read.c: No such file or directory.
(gdb)

เรารู้ว่ามันจะตายถ้า user ใส่ string ก้อนเดียว จากนั้นก็ดูโค้ดเราว่ามันควรแก้ตรงไหนบ้างเพื่อให้ไม่ตาย

6 char** split(char* input) {
7   char** result = malloc(10*sizeof(char*));
8   result[0] = input;
9   int j = 1;
20 int getInputAndRun() {
 21   char input[100];
 22   printf("Put string to split: ");
 23   fgets(input, 100, stdin);
 24   if (strcmp(input, "exit") == 0) return -1;
 25   else {
 26     char** result = split(input);
 27     *result[0] = toupper(result[0][0]);
 28     *result[1] = toupper(result[1][0]);
 29     printf("First str: %s\n", result[0]);
 30     printf("Second str: %s\n", result[1]);
 31     return 0;

ถ้าถูกต้องคงต้องไปแก้ return ให้เป็น struct แทนอะไรแบบนี้ แต่อันนี้ถ้าแก้ง่ายๆ ก็ให้ result = calloc แทน (ค่าเริ่มต้นจะได้เป็น 0 แน่นอน) จากนั้นบรรทัดที่ 28 ให้เช็คว่าถ้า result[1]==0 ก็ไม่ต้องทำ toupper ให้ข้ามไปบรรทัด 29 เลย ซึ่ง logic ทั้งหมดเขียนได้ด้วย GDB ตามข้างล่างเลย พอเสร็จแล้วสั่ง continue

(gdb) b example.c:8
Breakpoint 1 at 0x55beb209d875: file example.c, line 8.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>set var result = calloc(10*sizeof(char*),1)
>continue
>end
(gdb) b example.c:28 if result[1] == 0
Breakpoint 2 at 0x55beb209d995: file example.c, line 28.
(gdb) commands
Type commands for breakpoint(s) 2, one per line.
End with a line saying just "end".
>jump example.c:29
>continue
>end
(gdb) c
Continuing.

โปรแกรมผมก็จะไม่ตายแล้ว เราก็จะรู้ละว่าควรไปแก้โปรแกรมจริงๆของเรายังไง ให้มันไม่ตายครับ

Put string to split: helloworld
First str: Helloworld

Second str: (null)
Put string to split: helloworld
First str: Helloworld

Second str: (null)
Put string to split: test
First str: Test

Second str: (null)
Put string to split: a
First str: A

Put string to split: hello world
First str: Hello
Second str: World

Last updated