summaryrefslogtreecommitdiff
path: root/chromium/third_party/pyelftools/elftools/dwarf/abbrevtable.py
blob: 44ccdd5e5a277c43dda1df75ac8eb5324463b6d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#-------------------------------------------------------------------------------
# elftools: dwarf/abbrevtable.py
#
# DWARF abbreviation table
#
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
from ..common.utils import struct_parse, dwarf_assert


class AbbrevTable(object):
    """ Represents a DWARF abbreviation table.
    """
    def __init__(self, structs, stream, offset):
        """ Create new abbreviation table. Parses the actual table from the
            stream and stores it internally.
        
            structs:
                A DWARFStructs instance for parsing the data
            
            stream, offset:
                The stream and offset into the stream where this abbreviation
                table lives.
        """
        self.structs = structs
        self.stream = stream
        self.offset = offset
        
        self._abbrev_map = self._parse_abbrev_table()

    def get_abbrev(self, code):
        """ Get the AbbrevDecl for a given code. Raise KeyError if no
            declaration for this code exists.
        """
        return AbbrevDecl(code, self._abbrev_map[code])

    def _parse_abbrev_table(self):
        """ Parse the abbrev table from the stream
        """
        map = {}
        self.stream.seek(self.offset)
        while True:
            decl_code = struct_parse(
                struct=self.structs.Dwarf_uleb128(''),
                stream=self.stream)
            if decl_code == 0:
                break
            declaration = struct_parse(
                struct=self.structs.Dwarf_abbrev_declaration,
                stream=self.stream)
            map[decl_code] = declaration
        return map


class AbbrevDecl(object):
    """ Wraps a parsed abbreviation declaration, exposing its fields with 
        dict-like access, and adding some convenience methods.
        
        The abbreviation declaration represents an "entry" that points to it.
    """
    def __init__(self, code, decl):
        self.code = code
        self.decl = decl
    
    def has_children(self):
        """ Does the entry have children?
        """
        return self['children_flag'] == 'DW_CHILDREN_yes'

    def iter_attr_specs(self):
        """ Iterate over the attribute specifications for the entry. Yield
            (name, form) pairs.
        """
        for attr_spec in self['attr_spec']:
            yield attr_spec.name, attr_spec.form
            
    def __getitem__(self, entry):
        return self.decl[entry]