drgn/scripts/generate_dwarf_constants.py
Omar Sandoval 75c3679147 Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:

- It's too slow for some common use cases, like iterating over large
  data structures.
- It can't be reused in utilities written in other languages.

This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:

- Types are now represented by a single Type class rather than the messy
  polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
  functions.

The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.

Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-04-02 14:12:07 -07:00

62 lines
1.6 KiB
Python
Executable File

#!/usr/bin/env python3
import re
prefixes = [
'DW_AT',
'DW_ATE',
'DW_CHILDREN',
'DW_FORM',
'DW_LNE',
'DW_LNS',
'DW_OP',
'DW_TAG',
]
if __name__ == '__main__':
with open('/usr/include/dwarf.h', 'r') as f:
dwarf_h = f.read()
dwarf_h = re.sub(r'/\*.*?\*/', '', dwarf_h, flags=re.DOTALL)
dwarf_h = re.sub(r'\\\n', '', dwarf_h)
matches = re.findall(r'^\s*(' + '|'.join(prefixes) + r')_(\w+)\s*=\s*(0x[0-9a-fA-F]+|[0-9]+)',
dwarf_h, re.MULTILINE)
enums = {}
for enum, name, value in matches:
try:
enums[enum].append((name, int(value, 0)))
except KeyError:
enums[enum] = [(name, int(value, 0))]
print("""\
# Automatically generated from dwarf.h
import enum
from typing import Text
""")
first = True
for enum in prefixes:
assert enums[enum]
if not first:
print()
print()
first = False
print(f'class {enum}(enum.IntEnum):')
for name, value in enums[enum]:
if name in ['import', 'not', 'and', 'or']:
name += '_'
print(f' {name} = 0x{value:x}', end='')
if name == 'name':
print(' # type: ignore')
else:
print()
print()
print(' @classmethod')
print(' def str(cls, value: int) -> Text:')
print(' try:')
print(f" return f'{enum}_{{cls(value).name}}'")
print(' except ValueError:')
print(' return hex(value)')