1
2class CFGArchOptions(object):
3    """
4    Stores architecture-specific options and settings, as well as the detailed explanation of those options and
5    settings.
6
7    Suppose `ao` is the CFGArchOptions object, and there is an option called `ret_jumpkind_heuristics`, you can access
8    it by `ao.ret_jumpkind_heuristics` and set its value via `ao.ret_jumpkind_heuristics = True`
9
10    :ivar dict OPTIONS: A dict of all default options for different architectures.
11    :ivar archinfo.Arch arch: The architecture object.
12    :ivar dict _options: Values of all CFG options that are specific to the current architecture.
13    """
14
15    # option name: (option value type, default option value)
16
17    OPTIONS = {
18        'ARMEL': {
19            # Whether to perform some simple heuristics to detect returns that are incorrectly labeled as boring
20            # branches by VEX
21            'ret_jumpkind_heuristics': (bool, True),
22            # Whether to switch between ARM mode and THUMB mode when VEX fails to decode a block
23            'switch_mode_on_nodecode': (bool, False),
24        },
25        'ARMHF': {
26            'ret_jumpkind_heuristics': (bool, True),
27            'switch_mode_on_nodecode': (bool, False),
28        },
29        'ARMCortexM': {
30            'ret_jumpkind_heuristics': (bool, True),
31            'switch_mode_on_nodecode': (bool, False),
32        },
33    }
34
35    arch = None
36    _options = {}
37
38    def __init__(self, arch, **options):
39        """
40        Constructor.
41
42        :param archinfo.Arch arch: The architecture instance.
43        :param dict options: Architecture-specific options, which will be used to initialize this object.
44        """
45
46        self.arch = arch
47
48        self._options = {}
49
50        if self.arch.name in self.OPTIONS:
51            for k, (_, value) in self.OPTIONS[self.arch.name].items():
52                self._options[k] = value
53
54        # make sure options are valid
55        for k in options.keys():
56            if self.arch.name not in self.OPTIONS or k not in self.OPTIONS[self.arch.name]:
57                raise KeyError('Architecture %s does not support arch-specific option "%s".' % (self.arch.name, k))
58
59        for k, v in options.items():
60            self.__setattr__(k, v)
61
62    def __getattr__(self, option_name):
63        if option_name in self._options:
64            return self._options[option_name]
65
66        return self.__getattribute__(option_name)
67
68    def __setattr__(self, option_name, option_value):
69        if option_name in self._options:
70
71            # type checking
72            sort = self.OPTIONS[self.arch.name][option_name][0]
73
74            if sort is None or isinstance(option_value, sort):
75                self._options[option_name] = option_value
76            else:
77                raise ValueError('Value for option "%s" must be of type %s' % (option_name, sort))
78
79        else:
80            super(CFGArchOptions, self).__setattr__(option_name, option_value )
81