disasm.cpp 165 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Detours Disassembler (disasm.cpp of detours.lib)
  4. //
  5. // Microsoft Research Detours Package, Version 4.0.1
  6. //
  7. // Copyright (c) Microsoft Corporation. All rights reserved.
  8. //
  9. // #define DETOUR_DEBUG 1
  10. #define DETOURS_INTERNAL
  11. #include "detours.h"
  12. #include <limits.h>
  13. #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
  14. #error detours.h version mismatch
  15. #endif
  16. #undef ASSERT
  17. #define ASSERT(x)
  18. //////////////////////////////////////////////////////////////////////////////
  19. //
  20. // Special macros to handle the case when we are building disassembler for
  21. // offline processing.
  22. //
  23. #if defined(DETOURS_X86_OFFLINE_LIBRARY) \
  24. || defined(DETOURS_X64_OFFLINE_LIBRARY) \
  25. || defined(DETOURS_ARM_OFFLINE_LIBRARY) \
  26. || defined(DETOURS_ARM64_OFFLINE_LIBRARY) \
  27. || defined(DETOURS_IA64_OFFLINE_LIBRARY)
  28. #undef DETOURS_X64
  29. #undef DETOURS_X86
  30. #undef DETOURS_IA64
  31. #undef DETOURS_ARM
  32. #undef DETOURS_ARM64
  33. #if defined(DETOURS_X86_OFFLINE_LIBRARY)
  34. #define DetourCopyInstruction DetourCopyInstructionX86
  35. #define DetourSetCodeModule DetourSetCodeModuleX86
  36. #define CDetourDis CDetourDisX86
  37. #define DETOURS_X86
  38. #elif defined(DETOURS_X64_OFFLINE_LIBRARY)
  39. #if !defined(DETOURS_64BIT)
  40. // Fix this as/if bugs are discovered.
  41. //#error X64 disassembler can only build for 64-bit.
  42. #endif
  43. #define DetourCopyInstruction DetourCopyInstructionX64
  44. #define DetourSetCodeModule DetourSetCodeModuleX64
  45. #define CDetourDis CDetourDisX64
  46. #define DETOURS_X64
  47. #elif defined(DETOURS_ARM_OFFLINE_LIBRARY)
  48. #define DetourCopyInstruction DetourCopyInstructionARM
  49. #define DetourSetCodeModule DetourSetCodeModuleARM
  50. #define CDetourDis CDetourDisARM
  51. #define DETOURS_ARM
  52. #elif defined(DETOURS_ARM64_OFFLINE_LIBRARY)
  53. #define DetourCopyInstruction DetourCopyInstructionARM64
  54. #define DetourSetCodeModule DetourSetCodeModuleARM64
  55. #define CDetourDis CDetourDisARM64
  56. #define DETOURS_ARM64
  57. #elif defined(DETOURS_IA64_OFFLINE_LIBRARY)
  58. #define DetourCopyInstruction DetourCopyInstructionIA64
  59. #define DetourSetCodeModule DetourSetCodeModuleIA64
  60. #define DETOURS_IA64
  61. #else
  62. #error
  63. #endif
  64. #endif
  65. //////////////////////////////////////////////////////////////////////////////
  66. //
  67. // Function:
  68. // DetourCopyInstruction(PVOID pDst,
  69. // PVOID *ppDstPool
  70. // PVOID pSrc,
  71. // PVOID *ppTarget,
  72. // LONG *plExtra)
  73. // Purpose:
  74. // Copy a single instruction from pSrc to pDst.
  75. //
  76. // Arguments:
  77. // pDst:
  78. // Destination address for the instruction. May be NULL in which
  79. // case DetourCopyInstruction is used to measure an instruction.
  80. // If not NULL then the source instruction is copied to the
  81. // destination instruction and any relative arguments are adjusted.
  82. // ppDstPool:
  83. // Destination address for the end of the constant pool. The
  84. // constant pool works backwards toward pDst. All memory between
  85. // pDst and *ppDstPool must be available for use by this function.
  86. // ppDstPool may be NULL if pDst is NULL.
  87. // pSrc:
  88. // Source address of the instruction.
  89. // ppTarget:
  90. // Out parameter for any target instruction address pointed to by
  91. // the instruction. For example, a branch or a jump insruction has
  92. // a target, but a load or store instruction doesn't. A target is
  93. // another instruction that may be executed as a result of this
  94. // instruction. ppTarget may be NULL.
  95. // plExtra:
  96. // Out parameter for the number of extra bytes needed by the
  97. // instruction to reach the target. For example, lExtra = 3 if the
  98. // instruction had an 8-bit relative offset, but needs a 32-bit
  99. // relative offset.
  100. //
  101. // Returns:
  102. // Returns the address of the next instruction (following in the source)
  103. // instruction. By subtracting pSrc from the return value, the caller
  104. // can determinte the size of the instruction copied.
  105. //
  106. // Comments:
  107. // By following the pTarget, the caller can follow alternate
  108. // instruction streams. However, it is not always possible to determine
  109. // the target based on static analysis. For example, the destination of
  110. // a jump relative to a register cannot be determined from just the
  111. // instruction stream. The output value, pTarget, can have any of the
  112. // following outputs:
  113. // DETOUR_INSTRUCTION_TARGET_NONE:
  114. // The instruction has no targets.
  115. // DETOUR_INSTRUCTION_TARGET_DYNAMIC:
  116. // The instruction has a non-deterministic (dynamic) target.
  117. // (i.e. the jump is to an address held in a register.)
  118. // Address: The instruction has the specified target.
  119. //
  120. // When copying instructions, DetourCopyInstruction insures that any
  121. // targets remain constant. It does so by adjusting any IP relative
  122. // offsets.
  123. //
  124. #pragma data_seg(".detourd")
  125. #pragma const_seg(".detourc")
  126. //////////////////////////////////////////////////// X86 and X64 Disassembler.
  127. //
  128. // Includes full support for all x86 chips prior to the Pentium III, and some newer stuff.
  129. //
  130. #if defined(DETOURS_X64) || defined(DETOURS_X86)
  131. class CDetourDis
  132. {
  133. public:
  134. CDetourDis(_Out_opt_ PBYTE *ppbTarget,
  135. _Out_opt_ LONG *plExtra);
  136. PBYTE CopyInstruction(PBYTE pbDst, PBYTE pbSrc);
  137. static BOOL SanityCheckSystem();
  138. static BOOL SetCodeModule(PBYTE pbBeg, PBYTE pbEnd, BOOL fLimitReferencesToModule);
  139. public:
  140. struct COPYENTRY;
  141. typedef const COPYENTRY * REFCOPYENTRY;
  142. typedef PBYTE (CDetourDis::* COPYFUNC)(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  143. // nFlagBits flags.
  144. enum {
  145. DYNAMIC = 0x1u,
  146. ADDRESS = 0x2u,
  147. NOENLARGE = 0x4u,
  148. RAX = 0x8u,
  149. };
  150. // ModR/M Flags
  151. enum {
  152. SIB = 0x10u,
  153. RIP = 0x20u,
  154. NOTSIB = 0x0fu,
  155. };
  156. struct COPYENTRY
  157. {
  158. // Many of these fields are often ignored. See ENTRY_DataIgnored.
  159. ULONG nFixedSize : 4; // Fixed size of opcode
  160. ULONG nFixedSize16 : 4; // Fixed size when 16 bit operand
  161. ULONG nModOffset : 4; // Offset to mod/rm byte (0=none)
  162. ULONG nRelOffset : 4; // Offset to relative target.
  163. ULONG nFlagBits : 4; // Flags for DYNAMIC, etc.
  164. COPYFUNC pfCopy; // Function pointer.
  165. };
  166. protected:
  167. // These macros define common uses of nFixedSize, nFixedSize16, nModOffset, nRelOffset, nFlagBits, pfCopy.
  168. #define ENTRY_DataIgnored 0, 0, 0, 0, 0,
  169. #define ENTRY_CopyBytes1 { 1, 1, 0, 0, 0, &CDetourDis::CopyBytes }
  170. #ifdef DETOURS_X64
  171. #define ENTRY_CopyBytes1Address { 9, 5, 0, 0, ADDRESS, &CDetourDis::CopyBytes }
  172. #else
  173. #define ENTRY_CopyBytes1Address { 5, 3, 0, 0, ADDRESS, &CDetourDis::CopyBytes }
  174. #endif
  175. #define ENTRY_CopyBytes1Dynamic { 1, 1, 0, 0, DYNAMIC, &CDetourDis::CopyBytes }
  176. #define ENTRY_CopyBytes2 { 2, 2, 0, 0, 0, &CDetourDis::CopyBytes }
  177. #define ENTRY_CopyBytes2Jump { ENTRY_DataIgnored &CDetourDis::CopyBytesJump }
  178. #define ENTRY_CopyBytes2CantJump { 2, 2, 0, 1, NOENLARGE, &CDetourDis::CopyBytes }
  179. #define ENTRY_CopyBytes2Dynamic { 2, 2, 0, 0, DYNAMIC, &CDetourDis::CopyBytes }
  180. #define ENTRY_CopyBytes3 { 3, 3, 0, 0, 0, &CDetourDis::CopyBytes }
  181. #define ENTRY_CopyBytes3Dynamic { 3, 3, 0, 0, DYNAMIC, &CDetourDis::CopyBytes }
  182. #define ENTRY_CopyBytes3Or5 { 5, 3, 0, 0, 0, &CDetourDis::CopyBytes }
  183. #define ENTRY_CopyBytes3Or5Dynamic { 5, 3, 0, 0, DYNAMIC, &CDetourDis::CopyBytes }// x86 only
  184. #ifdef DETOURS_X64
  185. #define ENTRY_CopyBytes3Or5Rax { 5, 3, 0, 0, RAX, &CDetourDis::CopyBytes }
  186. #define ENTRY_CopyBytes3Or5Target { 5, 5, 0, 1, 0, &CDetourDis::CopyBytes }
  187. #else
  188. #define ENTRY_CopyBytes3Or5Rax { 5, 3, 0, 0, 0, &CDetourDis::CopyBytes }
  189. #define ENTRY_CopyBytes3Or5Target { 5, 3, 0, 1, 0, &CDetourDis::CopyBytes }
  190. #endif
  191. #define ENTRY_CopyBytes4 { 4, 4, 0, 0, 0, &CDetourDis::CopyBytes }
  192. #define ENTRY_CopyBytes5 { 5, 5, 0, 0, 0, &CDetourDis::CopyBytes }
  193. #define ENTRY_CopyBytes5Or7Dynamic { 7, 5, 0, 0, DYNAMIC, &CDetourDis::CopyBytes }
  194. #define ENTRY_CopyBytes7 { 7, 7, 0, 0, 0, &CDetourDis::CopyBytes }
  195. #define ENTRY_CopyBytes2Mod { 2, 2, 1, 0, 0, &CDetourDis::CopyBytes }
  196. #define ENTRY_CopyBytes2ModDynamic { 2, 2, 1, 0, DYNAMIC, &CDetourDis::CopyBytes }
  197. #define ENTRY_CopyBytes2Mod1 { 3, 3, 1, 0, 0, &CDetourDis::CopyBytes }
  198. #define ENTRY_CopyBytes2ModOperand { 6, 4, 1, 0, 0, &CDetourDis::CopyBytes }
  199. #define ENTRY_CopyBytes3Mod { 3, 3, 2, 0, 0, &CDetourDis::CopyBytes } // SSE3 0F 38 opcode modrm
  200. #define ENTRY_CopyBytes3Mod1 { 4, 4, 2, 0, 0, &CDetourDis::CopyBytes } // SSE3 0F 3A opcode modrm .. imm8
  201. #define ENTRY_CopyBytesPrefix { ENTRY_DataIgnored &CDetourDis::CopyBytesPrefix }
  202. #define ENTRY_CopyBytesSegment { ENTRY_DataIgnored &CDetourDis::CopyBytesSegment }
  203. #define ENTRY_CopyBytesRax { ENTRY_DataIgnored &CDetourDis::CopyBytesRax }
  204. #define ENTRY_CopyF2 { ENTRY_DataIgnored &CDetourDis::CopyF2 }
  205. #define ENTRY_CopyF3 { ENTRY_DataIgnored &CDetourDis::CopyF3 } // 32bit x86 only
  206. #define ENTRY_Copy0F { ENTRY_DataIgnored &CDetourDis::Copy0F }
  207. #define ENTRY_Copy0F78 { ENTRY_DataIgnored &CDetourDis::Copy0F78 }
  208. #define ENTRY_Copy0F00 { ENTRY_DataIgnored &CDetourDis::Copy0F00 } // 32bit x86 only
  209. #define ENTRY_Copy0FB8 { ENTRY_DataIgnored &CDetourDis::Copy0FB8 } // 32bit x86 only
  210. #define ENTRY_Copy66 { ENTRY_DataIgnored &CDetourDis::Copy66 }
  211. #define ENTRY_Copy67 { ENTRY_DataIgnored &CDetourDis::Copy67 }
  212. #define ENTRY_CopyF6 { ENTRY_DataIgnored &CDetourDis::CopyF6 }
  213. #define ENTRY_CopyF7 { ENTRY_DataIgnored &CDetourDis::CopyF7 }
  214. #define ENTRY_CopyFF { ENTRY_DataIgnored &CDetourDis::CopyFF }
  215. #define ENTRY_CopyC7 { ENTRY_DataIgnored &CDetourDis::CopyC7 }
  216. #define ENTRY_CopyVex2 { ENTRY_DataIgnored &CDetourDis::CopyVex2 }
  217. #define ENTRY_CopyVex3 { ENTRY_DataIgnored &CDetourDis::CopyVex3 }
  218. #define ENTRY_CopyEvex { ENTRY_DataIgnored &CDetourDis::CopyEvex } // 62, 3 byte payload, then normal with implied prefixes like vex
  219. #define ENTRY_CopyXop { ENTRY_DataIgnored &CDetourDis::CopyXop } // 0x8F ... POP /0 or AMD XOP
  220. #define ENTRY_CopyRex2 { ENTRY_DataIgnored &CDetourDis::CopyRex2 } // 0xD5 Intel APX REX2 (x64 only)
  221. #define ENTRY_CopyBytesXop { 5, 5, 4, 0, 0, &CDetourDis::CopyBytes } // 0x8F xop1 xop2 opcode modrm
  222. #define ENTRY_CopyBytesXop1 { 6, 6, 4, 0, 0, &CDetourDis::CopyBytes } // 0x8F xop1 xop2 opcode modrm ... imm8
  223. #define ENTRY_CopyBytesXop4 { 9, 9, 4, 0, 0, &CDetourDis::CopyBytes } // 0x8F xop1 xop2 opcode modrm ... imm32
  224. #define ENTRY_Invalid { ENTRY_DataIgnored &CDetourDis::Invalid }
  225. PBYTE CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  226. PBYTE CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  227. PBYTE CopyBytesSegment(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  228. PBYTE CopyBytesRax(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  229. PBYTE CopyBytesJump(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  230. PBYTE Invalid(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  231. PBYTE AdjustTarget(PBYTE pbDst, PBYTE pbSrc, UINT cbOp,
  232. UINT cbTargetOffset, UINT cbTargetSize);
  233. protected:
  234. PBYTE Copy0F(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  235. PBYTE Copy0F00(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); // x86 only sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6/dynamic invalid/7
  236. PBYTE Copy0F78(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); // vmread, 66/extrq/ib/ib, F2/insertq/ib/ib
  237. PBYTE Copy0FB8(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); // jmpe or F3/popcnt
  238. PBYTE Copy66(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  239. PBYTE Copy67(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  240. PBYTE CopyF2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  241. PBYTE CopyF3(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); // x86 only
  242. PBYTE CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  243. PBYTE CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  244. PBYTE CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  245. PBYTE CopyC7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  246. PBYTE CopyVex2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  247. PBYTE CopyVex3(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  248. PBYTE CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc);
  249. PBYTE CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p, BYTE fp16 = 0);
  250. PBYTE CopyEvex(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  251. PBYTE CopyXop(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
  252. PBYTE CopyRex2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); // AMD64 only, Intel APX REX2
  253. protected:
  254. static const COPYENTRY s_rceCopyTable[];
  255. static const COPYENTRY s_rceCopyTable0F[];
  256. static const BYTE s_rbModRm[256];
  257. static PBYTE s_pbModuleBeg;
  258. static PBYTE s_pbModuleEnd;
  259. static BOOL s_fLimitReferencesToModule;
  260. protected:
  261. BOOL m_bOperandOverride;
  262. BOOL m_bAddressOverride;
  263. BOOL m_bRaxOverride; // AMD64 only
  264. BOOL m_bVex;
  265. BOOL m_bEvex;
  266. BOOL m_bF2;
  267. BOOL m_bF3; // x86 only
  268. BYTE m_nSegmentOverride;
  269. PBYTE * m_ppbTarget;
  270. LONG * m_plExtra;
  271. LONG m_lScratchExtra;
  272. PBYTE m_pbScratchTarget;
  273. BYTE m_rbScratchDst[64]; // matches or exceeds rbCode
  274. };
  275. PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst,
  276. _Inout_opt_ PVOID *ppDstPool,
  277. _In_ PVOID pSrc,
  278. _Out_opt_ PVOID *ppTarget,
  279. _Out_opt_ LONG *plExtra)
  280. {
  281. UNREFERENCED_PARAMETER(ppDstPool); // x86 & x64 don't use a constant pool.
  282. CDetourDis oDetourDisasm((PBYTE*)ppTarget, plExtra);
  283. return oDetourDisasm.CopyInstruction((PBYTE)pDst, (PBYTE)pSrc);
  284. }
  285. /////////////////////////////////////////////////////////// Disassembler Code.
  286. //
  287. CDetourDis::CDetourDis(_Out_opt_ PBYTE *ppbTarget, _Out_opt_ LONG *plExtra) :
  288. m_bOperandOverride(FALSE),
  289. m_bAddressOverride(FALSE),
  290. m_bRaxOverride(FALSE),
  291. m_bVex(FALSE),
  292. m_bEvex(FALSE),
  293. m_bF2(FALSE),
  294. m_bF3(FALSE)
  295. {
  296. m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget;
  297. m_plExtra = plExtra ? plExtra : &m_lScratchExtra;
  298. *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_NONE;
  299. *m_plExtra = 0;
  300. }
  301. PBYTE CDetourDis::CopyInstruction(PBYTE pbDst, PBYTE pbSrc)
  302. {
  303. // Configure scratch areas if real areas are not available.
  304. if (NULL == pbDst) {
  305. pbDst = m_rbScratchDst;
  306. }
  307. if (NULL == pbSrc) {
  308. // We can't copy a non-existent instruction.
  309. SetLastError(ERROR_INVALID_DATA);
  310. return NULL;
  311. }
  312. // Figure out how big the instruction is, do the appropriate copy,
  313. // and figure out what the target of the instruction is if any.
  314. //
  315. REFCOPYENTRY pEntry = &s_rceCopyTable[pbSrc[0]];
  316. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  317. }
  318. PBYTE CDetourDis::CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  319. {
  320. UINT nBytesFixed;
  321. UINT const nModOffset = pEntry->nModOffset;
  322. UINT const nFlagBits = pEntry->nFlagBits;
  323. UINT const nFixedSize = pEntry->nFixedSize;
  324. UINT const nFixedSize16 = pEntry->nFixedSize16;
  325. if (nFlagBits & ADDRESS) {
  326. nBytesFixed = m_bAddressOverride ? nFixedSize16 : nFixedSize;
  327. }
  328. #ifdef DETOURS_X64
  329. // REX.W trumps 66
  330. else if (m_bRaxOverride) {
  331. nBytesFixed = nFixedSize + ((nFlagBits & RAX) ? 4 : 0);
  332. }
  333. #endif
  334. else if (m_bVex || m_bEvex) {
  335. // VEX/EVEX pp field does not shrink immediates to 16-bit.
  336. // This matters for EVEX MAP4 (APX) where entries like opcode 81
  337. // (Group 1 imm32) have nFixedSize=6 but nFixedSize16=4.
  338. nBytesFixed = nFixedSize;
  339. }
  340. else {
  341. nBytesFixed = m_bOperandOverride ? nFixedSize16 : nFixedSize;
  342. }
  343. UINT nBytes = nBytesFixed;
  344. UINT nRelOffset = pEntry->nRelOffset;
  345. UINT cbTarget = nBytes - nRelOffset;
  346. if (nModOffset > 0) {
  347. ASSERT(nRelOffset == 0);
  348. BYTE const bModRm = pbSrc[nModOffset];
  349. BYTE const bFlags = s_rbModRm[bModRm];
  350. nBytes += bFlags & NOTSIB;
  351. if (bFlags & SIB) {
  352. BYTE const bSib = pbSrc[nModOffset + 1];
  353. if ((bSib & 0x07) == 0x05) {
  354. if ((bModRm & 0xc0) == 0x00) {
  355. nBytes += 4;
  356. }
  357. else if ((bModRm & 0xc0) == 0x40) {
  358. nBytes += 1;
  359. }
  360. else if ((bModRm & 0xc0) == 0x80) {
  361. nBytes += 4;
  362. }
  363. }
  364. cbTarget = nBytes - nRelOffset;
  365. }
  366. #ifdef DETOURS_X64
  367. else if (bFlags & RIP) {
  368. nRelOffset = nModOffset + 1;
  369. cbTarget = 4;
  370. }
  371. #endif
  372. }
  373. CopyMemory(pbDst, pbSrc, nBytes);
  374. if (nRelOffset) {
  375. *m_ppbTarget = AdjustTarget(pbDst, pbSrc, nBytes, nRelOffset, cbTarget);
  376. #ifdef DETOURS_X64
  377. if (pEntry->nRelOffset == 0) {
  378. // This is a data target, not a code target, so we shouldn't return it.
  379. *m_ppbTarget = NULL;
  380. }
  381. #endif
  382. }
  383. if (nFlagBits & NOENLARGE) {
  384. *m_plExtra = -*m_plExtra;
  385. }
  386. if (nFlagBits & DYNAMIC) {
  387. *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  388. }
  389. return pbSrc + nBytes;
  390. }
  391. PBYTE CDetourDis::CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  392. {
  393. pbDst[0] = pbSrc[0];
  394. pEntry = &s_rceCopyTable[pbSrc[1]];
  395. return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
  396. }
  397. PBYTE CDetourDis::CopyBytesSegment(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  398. {
  399. m_nSegmentOverride = pbSrc[0];
  400. return CopyBytesPrefix(0, pbDst, pbSrc);
  401. }
  402. PBYTE CDetourDis::CopyBytesRax(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  403. { // AMD64 only
  404. if (pbSrc[0] & 0x8) {
  405. m_bRaxOverride = TRUE;
  406. }
  407. return CopyBytesPrefix(0, pbDst, pbSrc);
  408. }
  409. PBYTE CDetourDis::CopyBytesJump(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  410. {
  411. (void)pEntry;
  412. PVOID pvSrcAddr = &pbSrc[1];
  413. PVOID pvDstAddr = NULL;
  414. LONG_PTR nOldOffset = (LONG_PTR)*(signed char*&)pvSrcAddr;
  415. LONG_PTR nNewOffset = 0;
  416. *m_ppbTarget = pbSrc + 2 + nOldOffset;
  417. if (pbSrc[0] == 0xeb) {
  418. pbDst[0] = 0xe9;
  419. pvDstAddr = &pbDst[1];
  420. nNewOffset = nOldOffset - ((pbDst - pbSrc) + 3);
  421. *(UNALIGNED LONG*&)pvDstAddr = (LONG)nNewOffset;
  422. *m_plExtra = 3;
  423. return pbSrc + 2;
  424. }
  425. ASSERT(pbSrc[0] >= 0x70 && pbSrc[0] <= 0x7f);
  426. pbDst[0] = 0x0f;
  427. pbDst[1] = 0x80 | (pbSrc[0] & 0xf);
  428. pvDstAddr = &pbDst[2];
  429. nNewOffset = nOldOffset - ((pbDst - pbSrc) + 4);
  430. *(UNALIGNED LONG*&)pvDstAddr = (LONG)nNewOffset;
  431. *m_plExtra = 4;
  432. return pbSrc + 2;
  433. }
  434. PBYTE CDetourDis::AdjustTarget(PBYTE pbDst, PBYTE pbSrc, UINT cbOp,
  435. UINT cbTargetOffset, UINT cbTargetSize)
  436. {
  437. PBYTE pbTarget = NULL;
  438. #if 1 // fault injection to test test code
  439. #if defined(DETOURS_X64)
  440. typedef LONGLONG T;
  441. #else
  442. typedef LONG T;
  443. #endif
  444. T nOldOffset;
  445. T nNewOffset;
  446. PVOID pvTargetAddr = &pbDst[cbTargetOffset];
  447. switch (cbTargetSize) {
  448. case 1:
  449. nOldOffset = *(signed char*&)pvTargetAddr;
  450. break;
  451. case 2:
  452. nOldOffset = *(UNALIGNED SHORT*&)pvTargetAddr;
  453. break;
  454. case 4:
  455. nOldOffset = *(UNALIGNED LONG*&)pvTargetAddr;
  456. break;
  457. #if defined(DETOURS_X64)
  458. case 8:
  459. nOldOffset = *(UNALIGNED LONGLONG*&)pvTargetAddr;
  460. break;
  461. #endif
  462. default:
  463. ASSERT(!"cbTargetSize is invalid.");
  464. nOldOffset = 0;
  465. break;
  466. }
  467. pbTarget = pbSrc + cbOp + nOldOffset;
  468. nNewOffset = nOldOffset - (T)(pbDst - pbSrc);
  469. switch (cbTargetSize) {
  470. case 1:
  471. *(CHAR*&)pvTargetAddr = (CHAR)nNewOffset;
  472. if (nNewOffset < SCHAR_MIN || nNewOffset > SCHAR_MAX) {
  473. *m_plExtra = sizeof(ULONG) - 1;
  474. }
  475. break;
  476. case 2:
  477. *(UNALIGNED SHORT*&)pvTargetAddr = (SHORT)nNewOffset;
  478. if (nNewOffset < SHRT_MIN || nNewOffset > SHRT_MAX) {
  479. *m_plExtra = sizeof(ULONG) - 2;
  480. }
  481. break;
  482. case 4:
  483. *(UNALIGNED LONG*&)pvTargetAddr = (LONG)nNewOffset;
  484. if (nNewOffset < LONG_MIN || nNewOffset > LONG_MAX) {
  485. *m_plExtra = sizeof(ULONG) - 4;
  486. }
  487. break;
  488. #if defined(DETOURS_X64)
  489. case 8:
  490. *(UNALIGNED LONGLONG*&)pvTargetAddr = nNewOffset;
  491. break;
  492. #endif
  493. }
  494. #ifdef DETOURS_X64
  495. // When we are only computing size, source and dest can be
  496. // far apart, distance not encodable in 32bits. Ok.
  497. // At least still check the lower 32bits.
  498. if (pbDst >= m_rbScratchDst && pbDst < (sizeof(m_rbScratchDst) + m_rbScratchDst)) {
  499. ASSERT((((size_t)pbDst + cbOp + nNewOffset) & 0xFFFFFFFF) == (((size_t)pbTarget) & 0xFFFFFFFF));
  500. }
  501. else
  502. #endif
  503. {
  504. ASSERT(pbDst + cbOp + nNewOffset == pbTarget);
  505. }
  506. #endif
  507. return pbTarget;
  508. }
  509. PBYTE CDetourDis::Invalid(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  510. {
  511. (void)pbDst;
  512. (void)pEntry;
  513. ASSERT(!"Invalid Instruction");
  514. return pbSrc + 1;
  515. }
  516. ////////////////////////////////////////////////////// Individual Bytes Codes.
  517. //
  518. PBYTE CDetourDis::Copy0F(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  519. {
  520. pbDst[0] = pbSrc[0];
  521. pEntry = &s_rceCopyTable0F[pbSrc[1]];
  522. return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
  523. }
  524. PBYTE CDetourDis::Copy0F78(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  525. {
  526. // vmread, 66/extrq, F2/insertq
  527. static const COPYENTRY vmread = /* 78 */ ENTRY_CopyBytes2Mod;
  528. static const COPYENTRY extrq_insertq = /* 78 */ ENTRY_CopyBytes4;
  529. ASSERT(!(m_bF2 && m_bOperandOverride));
  530. // For insertq and presumably despite documentation extrq, mode must be 11, not checked.
  531. // insertq/extrq/78 are followed by two immediate bytes, and given mode == 11, mod/rm byte is always one byte,
  532. // and the 0x78 makes 4 bytes (not counting the 66/F2/F which are accounted for elsewhere)
  533. REFCOPYENTRY const pEntry = ((m_bF2 || m_bOperandOverride) ? &extrq_insertq : &vmread);
  534. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  535. }
  536. PBYTE CDetourDis::Copy0F00(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  537. {
  538. // jmpe is 32bit x86 only
  539. // Notice that the sizes are the same either way, but jmpe is marked as "dynamic".
  540. static const COPYENTRY other = /* B8 */ ENTRY_CopyBytes2Mod; // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6 invalid/7
  541. static const COPYENTRY jmpe = /* B8 */ ENTRY_CopyBytes2ModDynamic; // jmpe/6 x86-on-IA64 syscalls
  542. REFCOPYENTRY const pEntry = (((6 << 3) == ((7 << 3) & pbSrc[1])) ? &jmpe : &other);
  543. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  544. }
  545. PBYTE CDetourDis::Copy0FB8(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  546. {
  547. // jmpe is 32bit x86 only
  548. static const COPYENTRY popcnt = /* B8 */ ENTRY_CopyBytes2Mod;
  549. static const COPYENTRY jmpe = /* B8 */ ENTRY_CopyBytes3Or5Dynamic; // jmpe x86-on-IA64 syscalls
  550. REFCOPYENTRY const pEntry = m_bF3 ? &popcnt : &jmpe;
  551. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  552. }
  553. PBYTE CDetourDis::Copy66(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  554. { // Operand-size override prefix
  555. m_bOperandOverride = TRUE;
  556. return CopyBytesPrefix(pEntry, pbDst, pbSrc);
  557. }
  558. PBYTE CDetourDis::Copy67(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  559. { // Address size override prefix
  560. m_bAddressOverride = TRUE;
  561. return CopyBytesPrefix(pEntry, pbDst, pbSrc);
  562. }
  563. PBYTE CDetourDis::CopyF2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  564. {
  565. m_bF2 = TRUE;
  566. return CopyBytesPrefix(pEntry, pbDst, pbSrc);
  567. }
  568. PBYTE CDetourDis::CopyF3(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  569. { // x86 only
  570. m_bF3 = TRUE;
  571. return CopyBytesPrefix(pEntry, pbDst, pbSrc);
  572. }
  573. PBYTE CDetourDis::CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  574. {
  575. (void)pEntry;
  576. // TEST BYTE /0 and /1 (both encodings are TEST per Intel SDM Vol 2A Group 3
  577. // and AMD APM Vol 3; /1 is an undocumented alias of /0 historically but is
  578. // now documented in both manuals).
  579. if (0x00 == (0x30 & pbSrc[1])) { // reg(bits 543) of ModR/M == 000 or 001
  580. static const COPYENTRY ce = /* f6 */ ENTRY_CopyBytes2Mod1;
  581. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  582. }
  583. // DIV /6
  584. // IDIV /7
  585. // IMUL /5
  586. // MUL /4
  587. // NEG /3
  588. // NOT /2
  589. static const COPYENTRY ce = /* f6 */ ENTRY_CopyBytes2Mod;
  590. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  591. }
  592. PBYTE CDetourDis::CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  593. {
  594. (void)pEntry;
  595. // TEST WORD /0 and /1 (see CopyF6 for /1 rationale).
  596. if (0x00 == (0x30 & pbSrc[1])) { // reg(bits 543) of ModR/M == 000 or 001
  597. static const COPYENTRY ce = /* f7 */ ENTRY_CopyBytes2ModOperand;
  598. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  599. }
  600. // DIV /6
  601. // IDIV /7
  602. // IMUL /5
  603. // MUL /4
  604. // NEG /3
  605. // NOT /2
  606. static const COPYENTRY ce = /* f7 */ ENTRY_CopyBytes2Mod;
  607. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  608. }
  609. PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  610. { // INC /0
  611. // DEC /1
  612. // CALL /2
  613. // CALL /3
  614. // JMP /4
  615. // JMP /5
  616. // PUSH /6
  617. // invalid/7
  618. (void)pEntry;
  619. static const COPYENTRY ce = /* ff */ ENTRY_CopyBytes2Mod;
  620. PBYTE pbOut = (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  621. BYTE const b1 = pbSrc[1];
  622. if (0x15 == b1 || 0x25 == b1) { // CALL [], JMP []
  623. #ifdef DETOURS_X64
  624. // All segments but FS and GS are equivalent.
  625. if (m_nSegmentOverride != 0x64 && m_nSegmentOverride != 0x65)
  626. #else
  627. if (m_nSegmentOverride == 0 || m_nSegmentOverride == 0x2E)
  628. #endif
  629. {
  630. #ifdef DETOURS_X64
  631. INT32 offset = *(UNALIGNED INT32*)&pbSrc[2];
  632. PBYTE *ppbTarget = (PBYTE *)(pbSrc + 6 + offset);
  633. #else
  634. PBYTE *ppbTarget = (PBYTE *)(SIZE_T)*(UNALIGNED ULONG*)&pbSrc[2];
  635. #endif
  636. if (s_fLimitReferencesToModule &&
  637. (ppbTarget < (PVOID)s_pbModuleBeg || ppbTarget >= (PVOID)s_pbModuleEnd)) {
  638. *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  639. }
  640. else {
  641. // This can access violate on random bytes. Use DetourSetCodeModule.
  642. *m_ppbTarget = *ppbTarget;
  643. }
  644. }
  645. else {
  646. *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  647. }
  648. }
  649. else if (0x10 == (0x30 & b1) || // CALL /2 or /3 --> reg(bits 543) of ModR/M == 010 or 011
  650. 0x20 == (0x30 & b1)) { // JMP /4 or /5 --> reg(bits 543) of ModR/M == 100 or 101
  651. *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  652. }
  653. return pbOut;
  654. }
  655. PBYTE CDetourDis::CopyC7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  656. {
  657. (void)pEntry;
  658. // C7 /7 is XBEGIN rel32 (or rel16 with 66 prefix).
  659. // It has a relative displacement that must be relocated like CALL/JMP.
  660. if (0x38 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 111
  661. static const COPYENTRY ce = /* c7 /7 */ { 6, 4, 0, 2, 0, &CDetourDis::CopyBytes };
  662. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  663. }
  664. // MOV /0 r/m, imm16/32
  665. static const COPYENTRY ce = /* c7 /0 */ ENTRY_CopyBytes2ModOperand;
  666. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  667. }
  668. PBYTE CDetourDis::CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p, BYTE fp16)
  669. // m is first instead of last in the hopes of pbDst/pbSrc being
  670. // passed along efficiently in the registers they were already in.
  671. {
  672. static const COPYENTRY ceF38 = /* 38 */ ENTRY_CopyBytes2Mod;
  673. static const COPYENTRY ceF3A = /* 3A */ ENTRY_CopyBytes2Mod1;
  674. static const COPYENTRY ceInvalid = /* C4 */ ENTRY_Invalid;
  675. switch (p & 3) {
  676. case 0: break;
  677. case 1: m_bOperandOverride = TRUE; break;
  678. case 2: m_bF3 = TRUE; break;
  679. case 3: m_bF2 = TRUE; break;
  680. }
  681. REFCOPYENTRY pEntry;
  682. // see https://software.intel.com/content/www/us/en/develop/download/intel-avx512-fp16-architecture-specification.html
  683. // EVEX maps (with FP16 and APX mmm-bit extension):
  684. // mmm=001 (MAP1) and mmm=101 (MAP5) share the legacy 0F opcode structure,
  685. // so per-opcode sizing must come from s_rceCopyTable0F (e.g. MAP5 C2 /r ib = VCMPPH/VCMPSH).
  686. // mmm=010 (MAP2) and mmm=110 (MAP6) share the legacy 0F 38 structure (ModR/M, no imm).
  687. // mmm=011 (MAP3) has the 0F 3A structure (ModR/M + imm8).
  688. // mmm=100 (MAP4, APX) mirrors legacy MAP0 opcode structure (per-opcode sizing).
  689. switch (m | fp16) {
  690. default: return Invalid(&ceInvalid, pbDst, pbSrc);
  691. case 5: // MAP5 (FP16) - opcode structure mirrors 0F (MAP1).
  692. case 1: pEntry = &s_rceCopyTable0F[pbSrc[0]];
  693. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  694. case 6: // MAP6 (FP16) - opcode structure mirrors 0F 38 (MAP2).
  695. case 2: return CopyBytes(&ceF38, pbDst, pbSrc);
  696. case 3: return CopyBytes(&ceF3A, pbDst, pbSrc);
  697. case 4: // MAP4 (APX) - promoted legacy MAP0 instructions.
  698. pEntry = &s_rceCopyTable[pbSrc[0]];
  699. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  700. }
  701. }
  702. PBYTE CDetourDis::CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc)
  703. // m is first instead of last in the hopes of pbDst/pbSrc being
  704. // passed along efficiently in the registers they were already in.
  705. {
  706. m_bVex = TRUE;
  707. BYTE const p = (BYTE)(pbSrc[-1] & 3); // p in last byte
  708. return CopyVexEvexCommon(m, pbDst, pbSrc, p);
  709. }
  710. PBYTE CDetourDis::CopyVex3(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  711. // 3 byte VEX prefix 0xC4
  712. {
  713. #ifdef DETOURS_X86
  714. const static COPYENTRY ceLES = /* C4 */ ENTRY_CopyBytes2Mod;
  715. if ((pbSrc[1] & 0xC0) != 0xC0) {
  716. REFCOPYENTRY pEntry = &ceLES;
  717. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  718. }
  719. #endif
  720. pbDst[0] = pbSrc[0];
  721. pbDst[1] = pbSrc[1];
  722. pbDst[2] = pbSrc[2];
  723. #ifdef DETOURS_X64
  724. m_bRaxOverride |= !!(pbSrc[2] & 0x80); // w in last byte, see CopyBytesRax
  725. #else
  726. //
  727. // TODO
  728. //
  729. // Usually the VEX.W bit changes the size of a general purpose register and is ignored for 32bit.
  730. // Sometimes it is an opcode extension.
  731. // Look in the Intel manual, in the instruction-by-instruction reference, for ".W1",
  732. // without nearby wording saying it is ignored for 32bit.
  733. // For example: "VFMADD132PD/VFMADD213PD/VFMADD231PD Fused Multiply-Add of Packed Double-Precision Floating-Point Values".
  734. //
  735. // Then, go through each such case and determine if W0 vs. W1 affect the size of the instruction. Probably not.
  736. // Look for the same encoding but with "W1" changed to "W0".
  737. // Here is one such pairing:
  738. // VFMADD132PD/VFMADD213PD/VFMADD231PD Fused Multiply-Add of Packed Double-Precision Floating-Point Values
  739. //
  740. // VEX.DDS.128.66.0F38.W1 98 /r A V/V FMA Multiply packed double-precision floating-point values
  741. // from xmm0 and xmm2/mem, add to xmm1 and
  742. // put result in xmm0.
  743. // VFMADD132PD xmm0, xmm1, xmm2/m128
  744. //
  745. // VFMADD132PS/VFMADD213PS/VFMADD231PS Fused Multiply-Add of Packed Single-Precision Floating-Point Values
  746. // VEX.DDS.128.66.0F38.W0 98 /r A V/V FMA Multiply packed single-precision floating-point values
  747. // from xmm0 and xmm2/mem, add to xmm1 and put
  748. // result in xmm0.
  749. // VFMADD132PS xmm0, xmm1, xmm2/m128
  750. //
  751. #endif
  752. return CopyVexCommon(pbSrc[1] & 0x1F, pbDst + 3, pbSrc + 3);
  753. }
  754. PBYTE CDetourDis::CopyVex2(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  755. // 2 byte VEX prefix 0xC5
  756. {
  757. #ifdef DETOURS_X86
  758. const static COPYENTRY ceLDS = /* C5 */ ENTRY_CopyBytes2Mod;
  759. if ((pbSrc[1] & 0xC0) != 0xC0) {
  760. REFCOPYENTRY pEntry = &ceLDS;
  761. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  762. }
  763. #endif
  764. pbDst[0] = pbSrc[0];
  765. pbDst[1] = pbSrc[1];
  766. return CopyVexCommon(1, pbDst + 2, pbSrc + 2);
  767. }
  768. PBYTE CDetourDis::CopyEvex(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  769. // 62, 3 byte payload, x86 with implied prefixes like Vex
  770. // for 32bit, mode 0xC0 else fallback to bound /r
  771. {
  772. // NOTE: Intel and Wikipedia number these differently.
  773. // Intel says 0-2, Wikipedia says 1-3.
  774. BYTE const p0 = pbSrc[1];
  775. #ifdef DETOURS_X86
  776. const static COPYENTRY ceBound = /* 62 */ ENTRY_CopyBytes2Mod;
  777. if ((p0 & 0xC0) != 0xC0) {
  778. return CopyBytes(&ceBound, pbDst, pbSrc);
  779. }
  780. #endif
  781. static const COPYENTRY ceInvalid = /* 62 */ ENTRY_Invalid;
  782. BYTE const p1 = pbSrc[2];
  783. if ((p1 & 0x04) != 0x04)
  784. return Invalid(&ceInvalid, pbDst, pbSrc);
  785. // Copy 4 byte prefix.
  786. *(UNALIGNED ULONG *)pbDst = *(UNALIGNED ULONG*)pbSrc;
  787. m_bEvex = TRUE;
  788. #ifdef DETOURS_X64
  789. m_bRaxOverride |= !!(p1 & 0x80); // w
  790. #endif
  791. // P0 layout: R'(7) X(6) B3(5) R'4(4) B4(3) m(2) m(1) m(0)
  792. // Bits [2:0] = map (1-7). Bit 3 = B4 (APX register extension, not a map bit).
  793. // For FP16: bit 2 extends map (MAP5=101, MAP6=110).
  794. // For APX: map=4 (100) uses bit 2 as part of mmm field.
  795. return CopyVexEvexCommon(p0 & 3u, pbDst + 4, pbSrc + 4, p1 & 3u, p0 & 4u);
  796. }
  797. PBYTE CDetourDis::CopyXop(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
  798. /* 3 byte AMD XOP prefix 0x8F
  799. byte0: 0x8F
  800. byte1: RXBmmmmm
  801. byte2: WvvvvLpp
  802. byte3: opcode
  803. mmmmm >= 8, else pop
  804. mmmmm only otherwise defined for 8, 9, A.
  805. pp is like VEX but only instructions with 0 are defined
  806. */
  807. {
  808. const static COPYENTRY cePop = /* 8F */ ENTRY_CopyBytes2Mod;
  809. const static COPYENTRY ceXop = /* 8F */ ENTRY_CopyBytesXop;
  810. const static COPYENTRY ceXop1 = /* 8F */ ENTRY_CopyBytesXop1;
  811. const static COPYENTRY ceXop4 = /* 8F */ ENTRY_CopyBytesXop4;
  812. BYTE const m = (BYTE)(pbSrc[1] & 0x1F);
  813. ASSERT(m <= 10);
  814. switch (m)
  815. {
  816. default:
  817. return CopyBytes(&cePop, pbDst, pbSrc);
  818. case 8: // modrm with 8bit immediate
  819. return CopyBytes(&ceXop1, pbDst, pbSrc);
  820. case 9: // modrm with no immediate
  821. return CopyBytes(&ceXop, pbDst, pbSrc);
  822. case 10: // modrm with 32bit immediate
  823. return CopyBytes(&ceXop4, pbDst, pbSrc);
  824. }
  825. }
  826. PBYTE CDetourDis::CopyRex2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  827. // Intel APX REX2 prefix 0xD5 (64-bit mode only)
  828. // Byte 0: D5
  829. // Byte 1: M(7) R4(6) X4(5) B4(4) W(3) R3(2) X3(1) B3(0)
  830. // M: 0 = opcode from MAP0, 1 = opcode from MAP1 (no 0F escape needed)
  831. // W: operand size override to 64-bit (same as REX.W)
  832. {
  833. (void)pEntry;
  834. BYTE const payload = pbSrc[1];
  835. if (payload & 0x08) { // W bit (bit 3)
  836. m_bRaxOverride = TRUE;
  837. }
  838. pbDst[0] = pbSrc[0];
  839. pbDst[1] = pbSrc[1];
  840. PBYTE pbOut;
  841. if (payload & 0x80) { // M bit (bit 7) - MAP1
  842. REFCOPYENTRY pEntry2 = &s_rceCopyTable0F[pbSrc[2]];
  843. pbOut = (this->*pEntry2->pfCopy)(pEntry2, pbDst + 2, pbSrc + 2);
  844. }
  845. else { // MAP0
  846. REFCOPYENTRY pEntry2 = &s_rceCopyTable[pbSrc[2]];
  847. pbOut = (this->*pEntry2->pfCopy)(pEntry2, pbDst + 2, pbSrc + 2);
  848. }
  849. // JMPABS: REX2 with payload=0x00 (M=0, W=0, all ext bits 0) and opcode A1.
  850. // This is an absolute 64-bit jump whose target is the 8-byte immediate.
  851. if (payload == 0x00 && pbSrc[2] == 0xA1) {
  852. *m_ppbTarget = *(UNALIGNED PBYTE*)&pbSrc[3];
  853. }
  854. return pbOut;
  855. }
  856. //////////////////////////////////////////////////////////////////////////////
  857. //
  858. PBYTE CDetourDis::s_pbModuleBeg = NULL;
  859. PBYTE CDetourDis::s_pbModuleEnd = (PBYTE)~(ULONG_PTR)0;
  860. BOOL CDetourDis::s_fLimitReferencesToModule = FALSE;
  861. BOOL CDetourDis::SetCodeModule(PBYTE pbBeg, PBYTE pbEnd, BOOL fLimitReferencesToModule)
  862. {
  863. if (pbEnd < pbBeg) {
  864. return FALSE;
  865. }
  866. s_pbModuleBeg = pbBeg;
  867. s_pbModuleEnd = pbEnd;
  868. s_fLimitReferencesToModule = fLimitReferencesToModule;
  869. return TRUE;
  870. }
  871. ///////////////////////////////////////////////////////// Disassembler Tables.
  872. //
  873. const BYTE CDetourDis::s_rbModRm[256] = {
  874. 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 0x
  875. 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 1x
  876. 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 2x
  877. 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 3x
  878. 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 4x
  879. 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 5x
  880. 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 6x
  881. 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 7x
  882. 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // 8x
  883. 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // 9x
  884. 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // Ax
  885. 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // Bx
  886. 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Cx
  887. 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Dx
  888. 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Ex
  889. 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 // Fx
  890. };
  891. const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[] =
  892. {
  893. /* 00 */ ENTRY_CopyBytes2Mod, // ADD /r
  894. /* 01 */ ENTRY_CopyBytes2Mod, // ADD /r
  895. /* 02 */ ENTRY_CopyBytes2Mod, // ADD /r
  896. /* 03 */ ENTRY_CopyBytes2Mod, // ADD /r
  897. /* 04 */ ENTRY_CopyBytes2, // ADD ib
  898. /* 05 */ ENTRY_CopyBytes3Or5, // ADD iw
  899. #ifdef DETOURS_X64
  900. /* 06 */ ENTRY_Invalid, // Invalid
  901. /* 07 */ ENTRY_Invalid, // Invalid
  902. #else
  903. /* 06 */ ENTRY_CopyBytes1, // PUSH
  904. /* 07 */ ENTRY_CopyBytes1, // POP
  905. #endif
  906. /* 08 */ ENTRY_CopyBytes2Mod, // OR /r
  907. /* 09 */ ENTRY_CopyBytes2Mod, // OR /r
  908. /* 0A */ ENTRY_CopyBytes2Mod, // OR /r
  909. /* 0B */ ENTRY_CopyBytes2Mod, // OR /r
  910. /* 0C */ ENTRY_CopyBytes2, // OR ib
  911. /* 0D */ ENTRY_CopyBytes3Or5, // OR iw
  912. #ifdef DETOURS_X64
  913. /* 0E */ ENTRY_Invalid, // Invalid
  914. #else
  915. /* 0E */ ENTRY_CopyBytes1, // PUSH
  916. #endif
  917. /* 0F */ ENTRY_Copy0F, // Extension Ops
  918. /* 10 */ ENTRY_CopyBytes2Mod, // ADC /r
  919. /* 11 */ ENTRY_CopyBytes2Mod, // ADC /r
  920. /* 12 */ ENTRY_CopyBytes2Mod, // ADC /r
  921. /* 13 */ ENTRY_CopyBytes2Mod, // ADC /r
  922. /* 14 */ ENTRY_CopyBytes2, // ADC ib
  923. /* 15 */ ENTRY_CopyBytes3Or5, // ADC id
  924. #ifdef DETOURS_X64
  925. /* 16 */ ENTRY_Invalid, // Invalid
  926. /* 17 */ ENTRY_Invalid, // Invalid
  927. #else
  928. /* 16 */ ENTRY_CopyBytes1, // PUSH
  929. /* 17 */ ENTRY_CopyBytes1, // POP
  930. #endif
  931. /* 18 */ ENTRY_CopyBytes2Mod, // SBB /r
  932. /* 19 */ ENTRY_CopyBytes2Mod, // SBB /r
  933. /* 1A */ ENTRY_CopyBytes2Mod, // SBB /r
  934. /* 1B */ ENTRY_CopyBytes2Mod, // SBB /r
  935. /* 1C */ ENTRY_CopyBytes2, // SBB ib
  936. /* 1D */ ENTRY_CopyBytes3Or5, // SBB id
  937. #ifdef DETOURS_X64
  938. /* 1E */ ENTRY_Invalid, // Invalid
  939. /* 1F */ ENTRY_Invalid, // Invalid
  940. #else
  941. /* 1E */ ENTRY_CopyBytes1, // PUSH
  942. /* 1F */ ENTRY_CopyBytes1, // POP
  943. #endif
  944. /* 20 */ ENTRY_CopyBytes2Mod, // AND /r
  945. /* 21 */ ENTRY_CopyBytes2Mod, // AND /r
  946. /* 22 */ ENTRY_CopyBytes2Mod, // AND /r
  947. /* 23 */ ENTRY_CopyBytes2Mod, // AND /r
  948. /* 24 */ ENTRY_CopyBytes2, // AND ib
  949. /* 25 */ ENTRY_CopyBytes3Or5, // AND id
  950. /* 26 */ ENTRY_CopyBytesSegment, // ES prefix
  951. #ifdef DETOURS_X64
  952. /* 27 */ ENTRY_Invalid, // Invalid
  953. #else
  954. /* 27 */ ENTRY_CopyBytes1, // DAA
  955. #endif
  956. /* 28 */ ENTRY_CopyBytes2Mod, // SUB /r
  957. /* 29 */ ENTRY_CopyBytes2Mod, // SUB /r
  958. /* 2A */ ENTRY_CopyBytes2Mod, // SUB /r
  959. /* 2B */ ENTRY_CopyBytes2Mod, // SUB /r
  960. /* 2C */ ENTRY_CopyBytes2, // SUB ib
  961. /* 2D */ ENTRY_CopyBytes3Or5, // SUB id
  962. /* 2E */ ENTRY_CopyBytesSegment, // CS prefix
  963. #ifdef DETOURS_X64
  964. /* 2F */ ENTRY_Invalid, // Invalid
  965. #else
  966. /* 2F */ ENTRY_CopyBytes1, // DAS
  967. #endif
  968. /* 30 */ ENTRY_CopyBytes2Mod, // XOR /r
  969. /* 31 */ ENTRY_CopyBytes2Mod, // XOR /r
  970. /* 32 */ ENTRY_CopyBytes2Mod, // XOR /r
  971. /* 33 */ ENTRY_CopyBytes2Mod, // XOR /r
  972. /* 34 */ ENTRY_CopyBytes2, // XOR ib
  973. /* 35 */ ENTRY_CopyBytes3Or5, // XOR id
  974. /* 36 */ ENTRY_CopyBytesSegment, // SS prefix
  975. #ifdef DETOURS_X64
  976. /* 37 */ ENTRY_Invalid, // Invalid
  977. #else
  978. /* 37 */ ENTRY_CopyBytes1, // AAA
  979. #endif
  980. /* 38 */ ENTRY_CopyBytes2Mod, // CMP /r
  981. /* 39 */ ENTRY_CopyBytes2Mod, // CMP /r
  982. /* 3A */ ENTRY_CopyBytes2Mod, // CMP /r
  983. /* 3B */ ENTRY_CopyBytes2Mod, // CMP /r
  984. /* 3C */ ENTRY_CopyBytes2, // CMP ib
  985. /* 3D */ ENTRY_CopyBytes3Or5, // CMP id
  986. /* 3E */ ENTRY_CopyBytesSegment, // DS prefix
  987. #ifdef DETOURS_X64
  988. /* 3F */ ENTRY_Invalid, // Invalid
  989. #else
  990. /* 3F */ ENTRY_CopyBytes1, // AAS
  991. #endif
  992. #ifdef DETOURS_X64 // For Rax Prefix
  993. /* 40 */ ENTRY_CopyBytesRax, // Rax
  994. /* 41 */ ENTRY_CopyBytesRax, // Rax
  995. /* 42 */ ENTRY_CopyBytesRax, // Rax
  996. /* 43 */ ENTRY_CopyBytesRax, // Rax
  997. /* 44 */ ENTRY_CopyBytesRax, // Rax
  998. /* 45 */ ENTRY_CopyBytesRax, // Rax
  999. /* 46 */ ENTRY_CopyBytesRax, // Rax
  1000. /* 47 */ ENTRY_CopyBytesRax, // Rax
  1001. /* 48 */ ENTRY_CopyBytesRax, // Rax
  1002. /* 49 */ ENTRY_CopyBytesRax, // Rax
  1003. /* 4A */ ENTRY_CopyBytesRax, // Rax
  1004. /* 4B */ ENTRY_CopyBytesRax, // Rax
  1005. /* 4C */ ENTRY_CopyBytesRax, // Rax
  1006. /* 4D */ ENTRY_CopyBytesRax, // Rax
  1007. /* 4E */ ENTRY_CopyBytesRax, // Rax
  1008. /* 4F */ ENTRY_CopyBytesRax, // Rax
  1009. #else
  1010. /* 40 */ ENTRY_CopyBytes1, // INC
  1011. /* 41 */ ENTRY_CopyBytes1, // INC
  1012. /* 42 */ ENTRY_CopyBytes1, // INC
  1013. /* 43 */ ENTRY_CopyBytes1, // INC
  1014. /* 44 */ ENTRY_CopyBytes1, // INC
  1015. /* 45 */ ENTRY_CopyBytes1, // INC
  1016. /* 46 */ ENTRY_CopyBytes1, // INC
  1017. /* 47 */ ENTRY_CopyBytes1, // INC
  1018. /* 48 */ ENTRY_CopyBytes1, // DEC
  1019. /* 49 */ ENTRY_CopyBytes1, // DEC
  1020. /* 4A */ ENTRY_CopyBytes1, // DEC
  1021. /* 4B */ ENTRY_CopyBytes1, // DEC
  1022. /* 4C */ ENTRY_CopyBytes1, // DEC
  1023. /* 4D */ ENTRY_CopyBytes1, // DEC
  1024. /* 4E */ ENTRY_CopyBytes1, // DEC
  1025. /* 4F */ ENTRY_CopyBytes1, // DEC
  1026. #endif
  1027. /* 50 */ ENTRY_CopyBytes1, // PUSH
  1028. /* 51 */ ENTRY_CopyBytes1, // PUSH
  1029. /* 52 */ ENTRY_CopyBytes1, // PUSH
  1030. /* 53 */ ENTRY_CopyBytes1, // PUSH
  1031. /* 54 */ ENTRY_CopyBytes1, // PUSH
  1032. /* 55 */ ENTRY_CopyBytes1, // PUSH
  1033. /* 56 */ ENTRY_CopyBytes1, // PUSH
  1034. /* 57 */ ENTRY_CopyBytes1, // PUSH
  1035. /* 58 */ ENTRY_CopyBytes1, // POP
  1036. /* 59 */ ENTRY_CopyBytes1, // POP
  1037. /* 5A */ ENTRY_CopyBytes1, // POP
  1038. /* 5B */ ENTRY_CopyBytes1, // POP
  1039. /* 5C */ ENTRY_CopyBytes1, // POP
  1040. /* 5D */ ENTRY_CopyBytes1, // POP
  1041. /* 5E */ ENTRY_CopyBytes1, // POP
  1042. /* 5F */ ENTRY_CopyBytes1, // POP
  1043. #ifdef DETOURS_X64
  1044. /* 60 */ ENTRY_Invalid, // Invalid
  1045. /* 61 */ ENTRY_Invalid, // Invalid
  1046. /* 62 */ ENTRY_CopyEvex, // EVEX / AVX512
  1047. #else
  1048. /* 60 */ ENTRY_CopyBytes1, // PUSHAD
  1049. /* 61 */ ENTRY_CopyBytes1, // POPAD
  1050. /* 62 */ ENTRY_CopyEvex, // BOUND /r and EVEX / AVX512
  1051. #endif
  1052. /* 63 */ ENTRY_CopyBytes2Mod, // 32bit ARPL /r, 64bit MOVSXD
  1053. /* 64 */ ENTRY_CopyBytesSegment, // FS prefix
  1054. /* 65 */ ENTRY_CopyBytesSegment, // GS prefix
  1055. /* 66 */ ENTRY_Copy66, // Operand Prefix
  1056. /* 67 */ ENTRY_Copy67, // Address Prefix
  1057. /* 68 */ ENTRY_CopyBytes3Or5, // PUSH
  1058. /* 69 */ ENTRY_CopyBytes2ModOperand, // IMUL /r iz
  1059. /* 6A */ ENTRY_CopyBytes2, // PUSH
  1060. /* 6B */ ENTRY_CopyBytes2Mod1, // IMUL /r ib
  1061. /* 6C */ ENTRY_CopyBytes1, // INS
  1062. /* 6D */ ENTRY_CopyBytes1, // INS
  1063. /* 6E */ ENTRY_CopyBytes1, // OUTS/OUTSB
  1064. /* 6F */ ENTRY_CopyBytes1, // OUTS/OUTSW
  1065. /* 70 */ ENTRY_CopyBytes2Jump, // JO // 0f80
  1066. /* 71 */ ENTRY_CopyBytes2Jump, // JNO // 0f81
  1067. /* 72 */ ENTRY_CopyBytes2Jump, // JB/JC/JNAE // 0f82
  1068. /* 73 */ ENTRY_CopyBytes2Jump, // JAE/JNB/JNC // 0f83
  1069. /* 74 */ ENTRY_CopyBytes2Jump, // JE/JZ // 0f84
  1070. /* 75 */ ENTRY_CopyBytes2Jump, // JNE/JNZ // 0f85
  1071. /* 76 */ ENTRY_CopyBytes2Jump, // JBE/JNA // 0f86
  1072. /* 77 */ ENTRY_CopyBytes2Jump, // JA/JNBE // 0f87
  1073. /* 78 */ ENTRY_CopyBytes2Jump, // JS // 0f88
  1074. /* 79 */ ENTRY_CopyBytes2Jump, // JNS // 0f89
  1075. /* 7A */ ENTRY_CopyBytes2Jump, // JP/JPE // 0f8a
  1076. /* 7B */ ENTRY_CopyBytes2Jump, // JNP/JPO // 0f8b
  1077. /* 7C */ ENTRY_CopyBytes2Jump, // JL/JNGE // 0f8c
  1078. /* 7D */ ENTRY_CopyBytes2Jump, // JGE/JNL // 0f8d
  1079. /* 7E */ ENTRY_CopyBytes2Jump, // JLE/JNG // 0f8e
  1080. /* 7F */ ENTRY_CopyBytes2Jump, // JG/JNLE // 0f8f
  1081. /* 80 */ ENTRY_CopyBytes2Mod1, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 byte reg, immediate byte
  1082. /* 81 */ ENTRY_CopyBytes2ModOperand, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 byte reg, immediate word or dword
  1083. #ifdef DETOURS_X64
  1084. /* 82 */ ENTRY_Invalid, // Invalid
  1085. #else
  1086. /* 82 */ ENTRY_CopyBytes2Mod1, // MOV al,x
  1087. #endif
  1088. /* 83 */ ENTRY_CopyBytes2Mod1, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 reg, immediate byte
  1089. /* 84 */ ENTRY_CopyBytes2Mod, // TEST /r
  1090. /* 85 */ ENTRY_CopyBytes2Mod, // TEST /r
  1091. /* 86 */ ENTRY_CopyBytes2Mod, // XCHG /r @todo
  1092. /* 87 */ ENTRY_CopyBytes2Mod, // XCHG /r @todo
  1093. /* 88 */ ENTRY_CopyBytes2Mod, // MOV /r
  1094. /* 89 */ ENTRY_CopyBytes2Mod, // MOV /r
  1095. /* 8A */ ENTRY_CopyBytes2Mod, // MOV /r
  1096. /* 8B */ ENTRY_CopyBytes2Mod, // MOV /r
  1097. /* 8C */ ENTRY_CopyBytes2Mod, // MOV /r
  1098. /* 8D */ ENTRY_CopyBytes2Mod, // LEA /r
  1099. /* 8E */ ENTRY_CopyBytes2Mod, // MOV /r
  1100. /* 8F */ ENTRY_CopyXop, // POP /0 or AMD XOP
  1101. /* 90 */ ENTRY_CopyBytes1, // NOP
  1102. /* 91 */ ENTRY_CopyBytes1, // XCHG
  1103. /* 92 */ ENTRY_CopyBytes1, // XCHG
  1104. /* 93 */ ENTRY_CopyBytes1, // XCHG
  1105. /* 94 */ ENTRY_CopyBytes1, // XCHG
  1106. /* 95 */ ENTRY_CopyBytes1, // XCHG
  1107. /* 96 */ ENTRY_CopyBytes1, // XCHG
  1108. /* 97 */ ENTRY_CopyBytes1, // XCHG
  1109. /* 98 */ ENTRY_CopyBytes1, // CWDE
  1110. /* 99 */ ENTRY_CopyBytes1, // CDQ
  1111. #ifdef DETOURS_X64
  1112. /* 9A */ ENTRY_Invalid, // Invalid
  1113. #else
  1114. /* 9A */ ENTRY_CopyBytes5Or7Dynamic, // CALL cp
  1115. #endif
  1116. /* 9B */ ENTRY_CopyBytes1, // WAIT/FWAIT
  1117. /* 9C */ ENTRY_CopyBytes1, // PUSHFD
  1118. /* 9D */ ENTRY_CopyBytes1, // POPFD
  1119. /* 9E */ ENTRY_CopyBytes1, // SAHF
  1120. /* 9F */ ENTRY_CopyBytes1, // LAHF
  1121. /* A0 */ ENTRY_CopyBytes1Address, // MOV
  1122. /* A1 */ ENTRY_CopyBytes1Address, // MOV
  1123. /* A2 */ ENTRY_CopyBytes1Address, // MOV
  1124. /* A3 */ ENTRY_CopyBytes1Address, // MOV
  1125. /* A4 */ ENTRY_CopyBytes1, // MOVS
  1126. /* A5 */ ENTRY_CopyBytes1, // MOVS/MOVSD
  1127. /* A6 */ ENTRY_CopyBytes1, // CMPS/CMPSB
  1128. /* A7 */ ENTRY_CopyBytes1, // CMPS/CMPSW
  1129. /* A8 */ ENTRY_CopyBytes2, // TEST
  1130. /* A9 */ ENTRY_CopyBytes3Or5, // TEST
  1131. /* AA */ ENTRY_CopyBytes1, // STOS/STOSB
  1132. /* AB */ ENTRY_CopyBytes1, // STOS/STOSW
  1133. /* AC */ ENTRY_CopyBytes1, // LODS/LODSB
  1134. /* AD */ ENTRY_CopyBytes1, // LODS/LODSW
  1135. /* AE */ ENTRY_CopyBytes1, // SCAS/SCASB
  1136. /* AF */ ENTRY_CopyBytes1, // SCAS/SCASD
  1137. /* B0 */ ENTRY_CopyBytes2, // MOV B0+rb
  1138. /* B1 */ ENTRY_CopyBytes2, // MOV B0+rb
  1139. /* B2 */ ENTRY_CopyBytes2, // MOV B0+rb
  1140. /* B3 */ ENTRY_CopyBytes2, // MOV B0+rb
  1141. /* B4 */ ENTRY_CopyBytes2, // MOV B0+rb
  1142. /* B5 */ ENTRY_CopyBytes2, // MOV B0+rb
  1143. /* B6 */ ENTRY_CopyBytes2, // MOV B0+rb
  1144. /* B7 */ ENTRY_CopyBytes2, // MOV B0+rb
  1145. /* B8 */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb
  1146. /* B9 */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb
  1147. /* BA */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb
  1148. /* BB */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb
  1149. /* BC */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb
  1150. /* BD */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb
  1151. /* BE */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb
  1152. /* BF */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb
  1153. /* C0 */ ENTRY_CopyBytes2Mod1, // RCL/2 ib, etc.
  1154. /* C1 */ ENTRY_CopyBytes2Mod1, // RCL/2 ib, etc.
  1155. /* C2 */ ENTRY_CopyBytes3, // RET
  1156. /* C3 */ ENTRY_CopyBytes1, // RET
  1157. /* C4 */ ENTRY_CopyVex3, // LES, VEX 3-byte opcodes.
  1158. /* C5 */ ENTRY_CopyVex2, // LDS, VEX 2-byte opcodes.
  1159. /* C6 */ ENTRY_CopyBytes2Mod1, // MOV
  1160. /* C7 */ ENTRY_CopyC7, // MOV/0 XBEGIN/7
  1161. /* C8 */ ENTRY_CopyBytes4, // ENTER
  1162. /* C9 */ ENTRY_CopyBytes1, // LEAVE
  1163. /* CA */ ENTRY_CopyBytes3Dynamic, // RET
  1164. /* CB */ ENTRY_CopyBytes1Dynamic, // RET
  1165. /* CC */ ENTRY_CopyBytes1Dynamic, // INT 3
  1166. /* CD */ ENTRY_CopyBytes2Dynamic, // INT ib
  1167. #ifdef DETOURS_X64
  1168. /* CE */ ENTRY_Invalid, // Invalid
  1169. #else
  1170. /* CE */ ENTRY_CopyBytes1Dynamic, // INTO
  1171. #endif
  1172. /* CF */ ENTRY_CopyBytes1Dynamic, // IRET
  1173. /* D0 */ ENTRY_CopyBytes2Mod, // RCL/2, etc.
  1174. /* D1 */ ENTRY_CopyBytes2Mod, // RCL/2, etc.
  1175. /* D2 */ ENTRY_CopyBytes2Mod, // RCL/2, etc.
  1176. /* D3 */ ENTRY_CopyBytes2Mod, // RCL/2, etc.
  1177. #ifdef DETOURS_X64
  1178. /* D4 */ ENTRY_Invalid, // Invalid
  1179. /* D5 */ ENTRY_CopyRex2, // REX2 (Intel APX)
  1180. #else
  1181. /* D4 */ ENTRY_CopyBytes2, // AAM
  1182. /* D5 */ ENTRY_CopyBytes2, // AAD
  1183. #endif
  1184. /* D6 */ ENTRY_Invalid, // Invalid
  1185. /* D7 */ ENTRY_CopyBytes1, // XLAT/XLATB
  1186. /* D8 */ ENTRY_CopyBytes2Mod, // FADD, etc.
  1187. /* D9 */ ENTRY_CopyBytes2Mod, // F2XM1, etc.
  1188. /* DA */ ENTRY_CopyBytes2Mod, // FLADD, etc.
  1189. /* DB */ ENTRY_CopyBytes2Mod, // FCLEX, etc.
  1190. /* DC */ ENTRY_CopyBytes2Mod, // FADD/0, etc.
  1191. /* DD */ ENTRY_CopyBytes2Mod, // FFREE, etc.
  1192. /* DE */ ENTRY_CopyBytes2Mod, // FADDP, etc.
  1193. /* DF */ ENTRY_CopyBytes2Mod, // FBLD/4, etc.
  1194. /* E0 */ ENTRY_CopyBytes2CantJump, // LOOPNE cb
  1195. /* E1 */ ENTRY_CopyBytes2CantJump, // LOOPE cb
  1196. /* E2 */ ENTRY_CopyBytes2CantJump, // LOOP cb
  1197. /* E3 */ ENTRY_CopyBytes2CantJump, // JCXZ/JECXZ
  1198. /* E4 */ ENTRY_CopyBytes2, // IN ib
  1199. /* E5 */ ENTRY_CopyBytes2, // IN id
  1200. /* E6 */ ENTRY_CopyBytes2, // OUT ib
  1201. /* E7 */ ENTRY_CopyBytes2, // OUT ib
  1202. /* E8 */ ENTRY_CopyBytes3Or5Target, // CALL cd
  1203. /* E9 */ ENTRY_CopyBytes3Or5Target, // JMP cd
  1204. #ifdef DETOURS_X64
  1205. /* EA */ ENTRY_Invalid, // Invalid
  1206. #else
  1207. /* EA */ ENTRY_CopyBytes5Or7Dynamic, // JMP cp
  1208. #endif
  1209. /* EB */ ENTRY_CopyBytes2Jump, // JMP cb
  1210. /* EC */ ENTRY_CopyBytes1, // IN ib
  1211. /* ED */ ENTRY_CopyBytes1, // IN id
  1212. /* EE */ ENTRY_CopyBytes1, // OUT
  1213. /* EF */ ENTRY_CopyBytes1, // OUT
  1214. /* F0 */ ENTRY_CopyBytesPrefix, // LOCK prefix
  1215. /* F1 */ ENTRY_CopyBytes1Dynamic, // INT1 / ICEBP somewhat documented by AMD, not by Intel
  1216. /* F2 */ ENTRY_CopyF2, // REPNE prefix
  1217. //#ifdef DETOURS_X86
  1218. /* F3 */ ENTRY_CopyF3, // REPE prefix
  1219. //#else
  1220. // This does presently suffice for AMD64 but it requires tracing
  1221. // through a bunch of code to verify and seems not worth maintaining.
  1222. // /* F3 */ ENTRY_CopyBytesPrefix, // REPE prefix
  1223. //#endif
  1224. /* F4 */ ENTRY_CopyBytes1, // HLT
  1225. /* F5 */ ENTRY_CopyBytes1, // CMC
  1226. /* F6 */ ENTRY_CopyF6, // TEST/0, DIV/6
  1227. /* F7 */ ENTRY_CopyF7, // TEST/0, DIV/6
  1228. /* F8 */ ENTRY_CopyBytes1, // CLC
  1229. /* F9 */ ENTRY_CopyBytes1, // STC
  1230. /* FA */ ENTRY_CopyBytes1, // CLI
  1231. /* FB */ ENTRY_CopyBytes1, // STI
  1232. /* FC */ ENTRY_CopyBytes1, // CLD
  1233. /* FD */ ENTRY_CopyBytes1, // STD
  1234. /* FE */ ENTRY_CopyBytes2Mod, // DEC/1,INC/0
  1235. /* FF */ ENTRY_CopyFF, // CALL/2
  1236. };
  1237. const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable0F[] =
  1238. {
  1239. #ifdef DETOURS_X86
  1240. /* 00 */ ENTRY_Copy0F00, // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6/dynamic invalid/7
  1241. #else
  1242. /* 00 */ ENTRY_CopyBytes2Mod, // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6/dynamic invalid/7
  1243. #endif
  1244. /* 01 */ ENTRY_CopyBytes2Mod, // INVLPG/7, etc.
  1245. /* 02 */ ENTRY_CopyBytes2Mod, // LAR/r
  1246. /* 03 */ ENTRY_CopyBytes2Mod, // LSL/r
  1247. /* 04 */ ENTRY_Invalid, // _04
  1248. /* 05 */ ENTRY_CopyBytes1, // SYSCALL
  1249. /* 06 */ ENTRY_CopyBytes1, // CLTS
  1250. /* 07 */ ENTRY_CopyBytes1, // SYSRET
  1251. /* 08 */ ENTRY_CopyBytes1, // INVD
  1252. /* 09 */ ENTRY_CopyBytes1, // WBINVD
  1253. /* 0A */ ENTRY_Invalid, // _0A
  1254. /* 0B */ ENTRY_CopyBytes1, // UD2
  1255. /* 0C */ ENTRY_Invalid, // _0C
  1256. /* 0D */ ENTRY_CopyBytes2Mod, // PREFETCH
  1257. /* 0E */ ENTRY_CopyBytes1, // FEMMS (3DNow -- not in Intel documentation)
  1258. /* 0F */ ENTRY_CopyBytes2Mod1, // 3DNow Opcodes
  1259. /* 10 */ ENTRY_CopyBytes2Mod, // MOVSS MOVUPD MOVSD
  1260. /* 11 */ ENTRY_CopyBytes2Mod, // MOVSS MOVUPD MOVSD
  1261. /* 12 */ ENTRY_CopyBytes2Mod, // MOVLPD
  1262. /* 13 */ ENTRY_CopyBytes2Mod, // MOVLPD
  1263. /* 14 */ ENTRY_CopyBytes2Mod, // UNPCKLPD
  1264. /* 15 */ ENTRY_CopyBytes2Mod, // UNPCKHPD
  1265. /* 16 */ ENTRY_CopyBytes2Mod, // MOVHPD
  1266. /* 17 */ ENTRY_CopyBytes2Mod, // MOVHPD
  1267. /* 18 */ ENTRY_CopyBytes2Mod, // PREFETCHINTA...
  1268. /* 19 */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD
  1269. /* 1A */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD
  1270. /* 1B */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD
  1271. /* 1C */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD
  1272. /* 1D */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD
  1273. /* 1E */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD
  1274. /* 1F */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop
  1275. /* 20 */ ENTRY_CopyBytes2Mod, // MOV/r
  1276. /* 21 */ ENTRY_CopyBytes2Mod, // MOV/r
  1277. /* 22 */ ENTRY_CopyBytes2Mod, // MOV/r
  1278. /* 23 */ ENTRY_CopyBytes2Mod, // MOV/r
  1279. #ifdef DETOURS_X64
  1280. /* 24 */ ENTRY_Invalid, // _24
  1281. #else
  1282. /* 24 */ ENTRY_CopyBytes2Mod, // MOV/r,TR TR is test register on 80386 and 80486, removed in Pentium
  1283. #endif
  1284. /* 25 */ ENTRY_Invalid, // _25
  1285. #ifdef DETOURS_X64
  1286. /* 26 */ ENTRY_Invalid, // _26
  1287. #else
  1288. /* 26 */ ENTRY_CopyBytes2Mod, // MOV TR/r TR is test register on 80386 and 80486, removed in Pentium
  1289. #endif
  1290. /* 27 */ ENTRY_Invalid, // _27
  1291. /* 28 */ ENTRY_CopyBytes2Mod, // MOVAPS MOVAPD
  1292. /* 29 */ ENTRY_CopyBytes2Mod, // MOVAPS MOVAPD
  1293. /* 2A */ ENTRY_CopyBytes2Mod, // CVPI2PS &
  1294. /* 2B */ ENTRY_CopyBytes2Mod, // MOVNTPS MOVNTPD
  1295. /* 2C */ ENTRY_CopyBytes2Mod, // CVTTPS2PI &
  1296. /* 2D */ ENTRY_CopyBytes2Mod, // CVTPS2PI &
  1297. /* 2E */ ENTRY_CopyBytes2Mod, // UCOMISS UCOMISD
  1298. /* 2F */ ENTRY_CopyBytes2Mod, // COMISS COMISD
  1299. /* 30 */ ENTRY_CopyBytes1, // WRMSR
  1300. /* 31 */ ENTRY_CopyBytes1, // RDTSC
  1301. /* 32 */ ENTRY_CopyBytes1, // RDMSR
  1302. /* 33 */ ENTRY_CopyBytes1, // RDPMC
  1303. /* 34 */ ENTRY_CopyBytes1, // SYSENTER
  1304. /* 35 */ ENTRY_CopyBytes1, // SYSEXIT
  1305. /* 36 */ ENTRY_Invalid, // _36
  1306. /* 37 */ ENTRY_CopyBytes1, // GETSEC
  1307. /* 38 */ ENTRY_CopyBytes3Mod, // SSE3 Opcodes
  1308. /* 39 */ ENTRY_Invalid, // _39
  1309. /* 3A */ ENTRY_CopyBytes3Mod1, // SSE3 Opcodes
  1310. /* 3B */ ENTRY_Invalid, // _3B
  1311. /* 3C */ ENTRY_Invalid, // _3C
  1312. /* 3D */ ENTRY_Invalid, // _3D
  1313. /* 3E */ ENTRY_Invalid, // _3E
  1314. /* 3F */ ENTRY_Invalid, // _3F
  1315. /* 40 */ ENTRY_CopyBytes2Mod, // CMOVO (0F 40)
  1316. /* 41 */ ENTRY_CopyBytes2Mod, // CMOVNO (0F 41)
  1317. /* 42 */ ENTRY_CopyBytes2Mod, // CMOVB & CMOVNE (0F 42)
  1318. /* 43 */ ENTRY_CopyBytes2Mod, // CMOVAE & CMOVNB (0F 43)
  1319. /* 44 */ ENTRY_CopyBytes2Mod, // CMOVE & CMOVZ (0F 44)
  1320. /* 45 */ ENTRY_CopyBytes2Mod, // CMOVNE & CMOVNZ (0F 45)
  1321. /* 46 */ ENTRY_CopyBytes2Mod, // CMOVBE & CMOVNA (0F 46)
  1322. /* 47 */ ENTRY_CopyBytes2Mod, // CMOVA & CMOVNBE (0F 47)
  1323. /* 48 */ ENTRY_CopyBytes2Mod, // CMOVS (0F 48)
  1324. /* 49 */ ENTRY_CopyBytes2Mod, // CMOVNS (0F 49)
  1325. /* 4A */ ENTRY_CopyBytes2Mod, // CMOVP & CMOVPE (0F 4A)
  1326. /* 4B */ ENTRY_CopyBytes2Mod, // CMOVNP & CMOVPO (0F 4B)
  1327. /* 4C */ ENTRY_CopyBytes2Mod, // CMOVL & CMOVNGE (0F 4C)
  1328. /* 4D */ ENTRY_CopyBytes2Mod, // CMOVGE & CMOVNL (0F 4D)
  1329. /* 4E */ ENTRY_CopyBytes2Mod, // CMOVLE & CMOVNG (0F 4E)
  1330. /* 4F */ ENTRY_CopyBytes2Mod, // CMOVG & CMOVNLE (0F 4F)
  1331. /* 50 */ ENTRY_CopyBytes2Mod, // MOVMSKPD MOVMSKPD
  1332. /* 51 */ ENTRY_CopyBytes2Mod, // SQRTPS &
  1333. /* 52 */ ENTRY_CopyBytes2Mod, // RSQRTTS RSQRTPS
  1334. /* 53 */ ENTRY_CopyBytes2Mod, // RCPPS RCPSS
  1335. /* 54 */ ENTRY_CopyBytes2Mod, // ANDPS ANDPD
  1336. /* 55 */ ENTRY_CopyBytes2Mod, // ANDNPS ANDNPD
  1337. /* 56 */ ENTRY_CopyBytes2Mod, // ORPS ORPD
  1338. /* 57 */ ENTRY_CopyBytes2Mod, // XORPS XORPD
  1339. /* 58 */ ENTRY_CopyBytes2Mod, // ADDPS &
  1340. /* 59 */ ENTRY_CopyBytes2Mod, // MULPS &
  1341. /* 5A */ ENTRY_CopyBytes2Mod, // CVTPS2PD &
  1342. /* 5B */ ENTRY_CopyBytes2Mod, // CVTDQ2PS &
  1343. /* 5C */ ENTRY_CopyBytes2Mod, // SUBPS &
  1344. /* 5D */ ENTRY_CopyBytes2Mod, // MINPS &
  1345. /* 5E */ ENTRY_CopyBytes2Mod, // DIVPS &
  1346. /* 5F */ ENTRY_CopyBytes2Mod, // MASPS &
  1347. /* 60 */ ENTRY_CopyBytes2Mod, // PUNPCKLBW/r
  1348. /* 61 */ ENTRY_CopyBytes2Mod, // PUNPCKLWD/r
  1349. /* 62 */ ENTRY_CopyBytes2Mod, // PUNPCKLWD/r
  1350. /* 63 */ ENTRY_CopyBytes2Mod, // PACKSSWB/r
  1351. /* 64 */ ENTRY_CopyBytes2Mod, // PCMPGTB/r
  1352. /* 65 */ ENTRY_CopyBytes2Mod, // PCMPGTW/r
  1353. /* 66 */ ENTRY_CopyBytes2Mod, // PCMPGTD/r
  1354. /* 67 */ ENTRY_CopyBytes2Mod, // PACKUSWB/r
  1355. /* 68 */ ENTRY_CopyBytes2Mod, // PUNPCKHBW/r
  1356. /* 69 */ ENTRY_CopyBytes2Mod, // PUNPCKHWD/r
  1357. /* 6A */ ENTRY_CopyBytes2Mod, // PUNPCKHDQ/r
  1358. /* 6B */ ENTRY_CopyBytes2Mod, // PACKSSDW/r
  1359. /* 6C */ ENTRY_CopyBytes2Mod, // PUNPCKLQDQ
  1360. /* 6D */ ENTRY_CopyBytes2Mod, // PUNPCKHQDQ
  1361. /* 6E */ ENTRY_CopyBytes2Mod, // MOVD/r
  1362. /* 6F */ ENTRY_CopyBytes2Mod, // MOV/r
  1363. /* 70 */ ENTRY_CopyBytes2Mod1, // PSHUFW/r ib
  1364. /* 71 */ ENTRY_CopyBytes2Mod1, // PSLLW/6 ib,PSRAW/4 ib,PSRLW/2 ib
  1365. /* 72 */ ENTRY_CopyBytes2Mod1, // PSLLD/6 ib,PSRAD/4 ib,PSRLD/2 ib
  1366. /* 73 */ ENTRY_CopyBytes2Mod1, // PSLLQ/6 ib,PSRLQ/2 ib
  1367. /* 74 */ ENTRY_CopyBytes2Mod, // PCMPEQB/r
  1368. /* 75 */ ENTRY_CopyBytes2Mod, // PCMPEQW/r
  1369. /* 76 */ ENTRY_CopyBytes2Mod, // PCMPEQD/r
  1370. /* 77 */ ENTRY_CopyBytes1, // EMMS
  1371. // extrq/insertq require mode=3 and are followed by two immediate bytes
  1372. /* 78 */ ENTRY_Copy0F78, // VMREAD/r, 66/EXTRQ/r/ib/ib, F2/INSERTQ/r/ib/ib
  1373. // extrq/insertq require mod=3, therefore ENTRY_CopyBytes2, but it ends up the same
  1374. /* 79 */ ENTRY_CopyBytes2Mod, // VMWRITE/r, 66/EXTRQ/r, F2/INSERTQ/r
  1375. /* 7A */ ENTRY_Invalid, // _7A
  1376. /* 7B */ ENTRY_Invalid, // _7B
  1377. /* 7C */ ENTRY_CopyBytes2Mod, // HADDPS
  1378. /* 7D */ ENTRY_CopyBytes2Mod, // HSUBPS
  1379. /* 7E */ ENTRY_CopyBytes2Mod, // MOVD/r
  1380. /* 7F */ ENTRY_CopyBytes2Mod, // MOV/r
  1381. /* 80 */ ENTRY_CopyBytes3Or5Target, // JO
  1382. /* 81 */ ENTRY_CopyBytes3Or5Target, // JNO
  1383. /* 82 */ ENTRY_CopyBytes3Or5Target, // JB,JC,JNAE
  1384. /* 83 */ ENTRY_CopyBytes3Or5Target, // JAE,JNB,JNC
  1385. /* 84 */ ENTRY_CopyBytes3Or5Target, // JE,JZ,JZ
  1386. /* 85 */ ENTRY_CopyBytes3Or5Target, // JNE,JNZ
  1387. /* 86 */ ENTRY_CopyBytes3Or5Target, // JBE,JNA
  1388. /* 87 */ ENTRY_CopyBytes3Or5Target, // JA,JNBE
  1389. /* 88 */ ENTRY_CopyBytes3Or5Target, // JS
  1390. /* 89 */ ENTRY_CopyBytes3Or5Target, // JNS
  1391. /* 8A */ ENTRY_CopyBytes3Or5Target, // JP,JPE
  1392. /* 8B */ ENTRY_CopyBytes3Or5Target, // JNP,JPO
  1393. /* 8C */ ENTRY_CopyBytes3Or5Target, // JL,NGE
  1394. /* 8D */ ENTRY_CopyBytes3Or5Target, // JGE,JNL
  1395. /* 8E */ ENTRY_CopyBytes3Or5Target, // JLE,JNG
  1396. /* 8F */ ENTRY_CopyBytes3Or5Target, // JG,JNLE
  1397. /* 90 */ ENTRY_CopyBytes2Mod, // CMOVO (0F 40)
  1398. /* 91 */ ENTRY_CopyBytes2Mod, // CMOVNO (0F 41)
  1399. /* 92 */ ENTRY_CopyBytes2Mod, // CMOVB & CMOVC & CMOVNAE (0F 42)
  1400. /* 93 */ ENTRY_CopyBytes2Mod, // CMOVAE & CMOVNB & CMOVNC (0F 43)
  1401. /* 94 */ ENTRY_CopyBytes2Mod, // CMOVE & CMOVZ (0F 44)
  1402. /* 95 */ ENTRY_CopyBytes2Mod, // CMOVNE & CMOVNZ (0F 45)
  1403. /* 96 */ ENTRY_CopyBytes2Mod, // CMOVBE & CMOVNA (0F 46)
  1404. /* 97 */ ENTRY_CopyBytes2Mod, // CMOVA & CMOVNBE (0F 47)
  1405. /* 98 */ ENTRY_CopyBytes2Mod, // CMOVS (0F 48)
  1406. /* 99 */ ENTRY_CopyBytes2Mod, // CMOVNS (0F 49)
  1407. /* 9A */ ENTRY_CopyBytes2Mod, // CMOVP & CMOVPE (0F 4A)
  1408. /* 9B */ ENTRY_CopyBytes2Mod, // CMOVNP & CMOVPO (0F 4B)
  1409. /* 9C */ ENTRY_CopyBytes2Mod, // CMOVL & CMOVNGE (0F 4C)
  1410. /* 9D */ ENTRY_CopyBytes2Mod, // CMOVGE & CMOVNL (0F 4D)
  1411. /* 9E */ ENTRY_CopyBytes2Mod, // CMOVLE & CMOVNG (0F 4E)
  1412. /* 9F */ ENTRY_CopyBytes2Mod, // CMOVG & CMOVNLE (0F 4F)
  1413. /* A0 */ ENTRY_CopyBytes1, // PUSH
  1414. /* A1 */ ENTRY_CopyBytes1, // POP
  1415. /* A2 */ ENTRY_CopyBytes1, // CPUID
  1416. /* A3 */ ENTRY_CopyBytes2Mod, // BT (0F A3)
  1417. /* A4 */ ENTRY_CopyBytes2Mod1, // SHLD
  1418. /* A5 */ ENTRY_CopyBytes2Mod, // SHLD
  1419. /* A6 */ ENTRY_CopyBytes2Mod, // XBTS
  1420. /* A7 */ ENTRY_CopyBytes2Mod, // IBTS
  1421. /* A8 */ ENTRY_CopyBytes1, // PUSH
  1422. /* A9 */ ENTRY_CopyBytes1, // POP
  1423. /* AA */ ENTRY_CopyBytes1, // RSM
  1424. /* AB */ ENTRY_CopyBytes2Mod, // BTS (0F AB)
  1425. /* AC */ ENTRY_CopyBytes2Mod1, // SHRD
  1426. /* AD */ ENTRY_CopyBytes2Mod, // SHRD
  1427. // 0F AE mod76=mem mod543=0 fxsave
  1428. // 0F AE mod76=mem mod543=1 fxrstor
  1429. // 0F AE mod76=mem mod543=2 ldmxcsr
  1430. // 0F AE mod76=mem mod543=3 stmxcsr
  1431. // 0F AE mod76=mem mod543=4 xsave
  1432. // 0F AE mod76=mem mod543=5 xrstor
  1433. // 0F AE mod76=mem mod543=6 saveopt
  1434. // 0F AE mod76=mem mod543=7 clflush
  1435. // 0F AE mod76=11b mod543=5 lfence
  1436. // 0F AE mod76=11b mod543=6 mfence
  1437. // 0F AE mod76=11b mod543=7 sfence
  1438. // F3 0F AE mod76=11b mod543=0 rdfsbase
  1439. // F3 0F AE mod76=11b mod543=1 rdgsbase
  1440. // F3 0F AE mod76=11b mod543=2 wrfsbase
  1441. // F3 0F AE mod76=11b mod543=3 wrgsbase
  1442. /* AE */ ENTRY_CopyBytes2Mod, // fxsave fxrstor ldmxcsr stmxcsr xsave xrstor saveopt clflush lfence mfence sfence rdfsbase rdgsbase wrfsbase wrgsbase
  1443. /* AF */ ENTRY_CopyBytes2Mod, // IMUL (0F AF)
  1444. /* B0 */ ENTRY_CopyBytes2Mod, // CMPXCHG (0F B0)
  1445. /* B1 */ ENTRY_CopyBytes2Mod, // CMPXCHG (0F B1)
  1446. /* B2 */ ENTRY_CopyBytes2Mod, // LSS/r
  1447. /* B3 */ ENTRY_CopyBytes2Mod, // BTR (0F B3)
  1448. /* B4 */ ENTRY_CopyBytes2Mod, // LFS/r
  1449. /* B5 */ ENTRY_CopyBytes2Mod, // LGS/r
  1450. /* B6 */ ENTRY_CopyBytes2Mod, // MOVZX/r
  1451. /* B7 */ ENTRY_CopyBytes2Mod, // MOVZX/r
  1452. #ifdef DETOURS_X86
  1453. /* B8 */ ENTRY_Copy0FB8, // jmpe f3/popcnt
  1454. #else
  1455. /* B8 */ ENTRY_CopyBytes2Mod, // f3/popcnt
  1456. #endif
  1457. /* B9 */ ENTRY_Invalid, // _B9
  1458. /* BA */ ENTRY_CopyBytes2Mod1, // BT & BTC & BTR & BTS (0F BA)
  1459. /* BB */ ENTRY_CopyBytes2Mod, // BTC (0F BB)
  1460. /* BC */ ENTRY_CopyBytes2Mod, // BSF (0F BC)
  1461. /* BD */ ENTRY_CopyBytes2Mod, // BSR (0F BD)
  1462. /* BE */ ENTRY_CopyBytes2Mod, // MOVSX/r
  1463. /* BF */ ENTRY_CopyBytes2Mod, // MOVSX/r
  1464. /* C0 */ ENTRY_CopyBytes2Mod, // XADD/r
  1465. /* C1 */ ENTRY_CopyBytes2Mod, // XADD/r
  1466. /* C2 */ ENTRY_CopyBytes2Mod1, // CMPPS &
  1467. /* C3 */ ENTRY_CopyBytes2Mod, // MOVNTI
  1468. /* C4 */ ENTRY_CopyBytes2Mod1, // PINSRW /r ib
  1469. /* C5 */ ENTRY_CopyBytes2Mod1, // PEXTRW /r ib
  1470. /* C6 */ ENTRY_CopyBytes2Mod1, // SHUFPS & SHUFPD
  1471. /* C7 */ ENTRY_CopyBytes2Mod, // CMPXCHG8B (0F C7)
  1472. /* C8 */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd
  1473. /* C9 */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd
  1474. /* CA */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd
  1475. /* CB */ ENTRY_CopyBytes1, // CVTPD2PI BSWAP 0F C8 + rd
  1476. /* CC */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd
  1477. /* CD */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd
  1478. /* CE */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd
  1479. /* CF */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd
  1480. /* D0 */ ENTRY_CopyBytes2Mod, // ADDSUBPS (untestd)
  1481. /* D1 */ ENTRY_CopyBytes2Mod, // PSRLW/r
  1482. /* D2 */ ENTRY_CopyBytes2Mod, // PSRLD/r
  1483. /* D3 */ ENTRY_CopyBytes2Mod, // PSRLQ/r
  1484. /* D4 */ ENTRY_CopyBytes2Mod, // PADDQ
  1485. /* D5 */ ENTRY_CopyBytes2Mod, // PMULLW/r
  1486. /* D6 */ ENTRY_CopyBytes2Mod, // MOVDQ2Q / MOVQ2DQ
  1487. /* D7 */ ENTRY_CopyBytes2Mod, // PMOVMSKB/r
  1488. /* D8 */ ENTRY_CopyBytes2Mod, // PSUBUSB/r
  1489. /* D9 */ ENTRY_CopyBytes2Mod, // PSUBUSW/r
  1490. /* DA */ ENTRY_CopyBytes2Mod, // PMINUB/r
  1491. /* DB */ ENTRY_CopyBytes2Mod, // PAND/r
  1492. /* DC */ ENTRY_CopyBytes2Mod, // PADDUSB/r
  1493. /* DD */ ENTRY_CopyBytes2Mod, // PADDUSW/r
  1494. /* DE */ ENTRY_CopyBytes2Mod, // PMAXUB/r
  1495. /* DF */ ENTRY_CopyBytes2Mod, // PANDN/r
  1496. /* E0 */ ENTRY_CopyBytes2Mod , // PAVGB
  1497. /* E1 */ ENTRY_CopyBytes2Mod, // PSRAW/r
  1498. /* E2 */ ENTRY_CopyBytes2Mod, // PSRAD/r
  1499. /* E3 */ ENTRY_CopyBytes2Mod, // PAVGW
  1500. /* E4 */ ENTRY_CopyBytes2Mod, // PMULHUW/r
  1501. /* E5 */ ENTRY_CopyBytes2Mod, // PMULHW/r
  1502. /* E6 */ ENTRY_CopyBytes2Mod, // CTDQ2PD &
  1503. /* E7 */ ENTRY_CopyBytes2Mod, // MOVNTQ
  1504. /* E8 */ ENTRY_CopyBytes2Mod, // PSUBB/r
  1505. /* E9 */ ENTRY_CopyBytes2Mod, // PSUBW/r
  1506. /* EA */ ENTRY_CopyBytes2Mod, // PMINSW/r
  1507. /* EB */ ENTRY_CopyBytes2Mod, // POR/r
  1508. /* EC */ ENTRY_CopyBytes2Mod, // PADDSB/r
  1509. /* ED */ ENTRY_CopyBytes2Mod, // PADDSW/r
  1510. /* EE */ ENTRY_CopyBytes2Mod, // PMAXSW /r
  1511. /* EF */ ENTRY_CopyBytes2Mod, // PXOR/r
  1512. /* F0 */ ENTRY_CopyBytes2Mod, // LDDQU
  1513. /* F1 */ ENTRY_CopyBytes2Mod, // PSLLW/r
  1514. /* F2 */ ENTRY_CopyBytes2Mod, // PSLLD/r
  1515. /* F3 */ ENTRY_CopyBytes2Mod, // PSLLQ/r
  1516. /* F4 */ ENTRY_CopyBytes2Mod, // PMULUDQ/r
  1517. /* F5 */ ENTRY_CopyBytes2Mod, // PMADDWD/r
  1518. /* F6 */ ENTRY_CopyBytes2Mod, // PSADBW/r
  1519. /* F7 */ ENTRY_CopyBytes2Mod, // MASKMOVQ
  1520. /* F8 */ ENTRY_CopyBytes2Mod, // PSUBB/r
  1521. /* F9 */ ENTRY_CopyBytes2Mod, // PSUBW/r
  1522. /* FA */ ENTRY_CopyBytes2Mod, // PSUBD/r
  1523. /* FB */ ENTRY_CopyBytes2Mod, // FSUBQ/r
  1524. /* FC */ ENTRY_CopyBytes2Mod, // PADDB/r
  1525. /* FD */ ENTRY_CopyBytes2Mod, // PADDW/r
  1526. /* FE */ ENTRY_CopyBytes2Mod, // PADDD/r
  1527. /* FF */ ENTRY_Invalid, // _FF
  1528. };
  1529. BOOL CDetourDis::SanityCheckSystem()
  1530. {
  1531. C_ASSERT(ARRAYSIZE(CDetourDis::s_rceCopyTable) == 256);
  1532. C_ASSERT(ARRAYSIZE(CDetourDis::s_rceCopyTable0F) == 256);
  1533. return TRUE;
  1534. }
  1535. #endif // defined(DETOURS_X64) || defined(DETOURS_X86)
  1536. /////////////////////////////////////////////////////////// IA64 Disassembler.
  1537. //
  1538. #ifdef DETOURS_IA64
  1539. #if defined(_IA64_) != defined(DETOURS_IA64_OFFLINE_LIBRARY)
  1540. // Compile DETOUR_IA64_BUNDLE for native IA64 or cross, but not both -- we get duplicates otherwise.
  1541. const DETOUR_IA64_BUNDLE::DETOUR_IA64_METADATA DETOUR_IA64_BUNDLE::s_rceCopyTable[33] =
  1542. {
  1543. { 0x00, M_UNIT, I_UNIT, I_UNIT, },
  1544. { 0x01, M_UNIT, I_UNIT, I_UNIT, },
  1545. { 0x02, M_UNIT, I_UNIT, I_UNIT, },
  1546. { 0x03, M_UNIT, I_UNIT, I_UNIT, },
  1547. { 0x04, M_UNIT, L_UNIT, X_UNIT, },
  1548. { 0x05, M_UNIT, L_UNIT, X_UNIT, },
  1549. { 0x06, 0, 0, 0, },
  1550. { 0x07, 0, 0, 0, },
  1551. { 0x08, M_UNIT, M_UNIT, I_UNIT, },
  1552. { 0x09, M_UNIT, M_UNIT, I_UNIT, },
  1553. { 0x0a, M_UNIT, M_UNIT, I_UNIT, },
  1554. { 0x0b, M_UNIT, M_UNIT, I_UNIT, },
  1555. { 0x0c, M_UNIT, F_UNIT, I_UNIT, },
  1556. { 0x0d, M_UNIT, F_UNIT, I_UNIT, },
  1557. { 0x0e, M_UNIT, M_UNIT, F_UNIT, },
  1558. { 0x0f, M_UNIT, M_UNIT, F_UNIT, },
  1559. { 0x10, M_UNIT, I_UNIT, B_UNIT, },
  1560. { 0x11, M_UNIT, I_UNIT, B_UNIT, },
  1561. { 0x12, M_UNIT, B_UNIT, B_UNIT, },
  1562. { 0x13, M_UNIT, B_UNIT, B_UNIT, },
  1563. { 0x14, 0, 0, 0, },
  1564. { 0x15, 0, 0, 0, },
  1565. { 0x16, B_UNIT, B_UNIT, B_UNIT, },
  1566. { 0x17, B_UNIT, B_UNIT, B_UNIT, },
  1567. { 0x18, M_UNIT, M_UNIT, B_UNIT, },
  1568. { 0x19, M_UNIT, M_UNIT, B_UNIT, },
  1569. { 0x1a, 0, 0, 0, },
  1570. { 0x1b, 0, 0, 0, },
  1571. { 0x1c, M_UNIT, F_UNIT, B_UNIT, },
  1572. { 0x1d, M_UNIT, F_UNIT, B_UNIT, },
  1573. { 0x1e, 0, 0, 0, },
  1574. { 0x1f, 0, 0, 0, },
  1575. { 0x00, 0, 0, 0, },
  1576. };
  1577. // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0
  1578. // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0.
  1579. // 00
  1580. // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0.
  1581. // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0]
  1582. // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5]
  1583. // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42]
  1584. // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46]
  1585. // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83]
  1586. // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87]
  1587. // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124]
  1588. BYTE DETOUR_IA64_BUNDLE::GetTemplate() const
  1589. {
  1590. return (data[0] & 0x1f);
  1591. }
  1592. BYTE DETOUR_IA64_BUNDLE::GetInst0() const
  1593. {
  1594. return ((data[5] & 0x3c) >> 2);
  1595. }
  1596. BYTE DETOUR_IA64_BUNDLE::GetInst1() const
  1597. {
  1598. return ((data[10] & 0x78) >> 3);
  1599. }
  1600. BYTE DETOUR_IA64_BUNDLE::GetInst2() const
  1601. {
  1602. return ((data[15] & 0xf0) >> 4);
  1603. }
  1604. BYTE DETOUR_IA64_BUNDLE::GetUnit(BYTE slot) const
  1605. {
  1606. switch (slot) {
  1607. case 0: return GetUnit0();
  1608. case 1: return GetUnit1();
  1609. case 2: return GetUnit2();
  1610. }
  1611. __debugbreak();
  1612. return 0;
  1613. }
  1614. BYTE DETOUR_IA64_BUNDLE::GetUnit0() const
  1615. {
  1616. return s_rceCopyTable[data[0] & 0x1f].nUnit0;
  1617. }
  1618. BYTE DETOUR_IA64_BUNDLE::GetUnit1() const
  1619. {
  1620. return s_rceCopyTable[data[0] & 0x1f].nUnit1;
  1621. }
  1622. BYTE DETOUR_IA64_BUNDLE::GetUnit2() const
  1623. {
  1624. return s_rceCopyTable[data[0] & 0x1f].nUnit2;
  1625. }
  1626. UINT64 DETOUR_IA64_BUNDLE::GetData0() const
  1627. {
  1628. return (((wide[0] & 0x000003ffffffffe0) >> 5));
  1629. }
  1630. UINT64 DETOUR_IA64_BUNDLE::GetData1() const
  1631. {
  1632. return (((wide[0] & 0xffffc00000000000) >> 46) |
  1633. ((wide[1] & 0x000000000007ffff) << 18));
  1634. }
  1635. UINT64 DETOUR_IA64_BUNDLE::GetData2() const
  1636. {
  1637. return (((wide[1] & 0x0fffffffff800000) >> 23));
  1638. }
  1639. VOID DETOUR_IA64_BUNDLE::SetInst(BYTE slot, BYTE nInst)
  1640. {
  1641. switch (slot)
  1642. {
  1643. case 0: SetInst0(nInst); return;
  1644. case 1: SetInst1(nInst); return;
  1645. case 2: SetInst2(nInst); return;
  1646. }
  1647. __debugbreak();
  1648. }
  1649. VOID DETOUR_IA64_BUNDLE::SetInst0(BYTE nInst)
  1650. {
  1651. data[5] = (data[5] & ~0x3c) | ((nInst << 2) & 0x3c);
  1652. }
  1653. VOID DETOUR_IA64_BUNDLE::SetInst1(BYTE nInst)
  1654. {
  1655. data[10] = (data[10] & ~0x78) | ((nInst << 3) & 0x78);
  1656. }
  1657. VOID DETOUR_IA64_BUNDLE::SetInst2(BYTE nInst)
  1658. {
  1659. data[15] = (data[15] & ~0xf0) | ((nInst << 4) & 0xf0);
  1660. }
  1661. VOID DETOUR_IA64_BUNDLE::SetData(BYTE slot, UINT64 nData)
  1662. {
  1663. switch (slot)
  1664. {
  1665. case 0: SetData0(nData); return;
  1666. case 1: SetData1(nData); return;
  1667. case 2: SetData2(nData); return;
  1668. }
  1669. __debugbreak();
  1670. }
  1671. VOID DETOUR_IA64_BUNDLE::SetData0(UINT64 nData)
  1672. {
  1673. wide[0] = (wide[0] & ~0x000003ffffffffe0) | (( nData << 5) & 0x000003ffffffffe0);
  1674. }
  1675. VOID DETOUR_IA64_BUNDLE::SetData1(UINT64 nData)
  1676. {
  1677. wide[0] = (wide[0] & ~0xffffc00000000000) | ((nData << 46) & 0xffffc00000000000);
  1678. wide[1] = (wide[1] & ~0x000000000007ffff) | ((nData >> 18) & 0x000000000007ffff);
  1679. }
  1680. VOID DETOUR_IA64_BUNDLE::SetData2(UINT64 nData)
  1681. {
  1682. wide[1] = (wide[1] & ~0x0fffffffff800000) | ((nData << 23) & 0x0fffffffff800000);
  1683. }
  1684. UINT64 DETOUR_IA64_BUNDLE::GetInstruction(BYTE slot) const
  1685. {
  1686. switch (slot) {
  1687. case 0: return GetInstruction0();
  1688. case 1: return GetInstruction1();
  1689. case 2: return GetInstruction2();
  1690. }
  1691. __debugbreak();
  1692. return 0;
  1693. }
  1694. UINT64 DETOUR_IA64_BUNDLE::GetInstruction0() const
  1695. {
  1696. // 41 bits from wide[0], skipping the 5 bit template.
  1697. return GetBits(wide[0], DETOUR_IA64_INSTRUCTION0_OFFSET, DETOUR_IA64_INSTRUCTION_SIZE);
  1698. }
  1699. UINT64 DETOUR_IA64_BUNDLE::GetInstruction1() const
  1700. {
  1701. // 64-46 bits from wide[0] and the rest from wide[1].
  1702. const UINT count0 = 64 - DETOUR_IA64_INSTRUCTION1_OFFSET;
  1703. const UINT count1 = DETOUR_IA64_INSTRUCTION_SIZE - count0;
  1704. return GetBits(wide[0], DETOUR_IA64_INSTRUCTION1_OFFSET, count0) | (GetBits(wide[1], 0, count1) << count0);
  1705. }
  1706. UINT64 DETOUR_IA64_BUNDLE::GetInstruction2() const
  1707. {
  1708. // Upper 41 bits of wide[1].
  1709. return wide[1] >> (64 - DETOUR_IA64_INSTRUCTION_SIZE);
  1710. }
  1711. void DETOUR_IA64_BUNDLE::SetInstruction(BYTE slot, UINT64 instruction)
  1712. {
  1713. switch (slot) {
  1714. case 0: SetInstruction0(instruction); return;
  1715. case 1: SetInstruction1(instruction); return;
  1716. case 2: SetInstruction2(instruction); return;
  1717. }
  1718. __debugbreak();
  1719. }
  1720. void DETOUR_IA64_BUNDLE::SetInstruction0(UINT64 instruction)
  1721. {
  1722. wide[0] = SetBits(wide[0], DETOUR_IA64_INSTRUCTION0_OFFSET, DETOUR_IA64_INSTRUCTION_SIZE, instruction);
  1723. }
  1724. void DETOUR_IA64_BUNDLE::SetInstruction1(UINT64 instruction)
  1725. {
  1726. UINT const count0 = 64 - DETOUR_IA64_INSTRUCTION1_OFFSET;
  1727. UINT const count1 = DETOUR_IA64_INSTRUCTION_SIZE - count0;
  1728. UINT64 const wide0 = SetBits(wide[0], DETOUR_IA64_INSTRUCTION1_OFFSET, count0, instruction);
  1729. UINT64 const wide1 = SetBits(wide[1], 0, count1, instruction >> count0);
  1730. wide[0] = wide0;
  1731. wide[1] = wide1;
  1732. }
  1733. void DETOUR_IA64_BUNDLE::SetInstruction2(UINT64 instruction)
  1734. {
  1735. // Set upper 41 bits of wide[1].
  1736. wide[1] = SetBits(wide[1], 64 - DETOUR_IA64_INSTRUCTION_SIZE, DETOUR_IA64_INSTRUCTION_SIZE, instruction);
  1737. }
  1738. UINT64 DETOUR_IA64_BUNDLE::SignExtend(UINT64 Value, UINT64 Offset)
  1739. // This definition is from the IA64 manual.
  1740. {
  1741. if ((Value & (((UINT64)1) << (Offset - 1))) == 0)
  1742. return Value;
  1743. UINT64 const new_value = Value | ((~(UINT64)0) << Offset);
  1744. return new_value;
  1745. }
  1746. UINT64 DETOUR_IA64_BUNDLE::GetBits(UINT64 Value, UINT64 Offset, UINT64 Count)
  1747. {
  1748. UINT64 const new_value = (Value >> Offset) & ~(~((UINT64)0) << Count);
  1749. return new_value;
  1750. }
  1751. UINT64 DETOUR_IA64_BUNDLE::SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field)
  1752. {
  1753. UINT64 const mask = (~((~(UINT64)0) << Count)) << Offset;
  1754. UINT64 const new_value = (Value & ~mask) | ((Field << Offset) & mask);
  1755. return new_value;
  1756. }
  1757. UINT64 DETOUR_IA64_BUNDLE::GetOpcode(UINT64 instruction)
  1758. // Get 4bit primary opcode.
  1759. {
  1760. UINT64 const opcode = GetBits(instruction, DETOUR_IA64_INSTRUCTION_SIZE - 4, 4);
  1761. return opcode;
  1762. }
  1763. UINT64 DETOUR_IA64_BUNDLE::GetX(UINT64 instruction)
  1764. // Get 1bit opcode extension.
  1765. {
  1766. UINT64 const x = GetBits(instruction, 33, 1);
  1767. return x;
  1768. }
  1769. UINT64 DETOUR_IA64_BUNDLE::GetX3(UINT64 instruction)
  1770. // Get 3bit opcode extension.
  1771. {
  1772. UINT64 const x3 = GetBits(instruction, 33, 3);
  1773. return x3;
  1774. }
  1775. UINT64 DETOUR_IA64_BUNDLE::GetX6(UINT64 instruction)
  1776. // Get 6bit opcode extension.
  1777. {
  1778. UINT64 const x6 = GetBits(instruction, 27, 6);
  1779. return x6;
  1780. }
  1781. UINT64 DETOUR_IA64_BUNDLE::GetImm7a(UINT64 instruction)
  1782. {
  1783. UINT64 const imm7a = GetBits(instruction, 6, 7);
  1784. return imm7a;
  1785. }
  1786. UINT64 DETOUR_IA64_BUNDLE::SetImm7a(UINT64 instruction, UINT64 imm7a)
  1787. {
  1788. UINT64 const new_instruction = SetBits(instruction, 6, 7, imm7a);
  1789. return new_instruction;
  1790. }
  1791. UINT64 DETOUR_IA64_BUNDLE::GetImm13c(UINT64 instruction)
  1792. {
  1793. UINT64 const imm13c = GetBits(instruction, 20, 13);
  1794. return imm13c;
  1795. }
  1796. UINT64 DETOUR_IA64_BUNDLE::SetImm13c(UINT64 instruction, UINT64 imm13c)
  1797. {
  1798. UINT64 const new_instruction = SetBits(instruction, 20, 13, imm13c);
  1799. return new_instruction;
  1800. }
  1801. UINT64 DETOUR_IA64_BUNDLE::GetSignBit(UINT64 instruction)
  1802. {
  1803. UINT64 const signBit = GetBits(instruction, 36, 1);
  1804. return signBit;
  1805. }
  1806. UINT64 DETOUR_IA64_BUNDLE::SetSignBit(UINT64 instruction, UINT64 signBit)
  1807. {
  1808. UINT64 const new_instruction = SetBits(instruction, 36, 1, signBit);
  1809. return new_instruction;
  1810. }
  1811. UINT64 DETOUR_IA64_BUNDLE::GetImm20a(UINT64 instruction)
  1812. {
  1813. UINT64 const imm20a = GetBits(instruction, 6, 20);
  1814. return imm20a;
  1815. }
  1816. UINT64 DETOUR_IA64_BUNDLE::SetImm20a(UINT64 instruction, UINT64 imm20a)
  1817. {
  1818. UINT64 const new_instruction = SetBits(instruction, 6, 20, imm20a);
  1819. return new_instruction;
  1820. }
  1821. UINT64 DETOUR_IA64_BUNDLE::GetImm20b(UINT64 instruction)
  1822. {
  1823. UINT64 const imm20b = GetBits(instruction, 13, 20);
  1824. return imm20b;
  1825. }
  1826. UINT64 DETOUR_IA64_BUNDLE::SetImm20b(UINT64 instruction, UINT64 imm20b)
  1827. {
  1828. UINT64 const new_instruction = SetBits(instruction, 13, 20, imm20b);
  1829. return new_instruction;
  1830. }
  1831. bool DETOUR_IA64_BUNDLE::RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst,
  1832. _In_ BYTE slot,
  1833. _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const
  1834. /*
  1835. If pBundleExtra is provided and instruction is IP-relative,
  1836. this function relocates instruction to target pBundleExtra,
  1837. pBundleExtra is set to brl the original target, and return true.
  1838. [Not used] If pBundleExtra is not provided and instruction is IP-relative, return true.
  1839. Else return false.
  1840. The following IP-relative forms are recognized:
  1841. br and br.call
  1842. chk.s.m integer and float
  1843. chk.a.nc integer and float
  1844. chk.a.clr integer and float
  1845. chk.s.i
  1846. fchkf
  1847. Brl is handled elsewhere, because the code was previously written.
  1848. Branch prediction hints are not relocated.
  1849. */
  1850. {
  1851. UINT64 const instruction = GetInstruction(slot);
  1852. UINT64 const opcode = GetOpcode(instruction);
  1853. size_t const dest = (size_t)pDst;
  1854. size_t const extra = (size_t)pBundleExtra;
  1855. switch (GetUnit(slot)) {
  1856. case F_UNIT:
  1857. // F14 fchkf
  1858. if (opcode == 0 && GetX(instruction) == 0 && GetX6(instruction) == 8) {
  1859. goto imm20a;
  1860. }
  1861. return false;
  1862. case M_UNIT:
  1863. // M20 x3 == 1 integer chk.s.m
  1864. // M21 x3 == 3 floating point chk.s
  1865. if (opcode == 1) {
  1866. UINT64 const x3 = GetX3(instruction);
  1867. if (x3 == 1 || x3 == 3) {
  1868. goto imm13_7;
  1869. }
  1870. }
  1871. // M22 x3 == 4 integer chk.a.nc
  1872. // M22 x3 == 5 integer chk.a.clr
  1873. // M23 x3 == 6 floating point chk.a.nc
  1874. // M23 x3 == 7 floating point chk.a.clr
  1875. if (opcode == 0) {
  1876. UINT64 const x3 = GetX3(instruction);
  1877. if (x3 == 4 || x3 == 5 || x3 == 6 || x3 == 7) {
  1878. goto imm20b;
  1879. }
  1880. }
  1881. return false;
  1882. case I_UNIT:
  1883. // I20
  1884. if (opcode == 0 && GetX3(instruction) == 1) { // chk.s.i
  1885. goto imm13_7;
  1886. }
  1887. return false;
  1888. case B_UNIT:
  1889. // B1 B2 B3
  1890. // 4 br
  1891. // 5 br.call
  1892. if (opcode == 4 || opcode == 5) {
  1893. goto imm20b;
  1894. }
  1895. return false;
  1896. }
  1897. return false;
  1898. UINT64 imm;
  1899. UINT64 new_instruction;
  1900. imm13_7:
  1901. imm = SignExtend((GetSignBit(instruction) << 20) | (GetImm13c(instruction) << 7) | GetImm7a(instruction), 21) << 4;
  1902. new_instruction = SetSignBit(SetImm13c(SetImm7a(instruction, (extra - dest) >> 4), (extra - dest) >> 11), extra < dest);
  1903. goto set_brl;
  1904. imm20a:
  1905. imm = SignExtend((GetSignBit(instruction) << 20) | GetImm20a(instruction), 21) << 4;
  1906. new_instruction = SetSignBit(SetImm20a(instruction, (extra - dest) >> 4), extra < dest);
  1907. goto set_brl;
  1908. imm20b:
  1909. imm = SignExtend((GetSignBit(instruction) << 20) | GetImm20b(instruction), 21) << 4;
  1910. new_instruction = SetSignBit(SetImm20b(instruction, (extra - dest) >> 4), extra < dest);
  1911. goto set_brl;
  1912. set_brl:
  1913. if (pBundleExtra != NULL) {
  1914. pDst->SetInstruction(slot, new_instruction);
  1915. pBundleExtra->SetBrl((size_t)this + imm);
  1916. }
  1917. return true;
  1918. }
  1919. UINT DETOUR_IA64_BUNDLE::RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst,
  1920. _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const
  1921. /*
  1922. Having already copied the bundle unchanged, then relocate its instructions one at a time.
  1923. Return how many extra bytes are required to relocate the bundle.
  1924. */
  1925. {
  1926. UINT nExtraBytes = 0;
  1927. for (BYTE slot = 0; slot < DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE; ++slot) {
  1928. if (!RelocateInstruction(pDst, slot, pBundleExtra)) {
  1929. continue;
  1930. }
  1931. pBundleExtra -= !!pBundleExtra;
  1932. nExtraBytes += sizeof(DETOUR_IA64_BUNDLE);
  1933. }
  1934. return nExtraBytes;
  1935. }
  1936. BOOL DETOUR_IA64_BUNDLE::IsBrl() const
  1937. {
  1938. // f.e. d.c. b.a. 9.8. 7.6. 5. 4. 3. 2. 1. 0.
  1939. // c000 0070 0000 0000 0000 00 01 00 00 00 05 : brl.sptk.few
  1940. // c8ff fff0 007f fff0 ffff 00 01 00 00 00 05 : brl.sptk.few
  1941. // c000 0048 0000 0000 0001 00 00 00 00 00 05 : brl.sptk.many
  1942. return ((wide[0] & 0x000000000000001e) == 0x0000000000000004 && // 4 or 5.
  1943. (wide[1] & 0xe000000000000000) == 0xc000000000000000); // c or d.
  1944. }
  1945. VOID DETOUR_IA64_BUNDLE::SetBrl()
  1946. {
  1947. wide[0] = 0x0000000100000005; // few
  1948. //wide[0] = 0x0000000180000005; // many
  1949. wide[1] = 0xc000000800000000;
  1950. }
  1951. UINT64 DETOUR_IA64_BUNDLE::GetBrlImm() const
  1952. {
  1953. return (
  1954. // 0x0000000000fffff0
  1955. ((wide[1] & 0x00fffff000000000) >> 32) | // all 20 bits of imm20b.
  1956. // 0x000000ffff000000
  1957. ((wide[0] & 0xffff000000000000) >> 24) | // bottom 16 bits of imm39.
  1958. // 0x7fffff0000000000
  1959. ((wide[1] & 0x00000000007fffff) << 40) | // top 23 bits of imm39.
  1960. // 0x8000000000000000
  1961. ((wide[1] & 0x0800000000000000) << 4) // single bit of i.
  1962. );
  1963. }
  1964. VOID DETOUR_IA64_BUNDLE::SetBrlImm(UINT64 imm)
  1965. {
  1966. wide[0] = ((wide[0] & ~0xffff000000000000) |
  1967. // 0xffff000000000000
  1968. ((imm & 0x000000ffff000000) << 24) // bottom 16 bits of imm39.
  1969. );
  1970. wide[1] = ((wide[1] & ~0x08fffff0007fffff) |
  1971. // 0x00fffff000000000
  1972. ((imm & 0x0000000000fffff0) << 32) | // all 20 bits of imm20b.
  1973. // 0x00000000007fffff
  1974. ((imm & 0x7fffff0000000000) >> 40) | // top 23 bits of imm39.
  1975. // 0x0800000000000000
  1976. ((imm & 0x8000000000000000) >> 4) // single bit of i.
  1977. );
  1978. }
  1979. UINT64 DETOUR_IA64_BUNDLE::GetBrlTarget() const
  1980. {
  1981. return (UINT64)this + GetBrlImm();
  1982. }
  1983. VOID DETOUR_IA64_BUNDLE::SetBrl(UINT64 target)
  1984. {
  1985. UINT64 imm = target - (UINT64)this;
  1986. SetBrl();
  1987. SetBrlImm(imm);
  1988. }
  1989. VOID DETOUR_IA64_BUNDLE::SetBrlTarget(UINT64 target)
  1990. {
  1991. UINT64 imm = target - (UINT64)this;
  1992. SetBrlImm(imm);
  1993. }
  1994. BOOL DETOUR_IA64_BUNDLE::IsMovlGp() const
  1995. {
  1996. // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0.
  1997. // 6fff f7f0 207f ffff ffff c001 0000 0004
  1998. // 6000 0000 2000 0000 0000 0001 0000 0004
  1999. return ((wide[0] & 0x00003ffffffffffe) == 0x0000000100000004 &&
  2000. (wide[1] & 0xf000080fff800000) == 0x6000000020000000);
  2001. }
  2002. UINT64 DETOUR_IA64_BUNDLE::GetMovlGp() const
  2003. {
  2004. UINT64 raw = (
  2005. // 0x0000000000000070
  2006. ((wide[1] & 0x000007f000000000) >> 36) |
  2007. // 0x000000000000ff80
  2008. ((wide[1] & 0x07fc000000000000) >> 43) |
  2009. // 0x00000000001f0000
  2010. ((wide[1] & 0x0003e00000000000) >> 29) |
  2011. // 0x0000000000200000
  2012. ((wide[1] & 0x0000100000000000) >> 23) |
  2013. // 0x000000ffffc00000
  2014. ((wide[0] & 0xffffc00000000000) >> 24) |
  2015. // 0x7fffff0000000000
  2016. ((wide[1] & 0x00000000007fffff) << 40) |
  2017. // 0x8000000000000000
  2018. ((wide[1] & 0x0800000000000000) << 4)
  2019. );
  2020. return (INT64)raw;
  2021. }
  2022. VOID DETOUR_IA64_BUNDLE::SetMovlGp(UINT64 gp)
  2023. {
  2024. UINT64 raw = (UINT64)gp;
  2025. wide[0] = (0x0000000100000005 |
  2026. // 0xffffc00000000000
  2027. ((raw & 0x000000ffffc00000) << 24)
  2028. );
  2029. wide[1] = (
  2030. 0x6000000020000000 |
  2031. // 0x0000070000000000
  2032. ((raw & 0x0000000000000070) << 36) |
  2033. // 0x07fc000000000000
  2034. ((raw & 0x000000000000ff80) << 43) |
  2035. // 0x0003e00000000000
  2036. ((raw & 0x00000000001f0000) << 29) |
  2037. // 0x0000100000000000
  2038. ((raw & 0x0000000000200000) << 23) |
  2039. // 0x00000000007fffff
  2040. ((raw & 0x7fffff0000000000) >> 40) |
  2041. // 0x0800000000000000
  2042. ((raw & 0x8000000000000000) >> 4)
  2043. );
  2044. }
  2045. UINT DETOUR_IA64_BUNDLE::Copy(_Out_ DETOUR_IA64_BUNDLE *pDst,
  2046. _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const
  2047. {
  2048. // Copy the bytes unchanged.
  2049. #pragma warning(suppress:6001) // using uninitialized *pDst
  2050. pDst->wide[0] = wide[0];
  2051. pDst->wide[1] = wide[1];
  2052. // Relocate if necessary.
  2053. UINT nExtraBytes = RelocateBundle(pDst, pBundleExtra);
  2054. if (GetUnit1() == L_UNIT && IsBrl()) {
  2055. pDst->SetBrlTarget(GetBrlTarget());
  2056. }
  2057. return nExtraBytes;
  2058. }
  2059. BOOL DETOUR_IA64_BUNDLE::SetNop(BYTE slot)
  2060. {
  2061. switch (GetUnit(slot)) {
  2062. case I_UNIT:
  2063. case M_UNIT:
  2064. case F_UNIT:
  2065. SetInst(slot, 0);
  2066. SetData(slot, 0x8000000);
  2067. return true;
  2068. case B_UNIT:
  2069. SetInst(slot, 2);
  2070. SetData(slot, 0);
  2071. return true;
  2072. }
  2073. DebugBreak();
  2074. return false;
  2075. }
  2076. BOOL DETOUR_IA64_BUNDLE::SetNop0()
  2077. {
  2078. return SetNop(0);
  2079. }
  2080. BOOL DETOUR_IA64_BUNDLE::SetNop1()
  2081. {
  2082. return SetNop(1);
  2083. }
  2084. BOOL DETOUR_IA64_BUNDLE::SetNop2()
  2085. {
  2086. return SetNop(2);
  2087. }
  2088. VOID DETOUR_IA64_BUNDLE::SetStop()
  2089. {
  2090. data[0] |= 0x01;
  2091. }
  2092. #endif // DETOURS_IA64
  2093. PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst,
  2094. _Inout_opt_ PVOID *ppDstPool,
  2095. _In_ PVOID pSrc,
  2096. _Out_opt_ PVOID *ppTarget,
  2097. _Out_opt_ LONG *plExtra)
  2098. {
  2099. LONG nExtra;
  2100. DETOUR_IA64_BUNDLE bExtra;
  2101. DETOUR_IA64_BUNDLE *pbSrc = (DETOUR_IA64_BUNDLE *)pSrc;
  2102. DETOUR_IA64_BUNDLE *pbDst = pDst ? (DETOUR_IA64_BUNDLE *)pDst : &bExtra;
  2103. plExtra = plExtra ? plExtra : &nExtra;
  2104. *plExtra = 0;
  2105. if (ppTarget != NULL) {
  2106. if (pbSrc->IsBrl()) {
  2107. *ppTarget = (PVOID)pbSrc->GetBrlTarget();
  2108. }
  2109. else {
  2110. *ppTarget = DETOUR_INSTRUCTION_TARGET_NONE;
  2111. }
  2112. }
  2113. *plExtra = (LONG)pbSrc->Copy(pbDst, ppDstPool ? ((DETOUR_IA64_BUNDLE*)*ppDstPool) - 1 : (DETOUR_IA64_BUNDLE*)NULL);
  2114. return pbSrc + 1;
  2115. }
  2116. #endif // DETOURS_IA64
  2117. #ifdef DETOURS_ARM
  2118. #define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1))
  2119. #define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1))
  2120. #define c_PCAdjust 4 // The PC value of an instruction is the PC address plus 4.
  2121. #define c_PC 15 // The register number for the Program Counter
  2122. #define c_LR 14 // The register number for the Link Register
  2123. #define c_SP 13 // The register number for the Stack Pointer
  2124. #define c_NOP 0xbf00 // A nop instruction
  2125. #define c_BREAK 0xdefe // A nop instruction
  2126. class CDetourDis
  2127. {
  2128. public:
  2129. CDetourDis();
  2130. PBYTE CopyInstruction(PBYTE pDst,
  2131. PBYTE *ppDstPool,
  2132. PBYTE pSrc,
  2133. PBYTE *ppTarget,
  2134. LONG *plExtra);
  2135. public:
  2136. typedef BYTE (CDetourDis::* COPYFUNC)(PBYTE pbDst, PBYTE pbSrc);
  2137. struct COPYENTRY {
  2138. USHORT nOpcode;
  2139. COPYFUNC pfCopy;
  2140. };
  2141. typedef const COPYENTRY * REFCOPYENTRY;
  2142. struct Branch5
  2143. {
  2144. DWORD Register : 3;
  2145. DWORD Imm5 : 5;
  2146. DWORD Padding : 1;
  2147. DWORD I : 1;
  2148. DWORD OpCode : 6;
  2149. };
  2150. struct Branch5Target
  2151. {
  2152. DWORD Padding : 1;
  2153. DWORD Imm5 : 5;
  2154. DWORD I : 1;
  2155. DWORD Padding2 : 25;
  2156. };
  2157. struct Branch8
  2158. {
  2159. DWORD Imm8 : 8;
  2160. DWORD Condition : 4;
  2161. DWORD OpCode : 4;
  2162. };
  2163. struct Branch8Target
  2164. {
  2165. DWORD Padding : 1;
  2166. DWORD Imm8 : 8;
  2167. DWORD Padding2 : 23;
  2168. };
  2169. struct Branch11
  2170. {
  2171. DWORD Imm11 : 11;
  2172. DWORD OpCode : 5;
  2173. };
  2174. struct Branch11Target
  2175. {
  2176. DWORD Padding : 1;
  2177. DWORD Imm11 : 11;
  2178. DWORD Padding2 : 20;
  2179. };
  2180. struct Branch20
  2181. {
  2182. DWORD Imm11 : 11;
  2183. DWORD J2 : 1;
  2184. DWORD IT : 1;
  2185. DWORD J1 : 1;
  2186. DWORD Other : 2;
  2187. DWORD Imm6 : 6;
  2188. DWORD Condition : 4;
  2189. DWORD Sign : 1;
  2190. DWORD OpCode : 5;
  2191. };
  2192. struct Branch20Target
  2193. {
  2194. DWORD Padding : 1;
  2195. DWORD Imm11 : 11;
  2196. DWORD Imm6 : 6;
  2197. DWORD J1 : 1;
  2198. DWORD J2 : 1;
  2199. DWORD Sign : 1;
  2200. INT32 Padding2 : 11;
  2201. };
  2202. struct Branch24
  2203. {
  2204. DWORD Imm11 : 11;
  2205. DWORD J2 : 1;
  2206. DWORD InstructionSet : 1;
  2207. DWORD J1 : 1;
  2208. DWORD Link : 1;
  2209. DWORD Branch : 1;
  2210. DWORD Imm10 : 10;
  2211. DWORD Sign : 1;
  2212. DWORD OpCode : 5;
  2213. };
  2214. struct Branch24Target
  2215. {
  2216. DWORD Padding : 1;
  2217. DWORD Imm11 : 11;
  2218. DWORD Imm10 : 10;
  2219. DWORD I2 : 1;
  2220. DWORD I1 : 1;
  2221. DWORD Sign : 1;
  2222. INT32 Padding2 : 7;
  2223. };
  2224. struct LiteralLoad8
  2225. {
  2226. DWORD Imm8 : 8;
  2227. DWORD Register : 3;
  2228. DWORD OpCode : 5;
  2229. };
  2230. struct LiteralLoad8Target
  2231. {
  2232. DWORD Padding : 2;
  2233. DWORD Imm8 : 8;
  2234. DWORD Padding2 : 22;
  2235. };
  2236. struct LiteralLoad12
  2237. {
  2238. DWORD Imm12 : 12;
  2239. DWORD Register : 4;
  2240. DWORD OpCodeSuffix : 7;
  2241. DWORD Add : 1;
  2242. DWORD OpCodePrefix : 8;
  2243. };
  2244. struct LiteralLoad12Target
  2245. {
  2246. DWORD Imm12 : 12;
  2247. DWORD Padding : 20;
  2248. };
  2249. struct ImmediateRegisterLoad32
  2250. {
  2251. DWORD Imm12 : 12;
  2252. DWORD DestinationRegister : 4;
  2253. DWORD SourceRegister: 4;
  2254. DWORD OpCode : 12;
  2255. };
  2256. struct ImmediateRegisterLoad16
  2257. {
  2258. DWORD DestinationRegister : 3;
  2259. DWORD SourceRegister: 3;
  2260. DWORD OpCode : 10;
  2261. };
  2262. struct TableBranch
  2263. {
  2264. DWORD IndexRegister : 4;
  2265. DWORD HalfWord : 1;
  2266. DWORD OpCodeSuffix : 11;
  2267. DWORD BaseRegister : 4;
  2268. DWORD OpCodePrefix : 12;
  2269. };
  2270. struct Shift
  2271. {
  2272. DWORD Imm2 : 2;
  2273. DWORD Imm3 : 3;
  2274. };
  2275. struct Add32
  2276. {
  2277. DWORD SecondOperandRegister : 4;
  2278. DWORD Type : 2;
  2279. DWORD Imm2 : 2;
  2280. DWORD DestinationRegister : 4;
  2281. DWORD Imm3 : 3;
  2282. DWORD Padding : 1;
  2283. DWORD FirstOperandRegister : 4;
  2284. DWORD SetFlags : 1;
  2285. DWORD OpCode : 11;
  2286. };
  2287. struct LogicalShiftLeft32
  2288. {
  2289. DWORD SourceRegister : 4;
  2290. DWORD Padding : 2;
  2291. DWORD Imm2 : 2;
  2292. DWORD DestinationRegister : 4;
  2293. DWORD Imm3 : 3;
  2294. DWORD Padding2 : 5;
  2295. DWORD SetFlags : 1;
  2296. DWORD OpCode : 11;
  2297. };
  2298. struct StoreImmediate12
  2299. {
  2300. DWORD Imm12 : 12;
  2301. DWORD SourceRegister : 4;
  2302. DWORD BaseRegister : 4;
  2303. DWORD OpCode : 12;
  2304. };
  2305. protected:
  2306. BYTE PureCopy16(BYTE* pSource, BYTE* pDest);
  2307. BYTE PureCopy32(BYTE* pSource, BYTE* pDest);
  2308. BYTE CopyMiscellaneous16(BYTE* pSource, BYTE* pDest);
  2309. BYTE CopyConditionalBranchOrOther16(BYTE* pSource, BYTE* pDest);
  2310. BYTE CopyUnConditionalBranch16(BYTE* pSource, BYTE* pDest);
  2311. BYTE CopyLiteralLoad16(BYTE* pSource, BYTE* pDest);
  2312. BYTE CopyBranchExchangeOrDataProcessing16(BYTE* pSource, BYTE* pDest);
  2313. BYTE CopyBranch24(BYTE* pSource, BYTE* pDest);
  2314. BYTE CopyBranchOrMiscellaneous32(BYTE* pSource, BYTE* pDest);
  2315. BYTE CopyLiteralLoad32(BYTE* pSource, BYTE* pDest);
  2316. BYTE CopyLoadAndStoreSingle(BYTE* pSource, BYTE* pDest);
  2317. BYTE CopyLoadAndStoreMultipleAndSRS(BYTE* pSource, BYTE* pDest);
  2318. BYTE CopyTableBranch(BYTE* pSource, BYTE* pDest);
  2319. BYTE BeginCopy32(BYTE* pSource, BYTE* pDest);
  2320. LONG DecodeBranch5(ULONG opcode);
  2321. USHORT EncodeBranch5(ULONG originalOpCode, LONG delta);
  2322. LONG DecodeBranch8(ULONG opcode);
  2323. USHORT EncodeBranch8(ULONG originalOpCode, LONG delta);
  2324. LONG DecodeBranch11(ULONG opcode);
  2325. USHORT EncodeBranch11(ULONG originalOpCode, LONG delta);
  2326. BYTE EmitBranch11(PUSHORT& pDest, LONG relativeAddress);
  2327. LONG DecodeBranch20(ULONG opcode);
  2328. ULONG EncodeBranch20(ULONG originalOpCode, LONG delta);
  2329. LONG DecodeBranch24(ULONG opcode, BOOL& fLink);
  2330. ULONG EncodeBranch24(ULONG originalOpCode, LONG delta, BOOL fLink);
  2331. LONG DecodeLiteralLoad8(ULONG instruction);
  2332. LONG DecodeLiteralLoad12(ULONG instruction);
  2333. BYTE EmitLiteralLoad8(PUSHORT& pDest, BYTE targetRegister, PBYTE pLiteral);
  2334. BYTE EmitLiteralLoad12(PUSHORT& pDest, BYTE targetRegister, PBYTE pLiteral);
  2335. BYTE EmitImmediateRegisterLoad32(PUSHORT& pDest, BYTE reg);
  2336. BYTE EmitImmediateRegisterLoad16(PUSHORT& pDest, BYTE reg);
  2337. BYTE EmitLongLiteralLoad(PUSHORT& pDest, BYTE reg, PVOID pTarget);
  2338. BYTE EmitLongBranch(PUSHORT& pDest, PVOID pTarget);
  2339. USHORT CalculateExtra(BYTE sourceLength, BYTE* pDestStart, BYTE* pDestEnd);
  2340. protected:
  2341. ULONG GetLongInstruction(BYTE* pSource)
  2342. {
  2343. return (((PUSHORT)pSource)[0] << 16) | (((PUSHORT)pSource)[1]);
  2344. }
  2345. BYTE EmitLongInstruction(PUSHORT& pDstInst, ULONG instruction)
  2346. {
  2347. *pDstInst++ = (USHORT)(instruction >> 16);
  2348. *pDstInst++ = (USHORT)instruction;
  2349. return sizeof(ULONG);
  2350. }
  2351. BYTE EmitShortInstruction(PUSHORT& pDstInst, USHORT instruction)
  2352. {
  2353. *pDstInst++ = instruction;
  2354. return sizeof(USHORT);
  2355. }
  2356. PBYTE Align4(PBYTE pValue)
  2357. {
  2358. return (PBYTE)(((size_t)pValue) & ~(ULONG)3u);
  2359. }
  2360. PBYTE CalculateTarget(PBYTE pSource, LONG delta)
  2361. {
  2362. return (pSource + delta + c_PCAdjust);
  2363. }
  2364. LONG CalculateNewDelta(PBYTE pTarget, BYTE* pDest)
  2365. {
  2366. return (LONG)(pTarget - (pDest + c_PCAdjust));
  2367. }
  2368. BYTE EmitAdd32(PUSHORT& pDstInst, BYTE op1Reg, BYTE op2Reg, BYTE dstReg, BYTE shiftAmount)
  2369. {
  2370. Shift& shift = (Shift&)(shiftAmount);
  2371. const BYTE shiftType = 0x00; // LSL
  2372. Add32 add = { op2Reg, shiftType, shift.Imm2, dstReg, shift.Imm3,
  2373. 0x0, op1Reg, 0x0, 0x758 };
  2374. return EmitLongInstruction(pDstInst, (ULONG&)add);
  2375. }
  2376. BYTE EmitLogicalShiftLeft32(PUSHORT& pDstInst, BYTE srcReg, BYTE dstReg, BYTE shiftAmount)
  2377. {
  2378. Shift& shift = (Shift&)(shiftAmount);
  2379. LogicalShiftLeft32 shiftLeft = { srcReg, 0x00, shift.Imm2, dstReg, shift.Imm3, 0x1E,
  2380. 0x00, 0x752 };
  2381. return EmitLongInstruction(pDstInst, (ULONG&)shiftLeft);
  2382. }
  2383. BYTE EmitStoreImmediate12(PUSHORT& pDstInst, BYTE srcReg, BYTE baseReg, USHORT offset)
  2384. {
  2385. StoreImmediate12 store = { offset, srcReg, baseReg, 0xF8C };
  2386. return EmitLongInstruction(pDstInst, (ULONG&)store);
  2387. }
  2388. protected:
  2389. PBYTE m_pbTarget;
  2390. PBYTE m_pbPool;
  2391. LONG m_lExtra;
  2392. BYTE m_rbScratchDst[64]; // matches or exceeds rbCode
  2393. static const COPYENTRY s_rceCopyTable[33];
  2394. };
  2395. LONG CDetourDis::DecodeBranch5(ULONG opcode)
  2396. {
  2397. Branch5& branch = (Branch5&)(opcode);
  2398. Branch5Target target;
  2399. ZeroMemory(&target, sizeof(target));
  2400. target.Imm5 = branch.Imm5;
  2401. target.I = branch.I;
  2402. // Return zero-extended value
  2403. return (LONG&)target;
  2404. }
  2405. USHORT CDetourDis::EncodeBranch5(ULONG originalOpCode, LONG delta)
  2406. {
  2407. // Too large for a 5 bit branch (5 bit branches can be up to 7 bits due to I and the trailing 0)
  2408. if (delta < 0 || delta > 0x7F) {
  2409. return 0;
  2410. }
  2411. Branch5& branch = (Branch5&)(originalOpCode);
  2412. Branch5Target& target = (Branch5Target&)(delta);
  2413. branch.Imm5 = target.Imm5;
  2414. branch.I = target.I;
  2415. return (USHORT&)branch;
  2416. }
  2417. LONG CDetourDis::DecodeBranch8(ULONG opcode)
  2418. {
  2419. Branch8& branch = (Branch8&)(opcode);
  2420. Branch8Target target;
  2421. ZeroMemory(&target, sizeof(target));
  2422. target.Imm8 = branch.Imm8;
  2423. // Return sign extended value
  2424. return (((LONG&)target) << 23) >> 23;
  2425. }
  2426. USHORT CDetourDis::EncodeBranch8(ULONG originalOpCode, LONG delta)
  2427. {
  2428. // Too large for 8 bit branch (8 bit branches can be up to 9 bits due to the trailing 0)
  2429. if (delta < (-(int)0x100) || delta > 0xFF) {
  2430. return 0;
  2431. }
  2432. Branch8& branch = (Branch8&)(originalOpCode);
  2433. Branch8Target& target = (Branch8Target&)(delta);
  2434. branch.Imm8 = target.Imm8;
  2435. return (USHORT&)branch;
  2436. }
  2437. LONG CDetourDis::DecodeBranch11(ULONG opcode)
  2438. {
  2439. Branch11& branch = (Branch11&)(opcode);
  2440. Branch11Target target;
  2441. ZeroMemory(&target, sizeof(target));
  2442. target.Imm11 = branch.Imm11;
  2443. // Return sign extended value
  2444. return (((LONG&)target) << 20) >> 20;
  2445. }
  2446. USHORT CDetourDis::EncodeBranch11(ULONG originalOpCode, LONG delta)
  2447. {
  2448. // Too large for an 11 bit branch (11 bit branches can be up to 12 bits due to the trailing 0)
  2449. if (delta < (-(int)0x800) || delta > 0x7FF) {
  2450. return 0;
  2451. }
  2452. Branch11& branch = (Branch11&)(originalOpCode);
  2453. Branch11Target& target = (Branch11Target&)(delta);
  2454. branch.Imm11 = target.Imm11;
  2455. return (USHORT&)branch;
  2456. }
  2457. BYTE CDetourDis::EmitBranch11(PUSHORT& pDest, LONG relativeAddress)
  2458. {
  2459. Branch11Target& target = (Branch11Target&)(relativeAddress);
  2460. Branch11 branch11 = { target.Imm11, 0x1C };
  2461. *pDest++ = (USHORT&)branch11;
  2462. return sizeof(USHORT);
  2463. }
  2464. LONG CDetourDis::DecodeBranch20(ULONG opcode)
  2465. {
  2466. Branch20& branch = (Branch20&)(opcode);
  2467. Branch20Target target;
  2468. ZeroMemory(&target, sizeof(target));
  2469. target.Imm11 = branch.Imm11;
  2470. target.Imm6 = branch.Imm6;
  2471. target.Sign = branch.Sign;
  2472. target.J1 = branch.J1;
  2473. target.J2 = branch.J2;
  2474. // Sign extend
  2475. if (target.Sign) {
  2476. target.Padding2 = -1;
  2477. }
  2478. return (LONG&)target;
  2479. }
  2480. ULONG CDetourDis::EncodeBranch20(ULONG originalOpCode, LONG delta)
  2481. {
  2482. // Too large for 20 bit branch (20 bit branches can be up to 21 bits due to the trailing 0)
  2483. if (delta < (-(int)0x100000) || delta > 0xFFFFF) {
  2484. return 0;
  2485. }
  2486. Branch20& branch = (Branch20&)(originalOpCode);
  2487. Branch20Target& target = (Branch20Target&)(delta);
  2488. branch.Imm11 = target.Imm11;
  2489. branch.Imm6 = target.Imm6;
  2490. branch.Sign = target.Sign;
  2491. branch.J1 = target.J1;
  2492. branch.J2 = target.J2;
  2493. return (ULONG&)branch;
  2494. }
  2495. LONG CDetourDis::DecodeBranch24(ULONG opcode, BOOL& fLink)
  2496. {
  2497. Branch24& branch = (Branch24&)(opcode);
  2498. Branch24Target target;
  2499. ZeroMemory(&target, sizeof(target));
  2500. target.Imm11 = branch.Imm11;
  2501. target.Imm10 = branch.Imm10;
  2502. target.Sign = branch.Sign;
  2503. target.I1 = ~(branch.J1 ^ target.Sign);
  2504. target.I2 = ~(branch.J2 ^ target.Sign);
  2505. fLink = branch.Link;
  2506. // Sign extend
  2507. if (target.Sign) {
  2508. target.Padding2 = -1;
  2509. }
  2510. return (LONG&)target;
  2511. }
  2512. ULONG CDetourDis::EncodeBranch24(ULONG originalOpCode, LONG delta, BOOL fLink)
  2513. {
  2514. // Too large for 24 bit branch (24 bit branches can be up to 25 bits due to the trailing 0)
  2515. if (delta < static_cast<int>(0xFF000000) || delta > static_cast<int>(0xFFFFFF)) {
  2516. return 0;
  2517. }
  2518. Branch24& branch = (Branch24&)(originalOpCode);
  2519. Branch24Target& target = (Branch24Target&)(delta);
  2520. branch.Imm11 = target.Imm11;
  2521. branch.Imm10 = target.Imm10;
  2522. branch.Link = fLink;
  2523. branch.Sign = target.Sign;
  2524. branch.J1 = ~(target.I1 ^ branch.Sign);
  2525. branch.J2 = ~(target.I2 ^ branch.Sign);
  2526. return (ULONG&)branch;
  2527. }
  2528. LONG CDetourDis::DecodeLiteralLoad8(ULONG instruction)
  2529. {
  2530. LiteralLoad8& load = (LiteralLoad8&)(instruction);
  2531. LiteralLoad8Target target;
  2532. ZeroMemory(&target, sizeof(target));
  2533. target.Imm8 = load.Imm8;
  2534. return (LONG&)target;
  2535. }
  2536. BYTE CDetourDis::EmitLiteralLoad8(PUSHORT& pDest, BYTE targetRegister, PBYTE pLiteral)
  2537. {
  2538. // Note: We add 2 (which gets rounded down) because literals must be 32-bit
  2539. // aligned, but the ldr can be 16-bit aligned.
  2540. LONG newDelta = CalculateNewDelta((PBYTE)pLiteral + 2, (PBYTE)pDest);
  2541. LONG relative = ((newDelta > 0 ? newDelta : -newDelta) & 0x3FF);
  2542. LiteralLoad8Target& target = (LiteralLoad8Target&)(relative);
  2543. LiteralLoad8 load = { target.Imm8, targetRegister, 0x9 };
  2544. return EmitShortInstruction(pDest, (USHORT&)load);
  2545. }
  2546. LONG CDetourDis::DecodeLiteralLoad12(ULONG instruction)
  2547. {
  2548. LiteralLoad12& load = (LiteralLoad12&)(instruction);
  2549. LiteralLoad12Target target;
  2550. ZeroMemory(&target, sizeof(target));
  2551. target.Imm12 = load.Imm12;
  2552. return (LONG&)target;
  2553. }
  2554. BYTE CDetourDis::EmitLiteralLoad12(PUSHORT& pDest, BYTE targetRegister, PBYTE pLiteral)
  2555. {
  2556. // Note: We add 2 (which gets rounded down) because literals must be 32-bit
  2557. // aligned, but the ldr can be 16-bit aligned.
  2558. LONG newDelta = CalculateNewDelta((PBYTE)pLiteral + 2, (PBYTE)pDest);
  2559. LONG relative = ((newDelta > 0 ? newDelta : -newDelta) & 0xFFF);
  2560. LiteralLoad12Target& target = (LiteralLoad12Target&)(relative);
  2561. target.Imm12 -= target.Imm12 & 3;
  2562. LiteralLoad12 load = { target.Imm12, targetRegister, 0x5F, (DWORD)(newDelta > 0), 0xF8 };
  2563. return EmitLongInstruction(pDest, (ULONG&)load);
  2564. }
  2565. BYTE CDetourDis::EmitImmediateRegisterLoad32(PUSHORT& pDest, BYTE reg)
  2566. {
  2567. ImmediateRegisterLoad32 load = { 0, reg, reg, 0xF8D };
  2568. return EmitLongInstruction(pDest, (ULONG&)load);
  2569. }
  2570. BYTE CDetourDis::EmitImmediateRegisterLoad16(PUSHORT& pDest, BYTE reg)
  2571. {
  2572. ImmediateRegisterLoad16 load = { reg, reg, 0x680 >> 2 };
  2573. return EmitShortInstruction(pDest, (USHORT&)load);
  2574. }
  2575. BYTE CDetourDis::EmitLongLiteralLoad(PUSHORT& pDest, BYTE targetRegister, PVOID pTarget)
  2576. {
  2577. *--((PULONG&)m_pbPool) = (ULONG)(size_t)pTarget;
  2578. // ldr rn, target.
  2579. BYTE size = EmitLiteralLoad12(pDest, targetRegister, m_pbPool);
  2580. // This only makes sense if targetRegister != PC;
  2581. // otherwise, we would have branched with the previous instruction anyway
  2582. if (targetRegister != c_PC) {
  2583. // ldr rn, [rn]
  2584. if (targetRegister <= 7) {
  2585. size = (BYTE)(size + EmitImmediateRegisterLoad16(pDest, targetRegister));
  2586. }
  2587. else {
  2588. size = (BYTE)(size + EmitImmediateRegisterLoad32(pDest, targetRegister));
  2589. }
  2590. }
  2591. return size;
  2592. }
  2593. BYTE CDetourDis::EmitLongBranch(PUSHORT& pDest, PVOID pTarget)
  2594. {
  2595. // Emit a long literal load into PC
  2596. BYTE size = EmitLongLiteralLoad(pDest, c_PC, DETOURS_PBYTE_TO_PFUNC(pTarget));
  2597. return size;
  2598. }
  2599. BYTE CDetourDis::PureCopy16(BYTE* pSource, BYTE* pDest)
  2600. {
  2601. *(USHORT *)pDest = *(USHORT *)pSource;
  2602. return sizeof(USHORT);
  2603. }
  2604. BYTE CDetourDis::PureCopy32(BYTE* pSource, BYTE* pDest)
  2605. {
  2606. *(UNALIGNED ULONG *)pDest = *(UNALIGNED ULONG*)pSource;
  2607. return sizeof(DWORD);
  2608. }
  2609. USHORT CDetourDis::CalculateExtra(BYTE sourceLength, BYTE* pDestStart, BYTE* pDestEnd)
  2610. {
  2611. ULONG destinationLength = (ULONG)(pDestEnd - pDestStart);
  2612. return static_cast<USHORT>((destinationLength > sourceLength) ? (destinationLength - sourceLength) : 0);
  2613. }
  2614. BYTE CDetourDis::CopyMiscellaneous16(BYTE* pSource, BYTE* pDest)
  2615. {
  2616. USHORT instruction = *(PUSHORT)(pSource);
  2617. // Compare and branch imm5 (CBZ, CBNZ)
  2618. if ((instruction & 0x100) && !(instruction & 0x400)) { // (1011x0x1xxxxxxxx)
  2619. LONG oldDelta = DecodeBranch5(instruction);
  2620. PBYTE pTarget = CalculateTarget(pSource, oldDelta);
  2621. m_pbTarget = pTarget;
  2622. LONG newDelta = CalculateNewDelta(pTarget, pDest);
  2623. instruction = EncodeBranch5(instruction, newDelta);
  2624. if (instruction) {
  2625. // Copy the 16 bit instruction over
  2626. *(PUSHORT)(pDest) = instruction;
  2627. return sizeof(USHORT); // The source instruction was 16 bits
  2628. }
  2629. // If that fails, re-encode with 'conditional branch' logic, without using the condition flags
  2630. // For example, cbz r2,+0x56 (0x90432) becomes:
  2631. //
  2632. // 001df73a b92a cbnz r2,001df748
  2633. // 001df73c e002 b 001df744
  2634. // 001df73e bf00 nop
  2635. // 001df740 0432 dc.h 0432
  2636. // 001df742 0009 dc.h 0009
  2637. // 001df744 f85ff008 ldr pc,=0x90432
  2638. //
  2639. // Store where we will be writing our conditional branch, and move past it so we can emit a long branch
  2640. PUSHORT pDstInst = (PUSHORT)(pDest);
  2641. PUSHORT pConditionalBranchInstruction = pDstInst++;
  2642. // Emit the long branch instruction
  2643. BYTE longBranchSize = EmitLongBranch(pDstInst, pTarget);
  2644. // Invert the CBZ/CBNZ instruction to move past our 'long branch' if the inverse comparison succeeds
  2645. // Write the CBZ/CBNZ instruction *before* the long branch we emitted above
  2646. // This had to be done out of order, since the size of a long branch can vary due to alignment restrictions
  2647. instruction = EncodeBranch5(*(PUSHORT)(pSource), longBranchSize - c_PCAdjust + sizeof(USHORT));
  2648. Branch5& branch = (Branch5&)(instruction);
  2649. branch.OpCode = (branch.OpCode & 0x02) ? 0x2C : 0x2E; // Invert the CBZ/CBNZ comparison
  2650. *pConditionalBranchInstruction = instruction;
  2651. // Compute the extra space needed for the branch sequence
  2652. m_lExtra = CalculateExtra(sizeof(USHORT), pDest, (BYTE*)(pDstInst));
  2653. return sizeof(USHORT); // The source instruction was 16 bits
  2654. }
  2655. // If-Then Instruction (IT)
  2656. if ((instruction >> 8 == 0xBF) && (instruction & 0xF)) { //(10111111xxxx(mask != 0b0000))
  2657. // ToDo: Implement IT handler
  2658. ASSERT(false);
  2659. return sizeof(USHORT);
  2660. }
  2661. // ADD/SUB, SXTH, SXTB, UXTH, UXTB, CBZ, CBNZ, PUSH, POP, REV, REV15, REVSH, NOP, YIELD, WFE, WFI, SEV, etc.
  2662. return PureCopy16(pSource, pDest);
  2663. }
  2664. BYTE CDetourDis::CopyConditionalBranchOrOther16(BYTE* pSource, BYTE* pDest)
  2665. {
  2666. USHORT instruction = *(PUSHORT)(pSource);
  2667. // Could be a conditional branch, an Undefined instruction or a Service System Call
  2668. // Only the former needs special logic
  2669. if ((instruction & 0xE00) != 0xE00) { // 1101(!=111x)xxxxxxxx
  2670. LONG oldDelta = DecodeBranch8(instruction);
  2671. PBYTE pTarget = CalculateTarget(pSource, oldDelta);
  2672. m_pbTarget = pTarget;
  2673. LONG newDelta = CalculateNewDelta(pTarget, pDest);
  2674. instruction = EncodeBranch8(instruction, newDelta);
  2675. if (instruction) {
  2676. // Copy the 16 bit instruction over
  2677. *(PUSHORT)(pDest) = instruction;
  2678. return sizeof(USHORT); // The source instruction was 16 bits
  2679. }
  2680. // If that fails, re-encode as a sequence of branches
  2681. // For example, bne +0x6E (0x90452) becomes:
  2682. //
  2683. // 001df758 d100 bne 001df75c
  2684. // 001df75a e005 b 001df768
  2685. // 001df75c e002 b 001df764
  2686. // 001df75e bf00 nop
  2687. // 001df760 0452 dc.h 0452
  2688. // 001df762 0009 dc.h 0009
  2689. // 001df764 f85ff008 ldr pc,=0x90452
  2690. //
  2691. // First, reuse the existing conditional branch to, if successful, branch down to a 'long branch' that we will emit below
  2692. USHORT newInstruction = EncodeBranch8(*(PUSHORT)(pSource), 0); // Due to the size of c_PCAdjust a zero-length branch moves 4 bytes forward, past the following unconditional branch
  2693. ASSERT(newInstruction);
  2694. PUSHORT pDstInst = (PUSHORT)(pDest);
  2695. *pDstInst++ = newInstruction;
  2696. // Next, prepare to insert an unconditional branch that will be hit if the condition above is not met. This branch will branch over the following 'long branch'
  2697. // We can't actually encode this branch yet though, because 'long branches' can vary in size
  2698. PUSHORT pUnconditionalBranchInstruction = pDstInst++;
  2699. // Then, emit a 'long branch' that will be hit if the original condition is met
  2700. BYTE longBranchSize = EmitLongBranch(pDstInst, pTarget);
  2701. // Finally, encode and emit the unconditional branch that will be used to branch past the 'long branch' if the initial condition was not met
  2702. Branch11 branch11 = { 0x00, 0x1C };
  2703. newInstruction = EncodeBranch11(*(DWORD*)(&branch11), longBranchSize - c_PCAdjust + sizeof(USHORT));
  2704. ASSERT(newInstruction);
  2705. *pUnconditionalBranchInstruction = newInstruction;
  2706. // Compute the extra space needed for the branch sequence
  2707. m_lExtra = CalculateExtra(sizeof(USHORT), pDest, (BYTE*)(pDstInst));
  2708. return sizeof(USHORT); // The source instruction was 16 bits
  2709. }
  2710. return PureCopy16(pSource, pDest);
  2711. }
  2712. BYTE CDetourDis::CopyUnConditionalBranch16(BYTE* pSource, BYTE* pDest)
  2713. {
  2714. ULONG instruction = *(PUSHORT)(pSource);
  2715. LONG oldDelta = DecodeBranch11(instruction);
  2716. PBYTE pTarget = CalculateTarget(pSource, oldDelta);
  2717. m_pbTarget = pTarget;
  2718. LONG newDelta = CalculateNewDelta(pTarget, pDest);
  2719. instruction = EncodeBranch11(instruction, newDelta);
  2720. if (instruction) {
  2721. // Copy the 16 bit instruction over
  2722. *(PUSHORT)(pDest) = (USHORT)instruction;
  2723. return sizeof(USHORT); // The source instruction was 16 bits
  2724. }
  2725. // If that fails, re-encode as 32-bit
  2726. PUSHORT pDstInst = (PUSHORT)(pDest);
  2727. instruction = EncodeBranch24(0xf0009000, newDelta, FALSE);
  2728. if (instruction) {
  2729. // Copy both bytes of the instruction
  2730. EmitLongInstruction(pDstInst, instruction);
  2731. m_lExtra = sizeof(DWORD) - sizeof(USHORT); // The destination instruction was 32 bits
  2732. return sizeof(USHORT); // The source instruction was 16 bits
  2733. }
  2734. // If that fails, emit as a 'long branch'
  2735. if (!instruction) {
  2736. // For example, b +0x7FE (00090be6) becomes:
  2737. // 003f6d02 e001 b 003f6d08
  2738. // 003f6d04 0be6 dc.h 0be6
  2739. // 003f6d06 0009 dc.h 0009
  2740. // 003f6d08 f85ff008 ldr pc,=0x90BE6
  2741. EmitLongBranch(pDstInst, pTarget);
  2742. // Compute the extra space needed for the branch sequence
  2743. m_lExtra = CalculateExtra(sizeof(USHORT), pDest, (BYTE*)(pDstInst));
  2744. return sizeof(USHORT); // The source instruction was 16 bits
  2745. }
  2746. return sizeof(USHORT); // The source instruction was 16 bits
  2747. }
  2748. BYTE CDetourDis::CopyLiteralLoad16(BYTE* pSource, BYTE* pDest)
  2749. {
  2750. PBYTE pStart = pDest;
  2751. USHORT instruction = *(PUSHORT)(pSource);
  2752. LONG oldDelta = DecodeLiteralLoad8(instruction);
  2753. PBYTE pTarget = CalculateTarget(Align4(pSource), oldDelta);
  2754. // Re-encode as a 'long literal load'
  2755. // For example, ldr r0, [PC + 1E0] (0x905B4) becomes:
  2756. //
  2757. // 001df72c f85f0008 ldr r0,=0x905B4
  2758. // 001df730 f8d00000 ldr.w r0,[r0]
  2759. LiteralLoad8& load8 = (LiteralLoad8&)(instruction);
  2760. EmitLongLiteralLoad((PUSHORT&)pDest, load8.Register, pTarget);
  2761. m_lExtra = (LONG)(pDest - pStart - sizeof(USHORT));
  2762. return sizeof(USHORT); // The source instruction was 16 bits
  2763. }
  2764. BYTE CDetourDis::CopyBranchExchangeOrDataProcessing16(BYTE* pSource, BYTE* pDest)
  2765. {
  2766. ULONG instruction = *(PUSHORT)(pSource);
  2767. // BX
  2768. if ((instruction & 0xff80) == 0x4700) {
  2769. // The target is stored in a register
  2770. m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  2771. }
  2772. // AND, LSR, TST, ADD, CMP, MOV
  2773. return PureCopy16(pSource, pDest);
  2774. }
  2775. const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[33] =
  2776. {
  2777. // Shift by immediate, move register
  2778. // ToDo: Not handling moves from PC
  2779. /* 0b00000 */ { 0x00, &CDetourDis::PureCopy16 },
  2780. /* 0b00001 */ { 0x01, &CDetourDis::PureCopy16 },
  2781. /* 0b00010 */ { 0x02, &CDetourDis::PureCopy16 },
  2782. // Add/subtract register
  2783. // Add/subtract immediate
  2784. /* 0b00011 */ { 0x03, &CDetourDis::PureCopy16},
  2785. // Add/subtract/compare/move immediate
  2786. /* 0b00100 */ { 0x04, &CDetourDis::PureCopy16 },
  2787. /* 0b00101 */ { 0x05, &CDetourDis::PureCopy16 },
  2788. /* 0b00110 */ { 0x06, &CDetourDis::PureCopy16 },
  2789. /* 0b00111 */ { 0x07, &CDetourDis::PureCopy16 },
  2790. // Data-processing register
  2791. // Special data processing
  2792. // Branch/exchange instruction set
  2793. /* 0b01000 */ { 0x08, &CDetourDis::CopyBranchExchangeOrDataProcessing16 },
  2794. // Load from literal pool
  2795. /* 0b01001 */ { 0x09, &CDetourDis::CopyLiteralLoad16 },
  2796. // Load/store register offset
  2797. /* 0b01010 */ { 0x0a, &CDetourDis::PureCopy16 },
  2798. /* 0b01011 */ { 0x0b, &CDetourDis::PureCopy16 },
  2799. // Load/store word/byte immediate offset.
  2800. /* 0b01100 */ { 0x0c, &CDetourDis::PureCopy16 },
  2801. /* 0b01101 */ { 0x0d, &CDetourDis::PureCopy16 },
  2802. /* 0b01110 */ { 0x0e, &CDetourDis::PureCopy16 },
  2803. /* 0b01111 */ { 0x0f, &CDetourDis::PureCopy16 },
  2804. // Load/store halfword immediate offset.
  2805. /* 0b10000 */ { 0x10, &CDetourDis::PureCopy16 },
  2806. /* 0b10001 */ { 0x11, &CDetourDis::PureCopy16 },
  2807. // Load from or store to stack
  2808. /* 0b10010 */ { 0x12, &CDetourDis::PureCopy16 },
  2809. /* 0b10011 */ { 0x13, &CDetourDis::PureCopy16 },
  2810. // Add to SP or PC
  2811. /* 0b10100 */ { 0x14, &CDetourDis::PureCopy16 },
  2812. // ToDo: Is ADR (T1) blitt-able?
  2813. // It adds a value to PC and stores the result in a register.
  2814. // Does this count as a 'target' for detours?
  2815. /* 0b10101 */ { 0x15, &CDetourDis::PureCopy16 },
  2816. // Miscellaneous
  2817. /* 0b10110 */ { 0x16, &CDetourDis::CopyMiscellaneous16 },
  2818. /* 0b10111 */ { 0x17, &CDetourDis::CopyMiscellaneous16 },
  2819. // Load/store multiple
  2820. /* 0b11000 */ { 0x18, &CDetourDis::PureCopy16 },
  2821. /* 0b11001 */ { 0x19, &CDetourDis::PureCopy16 },
  2822. // ToDo: Are we sure these are all safe?
  2823. // LDMIA, for example, can include an 'embedded' branch.
  2824. // Does this count as a 'target' for detours?
  2825. // Conditional branch
  2826. /* 0b11010 */ { 0x1a, &CDetourDis::CopyConditionalBranchOrOther16 },
  2827. // Conditional branch
  2828. // Undefined instruction
  2829. // Service (system) call
  2830. /* 0b11011 */ { 0x1b, &CDetourDis::CopyConditionalBranchOrOther16 },
  2831. // Unconditional branch
  2832. /* 0b11100 */ { 0x1c, &CDetourDis::CopyUnConditionalBranch16 },
  2833. // 32-bit instruction
  2834. /* 0b11101 */ { 0x1d, &CDetourDis::BeginCopy32 },
  2835. /* 0b11110 */ { 0x1e, &CDetourDis::BeginCopy32 },
  2836. /* 0b11111 */ { 0x1f, &CDetourDis::BeginCopy32 },
  2837. { 0, NULL }
  2838. };
  2839. BYTE CDetourDis::CopyBranch24(BYTE* pSource, BYTE* pDest)
  2840. {
  2841. ULONG instruction = GetLongInstruction(pSource);
  2842. BOOL fLink;
  2843. LONG oldDelta = DecodeBranch24(instruction, fLink);
  2844. PBYTE pTarget = CalculateTarget(pSource, oldDelta);
  2845. m_pbTarget = pTarget;
  2846. // Re-encode as 32-bit
  2847. PUSHORT pDstInst = (PUSHORT)(pDest);
  2848. LONG newDelta = CalculateNewDelta(pTarget, pDest);
  2849. instruction = EncodeBranch24(instruction, newDelta, fLink);
  2850. if (instruction) {
  2851. // Copy both bytes of the instruction
  2852. EmitLongInstruction(pDstInst, instruction);
  2853. return sizeof(DWORD);
  2854. }
  2855. // If that fails, re-encode as a 'long branch'
  2856. EmitLongBranch(pDstInst, pTarget);
  2857. // Compute the extra space needed for the instruction
  2858. m_lExtra = CalculateExtra(sizeof(DWORD), pDest, (BYTE*)(pDstInst));
  2859. return sizeof(DWORD); // The source instruction was 32 bits
  2860. }
  2861. BYTE CDetourDis::CopyBranchOrMiscellaneous32(BYTE* pSource, BYTE* pDest)
  2862. {
  2863. ULONG instruction = GetLongInstruction(pSource);
  2864. if ((instruction & 0xf800d000) == 0xf0008000) { // B<c>.W <label>
  2865. LONG oldDelta = DecodeBranch20(instruction);
  2866. PBYTE pTarget = CalculateTarget(pSource, oldDelta);
  2867. m_pbTarget = pTarget;
  2868. // Re-encode as 32-bit
  2869. PUSHORT pDstInst = (PUSHORT)(pDest);
  2870. LONG newDelta = CalculateNewDelta(pTarget, pDest);
  2871. instruction = EncodeBranch20(instruction, newDelta);
  2872. if (instruction) {
  2873. // Copy both bytes of the instruction
  2874. EmitLongInstruction(pDstInst, instruction);
  2875. return sizeof(DWORD);
  2876. }
  2877. // If that fails, re-encode as a sequence of branches
  2878. // For example, bls.w +0x86 (00090480)| becomes:
  2879. //
  2880. // 001df788 f2408001 bls.w 001df78e
  2881. // 001df78c e004 b 001df798
  2882. // 001df78e e001 b 001df794
  2883. // 001df790 0480 dc.h 0480
  2884. // 001df792 0009 dc.h 0009
  2885. // 001df794 f85ff008 ldr pc,=0x90480
  2886. //
  2887. // First, reuse the existing conditional branch to, if successful,
  2888. // branch down to a 'long branch' that we will emit below
  2889. instruction = EncodeBranch20(GetLongInstruction(pSource), 2);
  2890. // Due to the size of c_PCAdjust a two-length branch moves 6 bytes forward,
  2891. // past the following unconditional branch
  2892. ASSERT(instruction);
  2893. EmitLongInstruction(pDstInst, instruction);
  2894. // Next, prepare to insert an unconditional branch that will be hit
  2895. // if the condition above is not met. This branch will branch over
  2896. // the following 'long branch'
  2897. // We can't actually encode this branch yet though, because
  2898. // 'long branches' can vary in size
  2899. PUSHORT pUnconditionalBranchInstruction = pDstInst++;
  2900. // Then, emit a 'long branch' that will be hit if the original condition is met
  2901. BYTE longBranchSize = EmitLongBranch(pDstInst, pTarget);
  2902. // Finally, encode and emit the unconditional branch that will be used
  2903. // to branch past the 'long branch' if the initial condition was not met
  2904. Branch11 branch11 = { 0x00, 0x1C };
  2905. instruction = EncodeBranch11(*(DWORD*)(&branch11), longBranchSize - c_PCAdjust + sizeof(USHORT));
  2906. ASSERT(instruction);
  2907. *pUnconditionalBranchInstruction = static_cast<USHORT>(instruction);
  2908. // Compute the extra space needed for the instruction
  2909. m_lExtra = CalculateExtra(sizeof(DWORD), pDest, (BYTE*)(pDstInst));
  2910. return sizeof(DWORD); // The source instruction was 32 bits
  2911. }
  2912. if ((instruction & 0xf800d000) == 0xf0009000) { // B.W <label>
  2913. // B <label> 11110xxxxxxxxxxx10xxxxxxxxxxxxxx
  2914. return CopyBranch24(pSource, pDest);
  2915. }
  2916. if ((instruction & 0xf800d000) == 0xf000d000) { // BL.W <label>
  2917. // B <label> 11110xxxxxxxxxxx10xxxxxxxxxxxxxx
  2918. PUSHORT pDstInst = (PUSHORT)(pDest);
  2919. BOOL fLink;
  2920. LONG oldDelta = DecodeBranch24(instruction, fLink);
  2921. PBYTE pTarget = CalculateTarget(pSource, oldDelta);
  2922. m_pbTarget = pTarget;
  2923. *--((PULONG&)m_pbPool) = (ULONG)(size_t)DETOURS_PBYTE_TO_PFUNC(pTarget);
  2924. // ldr lr, target.
  2925. EmitLiteralLoad12(pDstInst, c_LR, m_pbPool);
  2926. // blx lr
  2927. EmitShortInstruction(pDstInst, 0x47f0);
  2928. // Compute the extra space needed for the instruction
  2929. m_lExtra = CalculateExtra(sizeof(DWORD), pDest, (BYTE*)(pDstInst));
  2930. return sizeof(DWORD); // The source instruction was 32 bits
  2931. }
  2932. if ((instruction & 0xFFF0FFFF) == 0xF3C08F00) {
  2933. // BXJ 111100111100xxxx1000111100000000
  2934. // BXJ switches to Jazelle mode, which is not supported
  2935. ASSERT(false);
  2936. }
  2937. if ((instruction & 0xFFFFFF00) == 0xF3DE8F00) {
  2938. // SUBS PC, LR 111100111101111010001111xxxxxxxx
  2939. m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  2940. }
  2941. // Everything else should be blitt-able
  2942. return PureCopy32(pSource, pDest);
  2943. }
  2944. BYTE CDetourDis::CopyLiteralLoad32(BYTE* pSource, BYTE* pDest)
  2945. {
  2946. BYTE* pStart = pDest;
  2947. ULONG instruction = GetLongInstruction(pSource);
  2948. LONG oldDelta = DecodeLiteralLoad12(instruction);
  2949. PBYTE pTarget = CalculateTarget(Align4(pSource), oldDelta);
  2950. LiteralLoad12& load = (LiteralLoad12&)(instruction);
  2951. EmitLongLiteralLoad((PUSHORT&)pDest, load.Register, pTarget);
  2952. m_lExtra = (LONG)(pDest - pStart - sizeof(DWORD));
  2953. return sizeof(DWORD); // The source instruction was 32 bits
  2954. }
  2955. BYTE CDetourDis::CopyLoadAndStoreSingle(BYTE* pSource, BYTE* pDest)
  2956. {
  2957. ULONG instruction = GetLongInstruction(pSource);
  2958. // Note: The following masks only look at the interesting bits
  2959. // (not the opCode prefix, since that check was performed in
  2960. // order to get to this function)
  2961. if (!(instruction & 0x100000)) {
  2962. // 1111 100x xxx0 xxxxxxxxxxxxxxxxxxxx : STR, STRB, STRH, etc.
  2963. return PureCopy32(pSource, pDest);
  2964. }
  2965. if ((instruction & 0xF81F0000) == 0xF81F0000) {
  2966. // 1111100xxxx11111xxxxxxxxxxxxxxxx : PC +/- Imm12
  2967. return CopyLiteralLoad32(pSource, pDest);
  2968. }
  2969. if ((instruction & 0xFE70F000) == 0xF81FF000) {
  2970. // 1111100xx001xxxx1111xxxxxxxxxxxx : PLD, PLI
  2971. // Convert PC-Relative PLD/PLI instructions to noops (1111100Xx00111111111xxxxxxxxxxxx)
  2972. if ((instruction & 0xFE7FF000) == 0xF81FF000) {
  2973. PUSHORT pDstInst = (PUSHORT)(pDest);
  2974. *pDstInst++ = c_NOP;
  2975. *pDstInst++ = c_NOP;
  2976. return sizeof(DWORD); // The source instruction was 32 bits
  2977. }
  2978. // All other PLD/PLI instructions are blitt-able
  2979. return PureCopy32(pSource, pDest);
  2980. }
  2981. // If the load is writing to PC
  2982. if ((instruction & 0xF950F000) == 0xF850F000) {
  2983. m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  2984. }
  2985. // All other loads LDR (immediate), etc.
  2986. return PureCopy32(pSource, pDest);
  2987. }
  2988. BYTE CDetourDis::CopyLoadAndStoreMultipleAndSRS(BYTE* pSource, BYTE* pDest)
  2989. {
  2990. // Probably all blitt-able, although not positive since some of these can result in a branch (LDMIA, POP, etc.)
  2991. return PureCopy32(pSource, pDest);
  2992. }
  2993. BYTE CDetourDis::CopyTableBranch(BYTE* pSource, BYTE* pDest)
  2994. {
  2995. m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  2996. ULONG instruction = GetLongInstruction(pSource);
  2997. TableBranch& tableBranch = (TableBranch&)(instruction);
  2998. // If the base register is anything other than PC, we can simply copy the instruction
  2999. if (tableBranch.BaseRegister != c_PC) {
  3000. return PureCopy32(pSource, pDest);
  3001. }
  3002. __debugbreak();
  3003. // If the base register is PC, we need to manually perform the table lookup
  3004. // For example, this:
  3005. //
  3006. // 7ef40000 e8dff002 tbb [pc,r2]
  3007. //
  3008. // becomes this:
  3009. //
  3010. // 7ef40404 b401 push {r0} ; pushed as a placeholder for the target address
  3011. // 7ef40406 e92d0005 push.w {r0,r2} ; scratch register and another register are pushed; there's a minimum of two registers in the list for push.w
  3012. // 7ef40410 4820 ldr r0,=0x7EF40004 ; load the table address from the literal pool
  3013. // 7ef40414 eb000042 add r0,r0,r2,lsl #1 ; add the index value to the address of the table to get the table entry; lsl only used if it's a TBH instruction
  3014. // 7ef40418 f8d00000 ldr.w r0,[r0] ; dereference the table entry to get the value of the target
  3015. // 7ef4041c ea4f0040 lsl r0,r0,#1 ; multiply the offset by 2 (per the spec)
  3016. // 7ef40420 eb00000f add.w r0,r0,pc ; Add the offset to pc to get the target address
  3017. // 7ef40424 f8cd000c str.w r0,[sp,#0xC] ; store the target address on the stack (into the first push)
  3018. // 7ef40428 e8bd0005 pop.w {r0,r2} ; scratch register and another register are popped; there's a minimum of two registers in the list for pop.w
  3019. // 7ef4042c bd00 pop {pc} ; pop the address into pc
  3020. //
  3021. // Push r0 to make room for our jump address on the stack
  3022. PUSHORT pDstInst = (PUSHORT)(pDest);
  3023. *pDstInst++ = 0xb401;
  3024. // Locate a scratch register
  3025. BYTE scrReg = 0;
  3026. while (scrReg == tableBranch.IndexRegister) {
  3027. ++scrReg;
  3028. }
  3029. // Push scrReg and tableBranch.IndexRegister (push.w doesn't support pushing just 1 register)
  3030. DWORD pushInstruction = 0xe92d0000;
  3031. pushInstruction |= 1 << scrReg;
  3032. pushInstruction |= 1 << tableBranch.IndexRegister;
  3033. EmitLongInstruction(pDstInst, pushInstruction);
  3034. // Write the target address out to the 'literal pool';
  3035. // when the base register of a TBB/TBH is PC,
  3036. // the branch table immediately follows the instruction
  3037. BYTE* pTarget = CalculateTarget(pSource, 0);
  3038. *--((PUSHORT&)m_pbPool) = (USHORT)((size_t)pTarget & 0xffff);
  3039. *--((PUSHORT&)m_pbPool) = (USHORT)((size_t)pTarget >> 16);
  3040. // Load the literal pool value into our scratch register (this contains the address of the branch table)
  3041. // ldr rn, target
  3042. EmitLiteralLoad8(pDstInst, scrReg, m_pbPool);
  3043. // Add the index offset to the address of the branch table; the result will be the value within the table that contains the branch offset
  3044. // We need to multiply the index by two if we are using halfword indexing
  3045. // Will shift tableBranch.IndexRegister by 1 (multiply by 2) if using a TBH
  3046. EmitAdd32(pDstInst, scrReg, tableBranch.IndexRegister, scrReg, tableBranch.HalfWord);
  3047. // Dereference rn into rn, to load the value within the table
  3048. // ldr rn, [rn]
  3049. if (scrReg < 0x7) {
  3050. EmitImmediateRegisterLoad16(pDstInst, scrReg);
  3051. }
  3052. else {
  3053. EmitImmediateRegisterLoad32(pDstInst, scrReg);
  3054. }
  3055. // Multiply the offset by two to get the true offset value (as per the spec)
  3056. EmitLogicalShiftLeft32(pDstInst, scrReg, scrReg, 1);
  3057. // Add the offset to PC to get the target
  3058. EmitAdd32(pDstInst, scrReg, c_PC, scrReg, 0);
  3059. // Now write the contents of scrReg to the stack, so we can pop it into PC
  3060. // Write the address of the branch table entry to the stack, so we can pop it into PC
  3061. EmitStoreImmediate12(pDstInst, scrReg, c_SP, sizeof(DWORD) * 3);
  3062. // Pop scrReg and tableBranch.IndexRegister (pop.w doesn't support popping just 1 register)
  3063. DWORD popInstruction = 0xe8bd0000;
  3064. popInstruction |= 1 << scrReg;
  3065. popInstruction |= 1 << tableBranch.IndexRegister;
  3066. EmitLongInstruction(pDstInst, popInstruction);
  3067. // Pop PC
  3068. *pDstInst++ = 0xbd00;
  3069. // Compute the extra space needed for the branch sequence
  3070. m_lExtra = CalculateExtra(sizeof(USHORT), pDest, (BYTE*)(pDstInst));
  3071. return sizeof(DWORD);
  3072. }
  3073. BYTE CDetourDis::BeginCopy32(BYTE* pSource, BYTE* pDest)
  3074. {
  3075. ULONG instruction = GetLongInstruction(pSource);
  3076. // Immediate data processing instructions; ADD, SUB, MOV, MOVN, ADR, MOVT, BFC, SSAT16, etc.
  3077. if ((instruction & 0xF8008000) == 0xF0000000) { // 11110xxxxxxxxxxx0xxxxxxxxxxxxxxx
  3078. // Should all be blitt-able
  3079. // ToDo: What about ADR? Is it safe to do a straight-copy?
  3080. // ToDo: Not handling moves to or from PC
  3081. return PureCopy32(pSource, pDest);
  3082. }
  3083. // Non-Immediate data processing instructions; ADD, EOR, TST, etc.
  3084. if ((instruction & 0xEE000000) == 0xEA000000) { // 111x101xxxxxxxxxxxxxxxxxxxxxxx
  3085. // Should all be blitt-able
  3086. return PureCopy32(pSource, pDest);
  3087. }
  3088. // Load and store single data item, memory hints
  3089. if ((instruction & 0xFE000000) == 0xF8000000) { // 1111100xxxxxxxxxxxxxxxxxxxxxxxxx
  3090. return CopyLoadAndStoreSingle(pSource, pDest);
  3091. }
  3092. // Load and store, double and exclusive, and table branch
  3093. if ((instruction & 0xFE400000) == 0xE8400000) { // 1110100xx1xxxxxxxxxxxxxxxxxxxxxx
  3094. // Load and store double
  3095. if (instruction & 0x1200000) {
  3096. // LDRD, STRD (immediate) : xxxxxxxPxxWxxxxxxxxxxxxxxxxxxxxx where PW != 0b00
  3097. // The source register is PC
  3098. if ((instruction & 0xF0000) == 0xF0000) {
  3099. // ToDo: If the source register is PC, what should we do?
  3100. ASSERT(false);
  3101. }
  3102. // If either target registers are PC
  3103. if (((instruction & 0xF000) == 0xF000) ||
  3104. ((instruction & 0xF00) == 0xF00)) {
  3105. m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  3106. }
  3107. return PureCopy32(pSource, pDest);
  3108. }
  3109. // Load and store exclusive
  3110. if (!(instruction & 0x800000)) { // LDREX, STREX : xxxxxxxx0xxxxxxxxxxxxxxxxxxxxxxx
  3111. if ((instruction & 0xF000) == 0xF000) { // xxxxxxxxxxxx1111xxxxxxxxxxxx
  3112. m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  3113. }
  3114. return PureCopy32(pSource, pDest);
  3115. }
  3116. // Table branch
  3117. if ((instruction & 0x1000F0) == 0x100000 || // TBB : xxxxxxxxxxx1xxxxxxxxxxxx0000xxxx
  3118. (instruction & 0x1000F0) == 0x100010) { // TBH : xxxxxxxxxxx1xxxxxxxxxxxx0001xxxx
  3119. return CopyTableBranch(pSource, pDest);
  3120. }
  3121. // Load and store exclusive byte, halfword, doubleword (LDREXB, LDREXH, LDREXD, STREXB, STREXH, STREXD, etc.)
  3122. return PureCopy32(pSource, pDest);
  3123. }
  3124. // Load and store multiple, RFE and SRS
  3125. if ((instruction & 0xFE400000) == 0xE8000000) { // 1110100xx0xxxxxxxxxxxxxxxxxxxxxx
  3126. // Return from exception (RFE)
  3127. if ((instruction & 0xE9900000) == 0xE9900000 || // 1110100110x1xxxxxxxxxxxxxxxxxxxx
  3128. (instruction & 0xE8100000) == 0xE8100000) { // 1110100000x1xxxxxxxxxxxxxxxxxxxx
  3129. return PureCopy32(pSource, pDest);
  3130. }
  3131. return CopyLoadAndStoreMultipleAndSRS(pSource, pDest);
  3132. }
  3133. // Branches, miscellaneous control
  3134. if ((instruction & 0xF8008000) == 0xF0008000) { // 11110xxxxxxxxxxx0xxxxxxxxxxxxxxx
  3135. // Branches, miscellaneous control
  3136. return CopyBranchOrMiscellaneous32(pSource, pDest);
  3137. }
  3138. // Coprocessor instructions
  3139. if ((instruction & 0xEC000000) == 0xEC000000) { // 111x11xxxxxxxxxxxxxxxxxxxxxxxxxx
  3140. return PureCopy32(pSource, pDest);
  3141. }
  3142. // Unhandled instruction; should never make it this far
  3143. ASSERT(false);
  3144. return PureCopy32(pSource, pDest);
  3145. }
  3146. /////////////////////////////////////////////////////////// Disassembler Code.
  3147. //
  3148. CDetourDis::CDetourDis() :
  3149. m_pbTarget((PBYTE)DETOUR_INSTRUCTION_TARGET_NONE),
  3150. m_pbPool(NULL),
  3151. m_lExtra(0)
  3152. {
  3153. }
  3154. PBYTE CDetourDis::CopyInstruction(PBYTE pDst,
  3155. PBYTE *ppDstPool,
  3156. PBYTE pSrc,
  3157. PBYTE *ppTarget,
  3158. LONG *plExtra)
  3159. {
  3160. if (pDst && ppDstPool && ppDstPool != NULL) {
  3161. m_pbPool = (PBYTE)*ppDstPool;
  3162. }
  3163. else {
  3164. pDst = m_rbScratchDst;
  3165. m_pbPool = m_rbScratchDst + sizeof(m_rbScratchDst);
  3166. }
  3167. // Make sure the constant pool is 32-bit aligned.
  3168. m_pbPool -= ((ULONG_PTR)m_pbPool) & 3;
  3169. REFCOPYENTRY pEntry = &s_rceCopyTable[pSrc[1] >> 3];
  3170. ULONG size = (this->*pEntry->pfCopy)(pSrc, pDst);
  3171. pSrc += size;
  3172. // If the target is needed, store our target
  3173. if (ppTarget) {
  3174. *ppTarget = m_pbTarget;
  3175. }
  3176. if (plExtra) {
  3177. *plExtra = m_lExtra;
  3178. }
  3179. if (ppDstPool) {
  3180. *ppDstPool = m_pbPool;
  3181. }
  3182. return pSrc;
  3183. }
  3184. PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst,
  3185. _Inout_opt_ PVOID *ppDstPool,
  3186. _In_ PVOID pSrc,
  3187. _Out_opt_ PVOID *ppTarget,
  3188. _Out_opt_ LONG *plExtra)
  3189. {
  3190. CDetourDis state;
  3191. return (PVOID)state.CopyInstruction((PBYTE)pDst,
  3192. (PBYTE*)ppDstPool,
  3193. (PBYTE)pSrc,
  3194. (PBYTE*)ppTarget,
  3195. plExtra);
  3196. }
  3197. #endif // DETOURS_ARM
  3198. #ifdef DETOURS_ARM64
  3199. #define c_LR 30 // The register number for the Link Register
  3200. #define c_SP 31 // The register number for the Stack Pointer
  3201. #define c_NOP 0xd503201f // A nop instruction
  3202. #define c_BREAK (0xd4200000 | (0xf000 << 5)) // A break instruction
  3203. //
  3204. // Problematic instructions:
  3205. //
  3206. // ADR 0ll10000 hhhhhhhh hhhhhhhh hhhddddd & 0x9f000000 == 0x10000000 (l = low, h = high, d = Rd)
  3207. // ADRP 1ll10000 hhhhhhhh hhhhhhhh hhhddddd & 0x9f000000 == 0x90000000 (l = low, h = high, d = Rd)
  3208. //
  3209. // B.cond 01010100 iiiiiiii iiiiiiii iii0cccc & 0xff000010 == 0x54000000 (i = delta = SignExtend(imm19:00, 64), c = cond)
  3210. //
  3211. // B 000101ii iiiiiiii iiiiiiii iiiiiiii & 0xfc000000 == 0x14000000 (i = delta = SignExtend(imm26:00, 64))
  3212. // BL 100101ii iiiiiiii iiiiiiii iiiiiiii & 0xfc000000 == 0x94000000 (i = delta = SignExtend(imm26:00, 64))
  3213. //
  3214. // CBNZ z0110101 iiiiiiii iiiiiiii iiittttt & 0x7f000000 == 0x35000000 (z = size, i = delta = SignExtend(imm19:00, 64), t = Rt)
  3215. // CBZ z0110100 iiiiiiii iiiiiiii iiittttt & 0x7f000000 == 0x34000000 (z = size, i = delta = SignExtend(imm19:00, 64), t = Rt)
  3216. //
  3217. // LDR Wt 00011000 iiiiiiii iiiiiiii iiittttt & 0xff000000 == 0x18000000 (i = SignExtend(imm19:00, 64), t = Rt)
  3218. // LDR Xt 01011000 iiiiiiii iiiiiiii iiittttt & 0xff000000 == 0x58000000 (i = SignExtend(imm19:00, 64), t = Rt)
  3219. // LDRSW 10011000 iiiiiiii iiiiiiii iiittttt & 0xff000000 == 0x98000000 (i = SignExtend(imm19:00, 64), t = Rt)
  3220. // PRFM 11011000 iiiiiiii iiiiiiii iiittttt & 0xff000000 == 0xd8000000 (i = SignExtend(imm19:00, 64), t = Rt)
  3221. // LDR St 00011100 iiiiiiii iiiiiiii iiittttt & 0xff000000 == 0x1c000000 (i = SignExtend(imm19:00, 64), t = Rt)
  3222. // LDR Dt 01011100 iiiiiiii iiiiiiii iiittttt & 0xff000000 == 0x5c000000 (i = SignExtend(imm19:00, 64), t = Rt)
  3223. // LDR Qt 10011100 iiiiiiii iiiiiiii iiittttt & 0xff000000 == 0x9c000000 (i = SignExtend(imm19:00, 64), t = Rt)
  3224. // LDR inv 11011100 iiiiiiii iiiiiiii iiittttt & 0xff000000 == 0xdc000000 (i = SignExtend(imm19:00, 64), t = Rt)
  3225. //
  3226. // TBNZ z0110111 bbbbbiii iiiiiiii iiittttt & 0x7f000000 == 0x37000000 (z = size, b = bitnum, i = SignExtend(imm14:00, 64), t = Rt)
  3227. // TBZ z0110110 bbbbbiii iiiiiiii iiittttt & 0x7f000000 == 0x36000000 (z = size, b = bitnum, i = SignExtend(imm14:00, 64), t = Rt)
  3228. //
  3229. class CDetourDis
  3230. {
  3231. public:
  3232. CDetourDis();
  3233. PBYTE CopyInstruction(PBYTE pDst,
  3234. PBYTE pSrc,
  3235. PBYTE *ppTarget,
  3236. LONG *plExtra);
  3237. public:
  3238. typedef BYTE (CDetourDis::* COPYFUNC)(PBYTE pbDst, PBYTE pbSrc);
  3239. union AddImm12
  3240. {
  3241. DWORD Assembled;
  3242. struct
  3243. {
  3244. DWORD Rd : 5; // Destination register
  3245. DWORD Rn : 5; // Source register
  3246. DWORD Imm12 : 12; // 12-bit immediate
  3247. DWORD Shift : 2; // shift (must be 0 or 1)
  3248. DWORD Opcode1 : 7; // Must be 0010001 == 0x11
  3249. DWORD Size : 1; // 0 = 32-bit, 1 = 64-bit
  3250. } s;
  3251. static DWORD Assemble(DWORD size, DWORD rd, DWORD rn, ULONG imm, DWORD shift)
  3252. {
  3253. AddImm12 temp;
  3254. temp.s.Rd = rd;
  3255. temp.s.Rn = rn;
  3256. temp.s.Imm12 = imm & 0xfff;
  3257. temp.s.Shift = shift;
  3258. temp.s.Opcode1 = 0x11;
  3259. temp.s.Size = size;
  3260. return temp.Assembled;
  3261. }
  3262. static DWORD AssembleAdd32(DWORD rd, DWORD rn, ULONG imm, DWORD shift) { return Assemble(0, rd, rn, imm, shift); }
  3263. static DWORD AssembleAdd64(DWORD rd, DWORD rn, ULONG imm, DWORD shift) { return Assemble(1, rd, rn, imm, shift); }
  3264. };
  3265. union Adr19
  3266. {
  3267. DWORD Assembled;
  3268. struct
  3269. {
  3270. DWORD Rd : 5; // Destination register
  3271. DWORD Imm19 : 19; // 19-bit upper immediate
  3272. DWORD Opcode1 : 5; // Must be 10000 == 0x10
  3273. DWORD Imm2 : 2; // 2-bit lower immediate
  3274. DWORD Type : 1; // 0 = ADR, 1 = ADRP
  3275. } s;
  3276. inline LONG Imm() const { DWORD Imm = (s.Imm19 << 2) | s.Imm2; return (LONG)(Imm << 11) >> 11; }
  3277. static DWORD Assemble(DWORD type, DWORD rd, LONG delta)
  3278. {
  3279. Adr19 temp;
  3280. temp.s.Rd = rd;
  3281. temp.s.Imm19 = (delta >> 2) & 0x7ffff;
  3282. temp.s.Opcode1 = 0x10;
  3283. temp.s.Imm2 = delta & 3;
  3284. temp.s.Type = type;
  3285. return temp.Assembled;
  3286. }
  3287. static DWORD AssembleAdr(DWORD rd, LONG delta) { return Assemble(0, rd, delta); }
  3288. static DWORD AssembleAdrp(DWORD rd, LONG delta) { return Assemble(1, rd, delta); }
  3289. };
  3290. union Bcc19
  3291. {
  3292. DWORD Assembled;
  3293. struct
  3294. {
  3295. DWORD Condition : 4; // Condition
  3296. DWORD Opcode1 : 1; // Must be 0
  3297. DWORD Imm19 : 19; // 19-bit immediate
  3298. DWORD Opcode2 : 8; // Must be 01010100 == 0x54
  3299. } s;
  3300. inline LONG Imm() const { return (LONG)(s.Imm19 << 13) >> 11; }
  3301. static DWORD AssembleBcc(DWORD condition, LONG delta)
  3302. {
  3303. Bcc19 temp;
  3304. temp.s.Condition = condition;
  3305. temp.s.Opcode1 = 0;
  3306. temp.s.Imm19 = delta >> 2;
  3307. temp.s.Opcode2 = 0x54;
  3308. return temp.Assembled;
  3309. }
  3310. };
  3311. union Branch26
  3312. {
  3313. DWORD Assembled;
  3314. struct
  3315. {
  3316. DWORD Imm26 : 26; // 26-bit immediate
  3317. DWORD Opcode1 : 5; // Must be 00101 == 0x5
  3318. DWORD Link : 1; // 0 = B, 1 = BL
  3319. } s;
  3320. inline LONG Imm() const { return (LONG)(s.Imm26 << 6) >> 4; }
  3321. static DWORD Assemble(DWORD link, LONG delta)
  3322. {
  3323. Branch26 temp;
  3324. temp.s.Imm26 = delta >> 2;
  3325. temp.s.Opcode1 = 0x5;
  3326. temp.s.Link = link;
  3327. return temp.Assembled;
  3328. }
  3329. static DWORD AssembleB(LONG delta) { return Assemble(0, delta); }
  3330. static DWORD AssembleBl(LONG delta) { return Assemble(1, delta); }
  3331. };
  3332. union Br
  3333. {
  3334. DWORD Assembled;
  3335. struct
  3336. {
  3337. DWORD Opcode1 : 5; // Must be 00000 == 0
  3338. DWORD Rn : 5; // Register number
  3339. DWORD Opcode2 : 22; // Must be 1101011000011111000000 == 0x3587c0 for Br
  3340. // 0x358fc0 for Brl
  3341. } s;
  3342. static DWORD Assemble(DWORD rn, bool link)
  3343. {
  3344. Br temp;
  3345. temp.s.Opcode1 = 0;
  3346. temp.s.Rn = rn;
  3347. temp.s.Opcode2 = 0x3587c0;
  3348. if (link)
  3349. temp.Assembled |= 0x00200000;
  3350. return temp.Assembled;
  3351. }
  3352. static DWORD AssembleBr(DWORD rn)
  3353. {
  3354. return Assemble(rn, false);
  3355. }
  3356. static DWORD AssembleBrl(DWORD rn)
  3357. {
  3358. return Assemble(rn, true);
  3359. }
  3360. };
  3361. union Cbz19
  3362. {
  3363. DWORD Assembled;
  3364. struct
  3365. {
  3366. DWORD Rt : 5; // Register to test
  3367. DWORD Imm19 : 19; // 19-bit immediate
  3368. DWORD Nz : 1; // 0 = CBZ, 1 = CBNZ
  3369. DWORD Opcode1 : 6; // Must be 011010 == 0x1a
  3370. DWORD Size : 1; // 0 = 32-bit, 1 = 64-bit
  3371. } s;
  3372. inline LONG Imm() const { return (LONG)(s.Imm19 << 13) >> 11; }
  3373. static DWORD Assemble(DWORD size, DWORD nz, DWORD rt, LONG delta)
  3374. {
  3375. Cbz19 temp;
  3376. temp.s.Rt = rt;
  3377. temp.s.Imm19 = delta >> 2;
  3378. temp.s.Nz = nz;
  3379. temp.s.Opcode1 = 0x1a;
  3380. temp.s.Size = size;
  3381. return temp.Assembled;
  3382. }
  3383. };
  3384. union LdrLit19
  3385. {
  3386. DWORD Assembled;
  3387. struct
  3388. {
  3389. DWORD Rt : 5; // Destination register
  3390. DWORD Imm19 : 19; // 19-bit immediate
  3391. DWORD Opcode1 : 2; // Must be 0
  3392. DWORD FpNeon : 1; // 0 = LDR Wt/LDR Xt/LDRSW/PRFM, 1 = LDR St/LDR Dt/LDR Qt
  3393. DWORD Opcode2 : 3; // Must be 011 = 3
  3394. DWORD Size : 2; // 00 = LDR Wt/LDR St, 01 = LDR Xt/LDR Dt, 10 = LDRSW/LDR Qt, 11 = PRFM/invalid
  3395. } s;
  3396. inline LONG Imm() const { return (LONG)(s.Imm19 << 13) >> 11; }
  3397. static DWORD Assemble(DWORD size, DWORD fpneon, DWORD rt, LONG delta)
  3398. {
  3399. LdrLit19 temp;
  3400. temp.s.Rt = rt;
  3401. temp.s.Imm19 = delta >> 2;
  3402. temp.s.Opcode1 = 0;
  3403. temp.s.FpNeon = fpneon;
  3404. temp.s.Opcode2 = 3;
  3405. temp.s.Size = size;
  3406. return temp.Assembled;
  3407. }
  3408. };
  3409. union LdrFpNeonImm9
  3410. {
  3411. DWORD Assembled;
  3412. struct
  3413. {
  3414. DWORD Rt : 5; // Destination register
  3415. DWORD Rn : 5; // Base register
  3416. DWORD Imm12 : 12; // 12-bit immediate
  3417. DWORD Opcode1 : 1; // Must be 1 == 1
  3418. DWORD Opc : 1; // Part of size
  3419. DWORD Opcode2 : 6; // Must be 111101 == 0x3d
  3420. DWORD Size : 2; // Size (0=8-bit, 1=16-bit, 2=32-bit, 3=64-bit, 4=128-bit)
  3421. } s;
  3422. static DWORD Assemble(DWORD size, DWORD rt, DWORD rn, ULONG imm)
  3423. {
  3424. LdrFpNeonImm9 temp;
  3425. temp.s.Rt = rt;
  3426. temp.s.Rn = rn;
  3427. temp.s.Imm12 = imm;
  3428. temp.s.Opcode1 = 1;
  3429. temp.s.Opc = size >> 2;
  3430. temp.s.Opcode2 = 0x3d;
  3431. temp.s.Size = size & 3;
  3432. return temp.Assembled;
  3433. }
  3434. };
  3435. union Mov16
  3436. {
  3437. DWORD Assembled;
  3438. struct
  3439. {
  3440. DWORD Rd : 5; // Destination register
  3441. DWORD Imm16 : 16; // Immediate
  3442. DWORD Shift : 2; // Shift amount (0=0, 1=16, 2=32, 3=48)
  3443. DWORD Opcode : 6; // Must be 100101 == 0x25
  3444. DWORD Type : 2; // 0 = MOVN, 1 = reserved, 2 = MOVZ, 3 = MOVK
  3445. DWORD Size : 1; // 0 = 32-bit, 1 = 64-bit
  3446. } s;
  3447. static DWORD Assemble(DWORD size, DWORD type, DWORD rd, DWORD imm, DWORD shift)
  3448. {
  3449. Mov16 temp;
  3450. temp.s.Rd = rd;
  3451. temp.s.Imm16 = imm;
  3452. temp.s.Shift = shift;
  3453. temp.s.Opcode = 0x25;
  3454. temp.s.Type = type;
  3455. temp.s.Size = size;
  3456. return temp.Assembled;
  3457. }
  3458. static DWORD AssembleMovn32(DWORD rd, DWORD imm, DWORD shift) { return Assemble(0, 0, rd, imm, shift); }
  3459. static DWORD AssembleMovn64(DWORD rd, DWORD imm, DWORD shift) { return Assemble(1, 0, rd, imm, shift); }
  3460. static DWORD AssembleMovz32(DWORD rd, DWORD imm, DWORD shift) { return Assemble(0, 2, rd, imm, shift); }
  3461. static DWORD AssembleMovz64(DWORD rd, DWORD imm, DWORD shift) { return Assemble(1, 2, rd, imm, shift); }
  3462. static DWORD AssembleMovk32(DWORD rd, DWORD imm, DWORD shift) { return Assemble(0, 3, rd, imm, shift); }
  3463. static DWORD AssembleMovk64(DWORD rd, DWORD imm, DWORD shift) { return Assemble(1, 3, rd, imm, shift); }
  3464. };
  3465. union Tbz14
  3466. {
  3467. DWORD Assembled;
  3468. struct
  3469. {
  3470. DWORD Rt : 5; // Register to test
  3471. DWORD Imm14 : 14; // 14-bit immediate
  3472. DWORD Bit : 5; // 5-bit index
  3473. DWORD Nz : 1; // 0 = TBZ, 1 = TBNZ
  3474. DWORD Opcode1 : 6; // Must be 011011 == 0x1b
  3475. DWORD Size : 1; // 0 = 32-bit, 1 = 64-bit
  3476. } s;
  3477. inline LONG Imm() const { return (LONG)(s.Imm14 << 18) >> 16; }
  3478. static DWORD Assemble(DWORD size, DWORD nz, DWORD rt, DWORD bit, LONG delta)
  3479. {
  3480. Tbz14 temp;
  3481. temp.s.Rt = rt;
  3482. temp.s.Imm14 = delta >> 2;
  3483. temp.s.Bit = bit;
  3484. temp.s.Nz = nz;
  3485. temp.s.Opcode1 = 0x1b;
  3486. temp.s.Size = size;
  3487. return temp.Assembled;
  3488. }
  3489. };
  3490. protected:
  3491. BYTE PureCopy32(BYTE* pSource, BYTE* pDest);
  3492. BYTE EmitMovImmediate(PULONG& pDstInst, BYTE rd, UINT64 immediate);
  3493. BYTE CopyAdr(BYTE* pSource, BYTE* pDest, ULONG instruction);
  3494. BYTE CopyBcc(BYTE* pSource, BYTE* pDest, ULONG instruction);
  3495. BYTE CopyB(BYTE* pSource, BYTE* pDest, ULONG instruction);
  3496. BYTE CopyBl(BYTE* pSource, BYTE* pDest, ULONG instruction);
  3497. BYTE CopyB_or_Bl(BYTE* pSource, BYTE* pDest, ULONG instruction, bool link);
  3498. BYTE CopyCbz(BYTE* pSource, BYTE* pDest, ULONG instruction);
  3499. BYTE CopyTbz(BYTE* pSource, BYTE* pDest, ULONG instruction);
  3500. BYTE CopyLdrLiteral(BYTE* pSource, BYTE* pDest, ULONG instruction);
  3501. protected:
  3502. ULONG GetInstruction(BYTE* pSource)
  3503. {
  3504. return ((PULONG)pSource)[0];
  3505. }
  3506. BYTE EmitInstruction(PULONG& pDstInst, ULONG instruction)
  3507. {
  3508. *pDstInst++ = instruction;
  3509. return sizeof(ULONG);
  3510. }
  3511. protected:
  3512. PBYTE m_pbTarget;
  3513. BYTE m_rbScratchDst[128]; // matches or exceeds rbCode
  3514. };
  3515. BYTE CDetourDis::PureCopy32(BYTE* pSource, BYTE* pDest)
  3516. {
  3517. *(ULONG *)pDest = *(ULONG*)pSource;
  3518. return sizeof(DWORD);
  3519. }
  3520. /////////////////////////////////////////////////////////// Disassembler Code.
  3521. //
  3522. CDetourDis::CDetourDis() :
  3523. m_pbTarget((PBYTE)DETOUR_INSTRUCTION_TARGET_NONE)
  3524. {
  3525. }
  3526. PBYTE CDetourDis::CopyInstruction(PBYTE pDst,
  3527. PBYTE pSrc,
  3528. PBYTE *ppTarget,
  3529. LONG *plExtra)
  3530. {
  3531. if (pDst == NULL) {
  3532. pDst = m_rbScratchDst;
  3533. }
  3534. DWORD Instruction = GetInstruction(pSrc);
  3535. ULONG CopiedSize;
  3536. if ((Instruction & 0x1f000000) == 0x10000000) {
  3537. CopiedSize = CopyAdr(pSrc, pDst, Instruction);
  3538. } else if ((Instruction & 0xff000010) == 0x54000000) {
  3539. CopiedSize = CopyBcc(pSrc, pDst, Instruction);
  3540. } else if ((Instruction & 0x7c000000) == 0x14000000) {
  3541. CopiedSize = CopyB_or_Bl(pSrc, pDst, Instruction, (Instruction & 0x80000000) != 0);
  3542. } else if ((Instruction & 0x7e000000) == 0x34000000) {
  3543. CopiedSize = CopyCbz(pSrc, pDst, Instruction);
  3544. } else if ((Instruction & 0x7e000000) == 0x36000000) {
  3545. CopiedSize = CopyTbz(pSrc, pDst, Instruction);
  3546. } else if ((Instruction & 0x3b000000) == 0x18000000) {
  3547. CopiedSize = CopyLdrLiteral(pSrc, pDst, Instruction);
  3548. } else {
  3549. CopiedSize = PureCopy32(pSrc, pDst);
  3550. }
  3551. // If the target is needed, store our target
  3552. if (ppTarget) {
  3553. *ppTarget = m_pbTarget;
  3554. }
  3555. if (plExtra) {
  3556. *plExtra = CopiedSize - sizeof(DWORD);
  3557. }
  3558. return pSrc + 4;
  3559. }
  3560. BYTE CDetourDis::EmitMovImmediate(PULONG& pDstInst, BYTE rd, UINT64 immediate)
  3561. {
  3562. DWORD piece[4];
  3563. piece[3] = (DWORD)((immediate >> 48) & 0xffff);
  3564. piece[2] = (DWORD)((immediate >> 32) & 0xffff);
  3565. piece[1] = (DWORD)((immediate >> 16) & 0xffff);
  3566. piece[0] = (DWORD)((immediate >> 0) & 0xffff);
  3567. int count = 0;
  3568. // special case: MOVN with 32-bit dest
  3569. if (piece[3] == 0 && piece[2] == 0 && piece[1] == 0xffff)
  3570. {
  3571. EmitInstruction(pDstInst, Mov16::AssembleMovn32(rd, piece[0] ^ 0xffff, 0));
  3572. count++;
  3573. }
  3574. // MOVN/MOVZ with 64-bit dest
  3575. else
  3576. {
  3577. int zero_pieces = (piece[3] == 0x0000) + (piece[2] == 0x0000) + (piece[1] == 0x0000) + (piece[0] == 0x0000);
  3578. int ffff_pieces = (piece[3] == 0xffff) + (piece[2] == 0xffff) + (piece[1] == 0xffff) + (piece[0] == 0xffff);
  3579. DWORD defaultPiece = (ffff_pieces > zero_pieces) ? 0xffff : 0x0000;
  3580. bool first = true;
  3581. for (int pieceNum = 3; pieceNum >= 0; pieceNum--)
  3582. {
  3583. DWORD curPiece = piece[pieceNum];
  3584. if (curPiece != defaultPiece || (pieceNum == 0 && first))
  3585. {
  3586. count++;
  3587. if (first)
  3588. {
  3589. if (defaultPiece == 0xffff)
  3590. {
  3591. EmitInstruction(pDstInst, Mov16::AssembleMovn64(rd, curPiece ^ 0xffff, pieceNum));
  3592. }
  3593. else
  3594. {
  3595. EmitInstruction(pDstInst, Mov16::AssembleMovz64(rd, curPiece, pieceNum));
  3596. }
  3597. first = false;
  3598. }
  3599. else
  3600. {
  3601. EmitInstruction(pDstInst, Mov16::AssembleMovk64(rd, curPiece, pieceNum));
  3602. }
  3603. }
  3604. }
  3605. }
  3606. return (BYTE)(count * sizeof(DWORD));
  3607. }
  3608. BYTE CDetourDis::CopyAdr(BYTE* pSource, BYTE* pDest, ULONG instruction)
  3609. {
  3610. Adr19& decoded = (Adr19&)(instruction);
  3611. PULONG pDstInst = (PULONG)(pDest);
  3612. // ADR case
  3613. if (decoded.s.Type == 0)
  3614. {
  3615. BYTE* pTarget = pSource + decoded.Imm();
  3616. LONG64 delta = pTarget - pDest;
  3617. LONG64 deltaPage = ((ULONG_PTR)pTarget >> 12) - ((ULONG_PTR)pDest >> 12);
  3618. // output as ADR
  3619. if (delta >= -(1 << 20) && delta < (1 << 20))
  3620. {
  3621. EmitInstruction(pDstInst, Adr19::AssembleAdr(decoded.s.Rd, (LONG)delta));
  3622. }
  3623. // output as ADRP; ADD
  3624. else if (deltaPage >= -(1 << 20) && (deltaPage < (1 << 20)))
  3625. {
  3626. EmitInstruction(pDstInst, Adr19::AssembleAdrp(decoded.s.Rd, (LONG)deltaPage));
  3627. EmitInstruction(pDstInst, AddImm12::AssembleAdd32(decoded.s.Rd, decoded.s.Rd, ((ULONG)(ULONG_PTR)pTarget) & 0xfff, 0));
  3628. }
  3629. // output as immediate move
  3630. else
  3631. {
  3632. EmitMovImmediate(pDstInst, decoded.s.Rd, (ULONG_PTR)pTarget);
  3633. }
  3634. }
  3635. // ADRP case
  3636. else
  3637. {
  3638. BYTE* pTarget = (BYTE*)((((ULONG_PTR)pSource >> 12) + decoded.Imm()) << 12);
  3639. LONG64 deltaPage = ((ULONG_PTR)pTarget >> 12) - ((ULONG_PTR)pDest >> 12);
  3640. // output as ADRP
  3641. if (deltaPage >= -(1 << 20) && (deltaPage < (1 << 20)))
  3642. {
  3643. EmitInstruction(pDstInst, Adr19::AssembleAdrp(decoded.s.Rd, (LONG)deltaPage));
  3644. }
  3645. // output as immediate move
  3646. else
  3647. {
  3648. EmitMovImmediate(pDstInst, decoded.s.Rd, (ULONG_PTR)pTarget);
  3649. }
  3650. }
  3651. return (BYTE)((BYTE*)pDstInst - pDest);
  3652. }
  3653. BYTE CDetourDis::CopyBcc(BYTE* pSource, BYTE* pDest, ULONG instruction)
  3654. {
  3655. Bcc19& decoded = (Bcc19&)(instruction);
  3656. PULONG pDstInst = (PULONG)(pDest);
  3657. BYTE* pTarget = pSource + decoded.Imm();
  3658. m_pbTarget = pTarget;
  3659. LONG64 delta = pTarget - pDest;
  3660. LONG64 delta4 = pTarget - (pDest + 4);
  3661. // output as BCC
  3662. if (delta >= -(1 << 20) && delta < (1 << 20))
  3663. {
  3664. EmitInstruction(pDstInst, Bcc19::AssembleBcc(decoded.s.Condition, (LONG)delta));
  3665. }
  3666. // output as BCC <skip>; B
  3667. else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27)))
  3668. {
  3669. EmitInstruction(pDstInst, Bcc19::AssembleBcc(decoded.s.Condition ^ 1, 8));
  3670. EmitInstruction(pDstInst, Branch26::AssembleB((LONG)delta4));
  3671. }
  3672. // output as MOV x17, Target; BCC <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!)
  3673. else
  3674. {
  3675. EmitMovImmediate(pDstInst, 17, (ULONG_PTR)pTarget);
  3676. EmitInstruction(pDstInst, Bcc19::AssembleBcc(decoded.s.Condition ^ 1, 8));
  3677. EmitInstruction(pDstInst, Br::AssembleBr(17));
  3678. }
  3679. return (BYTE)((BYTE*)pDstInst - pDest);
  3680. }
  3681. BYTE CDetourDis::CopyB_or_Bl(BYTE* pSource, BYTE* pDest, ULONG instruction, bool link)
  3682. {
  3683. Branch26& decoded = (Branch26&)(instruction);
  3684. PULONG pDstInst = (PULONG)(pDest);
  3685. BYTE* pTarget = pSource + decoded.Imm();
  3686. m_pbTarget = pTarget;
  3687. LONG64 delta = pTarget - pDest;
  3688. // output as B or BRL
  3689. if (delta >= -(1 << 27) && (delta < (1 << 27)))
  3690. {
  3691. EmitInstruction(pDstInst, Branch26::Assemble(link, (LONG)delta));
  3692. }
  3693. // output as MOV x17, Target; BR or BRL x17 (BIG assumption that x17 isn't being used for anything!!)
  3694. else
  3695. {
  3696. EmitMovImmediate(pDstInst, 17, (ULONG_PTR)pTarget);
  3697. EmitInstruction(pDstInst, Br::Assemble(17, link));
  3698. }
  3699. return (BYTE)((BYTE*)pDstInst - pDest);
  3700. }
  3701. BYTE CDetourDis::CopyB(BYTE* pSource, BYTE* pDest, ULONG instruction)
  3702. {
  3703. return CopyB_or_Bl(pSource, pDest, instruction, false);
  3704. }
  3705. BYTE CDetourDis::CopyBl(BYTE* pSource, BYTE* pDest, ULONG instruction)
  3706. {
  3707. return CopyB_or_Bl(pSource, pDest, instruction, true);
  3708. }
  3709. BYTE CDetourDis::CopyCbz(BYTE* pSource, BYTE* pDest, ULONG instruction)
  3710. {
  3711. Cbz19& decoded = (Cbz19&)(instruction);
  3712. PULONG pDstInst = (PULONG)(pDest);
  3713. BYTE* pTarget = pSource + decoded.Imm();
  3714. m_pbTarget = pTarget;
  3715. LONG64 delta = pTarget - pDest;
  3716. LONG64 delta4 = pTarget - (pDest + 4);
  3717. // output as CBZ/NZ
  3718. if (delta >= -(1 << 20) && delta < (1 << 20))
  3719. {
  3720. EmitInstruction(pDstInst, Cbz19::Assemble(decoded.s.Size, decoded.s.Nz, decoded.s.Rt, (LONG)delta));
  3721. }
  3722. // output as CBNZ/Z <skip>; B
  3723. else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27)))
  3724. {
  3725. EmitInstruction(pDstInst, Cbz19::Assemble(decoded.s.Size, decoded.s.Nz ^ 1, decoded.s.Rt, 8));
  3726. EmitInstruction(pDstInst, Branch26::AssembleB((LONG)delta4));
  3727. }
  3728. // output as MOV x17, Target; CBNZ/Z <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!)
  3729. else
  3730. {
  3731. EmitMovImmediate(pDstInst, 17, (ULONG_PTR)pTarget);
  3732. EmitInstruction(pDstInst, Cbz19::Assemble(decoded.s.Size, decoded.s.Nz ^ 1, decoded.s.Rt, 8));
  3733. EmitInstruction(pDstInst, Br::AssembleBr(17));
  3734. }
  3735. return (BYTE)((BYTE*)pDstInst - pDest);
  3736. }
  3737. BYTE CDetourDis::CopyTbz(BYTE* pSource, BYTE* pDest, ULONG instruction)
  3738. {
  3739. Tbz14& decoded = (Tbz14&)(instruction);
  3740. PULONG pDstInst = (PULONG)(pDest);
  3741. BYTE* pTarget = pSource + decoded.Imm();
  3742. m_pbTarget = pTarget;
  3743. LONG64 delta = pTarget - pDest;
  3744. LONG64 delta4 = pTarget - (pDest + 4);
  3745. // output as TBZ/NZ
  3746. if (delta >= -(1 << 13) && delta < (1 << 13))
  3747. {
  3748. EmitInstruction(pDstInst, Tbz14::Assemble(decoded.s.Size, decoded.s.Nz, decoded.s.Rt, decoded.s.Bit, (LONG)delta));
  3749. }
  3750. // output as TBNZ/Z <skip>; B
  3751. else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27)))
  3752. {
  3753. EmitInstruction(pDstInst, Tbz14::Assemble(decoded.s.Size, decoded.s.Nz ^ 1, decoded.s.Rt, decoded.s.Bit, 8));
  3754. EmitInstruction(pDstInst, Branch26::AssembleB((LONG)delta4));
  3755. }
  3756. // output as MOV x17, Target; TBNZ/Z <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!)
  3757. else
  3758. {
  3759. EmitMovImmediate(pDstInst, 17, (ULONG_PTR)pTarget);
  3760. EmitInstruction(pDstInst, Tbz14::Assemble(decoded.s.Size, decoded.s.Nz ^ 1, decoded.s.Rt, decoded.s.Bit, 8));
  3761. EmitInstruction(pDstInst, Br::AssembleBr(17));
  3762. }
  3763. return (BYTE)((BYTE*)pDstInst - pDest);
  3764. }
  3765. BYTE CDetourDis::CopyLdrLiteral(BYTE* pSource, BYTE* pDest, ULONG instruction)
  3766. {
  3767. LdrLit19& decoded = (LdrLit19&)(instruction);
  3768. PULONG pDstInst = (PULONG)(pDest);
  3769. BYTE* pTarget = pSource + decoded.Imm();
  3770. LONG64 delta = pTarget - pDest;
  3771. // output as LDR
  3772. if (delta >= -(1 << 21) && delta < (1 << 21))
  3773. {
  3774. EmitInstruction(pDstInst, LdrLit19::Assemble(decoded.s.Size, decoded.s.FpNeon, decoded.s.Rt, (LONG)delta));
  3775. }
  3776. // output as move immediate
  3777. else if (decoded.s.FpNeon == 0)
  3778. {
  3779. UINT64 value = 0;
  3780. switch (decoded.s.Size)
  3781. {
  3782. case 0: value = *(ULONG*)pTarget; break;
  3783. case 1: value = *(UINT64*)pTarget; break;
  3784. case 2: value = *(LONG*)pTarget; break;
  3785. }
  3786. EmitMovImmediate(pDstInst, decoded.s.Rt, value);
  3787. }
  3788. // FP/NEON register: compute address in x17 and load from there (BIG assumption that x17 isn't being used for anything!!)
  3789. else
  3790. {
  3791. EmitMovImmediate(pDstInst, 17, (ULONG_PTR)pTarget);
  3792. EmitInstruction(pDstInst, LdrFpNeonImm9::Assemble(2 + decoded.s.Size, decoded.s.Rt, 17, 0));
  3793. }
  3794. return (BYTE)((BYTE*)pDstInst - pDest);
  3795. }
  3796. PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst,
  3797. _Inout_opt_ PVOID *ppDstPool,
  3798. _In_ PVOID pSrc,
  3799. _Out_opt_ PVOID *ppTarget,
  3800. _Out_opt_ LONG *plExtra)
  3801. {
  3802. UNREFERENCED_PARAMETER(ppDstPool);
  3803. CDetourDis state;
  3804. return (PVOID)state.CopyInstruction((PBYTE)pDst,
  3805. (PBYTE)pSrc,
  3806. (PBYTE*)ppTarget,
  3807. plExtra);
  3808. }
  3809. #endif // DETOURS_ARM64
  3810. BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule,
  3811. _In_ BOOL fLimitReferencesToModule)
  3812. {
  3813. #if defined(DETOURS_X64) || defined(DETOURS_X86)
  3814. PBYTE pbBeg = NULL;
  3815. PBYTE pbEnd = (PBYTE)~(ULONG_PTR)0;
  3816. if (hModule != NULL) {
  3817. ULONG cbModule = DetourGetModuleSize(hModule);
  3818. pbBeg = (PBYTE)hModule;
  3819. pbEnd = (PBYTE)hModule + cbModule;
  3820. }
  3821. return CDetourDis::SetCodeModule(pbBeg, pbEnd, fLimitReferencesToModule);
  3822. #elif defined(DETOURS_ARM) || defined(DETOURS_ARM64) || defined(DETOURS_IA64)
  3823. (void)hModule;
  3824. (void)fLimitReferencesToModule;
  3825. return TRUE;
  3826. #else
  3827. #error unknown architecture (x86, x64, arm, arm64, ia64)
  3828. #endif
  3829. }
  3830. //
  3831. ///////////////////////////////////////////////////////////////// End of File.