Line data Source code
1 : //! This module represents the PE's Thread Local Storage (TLS)
2 :
3 : use lief_ffi as ffi;
4 :
5 : use crate::common::{FromFFI, into_optional};
6 : use crate::to_slice;
7 : use std::marker::PhantomData;
8 :
9 : use crate::pe::Section;
10 : use crate::pe::DataDirectory;
11 :
12 : pub struct TLS<'a> {
13 : ptr: cxx::UniquePtr<ffi::PE_TLS>,
14 : _owner: PhantomData<&'a ffi::PE_Binary>,
15 : }
16 :
17 : impl std::fmt::Debug for TLS<'_> {
18 40 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 40 : f.debug_struct("TLS")
20 40 : .field("callbacks", &self.callbacks())
21 40 : .field("addressof_index", &self.addressof_index())
22 40 : .field("addressof_callbacks", &self.addressof_callbacks())
23 40 : .field("sizeof_zero_fill", &self.sizeof_zero_fill())
24 40 : .field("characteristics", &self.characteristics())
25 40 : .finish()
26 40 : }
27 : }
28 :
29 : impl TLS<'_> {
30 : /// List of callbacks associated with the current TLS
31 : ///
32 : /// These functions are called before any other functions.
33 40 : pub fn callbacks(&self) -> Vec<u64> {
34 40 : Vec::from(self.ptr.callbacks().as_slice())
35 40 : }
36 : /// The location to receive the TLS index assigned by the loader
37 40 : pub fn addressof_index(&self) -> u64 {
38 40 : self.ptr.addressof_index()
39 40 : }
40 :
41 : /// Pointer to an array of TLS callback functions.
42 : ///
43 : /// The array is null-terminated, so if there is no callback function this field points to 4
44 : /// bytes set to zero.
45 : ///
46 : /// See [`TLS::callbacks`]
47 40 : pub fn addressof_callbacks(&self) -> u64 {
48 40 : self.ptr.addressof_callbacks()
49 40 : }
50 :
51 : /// Size in bytes of the zero to be *padded* after the data specified by [`TLS::data_template`]
52 40 : pub fn sizeof_zero_fill(&self) -> u64 {
53 40 : self.ptr.sizeof_zero_fill()
54 40 : }
55 :
56 : /// The four bits `[23:20]` describe alignment info.
57 : ///
58 : /// Possible values are those defined as `IMAGE_SCN_ALIGN_*`, which are also used to describe
59 : /// alignment of section in object files.
60 : ///
61 : /// The other 28 bits are reserved for future use.
62 40 : pub fn characteristics(&self) -> u64 {
63 40 : self.ptr.characteristics()
64 40 : }
65 :
66 : /// The initial content used to initialize TLS data.
67 40 : pub fn data_template(&self) -> &[u8] {
68 40 : to_slice!(self.ptr.data_template());
69 40 : }
70 :
71 : /// Range of addresses where the [`TLS::data_template`] is located.
72 40 : pub fn addressof_raw_data(&self) -> (u64, u64) {
73 40 : let vec = Vec::from(self.ptr.addressof_raw_data().as_slice());
74 40 : if vec.len() != 2 {
75 0 : return (0, 0);
76 40 : }
77 40 : (vec[0], vec[1])
78 40 : }
79 :
80 : /// The section where the TLS structure is located
81 0 : pub fn section(&self) -> Option<Section> {
82 0 : into_optional(self.ptr.section())
83 0 : }
84 :
85 : /// The data directory describing the TLS
86 0 : pub fn directory(&self) -> Option<DataDirectory> {
87 0 : into_optional(self.ptr.data_directory())
88 0 : }
89 : }
90 :
91 : impl<'a> FromFFI<ffi::PE_TLS> for TLS<'a> {
92 40 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_TLS>) -> Self {
93 40 : TLS {
94 40 : ptr,
95 40 : _owner: PhantomData,
96 40 : }
97 40 : }
98 : }
|