# GDB macros for use with Quagga. # # Macros in this file are not daemon specific. E.g., OS or FRR library # APIs. # # The macro file can be loaded with 'source <filename>'. They can then be # called by the user. Macros that explore more complicated structs generally # take pointer arguments. # # E.g.: # # (gdb) source ~paul/code/frr/gdb/lib.txt # (gdb) break bgp_packet.c:613 # Breakpoint 3 at 0x7fa883033a32: file bgp_packet.c, line 613. # (gdb) cont # ... # (gdb) cont # Breakpoint 3, bgp_write_packet (peer=0x7fa885199080) at bgp_packet.c:614 # 614 if (CHECK_FLAG (adv->path->peer->cap,PEER_CAP_RESTART_RCV) # (gdb) dump_prefix4 &adv->rn->p # IPv4:10.1.1.0/24 # (gdb) dump_prefix &adv->rn->p # IPv4:10.1.1.0/24 # define def_ntohs set $data = (char *)$arg0 set $i = 0 set $_ = $data[$i++] << 8 set $_ += $data[$i++] end document def_ntohs Read a 2-byte short at the given pointed to area as big-endian and return it in $_ Argument: Pointer to a 2-byte, big-endian short word. Returns: Integer value of that word in $_ end define def_ntohl set $data = (char *)$arg0 set $i = 0 set $_ = $data[$i++] << 24 set $_ += $data[$i++] << 16 set $_ += $data[$i++] << 8 set $_ += $data[$i++] end document def_ntohl Read a 4-byte integer at the given pointed to area as big-endian and return it in $_ Argument: Pointer to a big-endian 4-byte word. Returns: Integer value of that word in $_ end # NB: This is in more complicated iterative form, rather than more # conventional and simpler recursive form, because GDB has a recursion limit # on macro calls (I think). define walk_route_table_next # callee saves set $_top = $top set $_node = $node set $_prevl = $prevl set $top = (struct route_node *)$arg0 set $node = (struct route_node *)$arg1 set $prevl = $node # first try left #echo try left\n set $node = $prevl->link[0] # otherwise try right if ($node == 0) #echo left null, try right\n set $node = $prevl->link[1] end # otherwise go up, till we find the first right that # we havn't been to yet if ($node == 0) set $node = $prevl while ($node != $top) #echo right null, try up and right\n set $prevl = $node set $parent = $node->parent set $node = $parent->link[1] if ($node != 0 && $node != $prevl) #echo found node \n loop_break end #echo go up\n set $node = $parent end end #printf "next node: 0x%x\n", $node set $_ = $node set $top = $_top set $node = $_node set $prevl = $_prevl end document walk_route_table_next Return the next node to visit in the given route_table (or subset of) and the given current node. Arguments: 1st: (struct route_node *) to the top of the route_table to walk 2nd: (struct route_node *) to the current node Returns: The (struct route_node *) for the next to visit in $_ end define walk_route_table set $_visited = $visited set $_node = $node set $top = $_top set $node = (struct route_node *)$arg0 set $top = (struct route_node *)$arg0 set $visited = 0 while ($node != 0) printf "Node: 0x%x", $node if ($node->info != 0) printf "\tinfo: 0x%x", $node->info set $visited = $visited + 1 end printf "\n" walk_route_table_next $top $node set $node = $_ # we've gotten back to the top, finish if ($node == $top) set $node = 0 end end printf "Visited: %u\n", $visited set $top = $_top set $visited = $_visited set $node = $_node end document walk_route_table Walk through a routing table (or subset thereof) and dump all the non-null (struct route_node *)->info pointers. Argument: A lib/thread.h::(struct route_node *) pointing to the route_node under which all data should be dumped end define dump_timeval set $tv = (struct timeval *)$arg0 set $day = 3600*24 if $tv->tv_sec > $day printf "%d days, ", $tv->tv_sec / $day end if $tv->tv_sec > 3600 printf "%dh", $tv->tv_sec / 3600 end if ($tv->tv_sec % 3600) > 60 printf "%dm", ($tv->tv_sec % 3600) / 60 end printf "%d", $tv->tv_sec % 3600 % 60 if $tv->tv_usec != 0 printf ".%06d", $tv->tv_usec end printf "s" end document dump_timeval Human readable dump of a (struct timeval *) argument end define dump_s_addr set $addr = (char *)$arg0 printf "%d.%d.%d.%d", $addr[0], $addr[1], $addr[2], $addr[3] end define dump_s6_addr set $a6 = (char *)$arg0 set $field = 0 while ($field < 16) set $i1 = $field++ set $i2 = $field++ printf "%x%x", $a6[$i1], $a6[$i2] if ($field > 2 && ($field % 4 == 0)) printf ":" end end end document dump_s6_addr Interpret the memory starting at given address as an IPv6 s6_addr and print in human readable form. end define dump_prefix4 set $p = (struct prefix *) $arg0 echo IPv4: dump_s_addr &($p->u.prefix4) printf "/%d\n", $p->prefixlen end document dump_prefix4 Textual dump of a (struct prefix4 *) argument. end define dump_prefix6 set $p = (struct prefix *) $arg0 echo IPv6: dump_s6_addr &($p->u.prefix6) printf "/%d\n", $p->prefixlen end document dump_prefix6 Textual dump of a (struct prefix6 *) argument. end define dump_prefix set $p = $arg0 if ($p->family == 2) dump_prefix4 $p end if ($p->family == 10) dump_prefix6 $p end end document dump_prefix Human readable dump of a (struct prefix *) argument. end define rn_next_down set $node = $arg0 while ($node != 0) print/x $node if ($node->link[0] != 0) set $node = $node->link[0] else set $node = $node->link[1] end end end document rn_next_down Walk left-down a given route table, dumping locations of route_nodes Argument: A single (struct route_node *). end define rn_next_up set $top = (struct route_node *)$arg0 set $node = (struct route_node *)$arg1 while ($node != $top) echo walk up\n set $prevl = $node set $parent = $node->parent set $node = $parent->link[1] if ($node != 0 && $node != $prevl) echo found a node\n loop_break end echo going up\n set $node = $parent end output/x $node echo \n end document rn_next_up Walk up-and-right from the given route_node to the next valid route_node which is not the given "top" route_node Arguments: 1st: A (struct route_node *) to the top of the route table. 2nd: The (struct route_node *) to walk up from end