public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Siddhesh Poyarekar <siddhesh@gotplt.org>
To: Florian Weimer <fweimer@redhat.com>, libc-alpha@sourceware.org
Subject: Re: [PATCH v2 3/3] elf: Extract glibcelf constants from <elf.h>
Date: Wed, 21 Sep 2022 14:05:37 -0400	[thread overview]
Message-ID: <42d147a4-24b6-5295-0b03-316e591a9ef8@gotplt.org> (raw)
In-Reply-To: <a57f6c2a0c07f8a62b1278d725bbf70b16b81ee4.1663167514.git.fweimer@redhat.com>

On 2022-09-14 11:00, Florian Weimer via Libc-alpha wrote:
> The need to maintain elf/elf.h and scripts/glibcelf.py in parallel
> results in a backporting hazard: they need to be kept in sync to
> avoid elf/tst-glibcelf consistency check failures.  glibcelf (unlike
> tst-glibcelf) does not use the C implementation to extract constants.
> This applies the additional glibcpp syntax checks to <elf.h>.
> 
> This  changereplaces the types derived from Python enum types with
> custom types _TypedConstant, _IntConstant, and _FlagConstant.  These
> types have fewer safeguards, but this also allows incremental
> construction and greater flexibility for grouping constants among
> the types.  Architectures-specific named constants are now added
> as members into their superclasses (but value-based lookup is
> still restricted to generic constants only).
> 
> Consequently, check_duplicates in elf/tst-glibcelf has been adjusted
> to accept differently-named constants of the same value if their
> subtypes are distinct.  The ordering check for named constants
> has been dropped because they are no longer strictly ordered.
> 
> Further test adjustments: Some of the type names are different.
> The new types do not support iteration (because it is unclear
> whether iteration should cover the all named values (including
> architecture-specific constants), or only the generic named values),
> so elf/tst-glibcelf now uses by_name explicit (to get all constants).
> PF_HP_SBP and PF_PARISC_SBP are now of distinct types (PfHP and
> PfPARISC), so they are how both present on the Python side.  EM_NUM
> and PT_NUM are filtered (which was an oversight in the old
> conversion).
> 
> The new version of glibcelf should also be compatible with earlier
> Python versions because it no longer depends on the enum module and its
> advanced features.
> ---
>   elf/tst-glibcelf.py |   79 +++-
>   scripts/glibcelf.py | 1016 ++++++++++++++++---------------------------
>   2 files changed, 438 insertions(+), 657 deletions(-)

LGTM.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>

> 
> diff --git a/elf/tst-glibcelf.py b/elf/tst-glibcelf.py
> index e5026e2289..a5bff45eae 100644
> --- a/elf/tst-glibcelf.py
> +++ b/elf/tst-glibcelf.py
> @@ -18,7 +18,6 @@
>   # <https://www.gnu.org/licenses/>.
>   
>   import argparse
> -import enum
>   import sys
>   
>   import glibcelf
> @@ -45,11 +44,57 @@ def find_constant_prefix(name):
>   
>   def find_enum_types():
>       """A generator for OpenIntEnum and IntFlag classes in glibcelf."""
> +    classes = set((glibcelf._TypedConstant, glibcelf._IntConstant,
> +                   glibcelf._FlagConstant))
>       for obj in vars(glibcelf).values():
> -        if isinstance(obj, type) and obj.__bases__[0] in (
> -                glibcelf._OpenIntEnum, enum.Enum, enum.IntFlag):
> +        if isinstance(obj, type) and obj not in classes \
> +           and obj.__bases__[0] in classes:
>               yield obj
>   
> +def check_basic():
> +    """Check basic functionality of the constant classes."""
> +
> +    if glibcelf.Pt.PT_NULL is not glibcelf.Pt(0):
> +        error('Pt(0) not interned')
> +    if glibcelf.Pt(17609) is glibcelf.Pt(17609):
> +        error('Pt(17609) unexpectedly interned')
> +    if glibcelf.Pt(17609) == glibcelf.Pt(17609):
> +        pass
> +    else:
> +        error('Pt(17609) equality')
> +    if glibcelf.Pt(17610) == glibcelf.Pt(17609):
> +        error('Pt(17610) equality')
> +
> +    if str(glibcelf.Pt.PT_NULL) != 'PT_NULL':
> +        error('str(PT_NULL)')
> +    if str(glibcelf.Pt(17609)) != '17609':
> +        error('str(Pt(17609))')
> +
> +    if repr(glibcelf.Pt.PT_NULL) != 'PT_NULL':
> +        error('repr(PT_NULL)')
> +    if repr(glibcelf.Pt(17609)) != 'Pt(17609)':
> +        error('repr(Pt(17609))')
> +
> +    if glibcelf.Pt('PT_AARCH64_MEMTAG_MTE') \
> +       is not glibcelf.Pt.PT_AARCH64_MEMTAG_MTE:
> +        error('PT_AARCH64_MEMTAG_MTE identity')
> +    if glibcelf.Pt(0x70000002) is glibcelf.Pt.PT_AARCH64_MEMTAG_MTE:
> +        error('Pt(0x70000002) identity')
> +    if glibcelf.PtAARCH64(0x70000002) is not glibcelf.Pt.PT_AARCH64_MEMTAG_MTE:
> +        error('PtAARCH64(0x70000002) identity')
> +    if glibcelf.Pt.PT_AARCH64_MEMTAG_MTE.short_name != 'AARCH64_MEMTAG_MTE':
> +        error('PT_AARCH64_MEMTAG_MTE short name')
> +
> +    # Special cases for int-like Shn.
> +    if glibcelf.Shn(32) == glibcelf.Shn.SHN_XINDEX:
> +        error('Shn(32)')
> +    if glibcelf.Shn(32) + 0 != 32:
> +        error('Shn(32) + 0')
> +    if 32 in glibcelf.Shn:
> +        error('32 in Shn')
> +    if 0 not in glibcelf.Shn:
> +        error('0 not in Shn')
> +
>   def check_duplicates():
>       """Verifies that enum types do not have duplicate values.
>   
> @@ -59,17 +104,16 @@ def check_duplicates():
>       global_seen = {}
>       for typ in find_enum_types():
>           seen = {}
> -        last = None
> -        for (name, e) in typ.__members__.items():
> +        for (name, e) in typ.by_name.items():
>               if e.value in seen:
> -                error('{} has {}={} and {}={}'.format(
> -                    typ, seen[e.value], e.value, name, e.value))
> -                last = e
> +                other = seen[e.value]
> +                # Value conflicts only count if they are between
> +                # the same base type.
> +                if e.__class__ is typ and other.__class__ is typ:
> +                    error('{} has {}={} and {}={}'.format(
> +                        typ, other, e.value, name, e.value))
>               else:
>                   seen[e.value] = name
> -                if last is not None and last.value > e.value:
> -                    error('{} has {}={} after {}={}'.format(
> -                        typ, name, e.value, last.name, last.value))
>                   if name in global_seen:
>                       error('{} used in {} and {}'.format(
>                           name, global_seen[name], typ))
> @@ -81,7 +125,7 @@ def check_constant_prefixes():
>       seen = set()
>       for typ in find_enum_types():
>           typ_prefix = None
> -        for val in typ:
> +        for val in typ.by_name.values():
>               prefix = find_constant_prefix(val.name)
>               if prefix is None:
>                   error('constant {!r} for {} has unknown prefix'.format(
> @@ -113,7 +157,6 @@ def find_elf_h_constants(cc):
>   # used in <elf.h>.
>   glibcelf_skipped_aliases = (
>       ('EM_ARC_A5', 'EM_ARC_COMPACT'),
> -    ('PF_PARISC_SBP', 'PF_HP_SBP')
>   )
>   
>   # Constants that provide little value and are not included in
> @@ -146,6 +189,7 @@ DT_VALRNGLO
>   DT_VERSIONTAGNUM
>   ELFCLASSNUM
>   ELFDATANUM
> +EM_NUM
>   ET_HIOS
>   ET_HIPROC
>   ET_LOOS
> @@ -159,6 +203,7 @@ PT_HISUNW
>   PT_LOOS
>   PT_LOPROC
>   PT_LOSUNW
> +PT_NUM
>   SHF_MASKOS
>   SHF_MASKPROC
>   SHN_HIOS
> @@ -193,7 +238,7 @@ def check_constant_values(cc):
>       """Checks the values of <elf.h> constants against glibcelf."""
>   
>       glibcelf_constants = {
> -        e.name: e for typ in find_enum_types() for e in typ}
> +        e.name: e for typ in find_enum_types() for e in typ.by_name.values()}
>       elf_h_constants = find_elf_h_constants(cc=cc)
>   
>       missing_in_glibcelf = (set(elf_h_constants) - set(glibcelf_constants)
> @@ -229,12 +274,13 @@ def check_constant_values(cc):
>       for name in sorted(set(glibcelf_constants) & set(elf_h_constants)):
>           glibcelf_value = glibcelf_constants[name].value
>           elf_h_value = int(elf_h_constants[name])
> -        # On 32-bit architectures <elf.h> as some constants that are
> +        # On 32-bit architectures <elf.h> has some constants that are
>           # parsed as signed, while they are unsigned in glibcelf.  So
>           # far, this only affects some flag constants, so special-case
>           # them here.
>           if (glibcelf_value != elf_h_value
> -            and not (isinstance(glibcelf_constants[name], enum.IntFlag)
> +            and not (isinstance(glibcelf_constants[name],
> +                                glibcelf._FlagConstant)
>                        and glibcelf_value == 1 << 31
>                        and elf_h_value == -(1 << 31))):
>               error('{}: glibcelf has {!r}, <elf.h> has {!r}'.format(
> @@ -266,6 +312,7 @@ def main():
>                           help='C compiler (including options) to use')
>       args = parser.parse_args()
>   
> +    check_basic()
>       check_duplicates()
>       check_constant_prefixes()
>       check_constant_values(cc=args.cc)
> diff --git a/scripts/glibcelf.py b/scripts/glibcelf.py
> index 5c8f46f590..420cb21943 100644
> --- a/scripts/glibcelf.py
> +++ b/scripts/glibcelf.py
> @@ -25,711 +25,445 @@ parsing it.
>   """
>   
>   import collections
> -import enum
> +import functools
> +import os
>   import struct
>   
> -if not hasattr(enum, 'IntFlag'):
> -    import sys
> -    sys.stdout.write(
> -        'warning: glibcelf.py needs Python 3.6 for enum support\n')
> -    sys.exit(77)
> +import glibcpp
> +
> +class _MetaNamedValue(type):
> +    """Used to set up _NamedValue subclasses."""
>   
> -class _OpenIntEnum(enum.IntEnum):
> -    """Integer enumeration that supports arbitrary int values."""
>       @classmethod
> -    def _missing_(cls, value):
> -        # See enum.IntFlag._create_pseudo_member_.  This allows
> -        # creating of enum constants with arbitrary integer values.
> -        pseudo_member = int.__new__(cls, value)
> -        pseudo_member._name_ = None
> -        pseudo_member._value_ = value
> -        return pseudo_member
> +    def __prepare__(metacls, cls, bases, **kwds):
> +        # Indicates an int-based class.  Needed for types like Shn.
> +        int_based = False
> +        for base in bases:
> +            if issubclass(base, int):
> +                int_based = int
> +                break
> +        return dict(by_value={},
> +                    by_name={},
> +                    prefix=None,
> +                    _int_based=int_based)
>   
> -    def __repr__(self):
> -        name = self._name_
> -        if name is not None:
> -            # The names have prefixes like SHT_, implying their type.
> -            return name
> -        return '{}({})'.format(self.__class__.__name__, self._value_)
> +    def __contains__(self, other):
> +        return other in self.by_value
> +
> +class _NamedValue(metaclass=_MetaNamedValue):
> +    """Typed, named integer constants.
> +
> +    Constants have the following instance attributes:
> +
> +    name: The full name of the constant (e.g., "PT_NULL").
> +    short_name: The name with of the constant without the prefix ("NULL").
> +    value: The integer value of the constant.
> +
> +    The following class attributes are available:
> +
> +    by_value: A dict mapping integers to constants.
> +    by_name: A dict mapping strings to constants.
> +    prefix: A string that is removed from the start of short names, or None.
> +
> +    """
> +
> +    def __new__(cls, arg0, arg1=None):
> +        """Instance creation.
> +
> +        For the one-argument form, the argument must be a string, an
> +        int, or an instance of this class.  Strings are looked up via
> +        by_name.  Values are looked up via by_value; if value lookup
> +        fails, a new unnamed instance is returned.  Instances of this
> +        class a re returned as-is.
> +
> +        The two-argument form expects the name (a string) and the
> +        value (an integer).  A new instance is created in this case.
> +        The instance is not registered in the by_value/by_name
> +        dictionaries (but the caller can do that).
> +
> +        """
> +
> +        typ0 = type(arg0)
> +        if arg1 is None:
> +            if isinstance(typ0, cls):
> +                # Re-use the existing object.
> +                return arg0
> +            if typ0 is int:
> +                by_value = cls.by_value
> +                try:
> +                    return by_value[arg0]
> +                except KeyError:
> +                    # Create a new object of the requested value.
> +                    if cls._int_based:
> +                        result = int.__new__(cls, arg0)
> +                    else:
> +                        result = object.__new__(cls)
> +                    result.value = arg0
> +                    result.name = None
> +                    return result
> +            if typ0 is str:
> +                by_name = cls.by_name
> +                try:
> +                    return by_name[arg0]
> +                except KeyError:
> +                    raise ValueError('unknown {} constant: {!r}'.format(
> +                        cls.__name__, arg0))
> +        else:
> +            # Types for the two-argument form are rigid.
> +            if typ0 is not str and typ0 is not None:
> +                raise ValueError('type {} of name {!r} should be str'.format(
> +                    typ0.__name__, arg0))
> +            if type(arg1) is not int:
> +                raise ValueError('type {} of value {!r} should be int'.format(
> +                    type(arg1).__name__, arg1))
> +            # Create a new named constants.
> +            if cls._int_based:
> +                result = int.__new__(cls, arg1)
> +            else:
> +                result = object.__new__(cls)
> +            result.value = arg1
> +            result.name = arg0
> +            # Set up the short_name attribute.
> +            prefix = cls.prefix
> +            if prefix and arg0.startswith(prefix):
> +                result.short_name = arg0[len(prefix):]
> +            else:
> +                result.short_name = arg0
> +            return result
>   
>       def __str__(self):
> -        name = self._name_
> -        if name is not None:
> +        name = self.name
> +        if name:
> +            return name
> +        else:
> +            return str(self.value)
> +
> +    def __repr__(self):
> +        name = self.name
> +        if name:
>               return name
> -        return str(self._value_)
> +        else:
> +            return '{}({})'.format(self.__class__.__name__, self.value)
> +
> +    def __setattr__(self, name, value):
> +        # Prevent modification of the critical attributes once they
> +        # have been set.
> +        if name in ('name', 'value', 'short_name') and hasattr(self, name):
> +            raise AttributeError('can\'t set attribute {}'.format(name))
> +        object.__setattr__(self, name, value)
> +
> +@functools.total_ordering
> +class _TypedConstant(_NamedValue):
> +    """Base class for integer-valued optionally named constants.
> +
> +    This type is not an integer type.
> +
> +    """
> +
> +    def __eq__(self, other):
> +        return isinstance(other, self.__class__) and self.value == other.value
> +
> +    def __lt__(self, other):
> +        return isinstance(other, self.__class__) and self.value <= other.value
> +
> +    def __hash__(self):
> +        return hash(self.value)
> +
> +class _IntConstant(_NamedValue, int):
> +    """Base class for integer-like optionally named constants.
> +
> +    Instances compare equal to the integer of the same value, and can
> +    be used in integer arithmetic.
> +
> +    """
>   
> -class ElfClass(_OpenIntEnum):
> +    pass
> +
> +class _FlagConstant(_TypedConstant, int):
> +    pass
> +
> +def _parse_elf_h():
> +    """Read ../elf/elf.h and return a dict with the constants in it."""
> +
> +    path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
> +                        '..', 'elf', 'elf.h')
> +    class TokenizerReporter:
> +        """Report tokenizer errors to standard output."""
> +
> +        def __init__(self):
> +            self.errors = 0
> +
> +        def error(self, token, message):
> +            self.errors += 1
> +            print('{}:{}:{}: error: {}'.format(
> +                path, token.line, token.column, message))
> +
> +    reporter = TokenizerReporter()
> +    with open(path) as inp:
> +        tokens = glibcpp.tokenize_c(inp.read(), reporter)
> +    if reporter.errors:
> +        raise IOError('parse error in elf.h')
> +
> +    class MacroReporter:
> +        """Report macro errors to standard output."""
> +
> +        def __init__(self):
> +            self.errors = 0
> +
> +        def error(self, line, message):
> +            errors += 1
> +            print('{}:{}: error: {}'.format(path, line, message))
> +
> +        def note(self, line, message):
> +            print('{}:{}: note: {}'.format(path, line, message))
> +
> +    reporter = MacroReporter()
> +    result = glibcpp.macro_eval(glibcpp.macro_definitions(tokens), reporter)
> +    if reporter.errors:
> +        raise IOError('parse error in elf.h')
> +
> +    return result
> +_elf_h = _parse_elf_h()
> +del _parse_elf_h
> +_elf_h_processed = set()
> +
> +def _register_elf_h(cls, prefix=None, skip=(), ranges=False, parent=None):
> +    prefix = prefix or cls.prefix
> +    if not prefix:
> +        raise ValueError('missing prefix for {}'.format(cls.__name__))
> +    by_value = cls.by_value
> +    by_name = cls.by_name
> +    processed = _elf_h_processed
> +
> +    skip = set(skip)
> +    skip.add(prefix + 'NUM')
> +    if ranges:
> +        skip.add(prefix + 'LOOS')
> +        skip.add(prefix + 'HIOS')
> +        skip.add(prefix + 'LOPROC')
> +        skip.add(prefix + 'HIPROC')
> +        cls.os_range = (_elf_h[prefix + 'LOOS'], _elf_h[prefix + 'HIOS'])
> +        cls.proc_range = (_elf_h[prefix + 'LOPROC'], _elf_h[prefix + 'HIPROC'])
> +
> +    # Inherit the prefix from the parent if not set.
> +    if parent and cls.prefix is None and parent.prefix is not None:
> +        cls.prefix = parent.prefix
> +
> +    processed_len_start = len(processed)
> +    for name, value in _elf_h.items():
> +        if name in skip or name in processed:
> +            continue
> +        if name.startswith(prefix):
> +            processed.add(name)
> +            if value in by_value:
> +                raise ValueError('duplicate value {}: {}, {}'.format(
> +                    value, name, by_value[value]))
> +            obj = cls(name, value)
> +            by_value[value] = obj
> +            by_name[name] = obj
> +            setattr(cls, name, obj)
> +            if parent:
> +                # Make the symbolic name available through the parent as well.
> +                parent.by_name[name] = obj
> +                setattr(parent, name, obj)
> +
> +    if len(processed) == processed_len_start:
> +        raise ValueError('nothing matched prefix {!r}'.format(prefix))
> +
> +class ElfClass(_TypedConstant):
>       """ELF word size.  Type of EI_CLASS values."""
> -    ELFCLASSNONE = 0
> -    ELFCLASS32 = 1
> -    ELFCLASS64 = 2
> +_register_elf_h(ElfClass, prefix='ELFCLASS')
>   
> -class ElfData(_OpenIntEnum):
> +class ElfData(_TypedConstant):
>       """ELF endianess.  Type of EI_DATA values."""
> -    ELFDATANONE = 0
> -    ELFDATA2LSB = 1
> -    ELFDATA2MSB = 2
> +_register_elf_h(ElfData, prefix='ELFDATA')
>   
> -class Machine(_OpenIntEnum):
> +class Machine(_TypedConstant):
>       """ELF machine type.  Type of values in Ehdr.e_machine field."""
> -    EM_NONE = 0
> -    EM_M32 = 1
> -    EM_SPARC = 2
> -    EM_386 = 3
> -    EM_68K = 4
> -    EM_88K = 5
> -    EM_IAMCU = 6
> -    EM_860 = 7
> -    EM_MIPS = 8
> -    EM_S370 = 9
> -    EM_MIPS_RS3_LE = 10
> -    EM_PARISC = 15
> -    EM_VPP500 = 17
> -    EM_SPARC32PLUS = 18
> -    EM_960 = 19
> -    EM_PPC = 20
> -    EM_PPC64 = 21
> -    EM_S390 = 22
> -    EM_SPU = 23
> -    EM_V800 = 36
> -    EM_FR20 = 37
> -    EM_RH32 = 38
> -    EM_RCE = 39
> -    EM_ARM = 40
> -    EM_FAKE_ALPHA = 41
> -    EM_SH = 42
> -    EM_SPARCV9 = 43
> -    EM_TRICORE = 44
> -    EM_ARC = 45
> -    EM_H8_300 = 46
> -    EM_H8_300H = 47
> -    EM_H8S = 48
> -    EM_H8_500 = 49
> -    EM_IA_64 = 50
> -    EM_MIPS_X = 51
> -    EM_COLDFIRE = 52
> -    EM_68HC12 = 53
> -    EM_MMA = 54
> -    EM_PCP = 55
> -    EM_NCPU = 56
> -    EM_NDR1 = 57
> -    EM_STARCORE = 58
> -    EM_ME16 = 59
> -    EM_ST100 = 60
> -    EM_TINYJ = 61
> -    EM_X86_64 = 62
> -    EM_PDSP = 63
> -    EM_PDP10 = 64
> -    EM_PDP11 = 65
> -    EM_FX66 = 66
> -    EM_ST9PLUS = 67
> -    EM_ST7 = 68
> -    EM_68HC16 = 69
> -    EM_68HC11 = 70
> -    EM_68HC08 = 71
> -    EM_68HC05 = 72
> -    EM_SVX = 73
> -    EM_ST19 = 74
> -    EM_VAX = 75
> -    EM_CRIS = 76
> -    EM_JAVELIN = 77
> -    EM_FIREPATH = 78
> -    EM_ZSP = 79
> -    EM_MMIX = 80
> -    EM_HUANY = 81
> -    EM_PRISM = 82
> -    EM_AVR = 83
> -    EM_FR30 = 84
> -    EM_D10V = 85
> -    EM_D30V = 86
> -    EM_V850 = 87
> -    EM_M32R = 88
> -    EM_MN10300 = 89
> -    EM_MN10200 = 90
> -    EM_PJ = 91
> -    EM_OPENRISC = 92
> -    EM_ARC_COMPACT = 93
> -    EM_XTENSA = 94
> -    EM_VIDEOCORE = 95
> -    EM_TMM_GPP = 96
> -    EM_NS32K = 97
> -    EM_TPC = 98
> -    EM_SNP1K = 99
> -    EM_ST200 = 100
> -    EM_IP2K = 101
> -    EM_MAX = 102
> -    EM_CR = 103
> -    EM_F2MC16 = 104
> -    EM_MSP430 = 105
> -    EM_BLACKFIN = 106
> -    EM_SE_C33 = 107
> -    EM_SEP = 108
> -    EM_ARCA = 109
> -    EM_UNICORE = 110
> -    EM_EXCESS = 111
> -    EM_DXP = 112
> -    EM_ALTERA_NIOS2 = 113
> -    EM_CRX = 114
> -    EM_XGATE = 115
> -    EM_C166 = 116
> -    EM_M16C = 117
> -    EM_DSPIC30F = 118
> -    EM_CE = 119
> -    EM_M32C = 120
> -    EM_TSK3000 = 131
> -    EM_RS08 = 132
> -    EM_SHARC = 133
> -    EM_ECOG2 = 134
> -    EM_SCORE7 = 135
> -    EM_DSP24 = 136
> -    EM_VIDEOCORE3 = 137
> -    EM_LATTICEMICO32 = 138
> -    EM_SE_C17 = 139
> -    EM_TI_C6000 = 140
> -    EM_TI_C2000 = 141
> -    EM_TI_C5500 = 142
> -    EM_TI_ARP32 = 143
> -    EM_TI_PRU = 144
> -    EM_MMDSP_PLUS = 160
> -    EM_CYPRESS_M8C = 161
> -    EM_R32C = 162
> -    EM_TRIMEDIA = 163
> -    EM_QDSP6 = 164
> -    EM_8051 = 165
> -    EM_STXP7X = 166
> -    EM_NDS32 = 167
> -    EM_ECOG1X = 168
> -    EM_MAXQ30 = 169
> -    EM_XIMO16 = 170
> -    EM_MANIK = 171
> -    EM_CRAYNV2 = 172
> -    EM_RX = 173
> -    EM_METAG = 174
> -    EM_MCST_ELBRUS = 175
> -    EM_ECOG16 = 176
> -    EM_CR16 = 177
> -    EM_ETPU = 178
> -    EM_SLE9X = 179
> -    EM_L10M = 180
> -    EM_K10M = 181
> -    EM_AARCH64 = 183
> -    EM_AVR32 = 185
> -    EM_STM8 = 186
> -    EM_TILE64 = 187
> -    EM_TILEPRO = 188
> -    EM_MICROBLAZE = 189
> -    EM_CUDA = 190
> -    EM_TILEGX = 191
> -    EM_CLOUDSHIELD = 192
> -    EM_COREA_1ST = 193
> -    EM_COREA_2ND = 194
> -    EM_ARCV2 = 195
> -    EM_OPEN8 = 196
> -    EM_RL78 = 197
> -    EM_VIDEOCORE5 = 198
> -    EM_78KOR = 199
> -    EM_56800EX = 200
> -    EM_BA1 = 201
> -    EM_BA2 = 202
> -    EM_XCORE = 203
> -    EM_MCHP_PIC = 204
> -    EM_INTELGT = 205
> -    EM_KM32 = 210
> -    EM_KMX32 = 211
> -    EM_EMX16 = 212
> -    EM_EMX8 = 213
> -    EM_KVARC = 214
> -    EM_CDP = 215
> -    EM_COGE = 216
> -    EM_COOL = 217
> -    EM_NORC = 218
> -    EM_CSR_KALIMBA = 219
> -    EM_Z80 = 220
> -    EM_VISIUM = 221
> -    EM_FT32 = 222
> -    EM_MOXIE = 223
> -    EM_AMDGPU = 224
> -    EM_RISCV = 243
> -    EM_BPF = 247
> -    EM_CSKY = 252
> -    EM_LOONGARCH = 258
> -    EM_NUM = 259
> -    EM_ALPHA = 0x9026
> -
> -class Et(_OpenIntEnum):
> +    prefix = 'EM_'
> +_register_elf_h(Machine, skip=('EM_ARC_A5',))
> +
> +class Et(_TypedConstant):
>       """ELF file type.  Type of ET_* values and the Ehdr.e_type field."""
> -    ET_NONE = 0
> -    ET_REL = 1
> -    ET_EXEC = 2
> -    ET_DYN = 3
> -    ET_CORE = 4
> +    prefix = 'ET_'
> +_register_elf_h(Et, ranges=True)
>   
> -class Shn(_OpenIntEnum):
> +class Shn(_IntConstant):
>       """ELF reserved section indices."""
> -    SHN_UNDEF = 0
> -    SHN_BEFORE = 0xff00
> -    SHN_AFTER = 0xff01
> -    SHN_ABS = 0xfff1
> -    SHN_COMMON = 0xfff2
> -    SHN_XINDEX = 0xffff
> -
> -class ShnMIPS(enum.Enum):
> +    prefix = 'SHN_'
> +class ShnMIPS(Shn):
>       """Supplemental SHN_* constants for EM_MIPS."""
> -    SHN_MIPS_ACOMMON = 0xff00
> -    SHN_MIPS_TEXT = 0xff01
> -    SHN_MIPS_DATA = 0xff02
> -    SHN_MIPS_SCOMMON = 0xff03
> -    SHN_MIPS_SUNDEFINED = 0xff04
> -
> -class ShnPARISC(enum.Enum):
> +class ShnPARISC(Shn):
>       """Supplemental SHN_* constants for EM_PARISC."""
> -    SHN_PARISC_ANSI_COMMON = 0xff00
> -    SHN_PARISC_HUGE_COMMON = 0xff01
> +_register_elf_h(ShnMIPS, prefix='SHN_MIPS_', parent=Shn)
> +_register_elf_h(ShnPARISC, prefix='SHN_PARISC_', parent=Shn)
> +_register_elf_h(Shn, skip='SHN_LORESERVE SHN_HIRESERVE'.split(), ranges=True)
>   
> -class Sht(_OpenIntEnum):
> +class Sht(_TypedConstant):
>       """ELF section types.  Type of SHT_* values."""
> -    SHT_NULL = 0
> -    SHT_PROGBITS = 1
> -    SHT_SYMTAB = 2
> -    SHT_STRTAB = 3
> -    SHT_RELA = 4
> -    SHT_HASH = 5
> -    SHT_DYNAMIC = 6
> -    SHT_NOTE = 7
> -    SHT_NOBITS = 8
> -    SHT_REL = 9
> -    SHT_SHLIB = 10
> -    SHT_DYNSYM = 11
> -    SHT_INIT_ARRAY = 14
> -    SHT_FINI_ARRAY = 15
> -    SHT_PREINIT_ARRAY = 16
> -    SHT_GROUP = 17
> -    SHT_SYMTAB_SHNDX = 18
> -    SHT_RELR = 19
> -    SHT_GNU_ATTRIBUTES = 0x6ffffff5
> -    SHT_GNU_HASH = 0x6ffffff6
> -    SHT_GNU_LIBLIST = 0x6ffffff7
> -    SHT_CHECKSUM = 0x6ffffff8
> -    SHT_SUNW_move = 0x6ffffffa
> -    SHT_SUNW_COMDAT = 0x6ffffffb
> -    SHT_SUNW_syminfo = 0x6ffffffc
> -    SHT_GNU_verdef = 0x6ffffffd
> -    SHT_GNU_verneed = 0x6ffffffe
> -    SHT_GNU_versym = 0x6fffffff
> -
> -class ShtALPHA(enum.Enum):
> +    prefix = 'SHT_'
> +class ShtALPHA(Sht):
>       """Supplemental SHT_* constants for EM_ALPHA."""
> -    SHT_ALPHA_DEBUG = 0x70000001
> -    SHT_ALPHA_REGINFO = 0x70000002
> -
> -class ShtARM(enum.Enum):
> +class ShtARM(Sht):
>       """Supplemental SHT_* constants for EM_ARM."""
> -    SHT_ARM_EXIDX = 0x70000001
> -    SHT_ARM_PREEMPTMAP = 0x70000002
> -    SHT_ARM_ATTRIBUTES = 0x70000003
> -
> -class ShtCSKY(enum.Enum):
> +class ShtCSKY(Sht):
>       """Supplemental SHT_* constants for EM_CSKY."""
> -    SHT_CSKY_ATTRIBUTES = 0x70000001
> -
> -class ShtIA_64(enum.Enum):
> +class ShtIA_64(Sht):
>       """Supplemental SHT_* constants for EM_IA_64."""
> -    SHT_IA_64_EXT = 0x70000000
> -    SHT_IA_64_UNWIND = 0x70000001
> -
> -class ShtMIPS(enum.Enum):
> +class ShtMIPS(Sht):
>       """Supplemental SHT_* constants for EM_MIPS."""
> -    SHT_MIPS_LIBLIST = 0x70000000
> -    SHT_MIPS_MSYM = 0x70000001
> -    SHT_MIPS_CONFLICT = 0x70000002
> -    SHT_MIPS_GPTAB = 0x70000003
> -    SHT_MIPS_UCODE = 0x70000004
> -    SHT_MIPS_DEBUG = 0x70000005
> -    SHT_MIPS_REGINFO = 0x70000006
> -    SHT_MIPS_PACKAGE = 0x70000007
> -    SHT_MIPS_PACKSYM = 0x70000008
> -    SHT_MIPS_RELD = 0x70000009
> -    SHT_MIPS_IFACE = 0x7000000b
> -    SHT_MIPS_CONTENT = 0x7000000c
> -    SHT_MIPS_OPTIONS = 0x7000000d
> -    SHT_MIPS_SHDR = 0x70000010
> -    SHT_MIPS_FDESC = 0x70000011
> -    SHT_MIPS_EXTSYM = 0x70000012
> -    SHT_MIPS_DENSE = 0x70000013
> -    SHT_MIPS_PDESC = 0x70000014
> -    SHT_MIPS_LOCSYM = 0x70000015
> -    SHT_MIPS_AUXSYM = 0x70000016
> -    SHT_MIPS_OPTSYM = 0x70000017
> -    SHT_MIPS_LOCSTR = 0x70000018
> -    SHT_MIPS_LINE = 0x70000019
> -    SHT_MIPS_RFDESC = 0x7000001a
> -    SHT_MIPS_DELTASYM = 0x7000001b
> -    SHT_MIPS_DELTAINST = 0x7000001c
> -    SHT_MIPS_DELTACLASS = 0x7000001d
> -    SHT_MIPS_DWARF = 0x7000001e
> -    SHT_MIPS_DELTADECL = 0x7000001f
> -    SHT_MIPS_SYMBOL_LIB = 0x70000020
> -    SHT_MIPS_EVENTS = 0x70000021
> -    SHT_MIPS_TRANSLATE = 0x70000022
> -    SHT_MIPS_PIXIE = 0x70000023
> -    SHT_MIPS_XLATE = 0x70000024
> -    SHT_MIPS_XLATE_DEBUG = 0x70000025
> -    SHT_MIPS_WHIRL = 0x70000026
> -    SHT_MIPS_EH_REGION = 0x70000027
> -    SHT_MIPS_XLATE_OLD = 0x70000028
> -    SHT_MIPS_PDR_EXCEPTION = 0x70000029
> -    SHT_MIPS_XHASH = 0x7000002b
> -
> -class ShtPARISC(enum.Enum):
> +class ShtPARISC(Sht):
>       """Supplemental SHT_* constants for EM_PARISC."""
> -    SHT_PARISC_EXT = 0x70000000
> -    SHT_PARISC_UNWIND = 0x70000001
> -    SHT_PARISC_DOC = 0x70000002
> -
> -class ShtRISCV(enum.Enum):
> +class ShtRISCV(Sht):
>       """Supplemental SHT_* constants for EM_RISCV."""
> -    SHT_RISCV_ATTRIBUTES = 0x70000003
> -
> -class Pf(enum.IntFlag):
> +_register_elf_h(ShtALPHA, prefix='SHT_ALPHA_', parent=Sht)
> +_register_elf_h(ShtARM, prefix='SHT_ARM_', parent=Sht)
> +_register_elf_h(ShtCSKY, prefix='SHT_CSKY_', parent=Sht)
> +_register_elf_h(ShtIA_64, prefix='SHT_IA_64_', parent=Sht)
> +_register_elf_h(ShtMIPS, prefix='SHT_MIPS_', parent=Sht)
> +_register_elf_h(ShtPARISC, prefix='SHT_PARISC_', parent=Sht)
> +_register_elf_h(ShtRISCV, prefix='SHT_RISCV_', parent=Sht)
> +_register_elf_h(Sht, ranges=True,
> +                skip='SHT_LOSUNW SHT_HISUNW SHT_LOUSER SHT_HIUSER'.split())
> +
> +class Pf(_FlagConstant):
>       """Program header flags.  Type of Phdr.p_flags values."""
> -    PF_X = 1
> -    PF_W = 2
> -    PF_R = 4
> -
> -class PfARM(enum.IntFlag):
> +    prefix = 'PF_'
> +class PfARM(Pf):
>       """Supplemental PF_* flags for EM_ARM."""
> -    PF_ARM_SB = 0x10000000
> -    PF_ARM_PI = 0x20000000
> -    PF_ARM_ABS = 0x40000000
> -
> -class PfPARISC(enum.IntFlag):
> -    """Supplemental PF_* flags for EM_PARISC."""
> -    PF_HP_PAGE_SIZE = 0x00100000
> -    PF_HP_FAR_SHARED = 0x00200000
> -    PF_HP_NEAR_SHARED = 0x00400000
> -    PF_HP_CODE = 0x01000000
> -    PF_HP_MODIFY = 0x02000000
> -    PF_HP_LAZYSWAP = 0x04000000
> -    PF_HP_SBP = 0x08000000
> -
> -class PfIA_64(enum.IntFlag):
> +class PfHP(Pf):
> +    """Supplemental PF_* flags for HP-UX."""
> +class PfIA_64(Pf):
>       """Supplemental PF_* flags for EM_IA_64."""
> -    PF_IA_64_NORECOV = 0x80000000
> -
> -class PfMIPS(enum.IntFlag):
> +class PfMIPS(Pf):
>       """Supplemental PF_* flags for EM_MIPS."""
> -    PF_MIPS_LOCAL = 0x10000000
> -
> -class Shf(enum.IntFlag):
> +class PfPARISC(Pf):
> +    """Supplemental PF_* flags for EM_PARISC."""
> +_register_elf_h(PfARM, prefix='PF_ARM_', parent=Pf)
> +_register_elf_h(PfHP, prefix='PF_HP_', parent=Pf)
> +_register_elf_h(PfIA_64, prefix='PF_IA_64_', parent=Pf)
> +_register_elf_h(PfMIPS, prefix='PF_MIPS_', parent=Pf)
> +_register_elf_h(PfPARISC, prefix='PF_PARISC_', parent=Pf)
> +_register_elf_h(Pf, skip='PF_MASKOS PF_MASKPROC'.split())
> +
> +class Shf(_FlagConstant):
>       """Section flags.  Type of Shdr.sh_type values."""
> -    SHF_WRITE = 1 << 0
> -    SHF_ALLOC = 1 << 1
> -    SHF_EXECINSTR = 1 << 2
> -    SHF_MERGE = 1 << 4
> -    SHF_STRINGS = 1 << 5
> -    SHF_INFO_LINK = 1 << 6
> -    SHF_LINK_ORDER = 1 << 7
> -    SHF_OS_NONCONFORMING = 256
> -    SHF_GROUP = 1 << 9
> -    SHF_TLS = 1 << 10
> -    SHF_COMPRESSED = 1 << 11
> -    SHF_GNU_RETAIN = 1 << 21
> -    SHF_ORDERED = 1 << 30
> -    SHF_EXCLUDE = 1 << 31
> -
> -class ShfALPHA(enum.IntFlag):
> +    prefix = 'SHF_'
> +class ShfALPHA(Shf):
>       """Supplemental SHF_* constants for EM_ALPHA."""
> -    SHF_ALPHA_GPREL = 0x10000000
> -
> -class ShfARM(enum.IntFlag):
> +class ShfARM(Shf):
>       """Supplemental SHF_* constants for EM_ARM."""
> -    SHF_ARM_ENTRYSECT = 0x10000000
> -    SHF_ARM_COMDEF = 0x80000000
> -
> -class ShfIA_64(enum.IntFlag):
> +class ShfIA_64(Shf):
>       """Supplemental SHF_* constants for EM_IA_64."""
> -    SHF_IA_64_SHORT  = 0x10000000
> -    SHF_IA_64_NORECOV = 0x20000000
> -
> -class ShfMIPS(enum.IntFlag):
> +class ShfMIPS(Shf):
>       """Supplemental SHF_* constants for EM_MIPS."""
> -    SHF_MIPS_GPREL = 0x10000000
> -    SHF_MIPS_MERGE = 0x20000000
> -    SHF_MIPS_ADDR = 0x40000000
> -    SHF_MIPS_STRINGS = 0x80000000
> -    SHF_MIPS_NOSTRIP = 0x08000000
> -    SHF_MIPS_LOCAL = 0x04000000
> -    SHF_MIPS_NAMES = 0x02000000
> -    SHF_MIPS_NODUPE = 0x01000000
> -
> -class ShfPARISC(enum.IntFlag):
> +class ShfPARISC(Shf):
>       """Supplemental SHF_* constants for EM_PARISC."""
> -    SHF_PARISC_SHORT = 0x20000000
> -    SHF_PARISC_HUGE = 0x40000000
> -    SHF_PARISC_SBP = 0x80000000
> -
> -class Stb(_OpenIntEnum):
> +_register_elf_h(ShfALPHA, prefix='SHF_ALPHA_', parent=Shf)
> +_register_elf_h(ShfARM, prefix='SHF_ARM_', parent=Shf)
> +_register_elf_h(ShfIA_64, prefix='SHF_IA_64_', parent=Shf)
> +_register_elf_h(ShfMIPS, prefix='SHF_MIPS_', parent=Shf)
> +_register_elf_h(ShfPARISC, prefix='SHF_PARISC_', parent=Shf)
> +_register_elf_h(Shf, skip='SHF_MASKOS SHF_MASKPROC'.split())
> +
> +class Stb(_TypedConstant):
>       """ELF symbol binding type."""
> -    STB_LOCAL = 0
> -    STB_GLOBAL = 1
> -    STB_WEAK = 2
> -    STB_GNU_UNIQUE = 10
> -    STB_MIPS_SPLIT_COMMON = 13
> +    prefix = 'STB_'
> +_register_elf_h(Stb, ranges=True)
>   
> -class Stt(_OpenIntEnum):
> +class Stt(_TypedConstant):
>       """ELF symbol type."""
> -    STT_NOTYPE = 0
> -    STT_OBJECT = 1
> -    STT_FUNC = 2
> -    STT_SECTION = 3
> -    STT_FILE = 4
> -    STT_COMMON = 5
> -    STT_TLS = 6
> -    STT_GNU_IFUNC = 10
> -
> -class SttARM(enum.Enum):
> +    prefix = 'STT_'
> +class SttARM(Sht):
>       """Supplemental STT_* constants for EM_ARM."""
> -    STT_ARM_TFUNC = 13
> -    STT_ARM_16BIT = 15
> -
> -class SttPARISC(enum.Enum):
> +class SttPARISC(Sht):
>       """Supplemental STT_* constants for EM_PARISC."""
> -    STT_HP_OPAQUE = 11
> -    STT_HP_STUB = 12
> -    STT_PARISC_MILLICODE = 13
> -
> -class SttSPARC(enum.Enum):
> +class SttSPARC(Sht):
>       """Supplemental STT_* constants for EM_SPARC."""
>       STT_SPARC_REGISTER = 13
> -
> -class SttX86_64(enum.Enum):
> +class SttX86_64(Sht):
>       """Supplemental STT_* constants for EM_X86_64."""
> -    SHT_X86_64_UNWIND = 0x70000001
> +_register_elf_h(SttARM, prefix='STT_ARM_', parent=Stt)
> +_register_elf_h(SttPARISC, prefix='STT_PARISC_', parent=Stt)
> +_register_elf_h(SttSPARC, prefix='STT_SPARC_', parent=Stt)
> +_register_elf_h(Stt, ranges=True)
> +
>   
> -class Pt(_OpenIntEnum):
> +class Pt(_TypedConstant):
>       """ELF program header types.  Type of Phdr.p_type."""
> -    PT_NULL = 0
> -    PT_LOAD = 1
> -    PT_DYNAMIC = 2
> -    PT_INTERP = 3
> -    PT_NOTE = 4
> -    PT_SHLIB = 5
> -    PT_PHDR = 6
> -    PT_TLS = 7
> -    PT_NUM = 8
> -    PT_GNU_EH_FRAME = 0x6474e550
> -    PT_GNU_STACK = 0x6474e551
> -    PT_GNU_RELRO = 0x6474e552
> -    PT_GNU_PROPERTY = 0x6474e553
> -    PT_SUNWBSS = 0x6ffffffa
> -    PT_SUNWSTACK = 0x6ffffffb
> -
> -class PtAARCH64(enum.Enum):
> +    prefix = 'PT_'
> +class PtAARCH64(Pt):
>       """Supplemental PT_* constants for EM_AARCH64."""
> -    PT_AARCH64_MEMTAG_MTE = 0x70000002
> -
> -class PtARM(enum.Enum):
> +class PtARM(Pt):
>       """Supplemental PT_* constants for EM_ARM."""
> -    PT_ARM_EXIDX = 0x70000001
> -
> -class PtIA_64(enum.Enum):
> +class PtHP(Pt):
> +    """Supplemental PT_* constants for HP-U."""
> +class PtIA_64(Pt):
>       """Supplemental PT_* constants for EM_IA_64."""
> -    PT_IA_64_HP_OPT_ANOT = 0x60000012
> -    PT_IA_64_HP_HSL_ANOT = 0x60000013
> -    PT_IA_64_HP_STACK = 0x60000014
> -    PT_IA_64_ARCHEXT = 0x70000000
> -    PT_IA_64_UNWIND = 0x70000001
> -
> -class PtMIPS(enum.Enum):
> +class PtMIPS(Pt):
>       """Supplemental PT_* constants for EM_MIPS."""
> -    PT_MIPS_REGINFO = 0x70000000
> -    PT_MIPS_RTPROC = 0x70000001
> -    PT_MIPS_OPTIONS = 0x70000002
> -    PT_MIPS_ABIFLAGS = 0x70000003
> -
> -class PtPARISC(enum.Enum):
> +class PtPARISC(Pt):
>       """Supplemental PT_* constants for EM_PARISC."""
> -    PT_HP_TLS = 0x60000000
> -    PT_HP_CORE_NONE = 0x60000001
> -    PT_HP_CORE_VERSION = 0x60000002
> -    PT_HP_CORE_KERNEL = 0x60000003
> -    PT_HP_CORE_COMM = 0x60000004
> -    PT_HP_CORE_PROC = 0x60000005
> -    PT_HP_CORE_LOADABLE = 0x60000006
> -    PT_HP_CORE_STACK = 0x60000007
> -    PT_HP_CORE_SHM = 0x60000008
> -    PT_HP_CORE_MMF = 0x60000009
> -    PT_HP_PARALLEL = 0x60000010
> -    PT_HP_FASTBIND = 0x60000011
> -    PT_HP_OPT_ANNOT = 0x60000012
> -    PT_HP_HSL_ANNOT = 0x60000013
> -    PT_HP_STACK = 0x60000014
> -    PT_PARISC_ARCHEXT = 0x70000000
> -    PT_PARISC_UNWIND = 0x70000001
> -
> -class PtRISCV(enum.Enum):
> +class PtRISCV(Pt):
>       """Supplemental PT_* constants for EM_RISCV."""
> -    PT_RISCV_ATTRIBUTES = 0x70000003
> -
> -class Dt(_OpenIntEnum):
> +_register_elf_h(PtAARCH64, prefix='PT_AARCH64_', parent=Pt)
> +_register_elf_h(PtARM, prefix='PT_ARM_', parent=Pt)
> +_register_elf_h(PtHP, prefix='PT_HP_', parent=Pt)
> +_register_elf_h(PtIA_64, prefix='PT_IA_64_', parent=Pt)
> +_register_elf_h(PtMIPS, prefix='PT_MIPS_', parent=Pt)
> +_register_elf_h(PtPARISC, prefix='PT_PARISC_', parent=Pt)
> +_register_elf_h(PtRISCV, prefix='PT_RISCV_', parent=Pt)
> +_register_elf_h(Pt, skip='PT_LOSUNW PT_HISUNW'.split(), ranges=True)
> +
> +class Dt(_TypedConstant):
>       """ELF dynamic segment tags.  Type of Dyn.d_val."""
> -    DT_NULL = 0
> -    DT_NEEDED = 1
> -    DT_PLTRELSZ = 2
> -    DT_PLTGOT = 3
> -    DT_HASH = 4
> -    DT_STRTAB = 5
> -    DT_SYMTAB = 6
> -    DT_RELA = 7
> -    DT_RELASZ = 8
> -    DT_RELAENT = 9
> -    DT_STRSZ = 10
> -    DT_SYMENT = 11
> -    DT_INIT = 12
> -    DT_FINI = 13
> -    DT_SONAME = 14
> -    DT_RPATH = 15
> -    DT_SYMBOLIC = 16
> -    DT_REL = 17
> -    DT_RELSZ = 18
> -    DT_RELENT = 19
> -    DT_PLTREL = 20
> -    DT_DEBUG = 21
> -    DT_TEXTREL = 22
> -    DT_JMPREL = 23
> -    DT_BIND_NOW = 24
> -    DT_INIT_ARRAY = 25
> -    DT_FINI_ARRAY = 26
> -    DT_INIT_ARRAYSZ = 27
> -    DT_FINI_ARRAYSZ = 28
> -    DT_RUNPATH = 29
> -    DT_FLAGS = 30
> -    DT_PREINIT_ARRAY = 32
> -    DT_PREINIT_ARRAYSZ = 33
> -    DT_SYMTAB_SHNDX = 34
> -    DT_RELRSZ = 35
> -    DT_RELR = 36
> -    DT_RELRENT = 37
> -    DT_GNU_PRELINKED = 0x6ffffdf5
> -    DT_GNU_CONFLICTSZ = 0x6ffffdf6
> -    DT_GNU_LIBLISTSZ = 0x6ffffdf7
> -    DT_CHECKSUM = 0x6ffffdf8
> -    DT_PLTPADSZ = 0x6ffffdf9
> -    DT_MOVEENT = 0x6ffffdfa
> -    DT_MOVESZ = 0x6ffffdfb
> -    DT_FEATURE_1 = 0x6ffffdfc
> -    DT_POSFLAG_1 = 0x6ffffdfd
> -    DT_SYMINSZ = 0x6ffffdfe
> -    DT_SYMINENT = 0x6ffffdff
> -    DT_GNU_HASH = 0x6ffffef5
> -    DT_TLSDESC_PLT = 0x6ffffef6
> -    DT_TLSDESC_GOT = 0x6ffffef7
> -    DT_GNU_CONFLICT = 0x6ffffef8
> -    DT_GNU_LIBLIST = 0x6ffffef9
> -    DT_CONFIG = 0x6ffffefa
> -    DT_DEPAUDIT = 0x6ffffefb
> -    DT_AUDIT = 0x6ffffefc
> -    DT_PLTPAD = 0x6ffffefd
> -    DT_MOVETAB = 0x6ffffefe
> -    DT_SYMINFO = 0x6ffffeff
> -    DT_VERSYM = 0x6ffffff0
> -    DT_RELACOUNT = 0x6ffffff9
> -    DT_RELCOUNT = 0x6ffffffa
> -    DT_FLAGS_1 = 0x6ffffffb
> -    DT_VERDEF = 0x6ffffffc
> -    DT_VERDEFNUM = 0x6ffffffd
> -    DT_VERNEED = 0x6ffffffe
> -    DT_VERNEEDNUM = 0x6fffffff
> -    DT_AUXILIARY = 0x7ffffffd
> -    DT_FILTER = 0x7fffffff
> -
> -class DtAARCH64(enum.Enum):
> +    prefix = 'DT_'
> +class DtAARCH64(Dt):
>       """Supplemental DT_* constants for EM_AARCH64."""
> -    DT_AARCH64_BTI_PLT = 0x70000001
> -    DT_AARCH64_PAC_PLT = 0x70000003
> -    DT_AARCH64_VARIANT_PCS = 0x70000005
> -
> -class DtALPHA(enum.Enum):
> +class DtALPHA(Dt):
>       """Supplemental DT_* constants for EM_ALPHA."""
> -    DT_ALPHA_PLTRO = 0x70000000
> -
> -class DtALTERA_NIOS2(enum.Enum):
> +class DtALTERA_NIOS2(Dt):
>       """Supplemental DT_* constants for EM_ALTERA_NIOS2."""
> -    DT_NIOS2_GP = 0x70000002
> -
> -class DtIA_64(enum.Enum):
> +class DtIA_64(Dt):
>       """Supplemental DT_* constants for EM_IA_64."""
> -    DT_IA_64_PLT_RESERVE = 0x70000000
> -
> -class DtMIPS(enum.Enum):
> +class DtMIPS(Dt):
>       """Supplemental DT_* constants for EM_MIPS."""
> -    DT_MIPS_RLD_VERSION = 0x70000001
> -    DT_MIPS_TIME_STAMP = 0x70000002
> -    DT_MIPS_ICHECKSUM = 0x70000003
> -    DT_MIPS_IVERSION = 0x70000004
> -    DT_MIPS_FLAGS = 0x70000005
> -    DT_MIPS_BASE_ADDRESS = 0x70000006
> -    DT_MIPS_MSYM = 0x70000007
> -    DT_MIPS_CONFLICT = 0x70000008
> -    DT_MIPS_LIBLIST = 0x70000009
> -    DT_MIPS_LOCAL_GOTNO = 0x7000000a
> -    DT_MIPS_CONFLICTNO = 0x7000000b
> -    DT_MIPS_LIBLISTNO = 0x70000010
> -    DT_MIPS_SYMTABNO = 0x70000011
> -    DT_MIPS_UNREFEXTNO = 0x70000012
> -    DT_MIPS_GOTSYM = 0x70000013
> -    DT_MIPS_HIPAGENO = 0x70000014
> -    DT_MIPS_RLD_MAP = 0x70000016
> -    DT_MIPS_DELTA_CLASS = 0x70000017
> -    DT_MIPS_DELTA_CLASS_NO = 0x70000018
> -    DT_MIPS_DELTA_INSTANCE = 0x70000019
> -    DT_MIPS_DELTA_INSTANCE_NO = 0x7000001a
> -    DT_MIPS_DELTA_RELOC = 0x7000001b
> -    DT_MIPS_DELTA_RELOC_NO = 0x7000001c
> -    DT_MIPS_DELTA_SYM = 0x7000001d
> -    DT_MIPS_DELTA_SYM_NO = 0x7000001e
> -    DT_MIPS_DELTA_CLASSSYM = 0x70000020
> -    DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021
> -    DT_MIPS_CXX_FLAGS = 0x70000022
> -    DT_MIPS_PIXIE_INIT = 0x70000023
> -    DT_MIPS_SYMBOL_LIB = 0x70000024
> -    DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025
> -    DT_MIPS_LOCAL_GOTIDX = 0x70000026
> -    DT_MIPS_HIDDEN_GOTIDX = 0x70000027
> -    DT_MIPS_PROTECTED_GOTIDX = 0x70000028
> -    DT_MIPS_OPTIONS = 0x70000029
> -    DT_MIPS_INTERFACE = 0x7000002a
> -    DT_MIPS_DYNSTR_ALIGN = 0x7000002b
> -    DT_MIPS_INTERFACE_SIZE = 0x7000002c
> -    DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002d
> -    DT_MIPS_PERF_SUFFIX = 0x7000002e
> -    DT_MIPS_COMPACT_SIZE = 0x7000002f
> -    DT_MIPS_GP_VALUE = 0x70000030
> -    DT_MIPS_AUX_DYNAMIC = 0x70000031
> -    DT_MIPS_PLTGOT = 0x70000032
> -    DT_MIPS_RWPLT = 0x70000034
> -    DT_MIPS_RLD_MAP_REL = 0x70000035
> -    DT_MIPS_XHASH = 0x70000036
> -
> -class DtPPC(enum.Enum):
> +class DtPPC(Dt):
>       """Supplemental DT_* constants for EM_PPC."""
> -    DT_PPC_GOT = 0x70000000
> -    DT_PPC_OPT = 0x70000001
> -
> -class DtPPC64(enum.Enum):
> +class DtPPC64(Dt):
>       """Supplemental DT_* constants for EM_PPC64."""
> -    DT_PPC64_GLINK = 0x70000000
> -    DT_PPC64_OPD = 0x70000001
> -    DT_PPC64_OPDSZ = 0x70000002
> -    DT_PPC64_OPT = 0x70000003
> -
> -class DtRISCV(enum.Enum):
> +class DtRISCV(Dt):
>       """Supplemental DT_* constants for EM_RISCV."""
> -    DT_RISCV_VARIANT_CC = 0x70000001
> -
> -class DtSPARC(enum.Enum):
> +class DtSPARC(Dt):
>       """Supplemental DT_* constants for EM_SPARC."""
> -    DT_SPARC_REGISTER = 0x70000001
> +_dt_skip = '''
> +DT_ENCODING DT_PROCNUM
> +DT_ADDRRNGLO DT_ADDRRNGHI DT_ADDRNUM
> +DT_VALRNGLO DT_VALRNGHI DT_VALNUM
> +DT_VERSIONTAGNUM DT_EXTRANUM
> +DT_AARCH64_NUM
> +DT_ALPHA_NUM
> +DT_IA_64_NUM
> +DT_MIPS_NUM
> +DT_PPC_NUM
> +DT_PPC64_NUM
> +DT_SPARC_NUM
> +'''.strip().split()
> +_register_elf_h(DtAARCH64, prefix='DT_AARCH64_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(DtALPHA, prefix='DT_ALPHA_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(DtALTERA_NIOS2, prefix='DT_NIOS2_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(DtIA_64, prefix='DT_IA_64_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(DtMIPS, prefix='DT_MIPS_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(DtPPC, prefix='DT_PPC_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(DtPPC64, prefix='DT_PPC64_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(DtRISCV, prefix='DT_RISCV_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(DtSPARC, prefix='DT_SPARC_', skip=_dt_skip, parent=Dt)
> +_register_elf_h(Dt, skip=_dt_skip, ranges=True)
> +del _dt_skip
> +
> +# Constant extraction is complete.
> +del _register_elf_h
> +del _elf_h
>   
>   class StInfo:
>       """ELF symbol binding and type.  Type of the Sym.st_info field."""

      reply	other threads:[~2022-09-21 18:05 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-14 14:59 [PATCH v2 0/3] Parse <elf.h> in the glibcelf Python module Florian Weimer
2022-09-14 14:59 ` [PATCH v2 1/3] scripts: Extract glibcpp.py from check-obsolete-constructs.py Florian Weimer
2022-09-14 15:00 ` [PATCH v2 2/3] scripts: Enhance glibcpp to do basic macro processing Florian Weimer
2022-09-21 17:08   ` Siddhesh Poyarekar
2022-09-14 15:00 ` [PATCH v2 3/3] elf: Extract glibcelf constants from <elf.h> Florian Weimer
2022-09-21 18:05   ` Siddhesh Poyarekar [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=42d147a4-24b6-5295-0b03-316e591a9ef8@gotplt.org \
    --to=siddhesh@gotplt.org \
    --cc=fweimer@redhat.com \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).