http://cosi.clarkson.edu/docs/kernel/setup/kgdb/x118.html

7. Rebooting, Setting up GDB, and the Basics of Debugging

This section will walk you through the actual use of KGDB.

7.1. Rebooting and Setting up GDB

When 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 ./vmlinux
Once 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 Debugging

to be continued...

7.4. Example Debugging: Trace of TCP Connection

We 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_connect
OR
(gdb)b /net/ipv4/tcp_ipv4.c:744
(gdb)c
and 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:51
we 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'}

Reply via email to