[docs]defregister_object(self,obj):ifnotsuper().register_object(obj):returnFalse# The PE TLS header says to write its index into a given addressifhasattr(obj,"tls_index_address"):obj.memory.pack_word(AT.from_lva(obj.tls_index_address,obj).to_rva(),obj.tls_module_id)returnTrue
@propertydef_thread_cls(self):returnPETLSObject
[docs]classPETLSObject(TLSObject):""" This class is used when parsing the Thread Local Storage of a PE binary. It represents both the TLS array and the TLS data area for a specific thread. In memory the ``PETLSObj`` is laid out as follows:: +----------------------+---------------------------------------+ | TLS array | TLS data area | +----------------------+---------------------------------------+ A more detailed description of the TLS array and TLS data areas is given below. **TLS array** The TLS array is an array of addresses that points into the TLS data area. In memory it is laid out as follows:: +-----------+-----------+-----+-----------+ | address | address | ... | address | +-----------+-----------+-----+-----------+ | index = 0 | index = 1 | | index = n | +-----------+-----------+-----+-----------+ The size of each address is architecture independent (e.g. on X86 it is 4 bytes). The number of addresses in the TLS array is equal to the number of modules that contain TLS data. At load time (i.e. in the ``finalize`` method), each module is assigned an index into the TLS array. The address of this module's TLS data area is then stored at this location in the array. **TLS data area** The TLS data area directly follows the TLS array and contains the actual TLS data for each module. In memory it is laid out as follows:: +----------+-----------+----------+-----------+-----+ | TLS data | zero fill | TLS data | zero fill | ... | +----------+-----------+----------+-----------+-----+ | module a | module b | ... | +---------------------------------------------------+ The size of each module's TLS data area is variable and can be found in the module's ``tls_data_size`` property. The same applies to the zero fill. At load time (i.e in the ``finalize`` method), the initial TLS data values are copied into the TLS data area. Because a TLS index is also assigned to each module, we can access a module's TLS data area using this index into the TLS array to get the start address of the TLS data. """
[docs]defget_tls_data_addr(self,tls_idx):""" Get the start address of a module's TLS data area via the module's TLS index. From the PE/COFF spec: The code uses the TLS index and the TLS array location (multiplying the index by the word size and using it as an offset into the array) to get the address of the TLS data area for the given program and module. """if0<=tls_idx<self.used_modules:returnself.memory.unpack_word(tls_idx*self.arch.bytes)else:raiseIndexError("TLS index out of range")
@propertydefmax_addr(self):returnself.mapped_base+self.data_start+self.used_data-1# PE is MUCH simpler in terms of what's the pointer to the thread data. Add these properties for compatibility.@propertydefthread_pointer(self):returnself.mapped_base@propertydefuser_thread_pointer(self):returnself.mapped_base