ROSE 2.15.0
Loading...
Searching...
No Matches
DispatcherCil.h
1#ifndef ROSE_BinaryAnalysis_InstructionSemantics_DispatcherCil_H
2#define ROSE_BinaryAnalysis_InstructionSemantics_DispatcherCil_H
3
4#include <featureTests.h>
5#ifdef ROSE_ENABLE_BINARY_ANALYSIS
6
7#include <Rose/BinaryAnalysis/BasicTypes.h>
8#include <Rose/BinaryAnalysis/Architecture/Base.h>
9#include <Rose/BinaryAnalysis/InstructionSemantics/BaseSemantics.h>
10#include <Rose/BinaryAnalysis/InstructionSemantics/BaseSemantics/Dispatcher.h>
11#include <Rose/BinaryAnalysis/InstructionEnumsCil.h>
12
13#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
14#include <boost/serialization/access.hpp>
15#include <boost/serialization/base_object.hpp>
16#include <boost/serialization/export.hpp>
17#include <boost/serialization/split_member.hpp>
18#endif
19
20// DQ (6/22/2026): It was suggested that we add these to the top of the file.
21#include <map>
22#include <set>
23#include <string>
24#include <vector>
25
26
27namespace Rose {
28namespace BinaryAnalysis {
29namespace InstructionSemantics {
30
32typedef boost::shared_ptr<class DispatcherCil> DispatcherCilPtr;
33
35 {
36 public:
39
42
43#if 0
44 public:
51 RegisterDescriptor REG_D[8], REG_A[8], REG_FP[8], REG_PC, REG_CCR, REG_CCR_C, REG_CCR_V, REG_CCR_Z, REG_CCR_N, REG_CCR_X;
52 RegisterDescriptor REG_MACSR_SU, REG_MACSR_FI, REG_MACSR_N, REG_MACSR_Z, REG_MACSR_V, REG_MACSR_C, REG_MAC_MASK;
53 RegisterDescriptor REG_MACEXT0, REG_MACEXT1, REG_MACEXT2, REG_MACEXT3, REG_SSP, REG_SR_S, REG_SR, REG_VBR;
54 // Floating-point condition code bits
55 RegisterDescriptor REG_FPCC_NAN, REG_FPCC_I, REG_FPCC_Z, REG_FPCC_N;
56 // Floating-point status register exception bits
57 RegisterDescriptor REG_EXC_BSUN, REG_EXC_OPERR, REG_EXC_OVFL, REG_EXC_UNFL, REG_EXC_DZ, REG_EXC_INAN;
58 RegisterDescriptor REG_EXC_IDE, REG_EXC_INEX;
59 // Floating-point status register accrued exception bits
60 RegisterDescriptor REG_AEXC_IOP, REG_AEXC_OVFL, REG_AEXC_UNFL, REG_AEXC_DZ, REG_AEXC_INEX;
62#else
63 public:
64 RegisterDescriptor REG_PC;
65#endif
66
67#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
68 private:
69 friend class boost::serialization::access;
70
71 template<class S>
72 void save(S &s, const unsigned /*version*/) const
73 {
74 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
75 };
76
77 template<class S>
78 void load(S &s, const unsigned /*version*/)
79 {
80 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
81#if 0
82 regcache_init();
83 iproc_init();
84 memory_init();
85#else
88#endif
89 }
90
91 BOOST_SERIALIZATION_SPLIT_MEMBER();
92#endif
93
94 private:
95 DispatcherCil(); // used only by boost::serialization
96
97 protected:
98 DispatcherCil(const Architecture::BaseConstPtr&); // prototypical constructor
100
101#if 0
105 void regcache_init(const Architecture::Base::ConstPtr&);
106#endif
107
112
117
118 public:
120
125
128
131
134
136 virtual RegisterDescriptor stackPointerRegister() const override;
137 virtual BaseSemantics::SValuePtr read(SgAsmExpression*, size_t value_nbits, size_t addr_nbits=0) override;
138
139 int iprocKey(SgAsmInstruction *insn_) const override;
141
144 const BaseSemantics::SValuePtr &b, SgAsmType *bType);
145
148
154 void updateFpsrExcOvfl(const BaseSemantics::SValuePtr &intermediate, SgAsmType *valueType, SgAsmType *rounding, SgAsmType *dstType);
155
163 void updateFpsrExcUnfl(const BaseSemantics::SValuePtr &intermediate, SgAsmType *valueType, SgAsmType *rounding, SgAsmType *dstType);
164
167
170
173
176
177 // DQ (6/7/2026): Adding support for type analysis...
179 {
180 public:
182 using TypeToken = uint32_t;
183 using TypeSet = std::set<TypeToken>;
184
185 private:
186 std::map<const void*, TypeSet> possibleTypes_;
187
188
189 public:
190 enum Nullness
191 {
192 NullnessUnknown,
193 DefinitelyNull,
194 DefinitelyNonNull,
195 MaybeNull
196 };
197
198 enum CilBranchCompareKind
199 {
200 BranchEq,
201 BranchGe,
202 BranchGt,
203 BranchLe,
204 BranchLt
205 };
206
207 // DQ (6/28/2026): Adding more support for assignability of types.
208 enum Assignability
209 {
210 AssignabilityNo,
211 AssignabilityYes,
212 AssignabilityUnknown
213 };
214#if 0
215 struct TypeDescriptor
216 {
217 uint32_t metadataToken = 0; // CIL metadata token for TypeDef/TypeRef/TypeSpec
218 std::string name; // Optional friendly/debug name
219 bool isValueType = false;
220 bool isReferenceType = true;
221 bool isInterface = false;
222 bool isArray = false;
223 size_t valueBitWidth = 0; // Useful for unbox.any, conv, etc.; 0 if unknown
224
225 TypeDescriptor() = default;
226
227 explicit TypeDescriptor(uint32_t token) : metadataToken(token) {}
228
229 TypeDescriptor(uint32_t token, const std::string &name) : metadataToken(token), name(name) {}
230
231 bool isValid() const
232 {
233 return metadataToken != 0;
234 }
235 };
236#else
238 {
239 // The token can be known even when the metadata record has not been resolved.
240 uint32_t metadataToken = 0;
241
242 // True only when the metadata provider actually resolved the token and filled
243 // in the type-category/layout information below.
244 bool metadataKnown = false;
245
246 std::string name;
247
248 // These are meaningful only when metadataKnown is true.
249 bool isValueType = false;
250 bool isReferenceType = false;
251 bool isInterface = false;
252 bool isArray = false;
253
254 // Optional hierarchy metadata. These are deliberately separate from
255 // metadataKnown because a provider can know a type's category/name without
256 // having loaded its inheritance/interface closure. A zero base token means
257 // "no base type" only when baseTypeKnown is true.
258 bool baseTypeKnown = false;
259 uint32_t baseTypeToken = 0;
260 bool interfaceTypesKnown = false;
261 std::set<uint32_t> interfaceTypeTokens;
262
263 // Storage size for value types, in bits. Zero means unknown layout.
264 size_t valueBitWidth = 0;
265
266 TypeDescriptor() = default;
267
268 // Token is known, but type metadata/layout is not known.
269 explicit TypeDescriptor(uint32_t token)
270 : metadataToken(token), metadataKnown(false)
271 {}
272
273 // Use this only when the caller really knows this is resolved metadata.
274 TypeDescriptor(uint32_t token, const std::string &name)
275 : metadataToken(token), metadataKnown(true), name(name)
276 {}
277
278 // This means "has a nonzero metadata token", not "metadata was resolved".
279 bool isValid() const
280 {
281 return metadataToken != 0;
282 }
283
284 bool isResolved() const
285 {
286 return metadataKnown;
287 }
288
289 bool isKnownReferenceType() const
290 {
291 return metadataKnown && isReferenceType && !isValueType;
292 }
293
294 bool isKnownValueType() const
295 {
296 return metadataKnown && isValueType;
297 }
298
299 bool hasKnownValueWidth() const
300 {
301 return metadataKnown && valueBitWidth != 0;
302 }
303
304 bool hasKnownBaseType() const
305 {
306 return metadataKnown && baseTypeKnown;
307 }
308
309 bool hasKnownInterfaceTypes() const
310 {
311 return metadataKnown && interfaceTypesKnown;
312 }
313 };
314#endif
316 {
317 enum Kind
318 {
319 UnknownMetadata,
320 TypeMetadata,
321 MethodMetadata,
322 FieldMetadata
323 };
324
325 uint32_t metadataToken = 0;
326 Kind kind = UnknownMetadata;
327 std::string name;
328
329 MetadataDescriptor() = default;
330
331 MetadataDescriptor(uint32_t token, Kind kind) : metadataToken(token), kind(kind) {}
332
333 bool isValid() const
334 {
335 return metadataToken != 0;
336 }
337 };
338
340 {
341 uint32_t metadataToken = 0;
342 std::string name;
343
344 bool signatureKnown = false;
345
346 // DQ (6/22/2026): Adding new data members.
347 // bool hasThis = false;
348 bool explicitThis = false;
349 bool isStatic = false;
350 bool isVirtual = false;
351
352 size_t parameterCount = 0;
353 bool hasThis = false;
354 bool returnsVoid = true;
355 size_t returnBits = 0;
356
357 // DQ (6/22/2026): Adding new data members.
358 // size_t returnBitWidth = 0;
359 // SValuePtr::ValueKind returnKind = SValuePtr::ValueKind::UNKNOWN;
360 Rose::BinaryAnalysis::InstructionSemantics::BaseSemantics::ValueKind returnKind = Rose::BinaryAnalysis::InstructionSemantics::BaseSemantics::ValueKind::Unknown;
361 std::string returnTypeDescriptor;
362 // std::vector<SValuePtr::ValueKind> parameterKinds;
363 std::vector<size_t> parameterBitWidths;
364 std::vector<std::string> parameterTypeDescriptors;
365
366 MethodDescriptor() = default;
367
368 explicit MethodDescriptor(uint32_t token) : metadataToken(token) {}
369
370 bool isValid() const
371 {
372 return metadataToken != 0;
373 }
374
375 size_t stackArgumentCount() const
376 {
377 return parameterCount + ((hasThis || explicitThis) ? 1 : 0);
378 }
379 };
380#if 0
381// DQ (6/22/2026): Suggested version of struct.
382struct MethodDescriptor {
383 uint32_t metadataToken = 0;
384
385 bool signatureKnown = false;
386
387 bool hasThis = false;
388 bool explicitThis = false;
389 bool isStatic = false;
390 bool isVirtual = false;
391
392 size_t parameterCount = 0;
393
394 bool returnsVoid = true;
395 size_t returnBitWidth = 0;
396
397 SValue::ValueKind returnKind = SValue::ValueKind::UNKNOWN;
398 std::string returnTypeDescriptor;
399
400 std::vector<SValue::ValueKind> parameterKinds;
401 std::vector<size_t> parameterBitWidths;
402 std::vector<std::string> parameterTypeDescriptors;
403};
404#endif
405
407 {
408 uint32_t signatureToken = 0;
409
410 bool signatureKnown = false;
411 size_t parameterCount = 0;
412 bool hasThis = false;
413 bool returnsVoid = true;
414 size_t returnBits = 0;
415
416 explicit CallSiteDescriptor(uint32_t token) : signatureToken(token) {}
417
418 size_t stackArgumentCount() const
419 {
420 return parameterCount + (hasThis ? 1 : 0);
421 }
422 };
423
425 {
426 bool returnsVoid = true;
427 size_t returnBits = 32;
428 BaseSemantics::ValueKind returnKind = BaseSemantics::ValueKind::Unknown;
429 std::string returnTypeDescriptor;
430 };
431#if 0
432 struct FieldDescriptor
433 {
434 uint32_t metadataToken = 0;
435 std::string name;
436
437 bool metadataKnown = false;
438
439 bool isStatic = false;
440
441 // Field storage layout.
442 bool offsetKnown = false;
443 uint64_t offsetBytes = 0;
444
445 // Field type/layout.
446 bool typeKnown = false;
447 size_t fieldBits = 32;
448 BaseSemantics::ValueKind valueKind = BaseSemantics::ValueKind::Unknown;
449
450 FieldDescriptor() = default;
451 explicit FieldDescriptor(uint32_t token) : metadataToken(token) {}
452
453 bool isValid() const { return metadataToken != 0; }
454 };
455#else
457 {
458 uint32_t metadataToken = 0;
459 std::string name;
460
461 bool metadataKnown = false;
462
463 bool isStatic = false;
464
465 // For instance fields.
466 bool offsetKnown = false;
467 uint64_t offsetBytes = 0;
468
469 // Field storage type.
470 bool typeKnown = false;
471 size_t fieldBits = 32;
472 BaseSemantics::ValueKind valueKind = BaseSemantics::ValueKind::Unknown;
473
474 // Recommended additions.
475 bool isReferenceType = false;
476 bool isValueType = false;
477 uint32_t fieldTypeToken = 0;
478 std::string typeDescriptor;
479
480 FieldDescriptor() = default;
481 explicit FieldDescriptor(uint32_t token): metadataToken(token) {}
482
483 bool isValid() const { return metadataToken != 0; }
484 };
485#endif
486#if 0
488 {
489 public:
490 virtual ~CilMetadataProvider() {}
491
493 resolveMethod(uint32_t methodToken) const = 0;
494
496 resolveCallSite(uint32_t standaloneSigToken) const = 0;
497
499 resolveType(uint32_t typeToken) const = 0;
500 };
501#else
503 {
504 public:
505 virtual ~CilMetadataProvider() {}
506
508 resolveMethod(uint32_t methodToken) const = 0;
509
510 // virtual DispatcherCil::CilTypeAnalysis::CallSiteDescriptor resolveCallSite(uint32_t standaloneSigToken) const = 0;
511 virtual CallSiteDescriptor resolveCallSite(uint32_t standaloneSigToken) const = 0;
512
513 // virtual DispatcherCil::CilTypeAnalysis::TypeDescriptor resolveType(uint32_t typeToken) const = 0;
514 virtual DispatcherCil::CilTypeAnalysis::TypeDescriptor resolveType(uint32_t typeToken) const = 0;
515
516 // virtual DispatcherCil::CilTypeAnalysis::FieldDescriptor resolveField(uint32_t fieldToken) const = 0;
517 virtual FieldDescriptor resolveField(uint32_t fieldToken) const = 0;
518 };
519#endif
520
521 static DispatcherCil::CilTypeAnalysis::FieldDescriptor resolveField(DispatcherCil* dispatcher, uint32_t token);
522#if 0
524 resolveField(DispatcherCil* dispatcher, uint32_t token)
525 {
526 if (dispatcher && dispatcher->cilMetadata())
527 return dispatcher->cilMetadata()->resolveField(token);
529 }
530#endif
531 void setPossibleTypes(const SValuePtr &v, const TypeSet &types);
532 void addPossibleType(const SValuePtr &v, TypeToken type);
533 TypeSet possibleDynamicTypes(const SValuePtr &v) const;
534 bool hasTypeInfo(const SValuePtr &v) const;
535 void rememberTypeDescriptor(const TypeDescriptor &type);
536 const TypeDescriptor* typeDescriptorFor(TypeToken type) const;
537
538 // DQ (6/17/2026): I can't get this to compile outside of the class definition, so leave it there.
539 static const void* key(const SValuePtr &v)
540 {
541 ASSERT_not_null(v);
542
543 // SValuePtr is Sawyer::SharedPointer, not std::shared_ptr,
544 // so it does not have v.get().
545 return static_cast<const void*>(v.operator->());
546 }
547
548 private:
549 std::map<const void*, Nullness> nullness_;
550 std::map<TypeToken, TypeDescriptor> knownTypes_;
551
552 public:
553 void setNullness(const SValuePtr &v, Nullness n);
554 Nullness nullness(const SValuePtr &v) const;
555 bool isDefinitelyNull(const SValuePtr &v) const;
556 bool isDefinitelyNonNull(const SValuePtr &v) const;
557#if 0
558 bool isAssignableTo(uint32_t sourceType, const TypeDescriptor *targetType);
559 bool allAssignableTo(const DispatcherCil::CilTypeAnalysis::TypeSet &possibleTypes, const TypeDescriptor *targetType);
560 bool noneAssignableTo(const DispatcherCil::CilTypeAnalysis::TypeSet &possibleTypes, const TypeDescriptor *targetType);
561#else
562 // DQ (6/28/2026): Adding function prototypes.
563 Assignability isAssignableTo(uint32_t sourceType, const TypeDescriptor *targetType);
564 bool allAssignableTo(const DispatcherCil::CilTypeAnalysis::TypeSet &possibleTypes, const TypeDescriptor *targetType);
565 bool noneAssignableTo(const DispatcherCil::CilTypeAnalysis::TypeSet &possibleTypes, const TypeDescriptor *targetType);
566#endif
567 void copyFacts(const SValuePtr &dst, const SValuePtr &src);
568 };
569
570 // DQ (6/15/2026): This is defined outside of the CilTypeAnalysis class as an experiment.
571 // Maybe all of what is in the CilTypeAnalysis should be declared in the DispatcherCil class?
573 {
574 bool hasUnaligned = false;
575 uint8_t unalignedBytes = 0;
576
577 bool isVolatile = false;
578 bool isTail = false;
579
580 bool hasConstrained = false;
581 uint32_t constrainedTypeToken = 0;
582
583 bool isReadonly = false;
584
585 void clear();
586 };
587
588 // DQ (6/7/2026): Adding suport for type analysis.
589 private:
590 CilTypeAnalysis typeAnalysis_;
591
592 public:
593 CilTypeAnalysis& typeAnalysis()
594 {
595 return typeAnalysis_;
596 }
597
598 const CilTypeAnalysis& typeAnalysis() const
599 {
600 return typeAnalysis_;
601 }
602
603 private:
604 CilPendingPrefixState pendingPrefix_;
605
606 public:
607 CilPendingPrefixState& pendingPrefix() { return pendingPrefix_; }
608 const CilPendingPrefixState& pendingPrefix() const { return pendingPrefix_; }
609 void clearPendingPrefix() { pendingPrefix_.clear(); }
610
611 // DQ (6/22/2026): Adding additional support for method calling.
612 private:
613 const DispatcherCil::CilTypeAnalysis::CilMetadataProvider *cilMetadata_ = nullptr;
614
615 public:
616 void cilMetadata(const DispatcherCil::CilTypeAnalysis::CilMetadataProvider *provider)
617 {
618 cilMetadata_ = provider;
619 }
620
621 const DispatcherCil::CilTypeAnalysis::CilMetadataProvider* cilMetadata() const
622 {
623 return cilMetadata_;
624 }
625
626 private:
627 CilTypeAnalysis::CurrentMethodDescriptor currentMethod_;
628
629 public:
630 const CilTypeAnalysis::CurrentMethodDescriptor& currentMethod() const
631 {
632 return currentMethod_;
633 }
634
635 void currentMethod(const CilTypeAnalysis::CurrentMethodDescriptor &m)
636 {
637 currentMethod_ = m;
638 }
639
640 public:
641 // DQ (6/26/2026): This constant will need to be set by the CIL loader (later).
642 size_t cilPointerBits_ = 32;
643
644 size_t
645 cilPointerBits()
646 {
647 // DQ (6/24/2026): This constant will need to be set by the CIL loader (later).
648 // return 32;
649 return cilPointerBits_;
650 }
651
652private:
653 bool allowByteOnlyExceptionFallback_ = true;
654
655public:
656 bool allowByteOnlyExceptionFallback() const
657 {
658 return allowByteOnlyExceptionFallback_;
659 }
660
661 void allowByteOnlyExceptionFallback(bool b)
662 {
663 allowByteOnlyExceptionFallback_ = b;
664 }
665
666 };
667
668} // namespace
669} // namespace
670} // namespace
671
672#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
674#endif
675
676#endif
677#endif
BaseConstPtr ConstPtr
Reference counting pointer to const object.
Dispatches instructions through the RISC layer.
Definition Dispatcher.h:47
Functor that knows how to dispatch a single kind of instruction.
Definition Dispatcher.h:28
Base class for most instruction semantics RISC operators.
static DispatcherCilPtr instance(const Architecture::BaseConstPtr &, const BaseSemantics::RiscOperatorsPtr &)
Constructor.
void initializeMemoryState()
Make sure memory is set up correctly.
void updateFpsrExcUnfl(const BaseSemantics::SValuePtr &intermediate, SgAsmType *valueType, SgAsmType *rounding, SgAsmType *dstType)
Set or clear FPSR EXC UVFL bit.
void updateFpsrExcInan(const BaseSemantics::SValuePtr &a, SgAsmType *aType, const BaseSemantics::SValuePtr &b, SgAsmType *bType)
Set or clear FPSR EXC INAN bit.
virtual BaseSemantics::SValuePtr read(SgAsmExpression *, size_t value_nbits, size_t addr_nbits=0) override
Reads an R-value expression.
void updateFpsrExcIde(const BaseSemantics::SValuePtr &a, SgAsmType *aType, const BaseSemantics::SValuePtr &b, SgAsmType *bType)
Set or clear FPSR EXC IDE bit.
BaseSemantics::SValuePtr condition(CilInstructionKind, BaseSemantics::RiscOperators *)
Determines if an instruction should branch.
void updateFpsrExcInex()
Set or clear FPSR EXC INEX bit.
DispatcherCilPtr Ptr
Shared-ownership pointer.
void updateFpsrExcOvfl(const BaseSemantics::SValuePtr &intermediate, SgAsmType *valueType, SgAsmType *rounding, SgAsmType *dstType)
Set or clear FPSR EXC OVFL bit.
virtual RegisterDescriptor stackPointerRegister() const override
Returns the stack pointer register.
static DispatcherCilPtr instance(const Architecture::BaseConstPtr &)
Construct a prototypical dispatcher.
BaseSemantics::InsnProcessor * iprocLookup(SgAsmInstruction *insn) override
Lookup the processor for an instruction.
static DispatcherCilPtr promote(const BaseSemantics::DispatcherPtr &)
Dynamic cast to DispatcherCilPtr with assertion.
int iprocKey(SgAsmInstruction *insn_) const override
Given an instruction, return the InsnProcessor key that can be used as an index into the iproc_table.
virtual RegisterDescriptor instructionPointerRegister() const override
Returns the instruction pointer register.
void accumulateFpExceptions()
Update accrued floating-point exceptions.
virtual BaseSemantics::DispatcherPtr create(const BaseSemantics::RiscOperatorsPtr &) const override
Virtual constructor.
void initializeDispatchTable()
Loads the iproc table with instruction processing functors.
void adjustFpConditionCodes(const BaseSemantics::SValuePtr &result, SgAsmFloatType *)
Set floating point condition codes according to result.
Describes (part of) a physical CPU register.
Base class for expressions.
Floating point types.
Base class for machine instructions.
Base class for binary types.
std::shared_ptr< const Base > BaseConstPtr
Reference counted pointer for Architecture::Base.
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
boost::shared_ptr< Dispatcher > DispatcherPtr
Shared-ownership pointer to a semantics instruction dispatcher.
ValueKind
Kind of an SValue for emulating JVM and CIL instructions.
Definition SValue.h:28
boost::shared_ptr< class DispatcherCil > DispatcherCilPtr
Shared-ownership pointer to an CIL instruction dispatcher.
The ROSE library.