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 : }
145 0 : }
146 : }
147 :
148 : impl From<Cpu> for u16 {
149 0 : fn from(value: Cpu) -> u16 {
150 0 : match value {
151 0 : Cpu::INTEL_8080 => 0x00000000,
152 0 : Cpu::INTEL_8086 => 0x00000001,
153 0 : Cpu::INTEL_80286 => 0x00000002,
154 0 : Cpu::INTEL_80386 => 0x00000003,
155 0 : Cpu::INTEL_80486 => 0x00000004,
156 0 : Cpu::PENTIUM => 0x00000005,
157 0 : Cpu::PENTIUMPRO => 0x00000006,
158 0 : Cpu::PENTIUM3 => 0x00000007,
159 0 : Cpu::MIPS => 0x00000010,
160 0 : Cpu::MIPS16 => 0x00000011,
161 0 : Cpu::MIPS32 => 0x00000012,
162 0 : Cpu::MIPS64 => 0x00000013,
163 0 : Cpu::MIPSI => 0x00000014,
164 0 : Cpu::MIPSII => 0x00000015,
165 0 : Cpu::MIPSIII => 0x00000016,
166 0 : Cpu::MIPSIV => 0x00000017,
167 0 : Cpu::MIPSV => 0x00000018,
168 0 : Cpu::M68000 => 0x00000020,
169 0 : Cpu::M68010 => 0x00000021,
170 0 : Cpu::M68020 => 0x00000022,
171 0 : Cpu::M68030 => 0x00000023,
172 0 : Cpu::M68040 => 0x00000024,
173 0 : Cpu::ALPHA => 0x00000030,
174 0 : Cpu::ALPHA_21164 => 0x00000031,
175 0 : Cpu::ALPHA_21164A => 0x00000032,
176 0 : Cpu::ALPHA_21264 => 0x00000033,
177 0 : Cpu::ALPHA_21364 => 0x00000034,
178 0 : Cpu::PPC601 => 0x00000040,
179 0 : Cpu::PPC603 => 0x00000041,
180 0 : Cpu::PPC604 => 0x00000042,
181 0 : Cpu::PPC620 => 0x00000043,
182 0 : Cpu::PPCFP => 0x00000044,
183 0 : Cpu::PPCBE => 0x00000045,
184 0 : Cpu::SH3 => 0x00000050,
185 0 : Cpu::SH3E => 0x00000051,
186 0 : Cpu::SH3DSP => 0x00000052,
187 0 : Cpu::SH4 => 0x00000053,
188 0 : Cpu::SHMEDIA => 0x00000054,
189 0 : Cpu::ARM3 => 0x00000060,
190 0 : Cpu::ARM4 => 0x00000061,
191 0 : Cpu::ARM4T => 0x00000062,
192 0 : Cpu::ARM5 => 0x00000063,
193 0 : Cpu::ARM5T => 0x00000064,
194 0 : Cpu::ARM6 => 0x00000065,
195 0 : Cpu::ARM_XMAC => 0x00000066,
196 0 : Cpu::ARM_WMMX => 0x00000067,
197 0 : Cpu::ARM7 => 0x00000068,
198 0 : Cpu::OMNI => 0x00000070,
199 0 : Cpu::IA64 => 0x00000080,
200 0 : Cpu::IA64_2 => 0x00000081,
201 0 : Cpu::CEE => 0x00000090,
202 0 : Cpu::AM33 => 0x000000a0,
203 0 : Cpu::M32R => 0x000000b0,
204 0 : Cpu::TRICORE => 0x000000c0,
205 0 : Cpu::X64 => 0x000000d0,
206 0 : Cpu::EBC => 0x000000e0,
207 0 : Cpu::THUMB => 0x000000f0,
208 0 : Cpu::ARMNT => 0x000000f4,
209 0 : Cpu::ARM64 => 0x000000f6,
210 0 : Cpu::HYBRID_X86ARM64 => 0x000000f7,
211 0 : Cpu::ARM64EC => 0x000000f8,
212 0 : Cpu::ARM64X => 0x000000f9,
213 0 : Cpu::D3D11_SHADER => 0x00000100,
214 0 : Cpu::UNKNOWN(value) => value,
215 :
216 : }
217 0 : }
218 : }
219 :
220 :
221 : #[allow(non_camel_case_types)]
222 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
223 : pub enum Lang {
224 : C,
225 : CPP,
226 : FORTRAN,
227 : MASM,
228 : PASCAL_LANG,
229 : BASIC,
230 : COBOL,
231 : LINK,
232 : CVTRES,
233 : CVTPGD,
234 : CSHARP,
235 : VB,
236 : ILASM,
237 : JAVA,
238 : JSCRIPT,
239 : MSIL,
240 : HLSL,
241 : OBJC,
242 : OBJCPP,
243 : SWIFT,
244 : ALIASOBJ,
245 : RUST,
246 : GO,
247 : UNKNOWN(u8),
248 : }
249 :
250 : impl From<u8> for Lang {
251 0 : fn from(value: u8) -> Self {
252 0 : match value {
253 0 : 0x00000000 => Lang::C,
254 0 : 0x00000001 => Lang::CPP,
255 0 : 0x00000002 => Lang::FORTRAN,
256 0 : 0x00000003 => Lang::MASM,
257 0 : 0x00000004 => Lang::PASCAL_LANG,
258 0 : 0x00000005 => Lang::BASIC,
259 0 : 0x00000006 => Lang::COBOL,
260 0 : 0x00000007 => Lang::LINK,
261 0 : 0x00000008 => Lang::CVTRES,
262 0 : 0x00000009 => Lang::CVTPGD,
263 0 : 0x0000000a => Lang::CSHARP,
264 0 : 0x0000000b => Lang::VB,
265 0 : 0x0000000c => Lang::ILASM,
266 0 : 0x0000000d => Lang::JAVA,
267 0 : 0x0000000e => Lang::JSCRIPT,
268 0 : 0x0000000f => Lang::MSIL,
269 0 : 0x00000010 => Lang::HLSL,
270 0 : 0x00000011 => Lang::OBJC,
271 0 : 0x00000012 => Lang::OBJCPP,
272 0 : 0x00000013 => Lang::SWIFT,
273 0 : 0x00000014 => Lang::ALIASOBJ,
274 0 : 0x00000015 => Lang::RUST,
275 0 : 0x00000016 => Lang::GO,
276 0 : _ => Lang::UNKNOWN(value),
277 :
278 : }
279 0 : }
280 : }
281 : impl From<Lang> for u8 {
282 0 : fn from(value: Lang) -> u8 {
283 0 : match value {
284 0 : Lang::C => 0x00000000,
285 0 : Lang::CPP => 0x00000001,
286 0 : Lang::FORTRAN => 0x00000002,
287 0 : Lang::MASM => 0x00000003,
288 0 : Lang::PASCAL_LANG => 0x00000004,
289 0 : Lang::BASIC => 0x00000005,
290 0 : Lang::COBOL => 0x00000006,
291 0 : Lang::LINK => 0x00000007,
292 0 : Lang::CVTRES => 0x00000008,
293 0 : Lang::CVTPGD => 0x00000009,
294 0 : Lang::CSHARP => 0x0000000a,
295 0 : Lang::VB => 0x0000000b,
296 0 : Lang::ILASM => 0x0000000c,
297 0 : Lang::JAVA => 0x0000000d,
298 0 : Lang::JSCRIPT => 0x0000000e,
299 0 : Lang::MSIL => 0x0000000f,
300 0 : Lang::HLSL => 0x00000010,
301 0 : Lang::OBJC => 0x00000011,
302 0 : Lang::OBJCPP => 0x00000012,
303 0 : Lang::SWIFT => 0x00000013,
304 0 : Lang::ALIASOBJ => 0x00000014,
305 0 : Lang::RUST => 0x00000015,
306 0 : Lang::GO => 0x00000016,
307 0 : Lang::UNKNOWN(value) => value,
308 :
309 : }
310 0 : }
311 : }
312 :
313 :
314 : /// This class wraps build metadata represented by the codeview symbols:
315 : /// `S_COMPILE3, S_COMPILE2, S_BUILDINFO`
316 : pub struct BuildMetadata<'a> {
317 : ptr: cxx::UniquePtr<ffi::PDB_BuildMetadata>,
318 : _owner: PhantomData<&'a ()>,
319 : }
320 :
321 : impl FromFFI<ffi::PDB_BuildMetadata> for BuildMetadata<'_> {
322 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PDB_BuildMetadata>) -> Self {
323 0 : Self {
324 0 : ptr,
325 0 : _owner: PhantomData,
326 0 : }
327 0 : }
328 : }
329 :
330 : impl BuildMetadata<'_> {
331 : /// Version of the frontend (e.g. `19.36.32537`)
332 0 : pub fn frontend_version(&self) -> Version {
333 0 : Version::from_ffi(self.ptr.frontend_version())
334 0 : }
335 :
336 : /// Version of the backend (e.g. `14.36.32537`)
337 0 : pub fn backend_version(&self) -> Version {
338 0 : Version::from_ffi(self.ptr.backend_version())
339 0 : }
340 :
341 : /// Version of the *tool* as a string. For instance, `Microsoft (R) CVTRES`,
342 : /// `Microsoft (R) LINK`.
343 0 : pub fn version(&self) -> String {
344 0 : self.ptr.version().to_string()
345 0 : }
346 :
347 : /// Source language
348 0 : pub fn language(&self) -> Lang {
349 0 : Lang::from(self.ptr.language())
350 0 : }
351 :
352 : /// Target CPU
353 0 : pub fn target_cpu(&self) -> Cpu {
354 0 : Cpu::from(self.ptr.target_cpu())
355 0 : }
356 :
357 : /// Environment information represented by the `S_ENVBLOCK` symbol
358 0 : pub fn env(&self) -> Vec<String> {
359 0 : self.ptr.env().iter().map(|e| e.to_string()).collect::<Vec<String>>()
360 0 : }
361 :
362 : /// Build information represented by the `S_BUILDINFO` symbol
363 0 : pub fn build_info(&self) -> Option<BuildInfo> {
364 0 : BuildInfo::from_ffi(self.ptr.build_info())
365 0 : }
366 : }
367 :
368 : impl std::fmt::Display for BuildMetadata<'_> {
369 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
370 0 : write!(f, "{}", self.ptr.to_string())
371 0 : }
372 : }
373 :
374 :
375 : impl std::fmt::Debug for BuildMetadata<'_> {
376 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
377 0 : f.debug_struct("BuildMetadata")
378 0 : .field("frontend_version", &self.frontend_version())
379 0 : .field("backend_version", &self.backend_version())
380 0 : .field("version", &self.version())
381 0 : .field("language", &self.language())
382 0 : .field("target_cpu", &self.target_cpu())
383 0 : .field("env", &self.env())
384 0 : .field("build_info", &self.build_info())
385 0 : .finish()
386 0 : }
387 : }
388 :
389 :
390 : /// This structure represents a version for the backend or the frontend.
391 0 : #[derive(Debug)]
392 : pub struct Version {
393 : /// Major Version
394 : pub major: u16,
395 :
396 : /// Minor Version
397 : pub minor: u16,
398 :
399 : /// Build Version
400 : pub build: u16,
401 :
402 : /// Quick Fix Engineeringa version
403 : pub qfe: u16,
404 : }
405 :
406 : impl Version {
407 : #[doc(hidden)]
408 0 : pub fn from_ffi(ffi: cxx::UniquePtr<cxx::CxxVector<u16>>) -> Self {
409 0 : let vec = ffi.as_ref().unwrap();
410 0 : Self {
411 0 : major: *vec.get(0).unwrap(),
412 0 : minor: *vec.get(1).unwrap(),
413 0 : build: *vec.get(2).unwrap(),
414 0 : qfe: *vec.get(3).unwrap(),
415 0 : }
416 0 : }
417 : }
418 :
419 : /// This structure represents information wrapped by the `S_BUILDINFO`
420 : /// symbol
421 0 : #[derive(Debug)]
422 : pub struct BuildInfo {
423 : /// Working directory where the *build tool* was invoked
424 : pub cwd: String,
425 :
426 : /// 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`)
427 : pub build_tool: String,
428 :
429 : /// Source file consumed by the *build tool*
430 : pub source_file: String,
431 :
432 : /// PDB path
433 : pub pdb: String,
434 :
435 : /// Command line arguments used to invoke the *build tool*
436 : pub command_line: String,
437 : }
438 :
439 : impl BuildInfo {
440 : #[doc(hidden)]
441 0 : pub fn from_ffi(ffi: cxx::UniquePtr<cxx::CxxVector<cxx::CxxString>>) -> Option<Self> {
442 0 : let vec = ffi.as_ref().unwrap();
443 0 : if vec.is_empty() {
444 0 : return None;
445 0 : }
446 0 :
447 0 : assert_eq!(vec.len(), 5);
448 0 : Some(Self {
449 0 : cwd: vec.get(0).unwrap().to_string(),
450 0 : build_tool: vec.get(1).unwrap().to_string(),
451 0 : source_file: vec.get(2).unwrap().to_string(),
452 0 : pdb: vec.get(3).unwrap().to_string(),
453 0 : command_line: vec.get(4).unwrap().to_string(),
454 0 : })
455 0 : }
456 : }
|