mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 17:12:33 +00:00
gdb: Add a directory of files with gdb macros
* gdb/: Directory to contain files with GDB macros. Organised by topic into separate files. * gdb/lib.txt: General OS API and Quagga lib macros: (def_ntohs) convert big-endian short to host order. (def_ntohl) convert big-endian long to host order. (walk_route_table_next) Walk to next route_node in a table, according to given top and current node arguments. (walk_route_table) walk the given route table dumping non-null info pointers, from the given root node. (dump_timeval) timeval to human readable output (dump_s_addr) Print IP address of given pointer to a (struct in_addr).s_addr (dump_s6_addr) Ditto for IPv6. (dump_prefix4) Dump a Quagga (struct prefix_ipv4 *) (dump_prefix6) Dump (struct prefix_ipv6 *) (dump_prefix) Dump a (struct prefix *). (rn_next_{down,up}) left-down and up-and-right walks of a route_table from a given route_node. * gdb/ospfd.txt: ospfd specific gdb macros, depends on gdb/lib.txt (dump_ospf_lsa_flags) LSA flags to text. (dump_ospf_lsa_data) dump the data of a (struct lsa_header *) argument. (dump_ospf_lsa) Dump the details of a (struct ospf_lsa *) (walk_ospf_lsdb) Go through an LSDB, rooted at the given (struct route_node *), and dump LSA details. (ospf_backbone_lsdb_top) Get the LSDB top pointer for the given LSA type. (cherry picked from commit 5bcbc3f58870bd28ab1deadfff75bf59d62db021)
This commit is contained in:
parent
24b46333dd
commit
b3fda2469f
295
gdb/lib.txt
Normal file
295
gdb/lib.txt
Normal file
@ -0,0 +1,295 @@
|
||||
# GDB macros for use with Quagga.
|
||||
#
|
||||
# Macros in this file are not daemon specific. E.g., OS or Quagga 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/quagga/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->binfo->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
|
137
gdb/ospf.txt
Normal file
137
gdb/ospf.txt
Normal file
@ -0,0 +1,137 @@
|
||||
# GDB macros for use with Quagga.
|
||||
#
|
||||
# Macros in this file are specific to ospfd/. Definitions here depend on the
|
||||
# lib.txt macros file, which must also be loaed.
|
||||
#
|
||||
# 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.
|
||||
|
||||
define dump_ospf_lsa_flags
|
||||
set $flags = $arg0
|
||||
|
||||
printf "%u: ", $flags
|
||||
|
||||
if $flags & 0x1
|
||||
echo Self,
|
||||
end
|
||||
if $flags & 0x2
|
||||
echo Self-checked,
|
||||
end
|
||||
if $flags & 0x4
|
||||
echo Recvd,
|
||||
end
|
||||
if $flags & 0x8
|
||||
echo Apprvd,
|
||||
end
|
||||
if $flags & 0x10
|
||||
echo Discard,
|
||||
end
|
||||
if $flags & 0x20
|
||||
echo Local-Xlt,
|
||||
end
|
||||
if $flags & 0x40
|
||||
echo Premature-Aged,
|
||||
end
|
||||
if $flags & 0x40
|
||||
echo In-Maxage,
|
||||
end
|
||||
echo \n
|
||||
end
|
||||
|
||||
define dump_ospf_lsa_data
|
||||
set $lsad = (struct lsa_header *)$arg0
|
||||
|
||||
echo ID / AdvRtr: \t\t
|
||||
dump_s_addr &$lsad->id.s_addr
|
||||
echo \ : \
|
||||
dump_s_addr &$lsad->adv_router.s_addr
|
||||
echo \n
|
||||
|
||||
def_ntohs &$lsad->ls_age
|
||||
printf "Type: %2u Age: %4u,", $lsad->type, $_
|
||||
|
||||
def_ntohs &$lsad->length
|
||||
printf " length: %2u", $_
|
||||
|
||||
def_ntohl &$lsad->ls_seqnum
|
||||
printf " Seqnum: 0x%08x", $_
|
||||
|
||||
def_ntohs &$lsad->checksum
|
||||
printf " csum: 0x%04x\n", $_
|
||||
|
||||
# return the age
|
||||
def_ntohs &$lsad->ls_age
|
||||
end
|
||||
|
||||
define dump_ospf_lsa
|
||||
set $lsa = (struct ospf_lsa *)$arg0
|
||||
|
||||
#print/x *$lsa
|
||||
|
||||
dump_ospf_lsa_data $lsa->data
|
||||
|
||||
set $relage = $_ + (relative_time.tv_sec - $lsa->tv_recv.tv_sec)
|
||||
printf "Relative age: %4u\n", $relage
|
||||
|
||||
dump_ospf_lsa_flags $lsa->flags
|
||||
|
||||
echo tv_recv: \
|
||||
dump_timeval &$lsa->tv_recv
|
||||
echo \ tv_orig: \
|
||||
dump_timeval &$lsa->tv_orig
|
||||
echo \n
|
||||
|
||||
printf "lock %2u", $lsa->lock
|
||||
printf " stat %2d", $lsa->stat
|
||||
printf " rtx count: %u", $lsa->retransmit_counter
|
||||
printf " rfsh list: %d", $lsa->refresh_list
|
||||
printf "\n\n"
|
||||
end
|
||||
|
||||
define walk_ospf_lsdb
|
||||
set $node = (struct route_node *)$arg0
|
||||
set $top = (struct route_node *)$arg0
|
||||
set $visited = 0
|
||||
|
||||
while ($node != 0)
|
||||
set $prevl = $node
|
||||
|
||||
if ($node->info != 0)
|
||||
dump_ospf_lsa $node->info
|
||||
set $visited = $visited + 1
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
document walk_ospf_lsdb
|
||||
Walk through an OSPF LSDB (or subset thereof) and dump all the LSAs
|
||||
contained there-in.
|
||||
|
||||
Argument: A (struct route_node *) pointing to the top of the
|
||||
LSDB route-table which should be dumped.
|
||||
end
|
||||
|
||||
define ospf_backbone_lsdb_top
|
||||
set $type = $arg0
|
||||
|
||||
set $ospf = ospf_master->ospf->head->data
|
||||
|
||||
output/x ((struct ospf *)$ospf)->backbone->lsdb->type[$type]->db->top
|
||||
echo \n
|
||||
end
|
||||
document ospf_backbone_lsdb_top
|
||||
Dump location of the LSDB in the backbone area for the given LSA type
|
||||
|
||||
Argument: Integer LSA type
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user