Merge pull request #14619 from briansull/emitter-cleanup
[platform/upstream/coreclr.git] / src / vm / stublink.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 // STUBLINK.H
6 // 
7
8 //
9 // A StubLinker object provides a way to link several location-independent
10 // code sources into one executable stub, resolving references,
11 // and choosing the shortest possible instruction size. The StubLinker
12 // abstracts out the notion of a "reference" so it is completely CPU
13 // independent. This StubLinker is intended not only to create method
14 // stubs but to create the PCode-marshaling stubs for Native/Direct.
15 //
16 // A StubLinker's typical life-cycle is:
17 //
18 //   1. Create a new StubLinker (it accumulates state for the stub being
19 //      generated.)
20 //   2. Emit code bytes and references (requiring fixups) into the StubLinker.
21 //   3. Call the Link() method to produce the final stub.
22 //   4. Destroy the StubLinker.
23 //
24 // StubLinkers are not multithread-aware: they're intended to be
25 // used entirely on a single thread. Also, StubLinker's report errors
26 // using COMPlusThrow. StubLinker's do have a destructor: to prevent
27 // C++ object unwinding from clashing with COMPlusThrow,
28 // you must use COMPLUSCATCH to ensure the StubLinker's cleanup in the
29 // event of an exception: the following code would do it:
30 //
31 //  StubLinker stublink;
32 //  Inner();
33 //
34 //
35 //  // Have to separate into inner function because VC++ forbids
36 //  // mixing __try & local objects in the same function.
37 //  void Inner() {
38 //      COMPLUSTRY {
39 //          ... do stuff ...
40 //          pLinker->Link();
41 //      } COMPLUSCATCH {
42 //      }
43 //  }
44 //
45
46
47 // This file should only be included via the platform-specific cgencpu.h.
48
49 #include "cgensys.h"
50
51 #ifndef __stublink_h__
52 #define __stublink_h__
53
54 #include "crst.h"
55 #include "util.hpp"
56 #include "eecontract.h"
57
58 //-------------------------------------------------------------------------
59 // Forward refs
60 //-------------------------------------------------------------------------
61 class  InstructionFormat;
62 class  Stub;
63 class  InterceptStub;
64 class  CheckDuplicatedStructLayouts;
65 class  CodeBasedStubCache;
66 struct  CodeLabel;
67
68 struct CodeRun;
69 struct LabelRef;
70 struct CodeElement;
71 struct IntermediateUnwindInfo;
72
73 #if !defined(_TARGET_X86_) && !defined(FEATURE_PAL)
74 #define STUBLINKER_GENERATES_UNWIND_INFO
75 #endif // !_TARGET_X86_ && !FEATURE_PAL
76
77
78 #ifdef STUBLINKER_GENERATES_UNWIND_INFO
79
80 typedef DPTR(struct StubUnwindInfoHeaderSuffix) PTR_StubUnwindInfoHeaderSuffix;
81 struct StubUnwindInfoHeaderSuffix
82 {
83     UCHAR nUnwindInfoSize;  // Size of unwind info in bytes
84 };
85
86 // Variable-sized struct that preceeds a Stub when the stub requires unwind
87 // information.  Followed by a StubUnwindInfoHeaderSuffix.
88 typedef DPTR(struct StubUnwindInfoHeader) PTR_StubUnwindInfoHeader;
89 struct StubUnwindInfoHeader
90 {
91     PTR_StubUnwindInfoHeader pNext;
92     T_RUNTIME_FUNCTION FunctionEntry;
93     UNWIND_INFO UnwindInfo;  // variable length
94
95     // Computes the size needed for this variable-sized struct.
96     static SIZE_T ComputeSize(UINT nUnwindInfoSize);
97
98     void Init ();
99
100     bool IsRegistered ();
101 };
102
103 // List of stub address ranges, in increasing address order.
104 struct StubUnwindInfoHeapSegment
105 {
106     PBYTE pbBaseAddress;
107     SIZE_T cbSegment;
108     StubUnwindInfoHeader *pUnwindHeaderList;
109     StubUnwindInfoHeapSegment *pNext;
110
111 #ifdef _WIN64
112     class UnwindInfoTable* pUnwindInfoTable;       // Used to publish unwind info to ETW stack crawler
113 #endif
114 };
115
116 VOID UnregisterUnwindInfoInLoaderHeap (UnlockedLoaderHeap *pHeap);
117
118 #endif // STUBLINKER_GENERATES_UNWIND_INFO
119
120
121 //-------------------------------------------------------------------------
122 // A non-multithreaded object that fixes up and emits one executable stub.
123 //-------------------------------------------------------------------------
124 class StubLinker
125 {
126     public:
127         //---------------------------------------------------------------
128         // Construction
129         //---------------------------------------------------------------
130         StubLinker();
131
132
133         //---------------------------------------------------------------
134         // Create a new undefined label. Label must be assigned to a code
135         // location using EmitLabel() prior to final linking.
136         // Throws exception on failure.
137         //---------------------------------------------------------------
138         CodeLabel* NewCodeLabel();
139
140         //---------------------------------------------------------------
141         // Create a new undefined label for which we want the absolute
142         // address, not offset. Label must be assigned to a code
143         // location using EmitLabel() prior to final linking.
144         // Throws exception on failure.
145         //---------------------------------------------------------------
146         CodeLabel* NewAbsoluteCodeLabel();
147
148         //---------------------------------------------------------------
149         // Combines NewCodeLabel() and EmitLabel() for convenience.
150         // Throws exception on failure.
151         //---------------------------------------------------------------
152         CodeLabel* EmitNewCodeLabel();
153
154
155         //---------------------------------------------------------------
156         // Returns final location of label as an offset from the start
157         // of the stub. Can only be called after linkage.
158         //---------------------------------------------------------------
159         UINT32 GetLabelOffset(CodeLabel *pLabel);
160
161         //---------------------------------------------------------------
162         // Append code bytes.
163         //---------------------------------------------------------------
164         VOID EmitBytes(const BYTE *pBytes, UINT numBytes);
165         VOID Emit8 (unsigned __int8  u8);
166         VOID Emit16(unsigned __int16 u16);
167         VOID Emit32(unsigned __int32 u32);
168         VOID Emit64(unsigned __int64 u64);
169         VOID EmitPtr(const VOID *pval);
170
171         //---------------------------------------------------------------
172         // Emit a UTF8 string
173         //---------------------------------------------------------------
174         VOID EmitUtf8(LPCUTF8 pUTF8)
175         {
176             WRAPPER_NO_CONTRACT;
177
178             LPCUTF8 p = pUTF8;
179             while (*(p++)) {
180                 //nothing
181             }
182             EmitBytes((const BYTE *)pUTF8, (unsigned int)(p-pUTF8-1));
183         }
184
185         //---------------------------------------------------------------
186         // Append an instruction containing a reference to a label.
187         //
188         //      target             - the label being referenced.
189         //      instructionFormat  - a platform-specific InstructionFormat object
190         //                           that gives properties about the reference.
191         //      variationCode      - uninterpreted data passed to the pInstructionFormat methods.
192         //---------------------------------------------------------------
193         VOID EmitLabelRef(CodeLabel* target, const InstructionFormat & instructionFormat, UINT variationCode);
194
195
196         //---------------------------------------------------------------
197         // Sets the label to point to the current "instruction pointer"
198         // It is invalid to call EmitLabel() twice on
199         // the same label.
200         //---------------------------------------------------------------
201         VOID EmitLabel(CodeLabel* pCodeLabel);
202
203         //---------------------------------------------------------------
204         // Emits the patch label for the stub.
205         // Throws exception on failure.
206         //---------------------------------------------------------------
207         void EmitPatchLabel();
208
209         //---------------------------------------------------------------
210         // Create a new label to an external address.
211         // Throws exception on failure.
212         //---------------------------------------------------------------
213         CodeLabel* NewExternalCodeLabel(LPVOID pExternalAddress);
214         CodeLabel* NewExternalCodeLabel(PCODE pExternalAddress)
215         {
216             return NewExternalCodeLabel((LPVOID)pExternalAddress);
217         }
218
219         //---------------------------------------------------------------
220         // Push and Pop can be used to keep track of stack growth.
221         // These should be adjusted by opcodes written to the stream.
222         //
223         // Note that popping & pushing stack size as opcodes are emitted
224         // is naive & may not be accurate in many cases,
225         // so complex stubs may have to manually adjust the stack size.
226         // However it should work for the vast majority of cases we care
227         // about.
228         //---------------------------------------------------------------
229         void Push(UINT size);
230         void Pop(UINT size);
231
232         INT GetStackSize() { LIMITED_METHOD_CONTRACT; return m_stackSize; }
233         void SetStackSize(SHORT size) { LIMITED_METHOD_CONTRACT; m_stackSize = size; }
234
235         void SetDataOnly(BOOL fDataOnly = TRUE) { LIMITED_METHOD_CONTRACT; m_fDataOnly = fDataOnly; }
236
237 #ifdef _TARGET_ARM_
238         void DescribeProlog(UINT cCalleeSavedRegs, UINT cbStackFrame, BOOL fPushArgRegs);
239 #elif defined(_TARGET_ARM64_)
240         void DescribeProlog(UINT cIntRegArgs, UINT cVecRegArgs, UINT cCalleeSavedRegs, UINT cbStackFrame);
241         UINT GetSavedRegArgsOffset();
242         UINT GetStackFrameSize();
243 #endif
244
245         //===========================================================================
246         // Unwind information
247
248         // Records location of preserved or parameter register
249         VOID UnwindSavedReg (UCHAR reg, ULONG SPRelativeOffset);
250         VOID UnwindPushedReg (UCHAR reg);
251
252         // Records "sub rsp, xxx"
253         VOID UnwindAllocStack (SHORT FrameSizeIncrement);
254
255         // Records frame pointer register
256         VOID UnwindSetFramePointer (UCHAR reg);
257
258         // In DEBUG, emits a call to m_pUnwindInfoCheckLabel (via
259         // EmitUnwindInfoCheckWorker).  Code at that label will call to a
260         // helper that will attempt to RtlVirtualUnwind through the stub.  The
261         // helper will preserve ALL registers.
262         VOID EmitUnwindInfoCheck();
263
264 #if defined(_DEBUG) && defined(STUBLINKER_GENERATES_UNWIND_INFO) && !defined(CROSSGEN_COMPILE)
265 protected:
266
267         // Injects a call to the given label.
268         virtual VOID EmitUnwindInfoCheckWorker (CodeLabel *pCheckLabel) { _ASSERTE(!"override me"); }
269
270         // Emits a call to a helper that will attempt to RtlVirtualUnwind
271         // through the stub.  The helper will preserve ALL registers.
272         virtual VOID EmitUnwindInfoCheckSubfunction() { _ASSERTE(!"override me"); }
273 #endif
274
275 public:
276
277         //---------------------------------------------------------------
278         // Generate the actual stub. The returned stub has a refcount of 1.
279         // No other methods (other than the destructor) should be called
280         // after calling Link().
281         //
282         // Throws exception on failure.
283         //---------------------------------------------------------------
284         Stub *Link(DWORD flags = 0) { WRAPPER_NO_CONTRACT; return Link(NULL, flags); }
285         Stub *Link(LoaderHeap *heap, DWORD flags = 0);
286
287         //---------------------------------------------------------------
288         // Generate the actual stub. The returned stub has a refcount of 1.
289         // No other methods (other than the destructor) should be called
290         // after calling Link(). The linked stub must have its increment
291         // increased by one prior to calling this method. This method
292         // does not increment the reference count of the interceptee.
293         //
294         // Throws exception on failure.
295         //---------------------------------------------------------------
296         Stub *LinkInterceptor(Stub* interceptee, void *pRealAddr)
297             { WRAPPER_NO_CONTRACT; return LinkInterceptor(NULL,interceptee, pRealAddr); }
298         Stub *LinkInterceptor(LoaderHeap *heap, Stub* interceptee, void *pRealAddr);
299
300     private:
301         CodeElement   *m_pCodeElements;     // stored in *reverse* order
302         CodeLabel     *m_pFirstCodeLabel;   // linked list of CodeLabels
303         LabelRef      *m_pFirstLabelRef;    // linked list of references
304         CodeLabel     *m_pPatchLabel;       // label of stub patch offset
305                                             // currently just for multicast
306                                             // frames.
307         SHORT         m_stackSize;          // count of pushes/pops
308         CQuickHeap    m_quickHeap;          // throwaway heap for
309                                             //   labels, and
310                                             //   internals.
311         BOOL          m_fDataOnly;          // the stub contains only data - does not need FlushInstructionCache
312         
313 #ifdef _TARGET_ARM_
314 protected:
315         BOOL            m_fProlog;              // True if DescribeProlog has been called
316         UINT            m_cCalleeSavedRegs;     // Count of callee saved registers (0 == none, 1 == r4, 2 ==
317                                                 // r4-r5 etc. up to 8 == r4-r11)
318         UINT            m_cbStackFrame;         // Count of bytes in the stack frame (excl of saved regs)
319         BOOL            m_fPushArgRegs;         // If true, r0-r3 are saved before callee saved regs
320 #endif // _TARGET_ARM_
321
322 #ifdef _TARGET_ARM64_
323 protected:
324         BOOL            m_fProlog;              // True if DescribeProlog has been called
325         UINT            m_cIntRegArgs;          // Count of int register arguments (x0 - x7)
326         UINT            m_cVecRegArgs;          // Count of FP register arguments (v0 - v7)
327         UINT            m_cCalleeSavedRegs;     // Count of callee saved registers (x19 - x28)
328         UINT            m_cbStackSpace;         // Additional stack space for return buffer and stack alignment
329 #endif // _TARGET_ARM64_
330
331 #ifdef STUBLINKER_GENERATES_UNWIND_INFO
332
333 #ifdef _DEBUG
334         CodeLabel     *m_pUnwindInfoCheckLabel;  // subfunction to call to unwind info check helper.
335                                                  // On AMD64, the prologue is restricted to 256
336                                                  // bytes, so this reduces the size of the injected
337                                                  // code from 14 to 5 bytes.
338 #endif
339
340 #ifdef _TARGET_AMD64_
341         IntermediateUnwindInfo *m_pUnwindInfoList;
342         UINT          m_nUnwindSlots;       // number of slots to allocate at end, == UNWIND_INFO::CountOfCodes
343         BOOL          m_fHaveFramePointer;  // indicates stack operations no longer need to be recorded
344
345         //
346         // Returns total UnwindInfoSize, including RUNTIME_FUNCTION entry
347         //
348         UINT UnwindInfoSize(UINT codeSize)
349         {
350             if (m_nUnwindSlots == 0) return 0;
351
352             return sizeof(T_RUNTIME_FUNCTION) + offsetof(UNWIND_INFO, UnwindCode) + m_nUnwindSlots * sizeof(UNWIND_CODE);
353         }
354 #endif // _TARGET_AMD64_
355
356 #ifdef _TARGET_ARM_
357 #define MAX_UNWIND_CODE_WORDS 5  /* maximum number of 32-bit words to store unwind codes */
358         // Cache information about the stack frame set up in the prolog and use it in the generation of the
359         // epilog.
360 private:
361         // Reserve fixed size block that's big enough to fit any unwind info we can have
362         static const int c_nUnwindInfoSize = sizeof(T_RUNTIME_FUNCTION) + sizeof(DWORD) + MAX_UNWIND_CODE_WORDS *4;
363
364         //
365         // Returns total UnwindInfoSize, including RUNTIME_FUNCTION entry
366         //
367         UINT UnwindInfoSize(UINT codeSize)
368         {
369             if (!m_fProlog) return 0;
370
371             return c_nUnwindInfoSize;
372         }
373 #endif // _TARGET_ARM_
374
375 #ifdef _TARGET_ARM64_
376 #define MAX_UNWIND_CODE_WORDS 5  /* maximum number of 32-bit words to store unwind codes */
377
378 private:
379         // Reserve fixed size block that's big enough to fit any unwind info we can have
380         static const int c_nUnwindInfoSize = sizeof(T_RUNTIME_FUNCTION) + sizeof(DWORD) + MAX_UNWIND_CODE_WORDS *4;
381         UINT UnwindInfoSize(UINT codeSize)
382         {
383             if (!m_fProlog) return 0;
384
385             return c_nUnwindInfoSize;
386         }
387
388 #endif // _TARGET_ARM64_
389
390 #endif // STUBLINKER_GENERATES_UNWIND_INFO
391
392         CodeRun *AppendNewEmptyCodeRun();
393
394
395         // Returns pointer to last CodeElement or NULL.
396         CodeElement *GetLastCodeElement()
397         {
398             LIMITED_METHOD_CONTRACT;
399             return m_pCodeElements;
400         }
401
402         // Appends a new CodeElement.
403         VOID AppendCodeElement(CodeElement *pCodeElement);
404
405
406         // Calculates the size of the stub code that is allocate
407         // immediately after the stub object. Returns the
408         // total size. GlobalSize contains the size without
409         // that data part.
410         virtual int CalculateSize(int* globalsize);
411
412         // Writes out the code element into memory following the
413         // stub object.
414         bool EmitStub(Stub* pStub, int globalsize);
415
416         CodeRun *GetLastCodeRunIfAny();
417
418         bool EmitUnwindInfo(Stub* pStub, int globalsize);
419
420 #if defined(_TARGET_AMD64_) && defined(STUBLINKER_GENERATES_UNWIND_INFO)
421         UNWIND_CODE *AllocUnwindInfo (UCHAR Op, UCHAR nExtraSlots = 0);
422 #endif // defined(_TARGET_AMD64_) && defined(STUBLINKER_GENERATES_UNWIND_INFO)
423 };
424
425 //************************************************************************
426 // CodeLabel
427 //************************************************************************
428 struct CodeLabel
429 {
430     // Link pointer for StubLink's list of labels
431     CodeLabel       *m_next;
432
433     // if FALSE, label refers to some code within the same stub
434     // if TRUE, label refers to some externally supplied address.
435     BOOL             m_fExternal;
436
437     // if TRUE, means we want the actual address of the label and
438     // not an offset to it
439     BOOL             m_fAbsolute;
440
441     union {
442
443         // Internal
444         struct {
445             // Indicates the position of the label, expressed
446             // as an offset into a CodeRun.
447             CodeRun         *m_pCodeRun;
448             UINT             m_localOffset;
449
450         } i;
451
452
453         // External
454         struct {
455             LPVOID           m_pExternalAddress;
456         } e;
457     };
458 };
459
460 enum NewStubFlags
461 {
462     NEWSTUB_FL_INTERCEPT        = 0x00000001,
463     NEWSTUB_FL_MULTICAST        = 0x00000002,
464     NEWSTUB_FL_EXTERNAL         = 0x00000004,
465     NEWSTUB_FL_LOADERHEAP       = 0x00000008
466 };
467
468
469 //-------------------------------------------------------------------------
470 // An executable stub. These can only be created by the StubLinker().
471 // Each stub has a reference count (which is maintained in a thread-safe
472 // manner.) When the ref-count goes to zero, the stub automatically
473 // cleans itself up.
474 //-------------------------------------------------------------------------
475 typedef DPTR(class Stub) PTR_Stub;
476 typedef DPTR(PTR_Stub) PTR_PTR_Stub;
477 class Stub
478 {
479     friend class CheckDuplicatedStructLayouts;
480     friend class CheckAsmOffsets;
481
482     protected:
483     enum
484     {
485         MULTICAST_DELEGATE_BIT = 0x80000000,
486         EXTERNAL_ENTRY_BIT     = 0x40000000,
487         LOADER_HEAP_BIT        = 0x20000000,
488         INTERCEPT_BIT          = 0x10000000,
489         UNWIND_INFO_BIT        = 0x08000000,
490
491         PATCH_OFFSET_MASK      = UNWIND_INFO_BIT - 1,
492         MAX_PATCH_OFFSET       = PATCH_OFFSET_MASK + 1,
493     };
494
495     static_assert_no_msg(PATCH_OFFSET_MASK < UNWIND_INFO_BIT);
496
497     public:
498         //-------------------------------------------------------------------
499         // Inc the refcount.
500         //-------------------------------------------------------------------
501         VOID IncRef();
502
503
504         //-------------------------------------------------------------------
505         // Dec the refcount.
506         // Returns true if the count went to zero and the stub was deleted
507         //-------------------------------------------------------------------
508         BOOL DecRef();
509
510
511
512         //-------------------------------------------------------------------
513         // Used for throwing out unused stubs from stub caches. This
514         // method cannot be 100% accurate due to race conditions. This
515         // is ok because stub cache management is robust in the face
516         // of missed or premature cleanups.
517         //-------------------------------------------------------------------
518         BOOL HeuristicLooksOrphaned()
519         {
520             LIMITED_METHOD_CONTRACT;
521             _ASSERTE(m_signature == kUsedStub);
522             return (m_refcount == 1);
523         }
524
525         //-------------------------------------------------------------------
526         // Used by the debugger to help step through stubs
527         //-------------------------------------------------------------------
528         BOOL IsIntercept()
529         {
530             LIMITED_METHOD_CONTRACT;
531             return (m_patchOffset & INTERCEPT_BIT) != 0;
532         }
533
534         BOOL IsMulticastDelegate()
535         {
536             LIMITED_METHOD_CONTRACT;
537             return (m_patchOffset & MULTICAST_DELEGATE_BIT) != 0;
538         }
539
540         //-------------------------------------------------------------------
541         // For stubs which execute user code, a patch offset needs to be set
542         // to tell the debugger how far into the stub code the debugger has
543         // to step until the frame is set up.
544         //-------------------------------------------------------------------
545         USHORT GetPatchOffset()
546         {
547             LIMITED_METHOD_CONTRACT;
548
549             return (USHORT)(m_patchOffset & PATCH_OFFSET_MASK);
550         }
551
552         void SetPatchOffset(USHORT offset)
553         {
554             LIMITED_METHOD_CONTRACT;
555             _ASSERTE(GetPatchOffset() == 0);
556             m_patchOffset |= offset;
557             _ASSERTE(GetPatchOffset() == offset);
558         }
559
560         TADDR GetPatchAddress()
561         {
562             WRAPPER_NO_CONTRACT;
563
564             return dac_cast<TADDR>(GetEntryPointInternal()) + GetPatchOffset();
565         }                
566
567         //-------------------------------------------------------------------
568         // Unwind information.
569         //-------------------------------------------------------------------
570
571 #ifdef STUBLINKER_GENERATES_UNWIND_INFO
572
573         BOOL HasUnwindInfo()
574         {
575             LIMITED_METHOD_CONTRACT;
576             return (m_patchOffset & UNWIND_INFO_BIT) != 0;
577         }
578
579         StubUnwindInfoHeaderSuffix *GetUnwindInfoHeaderSuffix()
580         {
581             CONTRACTL
582             {
583                 NOTHROW;
584                 GC_NOTRIGGER;
585                 FORBID_FAULT;
586                 SO_TOLERANT;
587             }
588             CONTRACTL_END
589
590             _ASSERTE(HasUnwindInfo());
591
592             TADDR info = dac_cast<TADDR>(this);
593
594             if (IsIntercept())
595             {
596                 info -= 2 * sizeof(TADDR);
597             }
598
599             return PTR_StubUnwindInfoHeaderSuffix
600                 (info - sizeof(StubUnwindInfoHeaderSuffix));
601         }
602
603         StubUnwindInfoHeader *GetUnwindInfoHeader()
604         {
605             CONTRACTL
606             {
607                 NOTHROW;
608                 GC_NOTRIGGER;
609                 FORBID_FAULT;
610             }
611             CONTRACTL_END
612
613             StubUnwindInfoHeaderSuffix *pSuffix = GetUnwindInfoHeaderSuffix();
614
615             TADDR suffixEnd = dac_cast<TADDR>(pSuffix) + sizeof(*pSuffix);
616
617             return PTR_StubUnwindInfoHeader(suffixEnd -
618                                             StubUnwindInfoHeader::ComputeSize(pSuffix->nUnwindInfoSize));
619         }
620
621 #endif // STUBLINKER_GENERATES_UNWIND_INFO
622
623         //-------------------------------------------------------------------
624         // Returns pointer to the start of the allocation containing this Stub.
625         //-------------------------------------------------------------------
626         TADDR GetAllocationBase();
627
628         //-------------------------------------------------------------------
629         // Return executable entrypoint after checking the ref count.
630         //-------------------------------------------------------------------
631         PCODE GetEntryPoint()
632         {
633             WRAPPER_NO_CONTRACT;
634             SUPPORTS_DAC;
635
636             _ASSERTE(m_signature == kUsedStub);
637             _ASSERTE(m_refcount > 0);
638
639             TADDR pEntryPoint = dac_cast<TADDR>(GetEntryPointInternal());
640
641 #ifdef _TARGET_ARM_
642
643 #ifndef THUMB_CODE
644 #define THUMB_CODE 1
645 #endif
646
647             pEntryPoint |= THUMB_CODE;
648 #endif
649
650             return pEntryPoint;
651         }
652
653         UINT GetNumCodeBytes()
654         {
655             WRAPPER_NO_CONTRACT;
656             SUPPORTS_DAC;
657             
658             return m_numCodeBytes;
659         }
660
661         //-------------------------------------------------------------------
662         // Return start of the stub blob
663         //-------------------------------------------------------------------
664         PTR_CBYTE GetBlob()
665         {
666             WRAPPER_NO_CONTRACT;
667             SUPPORTS_DAC;
668
669             _ASSERTE(m_signature == kUsedStub);
670             _ASSERTE(m_refcount > 0);
671
672             return GetEntryPointInternal();
673         }
674
675         //-------------------------------------------------------------------
676         // Return the Stub as in GetEntryPoint and size of the stub+code in bytes
677         //   WARNING: Depending on the stub kind this may be just Stub size as 
678         //            not all stubs have the info about the code size.
679         //            It's the caller responsibility to determine that
680         //-------------------------------------------------------------------
681         static Stub* RecoverStubAndSize(PCODE pEntryPoint, DWORD *pSize)
682         {
683             CONTRACT(Stub*)
684             {
685                 NOTHROW;
686                 GC_NOTRIGGER;
687                 MODE_ANY;
688
689                 PRECONDITION(pEntryPoint && pSize);
690             }
691             CONTRACT_END;
692
693             Stub *pStub = Stub::RecoverStub(pEntryPoint);
694             *pSize = sizeof(Stub) + pStub->m_numCodeBytes;
695             RETURN pStub;
696         }
697
698         HRESULT CloneStub(BYTE *pBuffer, DWORD dwBufferSize)
699         {
700             LIMITED_METHOD_CONTRACT;
701             if ((pBuffer == NULL) ||
702                 (dwBufferSize < (sizeof(*this) + m_numCodeBytes)))
703             {
704                 return E_INVALIDARG;
705             }
706
707             memcpyNoGCRefs(pBuffer, this, sizeof(*this) + m_numCodeBytes);
708             reinterpret_cast<Stub *>(pBuffer)->m_refcount = 1;
709
710             return S_OK;
711         }
712
713         //-------------------------------------------------------------------
714         // Reverse GetEntryPoint.
715         //-------------------------------------------------------------------
716         static Stub* RecoverStub(PCODE pEntryPoint)
717         {
718             STATIC_CONTRACT_NOTHROW;
719             STATIC_CONTRACT_GC_NOTRIGGER;
720
721             TADDR pStubData = PCODEToPINSTR(pEntryPoint);
722
723             Stub *pStub = PTR_Stub(pStubData - sizeof(*pStub));
724
725 #if !defined(DACCESS_COMPILE)
726             _ASSERTE(pStub->m_signature == kUsedStub);
727             _ASSERTE(pStub->GetEntryPoint() == pEntryPoint);
728 #elif defined(_DEBUG)
729             // If this isn't really a stub we don't want
730             // to continue with it.
731             // TODO: This should be removed once IsStub
732             // can adverstise whether it's safe to call
733             // further StubManager methods.
734             if (pStub->m_signature != kUsedStub ||
735                 pStub->GetEntryPoint() != pEntryPoint)
736             {
737                 DacError(E_INVALIDARG);
738             }
739 #endif
740             return pStub;
741         }
742
743         //-------------------------------------------------------------------
744         // Returns TRUE if entry point is not inside the Stub allocation.
745         //-------------------------------------------------------------------
746         BOOL HasExternalEntryPoint() const
747         {
748             LIMITED_METHOD_CONTRACT;
749
750             return (m_patchOffset & EXTERNAL_ENTRY_BIT) != 0;
751         }
752
753         //-------------------------------------------------------------------
754         // This is the guy that creates stubs.
755         //-------------------------------------------------------------------
756         static Stub* NewStub(LoaderHeap *pLoaderHeap, UINT numCodeBytes,
757                              DWORD flags = 0
758 #ifdef STUBLINKER_GENERATES_UNWIND_INFO
759                              , UINT nUnwindInfoSize = 0
760 #endif
761                              );
762
763         static Stub* NewStub(PTR_VOID pCode, DWORD flags = 0);
764         static Stub* NewStub(PCODE pCode, DWORD flags = 0)
765         {
766             return NewStub((PTR_VOID)pCode, flags);
767         }
768
769         //-------------------------------------------------------------------
770         // One-time init
771         //-------------------------------------------------------------------
772         static void Init();
773
774     protected:
775         // fMC: Set to true if the stub is a multicast delegate, false otherwise
776         void SetupStub(int numCodeBytes, DWORD flags
777 #ifdef STUBLINKER_GENERATES_UNWIND_INFO
778                        , UINT nUnwindInfoSlots
779 #endif
780                        );
781         void DeleteStub();
782
783         //-------------------------------------------------------------------
784         // Return executable entrypoint without checking the ref count.
785         //-------------------------------------------------------------------
786         inline PTR_CBYTE GetEntryPointInternal()
787         {
788             LIMITED_METHOD_CONTRACT;
789             SUPPORTS_DAC;
790
791             _ASSERTE(m_signature == kUsedStub);
792
793
794             if (HasExternalEntryPoint())
795             {
796                 return dac_cast<PTR_BYTE>(*dac_cast<PTR_PCODE>(dac_cast<TADDR>(this) + sizeof(*this)));
797             }
798             else
799             {
800                 // StubLink always puts the entrypoint first.
801                 return dac_cast<PTR_CBYTE>(this) + sizeof(*this);
802             }
803         }
804
805         ULONG   m_refcount;
806         ULONG   m_patchOffset;
807
808         UINT    m_numCodeBytes;
809
810 #ifdef _DEBUG
811         enum {
812             kUsedStub  = 0x42555453,     // 'STUB'
813             kFreedStub = 0x46555453,     // 'STUF'
814         };
815
816         UINT32  m_signature;
817 #else 
818 #ifdef _WIN64
819         //README ALIGNEMENT: in retail mode UINT m_numCodeBytes does not align to 16byte for the code
820         //                   after the Stub struct. This is to pad properly
821         UINT    m_pad_code_bytes; 
822 #endif // _WIN64
823 #endif // _DEBUG
824         
825 #ifdef _DEBUG
826         Stub()      // Stubs are created by NewStub(), not "new". Hide the
827         { LIMITED_METHOD_CONTRACT; }          //  constructor to enforce this.
828 #endif
829
830 };
831
832
833 /*
834  * The InterceptStub hides a reference to the real stub at a negative offset.
835  * When this stub is deleted it decrements the real stub cleaning it up as
836  * well. The InterceptStub is created by the Stublinker.
837  *
838  * <TODO>@TODO: Intercepted stubs need have a routine that will find the
839  *        last real stub in the chain.</TODO>
840  *        The stubs are linked - GetInterceptedStub will return either
841  *        a pointer to the next intercept stub (if there is one), or NULL,
842  *        indicating end-of-chain.  GetRealAddr will return the address of
843  *        the "real" code, which may, in fact, be another thunk (for example),
844  *        and thus should be traced as well.
845  */
846
847 typedef DPTR(class InterceptStub) PTR_InterceptStub;
848 class InterceptStub : public Stub
849 {
850     friend class Stub;
851     public:
852         //-------------------------------------------------------------------
853         // This is the guy that creates stubs.
854         //-------------------------------------------------------------------
855         static Stub* NewInterceptedStub(LoaderHeap *pHeap,
856                                         UINT numCodeBytes,
857                                         Stub* interceptee,
858                                         void* pRealAddr
859 #ifdef STUBLINKER_GENERATES_UNWIND_INFO
860                                         , UINT nUnwindInfoSize = 0
861 #endif
862                                         );
863
864         //---------------------------------------------------------------
865         // Expose key offsets and values for stub generation.
866         //---------------------------------------------------------------
867         int GetNegativeOffset()
868         {
869             LIMITED_METHOD_CONTRACT;
870             return sizeof(TADDR) + GetNegativeOffsetRealAddr();
871         }
872
873         PTR_PTR_Stub GetInterceptedStub()
874         {
875             LIMITED_METHOD_CONTRACT;
876             return dac_cast<PTR_PTR_Stub>(
877                 dac_cast<TADDR>(this) - GetNegativeOffset());
878         }
879
880         int GetNegativeOffsetRealAddr()
881         {
882             LIMITED_METHOD_CONTRACT;
883             return sizeof(TADDR);
884         }
885
886         PTR_TADDR GetRealAddr()
887         {
888             LIMITED_METHOD_CONTRACT;
889             return dac_cast<PTR_TADDR>(
890                 dac_cast<TADDR>(this) - GetNegativeOffsetRealAddr());
891         }
892
893         static Stub*     NewInterceptedStub(void* pCode,
894                                             Stub* interceptee,
895                                             void* pRealAddr);
896
897 protected:
898         void ReleaseInterceptedStub();
899
900 #ifdef _DEBUG
901         InterceptStub()  // Intercept stubs are only created by NewInterceptedStub.
902         { LIMITED_METHOD_CONTRACT; }
903 #endif
904 };
905
906 //-------------------------------------------------------------------------
907 // Each platform encodes the "branch" instruction in a different
908 // way. We use objects derived from InstructionFormat to abstract this
909 // information away. InstructionFormats don't contain any variable data
910 // so they should be allocated statically.
911 //
912 // Note that StubLinker does not create or define any InstructionFormats.
913 // The client does.
914 //
915 // The following example shows how to define a InstructionFormat for the
916 // X86 jump near instruction which takes on two forms:
917 //
918 //   EB xx        jmp  rel8    ;; SHORT JMP (signed 8-bit offset)
919 //   E9 xxxxxxxx  jmp  rel32   ;; NEAR JMP (signed 32-bit offset)
920 //
921 // InstructionFormat's provide StubLinker the following information:
922 //
923 //   RRT.m_allowedSizes
924 //
925 //     What are the possible sizes that the reference can
926 //     take? The X86 jump can take either an 8-bit or 32-bit offset
927 //     so this value is set to (k8|k32). StubLinker will try to
928 //     use the smallest size possible.
929 //
930 //
931 //   RRT.m_fTreatSizesAsSigned
932 //     Sign-extend or zero-extend smallsizes offsets to the platform
933 //     code pointer size? For x86, this field is set to TRUE (rel8
934 //     is considered signed.)
935 //
936 //
937 //   UINT RRT.GetSizeOfInstruction(refsize, variationCode)
938 //     Returns the total size of the instruction in bytes for a given
939 //     refsize. For this example:
940 //
941 //          if (refsize==k8) return 2;
942 //          if (refsize==k32) return 5;
943 //
944 //
945 //   UINT RRT.GetSizeOfData(refsize, variationCode)
946 //     Returns the total size of the seperate data area (if any) that the
947 //     instruction needs in bytes for a given refsize. For this example
948 //     on the SH3
949 //          if (refsize==k32) return 4; else return 0;
950 //
951 //   The default implem of this returns 0, so CPUs that don't have need
952 //   for a seperate constant area don't have to worry about it.
953 //
954 //
955 //   BOOL CanReach(refsize, variationcode, fExternal, offset)
956 //     Returns whether the instruction with the given variationcode &
957 //     refsize can reach the given offset. In the case of External
958 //     calls, fExternal is set and offset is the target address. In this case an
959 //     implementation should return TRUE only if refsize is big enough to fit a
960 //     full machine-sized pointer to anywhere in the address space.
961 //
962 //
963 //   VOID RRT.EmitInstruction(UINT     refsize,
964 //                            __int64  fixedUpReference,
965 //                            BYTE    *pOutBuffer,
966 //                            UINT     variationCode,
967 //                            BYTE    *pDataBuffer)
968 //
969 //     Given a chosen size (refsize) and the final offset value
970 //     computed by StubLink (fixedUpReference), write out the
971 //     instruction into the provided buffer (guaranteed to be
972 //     big enough provided you told the truth with GetSizeOfInstruction()).
973 //     If needed (e.g. on SH3) a data buffer is also passed in for
974 //     storage of constants.
975 //
976 //     For x86 jmp near:
977 //
978 //          if (refsize==k8) {
979 //              pOutBuffer[0] = 0xeb;
980 //              pOutBuffer[1] = (__int8)fixedUpReference;
981 //          } else if (refsize == k32) {
982 //              pOutBuffer[0] = 0xe9;
983 //              *((__int32*)(1+pOutBuffer)) = (__int32)fixedUpReference;
984 //          } else {
985 //              CRASH("Bad input.");
986 //          }
987 //
988 // VOID RRT.GetHotSpotOffset(UINT refsize, UINT variationCode)
989 //
990 //     The reference offset is always relative to some IP: this
991 //     method tells StubLinker where that IP is relative to the
992 //     start of the instruction. For X86, the offset is always
993 //     relative to the start of the *following* instruction so
994 //     the correct implementation is:
995 //
996 //          return GetSizeOfInstruction(refsize, variationCode);
997 //
998 //     Actually, InstructionFormat() provides a default implementation of this
999 //     method that does exactly this so X86 need not override this at all.
1000 //
1001 //
1002 // The extra "variationCode" argument is an __int32 that StubLinker receives
1003 // from EmitLabelRef() and passes uninterpreted to each RRT method.
1004 // This allows one RRT to handle a family of related instructions,
1005 // for example, the family of conditional jumps on the X86.
1006 //
1007 //-------------------------------------------------------------------------
1008 class InstructionFormat
1009 {
1010     private:
1011         enum
1012         {
1013         // if you want to add a size, insert it in-order (e.g. a 18-bit size would
1014         // go between k16 and k32) and shift all the higher values up. All values
1015         // must be a power of 2 since the get ORed together.
1016
1017             _k8,
1018 #ifdef INSTRFMT_K9
1019             _k9,
1020 #endif
1021 #ifdef INSTRFMT_K13
1022             _k13,
1023 #endif
1024             _k16,
1025 #ifdef INSTRFMT_K24
1026             _k24,
1027 #endif
1028 #ifdef INSTRFMT_K26
1029             _k26,
1030 #endif
1031             _k32,
1032 #ifdef INSTRFMT_K64SMALL
1033             _k64Small,
1034 #endif
1035 #ifdef INSTRFMT_K64
1036             _k64,
1037 #endif
1038             _kAllowAlways,
1039         };
1040
1041     public:
1042
1043         enum
1044         {
1045             k8          = (1 << _k8),
1046 #ifdef INSTRFMT_K9
1047             k9          = (1 << _k9),
1048 #endif
1049 #ifdef INSTRFMT_K13
1050             k13         = (1 << _k13),
1051 #endif
1052             k16         = (1 << _k16),
1053 #ifdef INSTRFMT_K24
1054             k24         = (1 << _k24),
1055 #endif
1056 #ifdef INSTRFMT_K26
1057             k26         = (1 << _k26),
1058 #endif
1059             k32         = (1 << _k32),
1060 #ifdef INSTRFMT_K64SMALL
1061             k64Small    = (1 << _k64Small),
1062 #endif
1063 #ifdef INSTRFMT_K64
1064             k64         = (1 << _k64),
1065 #endif
1066             kAllowAlways= (1 << _kAllowAlways),
1067             kMax = kAllowAlways,
1068         };
1069
1070         const UINT m_allowedSizes;         // OR mask using above "k" values
1071         InstructionFormat(UINT allowedSizes) : m_allowedSizes(allowedSizes)
1072         {
1073             LIMITED_METHOD_CONTRACT;
1074         }
1075
1076         virtual UINT GetSizeOfInstruction(UINT refsize, UINT variationCode) = 0;
1077         virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pCodeBuffer, UINT variationCode, BYTE *pDataBuffer) = 0;
1078         virtual UINT GetHotSpotOffset(UINT refsize, UINT variationCode)
1079         {
1080             WRAPPER_NO_CONTRACT;
1081             // Default implementation: the offset is added to the
1082             // start of the following instruction.
1083             return GetSizeOfInstruction(refsize, variationCode);
1084         }
1085
1086         virtual UINT GetSizeOfData(UINT refsize, UINT variationCode)
1087         {
1088             LIMITED_METHOD_CONTRACT;
1089             // Default implementation: 0 extra bytes needed (most CPUs)
1090             return 0;
1091         }
1092
1093         virtual BOOL CanReach(UINT refsize, UINT variationCode, BOOL fExternal, INT_PTR offset)
1094         {
1095             LIMITED_METHOD_CONTRACT;
1096
1097             if (fExternal) {
1098                 // For external, we don't have enough info to predict
1099                 // the offset yet so we only accept if the offset size
1100                 // is at least as large as the native pointer size.
1101                 switch(refsize) {
1102                     case InstructionFormat::k8: // intentional fallthru
1103                     case InstructionFormat::k16: // intentional fallthru
1104 #ifdef INSTRFMT_K24
1105                     case InstructionFormat::k24: // intentional fallthru
1106 #endif
1107 #ifdef INSTRFMT_K26
1108                     case InstructionFormat::k26: // intentional fallthru
1109 #endif
1110                         return FALSE;           // no 8 or 16-bit platforms
1111
1112                     case InstructionFormat::k32:
1113                         return sizeof(LPVOID) <= 4;
1114 #ifdef INSTRFMT_K64
1115                     case InstructionFormat::k64:
1116                         return sizeof(LPVOID) <= 8;
1117 #endif
1118                     case InstructionFormat::kAllowAlways:
1119                         return TRUE;
1120
1121                     default:
1122                         _ASSERTE(0);
1123                         return FALSE;
1124                 }
1125             } else {
1126                 switch(refsize)
1127                 {
1128                     case InstructionFormat::k8:
1129                         return FitsInI1(offset);
1130
1131                     case InstructionFormat::k16:
1132                         return FitsInI2(offset);
1133                         
1134 #ifdef INSTRFMT_K24
1135                     case InstructionFormat::k24:
1136                         return FitsInI2(offset>>8);
1137 #endif
1138
1139 #ifdef INSTRFMT_K26
1140                     case InstructionFormat::k26:
1141                         return FitsInI2(offset>>10);
1142 #endif
1143                     case InstructionFormat::k32:
1144                         return FitsInI4(offset);
1145 #ifdef INSTRFMT_K64
1146                     case InstructionFormat::k64:
1147                         // intentional fallthru
1148 #endif
1149                     case InstructionFormat::kAllowAlways:
1150                         return TRUE;
1151                     default:
1152                         _ASSERTE(0);
1153                         return FALSE;
1154
1155                 }
1156             }
1157         }
1158 };
1159
1160
1161
1162
1163
1164 //-------------------------------------------------------------------------
1165 // This stub cache associates stubs with an integer key.  For some clients,
1166 // this might represent the size of the argument stack in some cpu-specific
1167 // units (for the x86, the size is expressed in DWORDS.)  For other clients,
1168 // this might take into account the style of stub (e.g. whether it returns
1169 // an object reference or not).
1170 //-------------------------------------------------------------------------
1171 class ArgBasedStubCache
1172 {
1173     public:
1174        ArgBasedStubCache(UINT fixedSize = NUMFIXEDSLOTS);
1175        ~ArgBasedStubCache();
1176
1177        //-----------------------------------------------------------------
1178        // Retrieves the stub associated with the given key.
1179        //-----------------------------------------------------------------
1180        Stub *GetStub(UINT_PTR key);
1181
1182        //-----------------------------------------------------------------
1183        // Tries to associate the stub with the given key.
1184        // It may fail because another thread might swoop in and
1185        // do the association before you do. Thus, you must use the
1186        // return value stub rather than the pStub.
1187        //-----------------------------------------------------------------
1188        Stub* AttemptToSetStub(UINT_PTR key, Stub *pStub);
1189
1190
1191        // Suggestions for number of slots
1192        enum {
1193  #ifdef _DEBUG
1194              NUMFIXEDSLOTS = 3,
1195  #else
1196              NUMFIXEDSLOTS = 16,
1197  #endif
1198        };
1199
1200 #ifdef _DEBUG
1201        VOID Dump();  //Diagnostic dump
1202 #endif
1203
1204     private:
1205
1206        // How many low-numbered keys have direct access?
1207        UINT      m_numFixedSlots;
1208
1209        // For 'm_numFixedSlots' low-numbered keys, we store them in an array.
1210        Stub    **m_aStub;
1211
1212
1213        struct SlotEntry
1214        {
1215            Stub             *m_pStub;
1216            UINT_PTR         m_key;
1217            SlotEntry        *m_pNext;
1218        };
1219
1220        // High-numbered keys are stored in a sparse linked list.
1221        SlotEntry            *m_pSlotEntries;
1222
1223
1224        Crst                  m_crst;
1225 };
1226
1227
1228 #define CPUSTUBLINKER StubLinkerCPU
1229
1230 class NDirectStubLinker;
1231 class CPUSTUBLINKER;
1232
1233 #endif // __stublink_h__