http://cosi.clarkson.edu/docs/kernel/setup/kgdb/x118.html
7. Rebooting, Setting up GDB, and the Basics of DebuggingThis section will walk you through the actual use of KGDB. 7.1. Rebooting and Setting up GDBWhen you reboot the machine where the kernel was installed, make sure it boots the modified kernel. The kernel should halt on bootup and wait for a connection through the serial cable and say the following: Waiting for connection from remote gdb...On the machine that has a copy of the kernel, go to the base directory of the kernel and type the following: $sudo gdb ./vmlinuxOnce inside GDB, type: (gdb) shell echo -e "\003" > /dev/ttyS0 (gdb) set remotebaud 115200 (gdb) target remote /dev/ttyS0 Remote debugging using /dev/ttyS0 breakpoint () at kernel/kgdb.c:1212 1212 atomic_set(, 0); warning: shared library handler failed to enable breakpoint (gdb)At this point the kernel will continue to load. 7.2. Basic Debuggingto be continued... 7.3. How to Find the Source Code You Want to Debugto be continued... 7.4. Example Debugging: Trace of TCP ConnectionWe used lxr.linux.no to look up what name is of the function that initiates a TCP connection when connecting to a webpage. The function name is tcp_v4_connect. In GDB we set a breakpoint for this function by typing the following: (gdb)b tcp_v4_connectOR (gdb)b /net/ipv4/tcp_ipv4.c:744 (gdb)cand once we tried connecting to www.yahoo.com with a web client such as w3m, we received the following response from GDB. (gdb) c Continuing. [New Thread 2522] [Switching to Thread 2522] Breakpoint 9, tcp_v4_connect (sk=0xd44bc060, uaddr=0xd4781eec, addr_len=16) at ip.h:164 164 return &((struct inet_sock *)__sk)->inet; (gdb) In w3m the screen just displayed "Opening socket..." but this will vary depending on which browser you choose to make a connection with. Then we ran the command "bt"(backtrace) on the gdb command line, it will be something like (gdb) bt #0 tcp_connect (sk=0xcbbd0c1c) at tcp.h:441 #1 0xc028338f in tcp_v4_connect (sk=0xcbbd0c1c, uaddr=0xcc419eec, addr_len=16) at net/ipv4/tcp_ipv4.c:854 #2 0xc0294da9 in inet_stream_connect (sock=0xcbbc7eb4, uaddr=0xcc419eec, addr_len=-876803044, flags=2) at net/ipv4/af_inet.c:623 #3 0xc02448f6 in sys_connect (fd=-876803044, uservaddr=0xcbbd0c1c, addrlen=16) at net/socket.c:1372 #4 0xc02453e1 in sys_socketcall (call=3, args=0xcbbd0c1c) at net/socket.c:1867 #5 0xc01040a9 in sysenter_past_esp () at thread_info.h:51we can see that function tcp_v4_connect was passed the argument as sk=0xcbbd0c1c which is a control structure with a block of memory attached. And also we can see that the ip address was passed by as uaddr=0xcc419eec. And if we look further into the sk structure when we type the command "p *sk", we will have a detailed vision of what's in the structure sk: (gdb) p *sk $1 = {__sk_common = {skc_family = 2, skc_state = 2 '\002', skc_reuse = 0 '\0', skc_bound_dev_if = 0, skc_node = {next = 0x0, pprev = 0xd78d6168}, skc_bind_node = {next = 0x0, pprev = 0xd0826368}, skc_refcnt = { counter = 1}}, sk_zapped = 0 '\0', sk_shutdown = 0 '\0', sk_use_write_queue = 1 '\001', sk_userlocks = 0 '\0', sk_lock = { slock = {<No data fields>}, owner = 0x1, wq = {lock = {<No data fields>}, task_list = {next = 0xcbbd0c40, prev = 0xcbbd0c40}}}, sk_rcvbuf = 87380, sk_sleep = 0xcbbc7ecc, sk_dst_cache = 0xcbbd8ef4, sk_dst_lock = {<No data fields>}, sk_policy = {0x0, 0x0}, sk_rmem_alloc = { counter = 0}, sk_receive_queue = {next = 0xcbbd0c60, prev = 0xcbbd0c60, qlen = 0, lock = {<No data fields>}}, sk_wmem_alloc = {counter = 0}, sk_write_queue = {next = 0xcbbd0c70, prev = 0xcbbd0c70, qlen = 0, lock = {<No data fields>}}, sk_omem_alloc = {counter = 0}, sk_wmem_queued = 0, sk_forward_alloc = 0, sk_allocation = 208, sk_sndbuf = 16384, sk_flags = 0, sk_no_check = 0 '\0', sk_debug = 0 '\0', sk_rcvtstamp = 0 '\0', sk_no_largesend = 0 '\0', sk_route_caps = 3, sk_lingertime = 0, sk_hashent = 11309, sk_pair = 0x0, sk_backlog = { head = 0x0, tail = 0x0}, sk_callback_lock = {<No data fields>}, sk_error_queue = {next = 0xcbbd0cb0, prev = 0xcbbd0cb0, qlen = 0, lock = {<No data fields>}}, sk_prot = 0xc035df00, sk_err = 0, sk_err_soft = 0, sk_ack_backlog = 0, sk_max_ack_backlog = 0, sk_priority = 0, sk_type = 1, sk_localroute = 0 '\0', sk_protocol = 6 '\006', sk_peercred = { pid = 0, uid = 4294967295, gid = 4294967295}, sk_rcvlowat = 1, sk_rcvtimeo = 2147483647, sk_sndtimeo = 2147483647, sk_filter = 0x0, sk_protinfo = 0x0, sk_slab = 0xd7c13780, sk_timer = {entry = {next = 0x0, prev = 0x0}, expires = 0, lock = {<No data fields>}, magic = 1267182958, function = 0xc0281a40 <tcp_keepalive_timer>, data = "" base = 0x0}, sk_stamp = {tv_sec = -1, tv_usec = -1}, sk_socket = 0xcbbc7eb4, sk_user_data = 0x0, sk_owner = 0x0, ---Type <return> to continue, or q <return> to quit--- sk_security = 0x0, sk_state_change = 0xc0246ab0 <sock_def_wakeup>, sk_data_ready = 0xc0246b90 <sock_def_readable>, sk_write_space = 0xc0270c90 <tcp_write_space>, sk_error_report = 0xc0246b00 <sock_def_error_report>, sk_backlog_rcv = 0xc0285390 <tcp_v4_do_rcv>, sk_destruct = 0xc0294120 <inet_sock_destruct>}This structure is what represents a socket and contains Another structure that accompanies a socket is the socket buffer, called skb. (gdb) p *skb $5 = {next = 0x0, prev = 0x0, list = 0x0, sk = 0x0, stamp = {tv_sec = 0, tv_usec = 0}, dev = 0x0, real_dev = 0x0, h = {th = 0x0, uh = 0x0, icmph = 0x0, igmph = 0x0, ipiph = 0x0, ipv6h = 0x0, raw = 0x0}, nh = {iph = 0x0, ipv6h = 0x0, arph = 0x0, raw = 0x0}, mac = {ethernet = 0x0, raw = 0x0}, dst = 0x0, sp = 0x0, cb = '\0' <repeats 16 times>, "\uffff\202\226\031\uffff\202\226\031\uffff\uffff\006\000\002", '\0' <repeats 18 times>, len = 0, data_len = 0, mac_len = 1515870810, csum = 0, local_df = 0 '\0', cloned = 1 '\001', pkt_type = 0 '\0', ip_summed = 0 '\0', priority = 0, protocol = 0, security = 0, destructor = 0, nfmark = 0, nfcache = 0, nfct = 0x0, nf_bridge = 0x0, truesize = 396, users = {counter = 1}, head = 0xd303edf8 'Z' <repeats 200 times>..., data = "" 'Z' <repeats 16 times>, "\002", tail = 0xd303eec8 'Z' <repeats 16 times>, "\002", end = 0xd303eed8 "\002"} From the socket buffer we can extract the header file of the tcp package being prepared to be sent. (gdb) p *skb-<h.th $40 = {source = 23130, dest = 23130, seq = 1515870810, ack_seq = 1515870810, res1 = 10, doff = 5, fin = 0, syn = 1, rst = 0, psh = 1, ack = 1, urg = 0, ece = 1, cwr = 0, window = 23130, check = 23130, urg_ptr = 23130}Of course, a lot of these values are 23130 as you can see. The structure has only been created so far, but it hasn't been given proper values. Compare this to the RFC's illustration of the TCP header: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ And if we type c on the gdb command line, the webpage has been displayed on the testing machine and then we click another link on the webpage, we can see that it will breakpoint again and this time it passed the argument into the function as sk=0xcc9a0c1c, uaddr=0xcc419eec, the ip address is still the same but the sk structure's address has changed. While we debug the TCP step by step, we found a familiar structure sock in the source code (gdb) n sys_connect (fd=0, uservaddr=0x0, addrlen=16) at net/socket.c:1375 1375 sockfd_put(sock);Hence we print it out as "p *sock", it indicates: (gdb) p *sock $8 = {state = SS_CONNECTED, flags = 0, ops = 0xc035ed80, fasync_list = 0x0, file = 0xd1a43f6c, sk = 0xcc9a0c1c, wait = {lock = {<No data fields>}, task_list = {next = 0xcc407ecc, prev = 0xcc407ecc}}, type = 1, passcred = 0 '\0'} |