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, AsFFI};
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 90 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 90 : f.debug_struct("TLS")
20 90 : .field("callbacks", &self.callbacks())
21 90 : .field("addressof_index", &self.addressof_index())
22 90 : .field("addressof_callbacks", &self.addressof_callbacks())
23 90 : .field("sizeof_zero_fill", &self.sizeof_zero_fill())
24 90 : .field("characteristics", &self.characteristics())
25 90 : .finish()
26 90 : }
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 90 : pub fn callbacks(&self) -> Vec<u64> {
37 90 : Vec::from(self.ptr.callbacks().as_slice())
38 90 : }
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 90 : pub fn addressof_index(&self) -> u64 {
43 90 : self.ptr.addressof_index()
44 90 : }
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 90 : pub fn addressof_callbacks(&self) -> u64 {
53 90 : self.ptr.addressof_callbacks()
54 90 : }
55 :
56 : /// Size in bytes of the zero to be *padded* after the data specified by [`TLS::data_template`]
57 90 : pub fn sizeof_zero_fill(&self) -> u32 {
58 90 : self.ptr.sizeof_zero_fill()
59 90 : }
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 90 : pub fn characteristics(&self) -> u32 {
68 90 : self.ptr.characteristics()
69 90 : }
70 :
71 : /// The initial content used to initialize TLS data.
72 90 : pub fn data_template(&self) -> &[u8] {
73 90 : to_slice!(self.ptr.data_template());
74 90 : }
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 90 : pub fn addressof_raw_data(&self) -> (u64, u64) {
85 90 : let vec = Vec::from(self.ptr.addressof_raw_data().as_slice());
86 90 : if vec.len() != 2 {
87 0 : return (0, 0);
88 90 : }
89 90 : (vec[0], vec[1])
90 90 : }
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.pin_mut().set_callbacks(callbacks.as_ptr(), callbacks.len());
111 0 : }
112 0 : self
113 0 : }
114 :
115 0 : pub fn set_addressof_index(&mut self, addr: u64) -> &mut Self {
116 0 : self.ptr.pin_mut().set_addressof_index(addr);
117 0 : self
118 0 : }
119 :
120 0 : pub fn set_addressof_callback(&mut self, addr: u64) -> &mut Self {
121 0 : self.ptr.pin_mut().set_addressof_callback(addr);
122 0 : self
123 0 : }
124 :
125 0 : pub fn set_sizeof_zero_fill(&mut self, size: u32) -> &mut Self {
126 0 : self.ptr.pin_mut().set_sizeof_zero_fill(size);
127 0 : self
128 0 : }
129 :
130 0 : pub fn set_characteristics(&mut self, characteristics: u32) -> &mut Self {
131 0 : self.ptr.pin_mut().set_characteristics(characteristics);
132 0 : self
133 0 : }
134 :
135 0 : pub fn set_data_template(&mut self, data: &[u8]) -> &mut Self {
136 0 : unsafe {
137 0 : self.ptr.pin_mut().set_data_template(data.as_ptr(), data.len());
138 0 : }
139 0 : self
140 0 : }
141 : }
142 :
143 :
144 : impl<'a> FromFFI<ffi::PE_TLS> for TLS<'a> {
145 90 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_TLS>) -> Self {
146 90 : TLS {
147 90 : ptr,
148 90 : _owner: PhantomData,
149 90 : }
150 90 : }
151 : }
152 :
153 : impl<'a> AsFFI<ffi::PE_TLS> for TLS<'a> {
154 0 : fn as_ffi(&self) -> &ffi::PE_TLS {
155 0 : self.ptr.as_ref().unwrap()
156 0 : }
157 :
158 0 : fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::PE_TLS> {
159 0 : self.ptr.pin_mut()
160 0 : }
161 : }
|