Handles the complexities of UNWIND_INFO structure: * variable number of UWIND_CODEs * optional ExceptionHandler and FunctionEntry fields
| 1808 | |
| 1809 | |
| 1810 | class UnwindInfo(StructureWithBitfields): |
| 1811 | """Handles the complexities of UNWIND_INFO structure: |
| 1812 | * variable number of UWIND_CODEs |
| 1813 | * optional ExceptionHandler and FunctionEntry fields |
| 1814 | """ |
| 1815 | |
| 1816 | def __init__(self, file_offset=0): |
| 1817 | super(UnwindInfo, self).__init__( |
| 1818 | ( |
| 1819 | "UNWIND_INFO", |
| 1820 | ( |
| 1821 | "B:3,Version", |
| 1822 | "B:5,Flags", |
| 1823 | "B,SizeOfProlog", |
| 1824 | "B,CountOfCodes", |
| 1825 | "B:4,FrameRegister", |
| 1826 | "B:4,FrameOffset", |
| 1827 | ), |
| 1828 | ), |
| 1829 | file_offset=file_offset, |
| 1830 | ) |
| 1831 | self._full_size = super(UnwindInfo, self).sizeof() |
| 1832 | self._opt_field_name = None |
| 1833 | self._code_info = StructureWithBitfields( |
| 1834 | ("UNWIND_CODE", ("B,CodeOffset", "B:4,UnwindOp", "B:4,OpInfo")), |
| 1835 | file_offset=0, |
| 1836 | ) |
| 1837 | self._chained_entry = None |
| 1838 | self._finished_unpacking = False |
| 1839 | |
| 1840 | def unpack_in_stages(self, data): |
| 1841 | """Unpacks the UNWIND_INFO "in two calls", with the first call establishing |
| 1842 | a full size of the structure and the second, performing the actual unpacking. |
| 1843 | """ |
| 1844 | if self._finished_unpacking: |
| 1845 | return None |
| 1846 | |
| 1847 | super(UnwindInfo, self).__unpack__(data) |
| 1848 | codes_cnt_max = (self.CountOfCodes + 1) & ~1 |
| 1849 | hdlr_offset = ( |
| 1850 | super(UnwindInfo, self).sizeof() + codes_cnt_max * self._code_info.sizeof() |
| 1851 | ) |
| 1852 | self._full_size = hdlr_offset + ( |
| 1853 | 0 if self.Flags == 0 else STRUCT_SIZEOF_TYPES["I"] |
| 1854 | ) |
| 1855 | |
| 1856 | if len(data) < self._full_size: |
| 1857 | return None |
| 1858 | |
| 1859 | if self.Version != 1 and self.Version != 2: |
| 1860 | return "Unsupported version of UNWIND_INFO at " + hex(self.__file_offset__) |
| 1861 | |
| 1862 | self.UnwindCodes = [] |
| 1863 | ro = super(UnwindInfo, self).sizeof() |
| 1864 | codes_left = self.CountOfCodes |
| 1865 | while codes_left > 0: |
| 1866 | self._code_info.__unpack__(data[ro : ro + self._code_info.sizeof()]) |
| 1867 | ucode = PrologEpilogOpsFactory.create(self._code_info) |
no outgoing calls
no test coverage detected