cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lists.py (4261B)


      1#
      2# gdb helper commands and functions for Linux kernel debugging
      3#
      4#  list tools
      5#
      6# Copyright (c) Thiebaud Weksteen, 2015
      7#
      8# Authors:
      9#  Thiebaud Weksteen <thiebaud@weksteen.fr>
     10#
     11# This work is licensed under the terms of the GNU GPL version 2.
     12#
     13
     14import gdb
     15
     16from linux import utils
     17
     18list_head = utils.CachedType("struct list_head")
     19hlist_head = utils.CachedType("struct hlist_head")
     20hlist_node = utils.CachedType("struct hlist_node")
     21
     22
     23def list_for_each(head):
     24    if head.type == list_head.get_type().pointer():
     25        head = head.dereference()
     26    elif head.type != list_head.get_type():
     27        raise TypeError("Must be struct list_head not {}"
     28                           .format(head.type))
     29
     30    if head['next'] == 0:
     31        gdb.write("list_for_each: Uninitialized list '{}' treated as empty\n"
     32                     .format(head.address))
     33        return
     34
     35    node = head['next'].dereference()
     36    while node.address != head.address:
     37        yield node.address
     38        node = node['next'].dereference()
     39
     40
     41def list_for_each_entry(head, gdbtype, member):
     42    for node in list_for_each(head):
     43        yield utils.container_of(node, gdbtype, member)
     44
     45
     46def hlist_for_each(head):
     47    if head.type == hlist_head.get_type().pointer():
     48        head = head.dereference()
     49    elif head.type != hlist_head.get_type():
     50        raise TypeError("Must be struct hlist_head not {}"
     51                           .format(head.type))
     52
     53    node = head['first'].dereference()
     54    while node.address:
     55        yield node.address
     56        node = node['next'].dereference()
     57
     58
     59def hlist_for_each_entry(head, gdbtype, member):
     60    for node in hlist_for_each(head):
     61        yield utils.container_of(node, gdbtype, member)
     62
     63
     64def list_check(head):
     65    nb = 0
     66    if (head.type == list_head.get_type().pointer()):
     67        head = head.dereference()
     68    elif (head.type != list_head.get_type()):
     69        raise gdb.GdbError('argument must be of type (struct list_head [*])')
     70    c = head
     71    try:
     72        gdb.write("Starting with: {}\n".format(c))
     73    except gdb.MemoryError:
     74        gdb.write('head is not accessible\n')
     75        return
     76    while True:
     77        p = c['prev'].dereference()
     78        n = c['next'].dereference()
     79        try:
     80            if p['next'] != c.address:
     81                gdb.write('prev.next != current: '
     82                          'current@{current_addr}={current} '
     83                          'prev@{p_addr}={p}\n'.format(
     84                              current_addr=c.address,
     85                              current=c,
     86                              p_addr=p.address,
     87                              p=p,
     88                          ))
     89                return
     90        except gdb.MemoryError:
     91            gdb.write('prev is not accessible: '
     92                      'current@{current_addr}={current}\n'.format(
     93                          current_addr=c.address,
     94                          current=c
     95                      ))
     96            return
     97        try:
     98            if n['prev'] != c.address:
     99                gdb.write('next.prev != current: '
    100                          'current@{current_addr}={current} '
    101                          'next@{n_addr}={n}\n'.format(
    102                              current_addr=c.address,
    103                              current=c,
    104                              n_addr=n.address,
    105                              n=n,
    106                          ))
    107                return
    108        except gdb.MemoryError:
    109            gdb.write('next is not accessible: '
    110                      'current@{current_addr}={current}\n'.format(
    111                          current_addr=c.address,
    112                          current=c
    113                      ))
    114            return
    115        c = n
    116        nb += 1
    117        if c == head:
    118            gdb.write("list is consistent: {} node(s)\n".format(nb))
    119            return
    120
    121
    122class LxListChk(gdb.Command):
    123    """Verify a list consistency"""
    124
    125    def __init__(self):
    126        super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA,
    127                                        gdb.COMPLETE_EXPRESSION)
    128
    129    def invoke(self, arg, from_tty):
    130        argv = gdb.string_to_argv(arg)
    131        if len(argv) != 1:
    132            raise gdb.GdbError("lx-list-check takes one argument")
    133        list_check(gdb.parse_and_eval(argv[0]))
    134
    135
    136LxListChk()