Wednesday, December 25, 2013

GDB常用命令

help all:列出所有命令


  • file
    • load
    • run [argument]
    • show arch:show出現有CPU architecture
    • info target

    • info break:列出breakpoint
    • enable NUM:將breakpoint NUM enable
    • disable NUM:將breakpoint NUM disable
    • delete NUM:將breakpoint NUM delete掉

    • break FILE:NUM:於FILE中第NUM行設一中斷點
    • break *ADDRESS:於ADDRESS中設中斷點
    • break FUNC:於FUNCTION設中斷點

    • watch VAR:當VAR的值被改變時,停在VAR被改變點
    • rwatch VAR:當VAR的值被讀取時,停在VAR被讀取點

    • next:next statement,over function call
    • nexti:下一個instruction,不進入function
    • step:next statement,go into function call
    • stepi:下一個instruction,進入function
    • continue:continue run
    • bt:backtrace
    • kill

    • list:list source code
    • info reg:list registers value
    • set $reg value:設定register的值

    • monitor:送出命令供gdbserver執行

    Tuesday, December 24, 2013

    Gailser GRMON

    grmon可以將elf的執行檔upload到LEON2/3 platform的target。
    PC端可以是COM port,Target端是DSU。

    啟動用法:
    • 一般啟動:grmon
    • 啟動linux(with MMU):grmon -nb
    • -nb意思是當發生資料錯誤時grmon不中斷程式,比方說linux所發生的tt=0x09
    • 當作GDB server,可供GDB連接:grmon -gdb
    • target被連上之後,target會被reset
    • target被連上之後,被設定的register有
      • mcfg1 0x80000000
      • mcfg2 0x80000004
      • mcfg3 0x80000008
      • timer 1 0x80000040, 0x80000044, 0x80000048, 
      • Prescaler 0x80000060, 0x80000064
      • UART 1 0x80000070, 0x80000074, 0x80000078, 0x8000007C,

    GRMON命令:
    • mem ADDRESS:讀取address的資料
    • wmem ADDRESS VALUE:將VALUE寫入ADDRESS中
    • batch FILE:執行BATCH檔
    • load FILE:將elf格式的FILE,upload到LEON2/3 target中
    • run:根據load所上載的程式,從ELF中code區段開始執行
    • continue:根據PC所在連續執行
    • step:單步執行
    • hbreak ADDRESS:設置中斷點
    • break:list出所有中斷點
    • del NUM:取消編號NUM的中斷點
    • sys info:list出SOC的資料
    • mcfg1:讀寫MCG1值
    • mcfg2:讀寫MCG2值
    • mcfg3:讀寫MCG3值
    • reg:dump register資料

    GRMON,GDB結合:
    • grmon server(架設IP 192.168.1.10)中下"grmon -gdb"命令
    • gdb client中下"gsb --debugger sparc-linux-gdb"
    • (GDB)file ELF
    • (GDB)target extended-remote 192.168.1.10:2222
    • (GDB)load
    • (GDB)run
    • (GDB)monitor GRMON_COMMAND:於GDB中執行GRMON的命令

    Enter Kernel Mode from User Mode

    各個系統的application user從mode到kernel mode的進入點。

    說穿了,就是觸發一個interrupt/trap,使CPU的status改變,以下各個CPU跟不同OS間的配合:
    X86 WINNT: INT 0x2E
    X86 Linux: INT 0x80
    X86 FreeBSD: INT 0x80
    X86 BeOS: INT 0x25

    sparc V8 Linux: ta 0x10 (trap 0x90)
      (linux/arch/sparc/kernel/head.S)
    sparc V8 SunOS: ta 0x00 (trap 0x80)
      (linux/arch/sparc/kernel/head.S)
    sparc V8 Slowaris: ta 0x08 (trap 0x88)
      (linux/arch/sparc/kernel/head.S)
    sparc V8 Net-B.S:  ta 0x09 (trap 0x89)
      (linux/arch/sparc/kernel/head.S)
    WINNT中,它被稱之為native API
    Linux(UNIX)中,它被稱之為system call

    Hello World 補充

    這個連結提供了一些方式,讓code size更加精簡。
    Shortest ELF for “Hello world\n”

    類似hexdump工具的source code

    As title, the hexdump command is

    $ hexdump -C -v files.bin

    Write a simple tool is helpfull for the binary dump in the program...

      1 #include 
      2 #include 
      3
      4 #define BUF_SIZE    1024
      5
      6 int main(void)
      7 {
      8     int r;
      9     unsigned char buf[BUF_SIZE];
     10
     11     int seed = 0;
     12
     13     while (1)
     14     {
     15         int i, j;
     16
     17         r = fread(buf, 1, BUF_SIZE, stdin);
     18         if (0 == r)
     19         {
     20             break;
     21         }
     22
     23         i = 0;
     24
     25         for (i = 0; i < r; i += 0x10, seed += 0x10)
     26         {
     27
     28             printf("%08x ", seed);
     29
     30             j = i;
     31             for (j = i; j < i + 0x10;  j++)
     32             {
     33                 if (0 == (j % 8))
     34                 {
     35                     printf(" ");
     36                 }
     37                 printf("%02x ", buf[j]);
     38             }
     39
     40             j = i;
     41             for (j = i; j < i + 0x10;  j++)
     42             {
     43                 if (0 == (j % 8))
     44                 {
     45                     printf(" ");
     46                 }
     47                 if ((buf[j] >= ' ') && (buf[j] <= '~'))
     48                 {
     49                     printf("%c", buf[j]);
     50                 }
     51                 else
     52                 {
     53                     printf(".");
     54                 }
     55             }
     56             printf("\n");
     57         }
     58     }
     59
     60     return 0;
     61 }
     62

    The result is...


    $ gcc -Wall ddc.c -o ddc

    $
    $ ./ddc < s.jpg
    00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 00 00 01  ......JF IF......
    00000010  00 01 00 00 ff db 00 43  00 08 06 06 07 06 05 08  .......C ........
    00000020  07 07 07 09 09 08 0a 0c  14 0d 0c 0b 0b 0c 19 12  ........ ........
    00000030  13 0f 14 1d 1a 1f 1e 1d  1a 1c 1c 20 24 2e 27 20  ........ ... $.'
    00000040  22 2c 23 1c 1c 28 37 29  2c 30 31 34 34 34 1f 27  ",#..(7) ,01444.'
    00000050  39 3d 38 32 3c 2e 33 34  32 ff c0 00 0b 08 00 08  9=82<.34 2.......
    00000060  00 08 01 01 11 00 ff c4  00 1f 00 00 01 05 01 01  ........ ........
    00000070  01 01 01 01 00 00 00 00  00 00 00 00 01 02 03 04  ........ ........
    00000080  05 06 07 08 09 0a 0b ff  c4 00 b5 10 00 02 01 03  ........ ........
    00000090  03 02 04 03 05 05 04 04  00 00 01 7d 01 02 03 00  ........ ...}....
    000000a0  04 11 05 12 21 31 41 06  13 51 61 07 22 71 14 32  ....!1A. .Qa."q.2
    000000b0  81 91 a1 08 23 42 b1 c1  15 52 d1 f0 24 33 62 72  ....#B.. .R..$3br
    000000c0  82 09 0a 16 17 18 19 1a  25 26 27 28 29 2a 34 35  ........ %&'()*45
    000000d0  36 37 38 39 3a 43 44 45  46 47 48 49 4a 53 54 55  6789:CDE FGHIJSTU
    000000e0  56 57 58 59 5a 63 64 65  66 67 68 69 6a 73 74 75  VWXYZcde fghijstu
    000000f0  76 77 78 79 7a 83 84 85  86 87 88 89 8a 92 93 94  vwxyz... ........
    00000100  95 96 97 98 99 9a a2 a3  a4 a5 a6 a7 a8 a9 aa b2  ........ ........
    00000110  b3 b4 b5 b6 b7 b8 b9 ba  c2 c3 c4 c5 c6 c7 c8 c9  ........ ........
    00000120  ca d2 d3 d4 d5 d6 d7 d8  d9 da e1 e2 e3 e4 e5 e6  ........ ........
    00000130  e7 e8 e9 ea f1 f2 f3 f4  f5 f6 f7 f8 f9 fa ff da  ........ ........
    00000140  00 08 01 01 00 00 3f 00  f0 ba ff d9 18 07 24 00  ......?. ......$.

    $

    Monday, December 23, 2013

    Strong/Weak function

    GCC中有一個很好用的feature... strong/weak link

    __attribute__((weak))

    於C code中,可以先define一個function,其function型態為weak,如此可以library方式release出去。
    若第三方要修改此function,他方可以重複定義此function,於連結時第三方function取代原有default的function。

    example...

    /Working # cat CodeBase.c
    #include 

    void __attribute__((weak)) f()
    {
    printf("This is the original function\n");
    }

    int main(void)
    {
    f();
    return 0;
    }

    /Working # gcc CodeBase.c -o CodeBase
    /Working # ./CodeBase
    This is the original function
    /Working # cat CodeOverride.c
    #include 
    void f(void)
    {
    printf("This is override function\n");
    }

    /Working # gcc -c CodeBase.c CodeOverride.c
    /Working # nm *.o

    CodeBase.o:
    00000000 W f
    0000001c T main
    U puts

    CodeOverride.o:
    00000000 T f
    U puts
    /Working # gcc -o CodeBase CodeBase.o CodeOverride.o
    /Working # ./CodeBase
    This is override function
    /Working #

    Sunday, December 22, 2013

    Hello World - Assembly Language (SPARC V8)

    This is a "Hello World" program written in pure assembly language on Linux/SPARC V8 platform.

      1 #
      2 # Makefile for Hello World on Linux/SPARC V8 platform
      3 #
      4 all:
      5     sparc-linux-as hello.s -o hello.o
      6     sparc-linux-ld hello.o -o hello
      7 
      8 clean:
      9     rm -f hello.o hello

      1 /* hello.s */
      2 /* sparc-linux-as hello.s -o hello.o */
      3 /* sparc-linuc-ld hello.o -o hello   */
      4 
      5 .text
      6 .globl  _start
      7 
      8 _start:
      9 
     10     mov 1,      %o0
     11     set msg,    %o1
     12     mov 14,     %o2
     13     mov 4,      %g1
     14     ta  0x10
     15 
     16     mov 0,      %o0
     17     mov 1,      %g1
     18     ta  0x10
     19 
     20     msg:
     21     .string "Hello World\n"

    Result...

    $ uname -a
    Linux SPARC V8 2.6.24.1 #37 Thu Jan 28 10:11:06 CST 2010 sparc unknown
    $
    $ ./hello
    Hello World
    $

    Of Linux on SPARC V8 CPU...
    The Linux kernel entry, from user mode application into kernel mode, is triggled by ta 0x10 (trap 0x90) instrusion.
    The system call number is got from the CPU register g1.
    The system call parameter is placed in the sequence of o0, o1, o2...

    In the example of the WRITE() system call

    ssize_t write (int __fd, __const void *__buf, size_t __n);
     The system call index (g1) is 0x04
     __fd  is o0
     __buf is o1
     __n   is o2