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::{into_optional, AsFFI, FromFFI};
6 : use crate::to_slice;
7 : use std::marker::PhantomData;
8 :
9 : use crate::pe::DataDirectory;
10 : use crate::pe::Section;
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 117 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 117 : f.debug_struct("TLS")
20 117 : .field("callbacks", &self.callbacks())
21 117 : .field("addressof_index", &self.addressof_index())
22 117 : .field("addressof_callbacks", &self.addressof_callbacks())
23 117 : .field("sizeof_zero_fill", &self.sizeof_zero_fill())
24 117 : .field("characteristics", &self.characteristics())
25 117 : .finish()
26 117 : }
27 : }
28 :
29 : impl TLS<'_> {
30 0 : pub fn new() -> TLS<'static> {
31 0 : TLS::from_ffi(lief_ffi::PE_TLS::create())
32 0 : }
33 : /// List of callbacks associated with the current TLS
34 : ///
35 : /// These functions are called before any other functions.
36 117 : pub fn callbacks(&self) -> Vec<u64> {
37 117 : Vec::from(self.ptr.callbacks().as_slice())
38 117 : }
39 :
40 : /// The location to receive the TLS index assigned by the loader.
41 : /// This location should be located in a writable section like `.data`
42 117 : pub fn addressof_index(&self) -> u64 {
43 117 : self.ptr.addressof_index()
44 117 : }
45 :
46 : /// Pointer to an array of TLS callback functions.
47 : ///
48 : /// The array is null-terminated, so if there is no callback function this field points to 4
49 : /// bytes set to zero.
50 : ///
51 : /// See [`TLS::callbacks`]
52 117 : pub fn addressof_callbacks(&self) -> u64 {
53 117 : self.ptr.addressof_callbacks()
54 117 : }
55 :
56 : /// Size in bytes of the zero to be *padded* after the data specified by [`TLS::data_template`]
57 117 : pub fn sizeof_zero_fill(&self) -> u32 {
58 117 : self.ptr.sizeof_zero_fill()
59 117 : }
60 :
61 : /// The four bits `[23:20]` describe alignment info.
62 : ///
63 : /// Possible values are those defined as `IMAGE_SCN_ALIGN_*`, which are also used to describe
64 : /// alignment of section in object files.
65 : ///
66 : /// The other 28 bits are reserved for future use.
67 117 : pub fn characteristics(&self) -> u32 {
68 117 : self.ptr.characteristics()
69 117 : }
70 :
71 : /// The initial content used to initialize TLS data.
72 117 : pub fn data_template(&self) -> &[u8] {
73 117 : to_slice!(self.ptr.data_template());
74 117 : }
75 :
76 : /// Range of addresses where the [`TLS::data_template`] is located.
77 : ///
78 : /// The template is a block of data that is used to initialize TLS data.
79 : /// The system copies all of this data each time a thread is created, so it
80 : /// must not be corrupted.
81 : ///
82 : /// These addresses are not RVA. It is addresses for which there
83 : /// should be a rebase relocation in the `.reloc` section.
84 117 : pub fn addressof_raw_data(&self) -> (u64, u64) {
85 117 : let vec = Vec::from(self.ptr.addressof_raw_data().as_slice());
86 117 : if vec.len() != 2 {
87 0 : return (0, 0);
88 117 : }
89 117 : (vec[0], vec[1])
90 117 : }
91 :
92 : /// The section where the TLS structure is located
93 0 : pub fn section(&self) -> Option<Section<'_>> {
94 0 : into_optional(self.ptr.section())
95 0 : }
96 :
97 : /// The data directory describing the TLS
98 0 : pub fn directory(&self) -> Option<DataDirectory<'_>> {
99 0 : into_optional(self.ptr.data_directory())
100 0 : }
101 :
102 : /// Add an address to the list of callbacks
103 0 : pub fn add_callback(&mut self, addr: u64) -> &mut Self {
104 0 : self.ptr.pin_mut().add_callback(addr);
105 0 : self
106 0 : }
107 :
108 0 : pub fn set_callbacks(&mut self, callbacks: &[u64]) -> &mut Self {
109 0 : unsafe {
110 0 : self.ptr
111 0 : .pin_mut()
112 0 : .set_callbacks(callbacks.as_ptr(), callbacks.len());
113 0 : }
114 0 : self
115 0 : }
116 :
117 0 : pub fn set_addressof_index(&mut self, addr: u64) -> &mut Self {
118 0 : self.ptr.pin_mut().set_addressof_index(addr);
119 0 : self
120 0 : }
121 :
122 0 : pub fn set_addressof_callback(&mut self, addr: u64) -> &mut Self {
123 0 : self.ptr.pin_mut().set_addressof_callback(addr);
124 0 : self
125 0 : }
126 :
127 0 : pub fn set_sizeof_zero_fill(&mut self, size: u32) -> &mut Self {
128 0 : self.ptr.pin_mut().set_sizeof_zero_fill(size);
129 0 : self
130 0 : }
131 :
132 0 : pub fn set_characteristics(&mut self, characteristics: u32) -> &mut Self {
133 0 : self.ptr.pin_mut().set_characteristics(characteristics);
134 0 : self
135 0 : }
136 :
137 0 : pub fn set_data_template(&mut self, data: &[u8]) -> &mut Self {
138 0 : unsafe {
139 0 : self.ptr
140 0 : .pin_mut()
141 0 : .set_data_template(data.as_ptr(), data.len());
142 0 : }
143 0 : self
144 0 : }
145 : }
146 :
147 : impl<'a> FromFFI<ffi::PE_TLS> for TLS<'a> {
148 117 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_TLS>) -> Self {
149 117 : TLS {
150 117 : ptr,
151 117 : _owner: PhantomData,
152 117 : }
153 117 : }
154 : }
155 :
156 : impl<'a> AsFFI<ffi::PE_TLS> for TLS<'a> {
157 0 : fn as_ffi(&self) -> &ffi::PE_TLS {
158 0 : self.ptr.as_ref().unwrap()
159 0 : }
160 :
161 0 : fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::PE_TLS> {
162 0 : self.ptr.pin_mut()
163 0 : }
164 : }
|