80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
#-------------------------------------------------------------------------------
|
|
# 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 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] = AbbrevDecl(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]
|