Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use std::marker::PhantomData;
4 :
5 : use crate::common::FromFFI;
6 :
7 : #[allow(non_camel_case_types)]
8 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
9 : pub enum Cpu {
10 : INTEL_8080,
11 : INTEL_8086,
12 : INTEL_80286,
13 : INTEL_80386,
14 : INTEL_80486,
15 : PENTIUM,
16 : PENTIUMPRO,
17 : PENTIUM3,
18 : MIPS,
19 : MIPS16,
20 : MIPS32,
21 : MIPS64,
22 : MIPSI,
23 : MIPSII,
24 : MIPSIII,
25 : MIPSIV,
26 : MIPSV,
27 : M68000,
28 : M68010,
29 : M68020,
30 : M68030,
31 : M68040,
32 : ALPHA,
33 : ALPHA_21164,
34 : ALPHA_21164A,
35 : ALPHA_21264,
36 : ALPHA_21364,
37 : PPC601,
38 : PPC603,
39 : PPC604,
40 : PPC620,
41 : PPCFP,
42 : PPCBE,
43 : SH3,
44 : SH3E,
45 : SH3DSP,
46 : SH4,
47 : SHMEDIA,
48 : ARM3,
49 : ARM4,
50 : ARM4T,
51 : ARM5,
52 : ARM5T,
53 : ARM6,
54 : ARM_XMAC,
55 : ARM_WMMX,
56 : ARM7,
57 : OMNI,
58 : IA64,
59 : IA64_2,
60 : CEE,
61 : AM33,
62 : M32R,
63 : TRICORE,
64 : X64,
65 : EBC,
66 : THUMB,
67 : ARMNT,
68 : ARM64,
69 : HYBRID_X86ARM64,
70 : ARM64EC,
71 : ARM64X,
72 : D3D11_SHADER,
73 : UNKNOWN(u16),
74 : }
75 :
76 : impl From<u16> for Cpu {
77 0 : fn from(value: u16) -> Self {
78 0 : match value {
79 0 : 0x00000000 => Cpu::INTEL_8080,
80 0 : 0x00000001 => Cpu::INTEL_8086,
81 0 : 0x00000002 => Cpu::INTEL_80286,
82 0 : 0x00000003 => Cpu::INTEL_80386,
83 0 : 0x00000004 => Cpu::INTEL_80486,
84 0 : 0x00000005 => Cpu::PENTIUM,
85 0 : 0x00000006 => Cpu::PENTIUMPRO,
86 0 : 0x00000007 => Cpu::PENTIUM3,
87 0 : 0x00000010 => Cpu::MIPS,
88 0 : 0x00000011 => Cpu::MIPS16,
89 0 : 0x00000012 => Cpu::MIPS32,
90 0 : 0x00000013 => Cpu::MIPS64,
91 0 : 0x00000014 => Cpu::MIPSI,
92 0 : 0x00000015 => Cpu::MIPSII,
93 0 : 0x00000016 => Cpu::MIPSIII,
94 0 : 0x00000017 => Cpu::MIPSIV,
95 0 : 0x00000018 => Cpu::MIPSV,
96 0 : 0x00000020 => Cpu::M68000,
97 0 : 0x00000021 => Cpu::M68010,
98 0 : 0x00000022 => Cpu::M68020,
99 0 : 0x00000023 => Cpu::M68030,
100 0 : 0x00000024 => Cpu::M68040,
101 0 : 0x00000030 => Cpu::ALPHA,
102 0 : 0x00000031 => Cpu::ALPHA_21164,
103 0 : 0x00000032 => Cpu::ALPHA_21164A,
104 0 : 0x00000033 => Cpu::ALPHA_21264,
105 0 : 0x00000034 => Cpu::ALPHA_21364,
106 0 : 0x00000040 => Cpu::PPC601,
107 0 : 0x00000041 => Cpu::PPC603,
108 0 : 0x00000042 => Cpu::PPC604,
109 0 : 0x00000043 => Cpu::PPC620,
110 0 : 0x00000044 => Cpu::PPCFP,
111 0 : 0x00000045 => Cpu::PPCBE,
112 0 : 0x00000050 => Cpu::SH3,
113 0 : 0x00000051 => Cpu::SH3E,
114 0 : 0x00000052 => Cpu::SH3DSP,
115 0 : 0x00000053 => Cpu::SH4,
116 0 : 0x00000054 => Cpu::SHMEDIA,
117 0 : 0x00000060 => Cpu::ARM3,
118 0 : 0x00000061 => Cpu::ARM4,
119 0 : 0x00000062 => Cpu::ARM4T,
120 0 : 0x00000063 => Cpu::ARM5,
121 0 : 0x00000064 => Cpu::ARM5T,
122 0 : 0x00000065 => Cpu::ARM6,
123 0 : 0x00000066 => Cpu::ARM_XMAC,
124 0 : 0x00000067 => Cpu::ARM_WMMX,
125 0 : 0x00000068 => Cpu::ARM7,
126 0 : 0x00000070 => Cpu::OMNI,
127 0 : 0x00000080 => Cpu::IA64,
128 0 : 0x00000081 => Cpu::IA64_2,
129 0 : 0x00000090 => Cpu::CEE,
130 0 : 0x000000a0 => Cpu::AM33,
131 0 : 0x000000b0 => Cpu::M32R,
132 0 : 0x000000c0 => Cpu::TRICORE,
133 0 : 0x000000d0 => Cpu::X64,
134 0 : 0x000000e0 => Cpu::EBC,
135 0 : 0x000000f0 => Cpu::THUMB,
136 0 : 0x000000f4 => Cpu::ARMNT,
137 0 : 0x000000f6 => Cpu::ARM64,
138 0 : 0x000000f7 => Cpu::HYBRID_X86ARM64,
139 0 : 0x000000f8 => Cpu::ARM64EC,
140 0 : 0x000000f9 => Cpu::ARM64X,
141 0 : 0x00000100 => Cpu::D3D11_SHADER,
142 0 : _ => Cpu::UNKNOWN(value),
143 : }
144 0 : }
145 : }
146 :
147 : impl From<Cpu> for u16 {
148 0 : fn from(value: Cpu) -> u16 {
149 0 : match value {
150 0 : Cpu::INTEL_8080 => 0x00000000,
151 0 : Cpu::INTEL_8086 => 0x00000001,
152 0 : Cpu::INTEL_80286 => 0x00000002,
153 0 : Cpu::INTEL_80386 => 0x00000003,
154 0 : Cpu::INTEL_80486 => 0x00000004,
155 0 : Cpu::PENTIUM => 0x00000005,
156 0 : Cpu::PENTIUMPRO => 0x00000006,
157 0 : Cpu::PENTIUM3 => 0x00000007,
158 0 : Cpu::MIPS => 0x00000010,
159 0 : Cpu::MIPS16 => 0x00000011,
160 0 : Cpu::MIPS32 => 0x00000012,
161 0 : Cpu::MIPS64 => 0x00000013,
162 0 : Cpu::MIPSI => 0x00000014,
163 0 : Cpu::MIPSII => 0x00000015,
164 0 : Cpu::MIPSIII => 0x00000016,
165 0 : Cpu::MIPSIV => 0x00000017,
166 0 : Cpu::MIPSV => 0x00000018,
167 0 : Cpu::M68000 => 0x00000020,
168 0 : Cpu::M68010 => 0x00000021,
169 0 : Cpu::M68020 => 0x00000022,
170 0 : Cpu::M68030 => 0x00000023,
171 0 : Cpu::M68040 => 0x00000024,
172 0 : Cpu::ALPHA => 0x00000030,
173 0 : Cpu::ALPHA_21164 => 0x00000031,
174 0 : Cpu::ALPHA_21164A => 0x00000032,
175 0 : Cpu::ALPHA_21264 => 0x00000033,
176 0 : Cpu::ALPHA_21364 => 0x00000034,
177 0 : Cpu::PPC601 => 0x00000040,
178 0 : Cpu::PPC603 => 0x00000041,
179 0 : Cpu::PPC604 => 0x00000042,
180 0 : Cpu::PPC620 => 0x00000043,
181 0 : Cpu::PPCFP => 0x00000044,
182 0 : Cpu::PPCBE => 0x00000045,
183 0 : Cpu::SH3 => 0x00000050,
184 0 : Cpu::SH3E => 0x00000051,
185 0 : Cpu::SH3DSP => 0x00000052,
186 0 : Cpu::SH4 => 0x00000053,
187 0 : Cpu::SHMEDIA => 0x00000054,
188 0 : Cpu::ARM3 => 0x00000060,
189 0 : Cpu::ARM4 => 0x00000061,
190 0 : Cpu::ARM4T => 0x00000062,
191 0 : Cpu::ARM5 => 0x00000063,
192 0 : Cpu::ARM5T => 0x00000064,
193 0 : Cpu::ARM6 => 0x00000065,
194 0 : Cpu::ARM_XMAC => 0x00000066,
195 0 : Cpu::ARM_WMMX => 0x00000067,
196 0 : Cpu::ARM7 => 0x00000068,
197 0 : Cpu::OMNI => 0x00000070,
198 0 : Cpu::IA64 => 0x00000080,
199 0 : Cpu::IA64_2 => 0x00000081,
200 0 : Cpu::CEE => 0x00000090,
201 0 : Cpu::AM33 => 0x000000a0,
202 0 : Cpu::M32R => 0x000000b0,
203 0 : Cpu::TRICORE => 0x000000c0,
204 0 : Cpu::X64 => 0x000000d0,
205 0 : Cpu::EBC => 0x000000e0,
206 0 : Cpu::THUMB => 0x000000f0,
207 0 : Cpu::ARMNT => 0x000000f4,
208 0 : Cpu::ARM64 => 0x000000f6,
209 0 : Cpu::HYBRID_X86ARM64 => 0x000000f7,
210 0 : Cpu::ARM64EC => 0x000000f8,
211 0 : Cpu::ARM64X => 0x000000f9,
212 0 : Cpu::D3D11_SHADER => 0x00000100,
213 0 : Cpu::UNKNOWN(value) => value,
214 : }
215 0 : }
216 : }
217 :
218 : #[allow(non_camel_case_types)]
219 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
220 : pub enum Lang {
221 : C,
222 : CPP,
223 : FORTRAN,
224 : MASM,
225 : PASCAL_LANG,
226 : BASIC,
227 : COBOL,
228 : LINK,
229 : CVTRES,
230 : CVTPGD,
231 : CSHARP,
232 : VB,
233 : ILASM,
234 : JAVA,
235 : JSCRIPT,
236 : MSIL,
237 : HLSL,
238 : OBJC,
239 : OBJCPP,
240 : SWIFT,
241 : ALIASOBJ,
242 : RUST,
243 : GO,
244 : UNKNOWN(u8),
245 : }
246 :
247 : impl From<u8> for Lang {
248 0 : fn from(value: u8) -> Self {
249 0 : match value {
250 0 : 0x00000000 => Lang::C,
251 0 : 0x00000001 => Lang::CPP,
252 0 : 0x00000002 => Lang::FORTRAN,
253 0 : 0x00000003 => Lang::MASM,
254 0 : 0x00000004 => Lang::PASCAL_LANG,
255 0 : 0x00000005 => Lang::BASIC,
256 0 : 0x00000006 => Lang::COBOL,
257 0 : 0x00000007 => Lang::LINK,
258 0 : 0x00000008 => Lang::CVTRES,
259 0 : 0x00000009 => Lang::CVTPGD,
260 0 : 0x0000000a => Lang::CSHARP,
261 0 : 0x0000000b => Lang::VB,
262 0 : 0x0000000c => Lang::ILASM,
263 0 : 0x0000000d => Lang::JAVA,
264 0 : 0x0000000e => Lang::JSCRIPT,
265 0 : 0x0000000f => Lang::MSIL,
266 0 : 0x00000010 => Lang::HLSL,
267 0 : 0x00000011 => Lang::OBJC,
268 0 : 0x00000012 => Lang::OBJCPP,
269 0 : 0x00000013 => Lang::SWIFT,
270 0 : 0x00000014 => Lang::ALIASOBJ,
271 0 : 0x00000015 => Lang::RUST,
272 0 : 0x00000016 => Lang::GO,
273 0 : _ => Lang::UNKNOWN(value),
274 : }
275 0 : }
276 : }
277 : impl From<Lang> for u8 {
278 0 : fn from(value: Lang) -> u8 {
279 0 : match value {
280 0 : Lang::C => 0x00000000,
281 0 : Lang::CPP => 0x00000001,
282 0 : Lang::FORTRAN => 0x00000002,
283 0 : Lang::MASM => 0x00000003,
284 0 : Lang::PASCAL_LANG => 0x00000004,
285 0 : Lang::BASIC => 0x00000005,
286 0 : Lang::COBOL => 0x00000006,
287 0 : Lang::LINK => 0x00000007,
288 0 : Lang::CVTRES => 0x00000008,
289 0 : Lang::CVTPGD => 0x00000009,
290 0 : Lang::CSHARP => 0x0000000a,
291 0 : Lang::VB => 0x0000000b,
292 0 : Lang::ILASM => 0x0000000c,
293 0 : Lang::JAVA => 0x0000000d,
294 0 : Lang::JSCRIPT => 0x0000000e,
295 0 : Lang::MSIL => 0x0000000f,
296 0 : Lang::HLSL => 0x00000010,
297 0 : Lang::OBJC => 0x00000011,
298 0 : Lang::OBJCPP => 0x00000012,
299 0 : Lang::SWIFT => 0x00000013,
300 0 : Lang::ALIASOBJ => 0x00000014,
301 0 : Lang::RUST => 0x00000015,
302 0 : Lang::GO => 0x00000016,
303 0 : Lang::UNKNOWN(value) => value,
304 : }
305 0 : }
306 : }
307 :
308 : /// This class wraps build metadata represented by the codeview symbols:
309 : /// `S_COMPILE3, S_COMPILE2, S_BUILDINFO`
310 : pub struct BuildMetadata<'a> {
311 : ptr: cxx::UniquePtr<ffi::PDB_BuildMetadata>,
312 : _owner: PhantomData<&'a ()>,
313 : }
314 :
315 : impl FromFFI<ffi::PDB_BuildMetadata> for BuildMetadata<'_> {
316 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PDB_BuildMetadata>) -> Self {
317 0 : Self {
318 0 : ptr,
319 0 : _owner: PhantomData,
320 0 : }
321 0 : }
322 : }
323 :
324 : impl BuildMetadata<'_> {
325 : /// Version of the frontend (e.g. `19.36.32537`)
326 0 : pub fn frontend_version(&self) -> Version {
327 0 : Version::from_ffi(self.ptr.frontend_version())
328 0 : }
329 :
330 : /// Version of the backend (e.g. `14.36.32537`)
331 0 : pub fn backend_version(&self) -> Version {
332 0 : Version::from_ffi(self.ptr.backend_version())
333 0 : }
334 :
335 : /// Version of the *tool* as a string. For instance, `Microsoft (R) CVTRES`,
336 : /// `Microsoft (R) LINK`.
337 0 : pub fn version(&self) -> String {
338 0 : self.ptr.version().to_string()
339 0 : }
340 :
341 : /// Source language
342 0 : pub fn language(&self) -> Lang {
343 0 : Lang::from(self.ptr.language())
344 0 : }
345 :
346 : /// Target CPU
347 0 : pub fn target_cpu(&self) -> Cpu {
348 0 : Cpu::from(self.ptr.target_cpu())
349 0 : }
350 :
351 : /// Environment information represented by the `S_ENVBLOCK` symbol
352 0 : pub fn env(&self) -> Vec<String> {
353 0 : self.ptr
354 0 : .env()
355 0 : .iter()
356 0 : .map(|e| e.to_string())
357 0 : .collect::<Vec<String>>()
358 0 : }
359 :
360 : /// Build information represented by the `S_BUILDINFO` symbol
361 0 : pub fn build_info(&self) -> Option<BuildInfo> {
362 0 : BuildInfo::from_ffi(self.ptr.build_info())
363 0 : }
364 : }
365 :
366 : impl std::fmt::Display for BuildMetadata<'_> {
367 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
368 0 : write!(f, "{}", self.ptr.to_string())
369 0 : }
370 : }
371 :
372 : impl std::fmt::Debug for BuildMetadata<'_> {
373 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
374 0 : f.debug_struct("BuildMetadata")
375 0 : .field("frontend_version", &self.frontend_version())
376 0 : .field("backend_version", &self.backend_version())
377 0 : .field("version", &self.version())
378 0 : .field("language", &self.language())
379 0 : .field("target_cpu", &self.target_cpu())
380 0 : .field("env", &self.env())
381 0 : .field("build_info", &self.build_info())
382 0 : .finish()
383 0 : }
384 : }
385 :
386 : /// This structure represents a version for the backend or the frontend.
387 0 : #[derive(Debug)]
388 : pub struct Version {
389 : /// Major Version
390 : pub major: u16,
391 :
392 : /// Minor Version
393 : pub minor: u16,
394 :
395 : /// Build Version
396 : pub build: u16,
397 :
398 : /// Quick Fix Engineeringa version
399 : pub qfe: u16,
400 : }
401 :
402 : impl Version {
403 : #[doc(hidden)]
404 0 : pub fn from_ffi(ffi: cxx::UniquePtr<cxx::CxxVector<u16>>) -> Self {
405 0 : let vec = ffi.as_ref().unwrap();
406 0 : Self {
407 0 : major: *vec.get(0).unwrap(),
408 0 : minor: *vec.get(1).unwrap(),
409 0 : build: *vec.get(2).unwrap(),
410 0 : qfe: *vec.get(3).unwrap(),
411 0 : }
412 0 : }
413 : }
414 :
415 : /// This structure represents information wrapped by the `S_BUILDINFO`
416 : /// symbol
417 0 : #[derive(Debug)]
418 : pub struct BuildInfo {
419 : /// Working directory where the *build tool* was invoked
420 : pub cwd: String,
421 :
422 : /// Path to the build tool (e.g. `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\bin\HostX64\x64\CL.exe`)
423 : pub build_tool: String,
424 :
425 : /// Source file consumed by the *build tool*
426 : pub source_file: String,
427 :
428 : /// PDB path
429 : pub pdb: String,
430 :
431 : /// Command line arguments used to invoke the *build tool*
432 : pub command_line: String,
433 : }
434 :
435 : impl BuildInfo {
436 : #[doc(hidden)]
437 0 : pub fn from_ffi(ffi: cxx::UniquePtr<cxx::CxxVector<cxx::CxxString>>) -> Option<Self> {
438 0 : let vec = ffi.as_ref().unwrap();
439 0 : if vec.is_empty() {
440 0 : return None;
441 0 : }
442 0 :
443 0 : assert_eq!(vec.len(), 5);
444 0 : Some(Self {
445 0 : cwd: vec.get(0).unwrap().to_string(),
446 0 : build_tool: vec.get(1).unwrap().to_string(),
447 0 : source_file: vec.get(2).unwrap().to_string(),
448 0 : pdb: vec.get(3).unwrap().to_string(),
449 0 : command_line: vec.get(4).unwrap().to_string(),
450 0 : })
451 0 : }
452 : }
|