monoscript.lua 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577
  1. MONOCMD_INITMONO=0
  2. MONOCMD_OBJECT_GETCLASS=1
  3. MONOCMD_ENUMDOMAINS=2
  4. MONOCMD_SETCURRENTDOMAIN=3
  5. MONOCMD_ENUMASSEMBLIES=4
  6. MONOCMD_GETIMAGEFROMASSEMBLY=5
  7. MONOCMD_GETIMAGENAME=6
  8. MONOCMD_ENUMCLASSESINIMAGE=7
  9. MONOCMD_ENUMFIELDSINCLASS=8
  10. MONOCMD_ENUMMETHODSINCLASS=9
  11. MONOCMD_COMPILEMETHOD=10
  12. MONOCMD_GETMETHODHEADER=11
  13. MONOCMD_GETMETHODHEADER_CODE=12
  14. MONOCMD_LOOKUPRVA=13
  15. MONOCMD_GETJITINFO=14
  16. MONOCMD_FINDCLASS=15
  17. MONOCMD_FINDMETHOD=16
  18. MONOCMD_GETMETHODNAME=17
  19. MONOCMD_GETMETHODCLASS=18
  20. MONOCMD_GETCLASSNAME=19
  21. MONOCMD_GETCLASSNAMESPACE=20
  22. MONOCMD_FREEMETHOD=21
  23. MONOCMD_TERMINATE=22
  24. MONOCMD_DISASSEMBLE=23
  25. MONOCMD_GETMETHODSIGNATURE=24
  26. MONOCMD_GETPARENTCLASS=25
  27. MONOCMD_GETSTATICFIELDADDRESSFROMCLASS=26
  28. MONOCMD_GETTYPECLASS=27
  29. MONOCMD_GETARRAYELEMENTCLASS=28
  30. MONOCMD_FINDMETHODBYDESC=29
  31. MONOCMD_INVOKEMETHOD=30
  32. MONOCMD_LOADASSEMBLY=31
  33. MONOCMD_GETFULLTYPENAME=32
  34. MONO_TYPE_END = 0x00 -- End of List
  35. MONO_TYPE_VOID = 0x01
  36. MONO_TYPE_BOOLEAN = 0x02
  37. MONO_TYPE_CHAR = 0x03
  38. MONO_TYPE_I1 = 0x04
  39. MONO_TYPE_U1 = 0x05
  40. MONO_TYPE_I2 = 0x06
  41. MONO_TYPE_U2 = 0x07
  42. MONO_TYPE_I4 = 0x08
  43. MONO_TYPE_U4 = 0x09
  44. MONO_TYPE_I8 = 0x0a
  45. MONO_TYPE_U8 = 0x0b
  46. MONO_TYPE_R4 = 0x0c
  47. MONO_TYPE_R8 = 0x0d
  48. MONO_TYPE_STRING = 0x0e
  49. MONO_TYPE_PTR = 0x0f -- arg: <type> token
  50. MONO_TYPE_BYREF = 0x10 -- arg: <type> token
  51. MONO_TYPE_VALUETYPE = 0x11 -- arg: <type> token
  52. MONO_TYPE_CLASS = 0x12 -- arg: <type> token
  53. MONO_TYPE_VAR = 0x13 -- number
  54. MONO_TYPE_ARRAY = 0x14 -- type, rank, boundsCount, bound1, loCount, lo1
  55. MONO_TYPE_GENERICINST= 0x15 -- <type> <type-arg-count> <type-1> \x{2026} <type-n> */
  56. MONO_TYPE_TYPEDBYREF = 0x16
  57. MONO_TYPE_I = 0x18
  58. MONO_TYPE_U = 0x19
  59. MONO_TYPE_FNPTR = 0x1b -- arg: full method signature */
  60. MONO_TYPE_OBJECT = 0x1c
  61. MONO_TYPE_SZARRAY = 0x1d -- 0-based one-dim-array */
  62. MONO_TYPE_MVAR = 0x1e -- number */
  63. MONO_TYPE_CMOD_REQD = 0x1f -- arg: typedef or typeref token */
  64. MONO_TYPE_CMOD_OPT = 0x20 -- optional arg: typedef or typref token */
  65. MONO_TYPE_INTERNAL = 0x21 -- CLR internal type */
  66. MONO_TYPE_MODIFIER = 0x40 -- Or with the following types */
  67. MONO_TYPE_SENTINEL = 0x41 -- Sentinel for varargs method signature */
  68. MONO_TYPE_PINNED = 0x45 -- Local var that points to pinned object */
  69. MONO_TYPE_ENUM = 0x55 -- an enumeration */
  70. monoTypeToVartypeLookup={}
  71. monoTypeToVartypeLookup[MONO_TYPE_BOOLEAN]=vtByte
  72. monoTypeToVartypeLookup[MONO_TYPE_CHAR]=vtString
  73. monoTypeToVartypeLookup[MONO_TYPE_I1]=vtByte
  74. monoTypeToVartypeLookup[MONO_TYPE_U1]=vtByte
  75. monoTypeToVartypeLookup[MONO_TYPE_I2]=vtWord
  76. monoTypeToVartypeLookup[MONO_TYPE_U2]=vtWord
  77. monoTypeToVartypeLookup[MONO_TYPE_I4]=vtDword
  78. monoTypeToVartypeLookup[MONO_TYPE_U4]=vtDword
  79. monoTypeToVartypeLookup[MONO_TYPE_I8]=vtQword
  80. monoTypeToVartypeLookup[MONO_TYPE_U8]=vtQword
  81. monoTypeToVartypeLookup[MONO_TYPE_R4]=vtSingle
  82. monoTypeToVartypeLookup[MONO_TYPE_R8]=vtDouble
  83. monoTypeToVartypeLookup[MONO_TYPE_STRING]=vtPointer --pointer to a string object
  84. monoTypeToVartypeLookup[MONO_TYPE_PTR]=vtPointer
  85. monoTypeToVartypeLookup[MONO_TYPE_BYREF]=vtPointer
  86. monoTypeToVartypeLookup[MONO_TYPE_CLASS]=vtPointer
  87. monoTypeToVartypeLookup[MONO_TYPE_FNPTR]=vtPointer
  88. monoTypeToVartypeLookup[MONO_TYPE_GENERICINST]=vtPointer
  89. monoTypeToVartypeLookup[MONO_TYPE_ARRAY]=vtPointer
  90. monoTypeToVartypeLookup[MONO_TYPE_SZARRAY]=vtPointer
  91. FIELD_ATTRIBUTE_FIELD_ACCESS_MASK=0x0007
  92. FIELD_ATTRIBUTE_COMPILER_CONTROLLED=0x0000
  93. FIELD_ATTRIBUTE_PRIVATE=0x0001
  94. FIELD_ATTRIBUTE_FAM_AND_ASSEM=0x0002
  95. FIELD_ATTRIBUTE_ASSEMBLY=0x0003
  96. FIELD_ATTRIBUTE_FAMILY=0x0004
  97. FIELD_ATTRIBUTE_FAM_OR_ASSEM=0x0005
  98. FIELD_ATTRIBUTE_PUBLIC=0x0006
  99. FIELD_ATTRIBUTE_STATIC=0x0010
  100. FIELD_ATTRIBUTE_INIT_ONLY=0x0020
  101. FIELD_ATTRIBUTE_LITERAL=0x0040
  102. FIELD_ATTRIBUTE_NOT_SERIALIZED=0x0080
  103. FIELD_ATTRIBUTE_SPECIAL_NAME=0x0200
  104. FIELD_ATTRIBUTE_PINVOKE_IMPL=0x2000
  105. FIELD_ATTRIBUTE_RESERVED_MASK=0x9500
  106. FIELD_ATTRIBUTE_RT_SPECIAL_NAME=0x0400
  107. FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL=0x1000
  108. FIELD_ATTRIBUTE_HAS_DEFAULT=0x8000
  109. FIELD_ATTRIBUTE_HAS_FIELD_RVA=0x0100
  110. MONO_TYPE_NAME_FORMAT_IL=0
  111. MONO_TYPE_NAME_FORMAT_REFLECTION=1
  112. MONO_TYPE_NAME_FORMAT_FULL_NAME=2
  113. MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED=3
  114. function monoTypeToVarType(monoType)
  115. --MonoTypeEnum
  116. local result=monoTypeToVartypeLookup[monoType]
  117. if result==nil then
  118. result=vtDword --just give it something
  119. end
  120. return result
  121. end
  122. function LaunchMonoDataCollector()
  123. if debug_canBreak() then return 0 end
  124. if (monopipe~=nil) then
  125. if (mono_AttachedProcess==getOpenedProcessID()) then
  126. return monoBase --already attached to this process
  127. end
  128. monopipe.destroy()
  129. monopipe=nil
  130. end
  131. if (monoeventpipe~=nil) then
  132. monoeventpipe.destroy()
  133. monoeventpipe=nil
  134. end
  135. local dllname="MonoDataCollector"
  136. if targetIs64Bit() then
  137. dllname=dllname.."64.dll"
  138. else
  139. dllname=dllname.."32.dll"
  140. end
  141. if injectDLL(getCheatEngineDir()..[[\autorun\dlls\]]..dllname)==false then
  142. print("Failure injecting the MonoDatacollector dll")
  143. return 0
  144. end
  145. --wait till attached
  146. local timeout=getTickCount()+5000;
  147. while (monopipe==nil) and (getTickCount()<timeout) do
  148. monopipe=connectToPipe('cemonodc_pid'..getOpenedProcessID())
  149. end
  150. if (monopipe==nil) then
  151. return 0 --failure
  152. end
  153. --in case you implement the profiling tools use a secondary pipe to receive profiler events
  154. -- while (monoeventpipe==nil) do
  155. -- monoeventpipe=connectToPipe('cemonodc_pid'..getOpenedProcessID()..'_events')
  156. -- end
  157. mono_AttachedProcess=getOpenedProcessID()
  158. monopipe.writeByte(CMD_INITMONO)
  159. monopipe.ProcessID=getOpenedProcessID()
  160. monoBase=monopipe.readQword()
  161. if (monoBase~=0) then
  162. if mono_AddressLookupID==nil then
  163. mono_AddressLookupID=registerAddressLookupCallback(mono_addressLookupCallback)
  164. end
  165. if mono_SymbolLookupID==nil then
  166. mono_SymbolLookupID=registerSymbolLookupCallback(mono_symbolLookupCallback, slNotSymbol)
  167. end
  168. if mono_StructureNameLookupID==nil then
  169. mono_StructureNameLookupID=registerStructureNameLookup(mono_structureNameLookupCallback)
  170. end
  171. if mono_StructureDissectOverrideID==nil then
  172. mono_StructureDissectOverrideID=registerStructureDissectOverride(mono_structureDissectOverrideCallback)
  173. end
  174. end
  175. if (monoSettings==nil) then
  176. monoSettings=getSettings("MonoExtension")
  177. end
  178. return monoBase
  179. end
  180. function mono_structureDissectOverrideCallback(structure, baseaddress)
  181. -- print("oc")
  182. local realaddress, classaddress=mono_object_findRealStartOfObject(baseaddress)
  183. if (realaddress==baseaddress) then
  184. local smap = {}
  185. local s = monoform_exportStructInternal(structure, classaddress, true, false, smap, false)
  186. return s~=nil
  187. else
  188. return nil
  189. end
  190. end
  191. function mono_structureNameLookupCallback(address)
  192. local currentaddress, classaddress, classname
  193. local always=monoSettings.Value["AlwaysUseForDissect"]
  194. local r
  195. if (always==nil) or (always=="") then
  196. r=messageDialog("Do you wish to let the mono extention figure out the name and start address? If it's not a proper object this may crash the target.", mtConfirmation, mbYes, mbNo, mbYesToAll, mbNoToAll)
  197. else
  198. if (always=="1") then
  199. r=mrYes
  200. else
  201. r=mrNo
  202. end
  203. end
  204. if (r==mrYes) or (r==mbYesToAll) then
  205. currentaddress, classaddress, classname=mono_object_findRealStartOfObject(address)
  206. if (currentaddress~=nil) then
  207. -- print("currentaddress~=nil : "..currentaddress)
  208. return classname,currentaddress
  209. else
  210. -- print("currentaddress==nil")
  211. return nil
  212. end
  213. end
  214. --still alive, so the user made a good choice
  215. if (r==mrYesToAll) then
  216. monoSettings.Value["AlwaysUseForDissect"]="1"
  217. elseif (r==mrNoToAll) then
  218. monoSettings.Value["AlwaysUseForDissect"]="0"
  219. end
  220. end
  221. function mono_symbolLookupCallback(symbol)
  222. if debug_canBreak() then return nil end
  223. local parts={}
  224. local x
  225. for x in string.gmatch(symbol, "[^:]+") do
  226. table.insert(parts, x)
  227. end
  228. local methodname=''
  229. local classname=''
  230. local namespace=''
  231. if (#parts>0) then
  232. methodname=parts[#parts]
  233. if (#parts>1) then
  234. classname=parts[#parts-1]
  235. if (#parts>2) then
  236. namespace=parts[#parts-2]
  237. end
  238. end
  239. end
  240. if (methodname~='') and (classname~='') then
  241. local method=mono_findMethod(namespace, classname, methodname)
  242. if (method==0) then
  243. return nil
  244. end
  245. local methodaddress=mono_compile_method(method)
  246. if (methodaddress~=0) then
  247. return methodaddress
  248. end
  249. end
  250. --still here,
  251. return nil
  252. end
  253. function mono_addressLookupCallback(address)
  254. if (inMainThread()==false) or (debug_canBreak()) then --the debugger thread might call this
  255. return nil
  256. end
  257. local ji=mono_getJitInfo(address)
  258. local result=''
  259. if ji~=nil then
  260. --[[
  261. ji.jitinfo;
  262. ji.method
  263. ji.code_start
  264. ji.code_size
  265. --]]
  266. if (ji.method~=0) then
  267. local class=mono_method_getClass(ji.method)
  268. if class==nil then return nil end
  269. local classname=mono_class_getName(class)
  270. local namespace=mono_class_getNamespace(class)
  271. if (classname==nil) or (namespace==nil) then return nil end
  272. if namespace~='' then
  273. namespace=namespace..':'
  274. end
  275. result=namespace..classname..":"..mono_method_getName(ji.method)
  276. if address~=ji.code_start then
  277. result=result..string.format("+%x",address-ji.code_start)
  278. end
  279. end
  280. end
  281. return result
  282. end
  283. function mono_object_getClass(address)
  284. if debug_canBreak() then return nil end
  285. monopipe.lock()
  286. monopipe.writeByte(MONOCMD_OBJECT_GETCLASS)
  287. monopipe.writeQword(address)
  288. local classaddress=monopipe.readQword()
  289. if (classaddress~=nil) and (classaddress~=0) then
  290. local stringlength=monopipe.readWord()
  291. local classname
  292. if stringlength>0 then
  293. classname=monopipe.readString(stringlength)
  294. end
  295. monopipe.unlock()
  296. return classaddress, classname
  297. else
  298. monopipe.unlock()
  299. return nil
  300. end
  301. end
  302. function mono_enumDomains()
  303. if debug_canBreak() then return nil end
  304. if monopipe==nil then return nil end
  305. monopipe.lock()
  306. monopipe.writeByte(MONOCMD_ENUMDOMAINS)
  307. local count=monopipe.readDword()
  308. local result={}
  309. local i
  310. if (count~=nil) then
  311. for i=1, count do
  312. result[i]=monopipe.readQword()
  313. end
  314. end
  315. monopipe.unlock()
  316. return result
  317. end
  318. function mono_setCurrentDomain(domain)
  319. if debug_canBreak() then return nil end
  320. monopipe.lock()
  321. monopipe.writeByte(MONOCMD_SETCURRENTDOMAIN)
  322. monopipe.writeQword(domain)
  323. local result=monopipe.readDword()
  324. monopipe.unlock()
  325. return result;
  326. end
  327. function mono_enumAssemblies()
  328. local result=nil
  329. if debug_canBreak() then return nil end
  330. monopipe.lock()
  331. monopipe.writeByte(MONOCMD_ENUMASSEMBLIES)
  332. local count=monopipe.readDword()
  333. if count~=nil then
  334. result={}
  335. local i
  336. for i=1, count do
  337. result[i]=monopipe.readQword()
  338. end
  339. end
  340. monopipe.unlock()
  341. return result
  342. end
  343. function mono_getImageFromAssembly(assembly)
  344. if debug_canBreak() then return nil end
  345. monopipe.lock()
  346. monopipe.writeByte(MONOCMD_GETIMAGEFROMASSEMBLY)
  347. monopipe.writeQword(assembly)
  348. monopipe.unlock()
  349. return monopipe.readQword()
  350. end
  351. function mono_image_get_name(image)
  352. if debug_canBreak() then return nil end
  353. monopipe.lock()
  354. monopipe.writeByte(MONOCMD_GETIMAGENAME)
  355. monopipe.writeQword(image)
  356. local namelength=monopipe.readWord()
  357. local name=monopipe.readString(namelength)
  358. monopipe.unlock()
  359. return name
  360. end
  361. function mono_image_enumClasses(image)
  362. if debug_canBreak() then return nil end
  363. monopipe.lock()
  364. monopipe.writeByte(MONOCMD_ENUMCLASSESINIMAGE)
  365. monopipe.writeQword(image)
  366. local classcount=monopipe.readDword()
  367. local classes={}
  368. local i;
  369. for i=1, classcount do
  370. classes[i]={}
  371. classes[i].class=monopipe.readQword()
  372. local classnamelength=monopipe.readWord()
  373. if classnamelength>0 then
  374. classes[i].classname=monopipe.readString(classnamelength)
  375. else
  376. classes[i].classname=''
  377. end
  378. local namespacelength=monopipe.readWord()
  379. if namespacelength>0 then
  380. classes[i].namespace=monopipe.readString(namespacelength)
  381. else
  382. classes[i].namespace=''
  383. end
  384. end
  385. monopipe.unlock()
  386. return classes;
  387. end
  388. function mono_class_getName(clasS)
  389. if debug_canBreak() then return nil end
  390. local result=''
  391. monopipe.lock()
  392. monopipe.writeByte(MONOCMD_GETCLASSNAME)
  393. monopipe.writeQword(clasS)
  394. local namelength=monopipe.readWord();
  395. result=monopipe.readString(namelength);
  396. monopipe.unlock()
  397. return result;
  398. end
  399. function mono_class_getNamespace(clasS)
  400. if debug_canBreak() then return nil end
  401. local result=''
  402. monopipe.lock()
  403. monopipe.writeByte(MONOCMD_GETCLASSNAMESPACE)
  404. monopipe.writeQword(clasS)
  405. local namelength=monopipe.readWord();
  406. result=monopipe.readString(namelength);
  407. monopipe.unlock()
  408. return result;
  409. end
  410. function mono_class_getFullName(typeptr, isclass, nameformat)
  411. if debug_canBreak() then return nil end
  412. if isclass==nil then isclass=1 end
  413. if nameformat==nil then nameformat=MONO_TYPE_NAME_FORMAT_REFLECTION end
  414. local result=''
  415. monopipe.lock()
  416. monopipe.writeByte(MONOCMD_GETFULLTYPENAME)
  417. monopipe.writeQword(typeptr)
  418. monopipe.writeByte(isclass)
  419. monopipe.writeDword(nameformat)
  420. local namelength=monopipe.readWord();
  421. result=monopipe.readString(namelength);
  422. monopipe.unlock()
  423. return result;
  424. end
  425. function mono_class_getParent(class)
  426. if debug_canBreak() then return nil end
  427. local result=0
  428. monopipe.lock()
  429. monopipe.writeByte(MONOCMD_GETPARENTCLASS)
  430. monopipe.writeQword(class)
  431. result=monopipe.readQword()
  432. monopipe.unlock()
  433. return result;
  434. end
  435. function mono_type_getClass(monotype)
  436. if debug_canBreak() then return nil end
  437. local result=0
  438. monopipe.lock()
  439. monopipe.writeByte(MONOCMD_GETTYPECLASS)
  440. monopipe.writeQword(monotype)
  441. result=monopipe.readQword()
  442. monopipe.unlock()
  443. return result;
  444. end
  445. function mono_class_getArrayElementClass(klass)
  446. if debug_canBreak() then return nil end
  447. local result=0
  448. monopipe.lock()
  449. monopipe.writeByte(MONOCMD_GETARRAYELEMENTCLASS)
  450. monopipe.writeQword(klass)
  451. result=monopipe.readQword()
  452. monopipe.unlock()
  453. return result;
  454. end
  455. function mono_class_getStaticFieldAddress(domain, class)
  456. if debug_canBreak() then return nil end
  457. local result=0
  458. monopipe.lock()
  459. monopipe.writeByte(MONOCMD_GETSTATICFIELDADDRESSFROMCLASS)
  460. monopipe.writeQword(domain)
  461. monopipe.writeQword(class)
  462. result=monopipe.readQword()
  463. monopipe.unlock()
  464. return result;
  465. end
  466. function mono_class_enumFields(class)
  467. if debug_canBreak() then return nil end
  468. local classfield;
  469. local index=1;
  470. local fields={}
  471. monopipe.lock()
  472. monopipe.writeByte(MONOCMD_ENUMFIELDSINCLASS)
  473. monopipe.writeQword(class)
  474. repeat
  475. classfield=monopipe.readQword()
  476. if (classfield~=nil) and (classfield~=0) then
  477. local namelength;
  478. fields[index]={}
  479. fields[index].field=classfield
  480. fields[index].type=monopipe.readQword()
  481. fields[index].monotype=monopipe.readDword()
  482. fields[index].parent=monopipe.readQword()
  483. fields[index].offset=monopipe.readDword()
  484. fields[index].flags=monopipe.readDword()
  485. fields[index].isStatic=(bAnd(fields[index].flags, bOr(FIELD_ATTRIBUTE_STATIC, FIELD_ATTRIBUTE_HAS_FIELD_RVA))) ~= 0 --check mono for other fields you'd like to test
  486. fields[index].isConst=(bAnd(fields[index].flags, FIELD_ATTRIBUTE_LITERAL)) ~= 0
  487. namelength=monopipe.readWord();
  488. fields[index].name=monopipe.readString(namelength);
  489. namelength=monopipe.readWord();
  490. fields[index].typename=monopipe.readString(namelength);
  491. index=index+1
  492. end
  493. until (classfield==nil) or (classfield==0)
  494. monopipe.unlock()
  495. return fields
  496. end
  497. function mono_class_enumMethods(class)
  498. if debug_canBreak() then return nil end
  499. local method
  500. local index=1
  501. local methods={}
  502. monopipe.lock()
  503. monopipe.writeByte(MONOCMD_ENUMMETHODSINCLASS)
  504. monopipe.writeQword(class)
  505. repeat
  506. method=monopipe.readQword()
  507. if (method~=nil) and (method~=0) then
  508. local namelength;
  509. methods[index]={}
  510. methods[index].method=method
  511. namelength=monopipe.readWord();
  512. methods[index].name=monopipe.readString(namelength);
  513. index=index+1
  514. end
  515. until (method==nil) or (method==0)
  516. monopipe.unlock()
  517. return methods
  518. end
  519. function mono_getJitInfo(address)
  520. if debug_canBreak() then return nil end
  521. local d=mono_enumDomains()
  522. if (d~=nil) then
  523. monopipe.lock()
  524. for i=1, #d do
  525. monopipe.writeByte(MONOCMD_GETJITINFO)
  526. monopipe.writeQword(d[i])
  527. monopipe.writeQword(address)
  528. local jitinfo=monopipe.readQword()
  529. if (jitinfo~=nil) and (jitinfo~=0) then
  530. local result={}
  531. result.jitinfo=jitinfo;
  532. result.method=monopipe.readQword();
  533. result.code_start=monopipe.readQword();
  534. result.code_size=monopipe.readDword();
  535. monopipe.unlock() --found something
  536. return result
  537. end
  538. end
  539. monopipe.unlock()
  540. end
  541. return nil
  542. end
  543. function mono_object_findRealStartOfObject(address, maxsize)
  544. if debug_canBreak() then return nil end
  545. if maxsize==nil then
  546. maxsize=4096
  547. end
  548. if address==nil then
  549. error("address==nil")
  550. end
  551. local currentaddress=bAnd(address, 0xfffffffffffffffc)
  552. while (currentaddress>address-maxsize) do
  553. local classaddress,classname=mono_object_getClass(currentaddress)
  554. if (classaddress~=nil) and (classname~=nil) then
  555. classname=classname:match "^%s*(.-)%s*$" --trim
  556. if (classname~='') then
  557. local r=string.find(classname, "[^%a%d_.]", 1) --scan for characters that are not decimal or characters, or have a _ or . in the name
  558. if (r==nil) or (r>=5) then
  559. return currentaddress, classaddress, classname --good enough
  560. end
  561. end
  562. end
  563. currentaddress=currentaddress-4
  564. end
  565. --still here
  566. return nil
  567. end
  568. --function mono_findReferencesToObject(class) --scan the memory for objects with a vtable to a specific class
  569. --end
  570. function mono_image_findClass(image, namespace, classname)
  571. if debug_canBreak() then return nil end
  572. --find a class in a specific image
  573. monopipe.lock()
  574. monopipe.writeByte(MONOCMD_FINDCLASS)
  575. monopipe.writeQword(image)
  576. monopipe.writeWord(#classname)
  577. monopipe.writeString(classname)
  578. if (namespace~=nil) then
  579. monopipe.writeWord(#namespace)
  580. monopipe.writeString(namespace)
  581. else
  582. monopipe.writeWord(0)
  583. end
  584. result=monopipe.readQword()
  585. monopipe.unlock()
  586. return result
  587. end
  588. function mono_findClass(namespace, classname)
  589. if debug_canBreak() then return nil end
  590. --searches all images for a specific class
  591. local ass=mono_enumAssemblies()
  592. local result=0
  593. for i=1, #ass do
  594. result=mono_image_findClass(mono_getImageFromAssembly(ass[i]), namespace, classname)
  595. if (result~=0) then
  596. return result;
  597. end
  598. end
  599. --still here:
  600. return 0
  601. end
  602. function mono_class_findMethod(class, methodname)
  603. if debug_canBreak() then return nil end
  604. if methodname==nil then return 0 end
  605. monopipe.lock()
  606. monopipe.writeByte(MONOCMD_FINDMETHOD)
  607. monopipe.writeQword(class)
  608. monopipe.writeWord(#methodname)
  609. monopipe.writeString(methodname)
  610. local result=monopipe.readQword()
  611. monopipe.unlock()
  612. return result
  613. end
  614. function mono_findMethod(namespace, classname, methodname)
  615. if debug_canBreak() then return nil end
  616. local class=mono_findClass(namespace, classname)
  617. local result=0
  618. if class~=0 then
  619. result=mono_class_findMethod(class, methodname)
  620. end
  621. return result
  622. end
  623. function mono_class_findMethodByDesc(image, methoddesc)
  624. if debug_canBreak() then return nil end
  625. if image==nil then return 0 end
  626. if methoddesc==nil then return 0 end
  627. monopipe.lock()
  628. monopipe.writeByte(MONOCMD_FINDMETHODBYDESC)
  629. monopipe.writeQword(image)
  630. monopipe.writeWord(#methoddesc)
  631. monopipe.writeString(methoddesc)
  632. local result=monopipe.readQword()
  633. monopipe.unlock()
  634. return result
  635. end
  636. function mono_findMethodByDesc(assemblyname, methoddesc)
  637. if debug_canBreak() then return nil end
  638. local assemblies = mono_enumAssemblies()
  639. for i=1, #assemblies do
  640. local image = mono_getImageFromAssembly(assemblies[i])
  641. local imagename = mono_image_get_name(image)
  642. if imagename == 'UnityEngine' then
  643. return mono_class_findMethodByDesc(image, methoddesc)
  644. end
  645. end
  646. return nil
  647. end
  648. --idea for the future:
  649. --function mono_invokeMethod()
  650. -- print("Not yet implemented")
  651. --end
  652. function mono_method_getName(method)
  653. if debug_canBreak() then return nil end
  654. local result=''
  655. monopipe.lock()
  656. monopipe.writeByte(MONOCMD_GETMETHODNAME)
  657. monopipe.writeQword(method)
  658. local namelength=monopipe.readWord();
  659. result=monopipe.readString(namelength);
  660. monopipe.unlock()
  661. return result;
  662. end
  663. function mono_method_getHeader(method)
  664. if debug_canBreak() then return nil end
  665. monopipe.lock()
  666. monopipe.writeByte(MONOCMD_GETMETHODHEADER)
  667. monopipe.writeQword(method)
  668. local result=monopipe.readQword()
  669. monopipe.unlock()
  670. return result;
  671. end
  672. function mono_method_getSignature(method)
  673. --Gets the method 'signature', the corresponding parameter names, and the returntype
  674. if debug_canBreak() then return nil end
  675. local result=''
  676. local parameternames={}
  677. local returntype=''
  678. monopipe.lock()
  679. monopipe.writeByte(MONOCMD_GETMETHODSIGNATURE)
  680. monopipe.writeQword(method)
  681. local paramcount=monopipe.readByte()
  682. local i
  683. for i=1, paramcount do
  684. local namelength=monopipe.readByte()
  685. if namelength>0 then
  686. parameternames[i]=monopipe.readString(namelength)
  687. else
  688. parameternames[i]='param'..i
  689. end
  690. end
  691. local resultlength=monopipe.readWord();
  692. result=monopipe.readString(resultlength);
  693. local returntypelength=monopipe.readByte()
  694. returntype=monopipe.readString(returntypelength)
  695. monopipe.unlock()
  696. return result, parameternames, returntype;
  697. end
  698. function mono_method_disassemble(method)
  699. if debug_canBreak() then return nil end
  700. local result=''
  701. monopipe.lock()
  702. monopipe.writeByte(MONOCMD_DISASSEMBLE)
  703. monopipe.writeQword(method)
  704. local resultlength=monopipe.readWord();
  705. result=monopipe.readString(resultlength);
  706. monopipe.unlock()
  707. return result;
  708. end
  709. function mono_method_getClass(method)
  710. if debug_canBreak() then return nil end
  711. monopipe.lock()
  712. monopipe.writeByte(MONOCMD_GETMETHODCLASS)
  713. monopipe.writeQword(method)
  714. local result=monopipe.readQword()
  715. monopipe.unlock()
  716. return result;
  717. end
  718. function mono_compile_method(method) --Jit a method if it wasn't jitted yet
  719. if debug_canBreak() then return nil end
  720. monopipe.lock()
  721. monopipe.writeByte(MONOCMD_COMPILEMETHOD)
  722. monopipe.writeQword(method)
  723. local result=monopipe.readQword()
  724. monopipe.unlock()
  725. return result
  726. end
  727. --note: does not work while the profiler is active (Current implementation doesn't use the profiler, so we're good to go)
  728. function mono_free_method(method) --unjit the method. Only works on dynamic methods. (most are not)
  729. if debug_canBreak() then return nil end
  730. monopipe.lock()
  731. monopipe.writeByte(MONOCMD_FREEMETHOD)
  732. monopipe.writeQword(method)
  733. monopipe.unlock()
  734. end
  735. function mono_methodheader_getILCode(methodheader)
  736. if debug_canBreak() then return nil end
  737. monopipe.lock()
  738. monopipe.writeByte(MONOCMD_GETMETHODHEADER_CODE)
  739. monopipe.writeQword(methodheader)
  740. local address=monopipe.readQword()
  741. local size=monopipe.readDword()
  742. monopipe.unlock()
  743. return address, size;
  744. end
  745. function mono_getILCodeFromMethod(method)
  746. local hdr=mono_method_getHeader(method)
  747. return mono_methodheader_getILCode(hdr)
  748. end
  749. function mono_image_rva_map(image, offset)
  750. if debug_canBreak() then return nil end
  751. monopipe.lock()
  752. monopipe.writeByte(MONOCMD_LOOKUPRVA)
  753. monopipe.writeQword(image)
  754. monopipe.writeDword(offset)
  755. local address=monopipe.readQword()
  756. monopipe.unlock()
  757. return address;
  758. end
  759. function mono_readObject()
  760. local vtype = monopipe.readByte()
  761. if vtype == MONO_TYPE_VOID then
  762. return nil
  763. elseif vtype == MONO_TYPE_STRING then
  764. local resultlength=monopipe.readWord();
  765. return monopipe.readString(resultlength);
  766. end
  767. local vartype = monoTypeToVartypeLookup[vtype]
  768. if vartype == vtByte then
  769. return monopipe.readByte()
  770. elseif vartype == vtWord then
  771. return monopipe.readWord()
  772. elseif vartype == vtDword then
  773. return monopipe.readDword()
  774. elseif vartype == vtQword then
  775. return monopipe.readQword()
  776. elseif vartype == vtSingle then
  777. return monopipe.readFloat()
  778. elseif vartype == vtDouble then
  779. return monopipe.readDouble()
  780. elseif vartype == vtPointer then
  781. return monopipe.readQword()
  782. end
  783. return nil
  784. end
  785. function mono_writeObject(vartype, value)
  786. if vartype == vtString then
  787. -- monopipe.writeByte(MONO_TYPE_STRING)
  788. monopipe.writeWord(#value);
  789. monopipe.writeString(value);
  790. elseif vartype == vtByte then
  791. -- monopipe.writeByte(MONO_TYPE_I1)
  792. monopipe.writeByte(value)
  793. elseif vartype == vtWord then
  794. -- monopipe.writeByte(MONO_TYPE_I2)
  795. monopipe.writeWord(value)
  796. elseif vartype == vtDword then
  797. -- monopipe.writeByte(MONO_TYPE_I4)
  798. monopipe.writeDword(value)
  799. elseif vartype == vtPointer then
  800. -- monopipe.writeByte(MONO_TYPE_PTR)
  801. monopipe.writeQword(value)
  802. elseif vartype == vtQword then
  803. -- monopipe.writeByte(MONO_TYPE_I8)
  804. monopipe.writeQword(value)
  805. elseif vartype == vtSingle then
  806. -- monopipe.writeByte(MONO_TYPE_R4)
  807. monopipe.writeFloat(value)
  808. elseif vartype == vtDouble then
  809. -- monopipe.writeByte(MONO_TYPE_R8)
  810. monopipe.writeDouble(value)
  811. else
  812. -- monopipe.writeByte(MONO_TYPE_VOID)
  813. end
  814. return nil
  815. end
  816. function mono_writeVarType(vartype)
  817. if vartype == vtString then
  818. monopipe.writeByte(MONO_TYPE_STRING)
  819. elseif vartype == vtByte then
  820. monopipe.writeByte(MONO_TYPE_I1)
  821. elseif vartype == vtWord then
  822. monopipe.writeByte(MONO_TYPE_I2)
  823. elseif vartype == vtDword then
  824. monopipe.writeByte(MONO_TYPE_I4)
  825. elseif vartype == vtPointer then
  826. monopipe.writeByte(MONO_TYPE_PTR)
  827. elseif vartype == vtQword then
  828. monopipe.writeByte(MONO_TYPE_I8)
  829. elseif vartype == vtSingle then
  830. monopipe.writeByte(MONO_TYPE_R4)
  831. elseif vartype == vtDouble then
  832. monopipe.writeByte(MONO_TYPE_R8)
  833. else
  834. monopipe.writeByte(MONO_TYPE_VOID)
  835. end
  836. end
  837. function mono_invoke_method(domain, method, object, args)
  838. if debug_canBreak() then return nil end
  839. monopipe.lock()
  840. monopipe.writeByte(MONOCMD_INVOKEMETHOD)
  841. monopipe.writeQword(domain)
  842. monopipe.writeQword(method)
  843. monopipe.writeQword(object)
  844. monopipe.writeWord(#args)
  845. for i=1, #args do
  846. mono_writeVarType(args[i].type)
  847. end
  848. for i=1, #args do
  849. mono_writeObject(args[i].type, args[i].value)
  850. end
  851. local result=mono_readObject()
  852. monopipe.unlock()
  853. return result;
  854. end
  855. function mono_loadAssemblyFromFile(fname)
  856. if debug_canBreak() then return nil end
  857. monopipe.lock()
  858. monopipe.writeByte(MONOCMD_LOADASSEMBLY)
  859. monopipe.writeWord(#fname)
  860. monopipe.writeString(fname)
  861. local result = monopipe.readQword()
  862. monopipe.unlock()
  863. return result;
  864. end
  865. --[[
  866. --------code belonging to the mono dissector form---------
  867. --]]
  868. function monoform_killform(sender)
  869. return caFree
  870. end
  871. function monoform_miShowILDisassemblyClick(sender)
  872. if (monoForm.TV.Selected~=nil) then
  873. local node=monoForm.TV.Selected
  874. if (node~=nil) and (node.Level==4) and (node.Parent.Text=='methods') then
  875. local f=createForm()
  876. f.BorderStyle=bsSizeable
  877. f.centerScreen()
  878. f.Caption=node.Text
  879. f.OnClose=function(sender) return caFree end
  880. local m=createMemo(f)
  881. m.Align=alClient
  882. m.ScrollBars=ssBoth
  883. m.Lines.Text=mono_method_disassemble(node.Data)
  884. end
  885. end
  886. end
  887. function monoform_miRejitClick(sender)
  888. if (monoForm.TV.Selected~=nil) then
  889. local node=monoForm.TV.Selected
  890. if (node~=nil) and (node.Level==4) and (node.Parent.Text=='methods') then
  891. local r=mono_compile_method(node.Data)
  892. getMemoryViewForm().DisassemblerView.SelectedAddress=r
  893. getMemoryViewForm().show()
  894. -- print(string.format("Method at %x", r))
  895. end
  896. end
  897. end
  898. function monoform_miGetILCodeClick(sender)
  899. if (monoForm.TV.Selected~=nil) then
  900. local node=monoForm.TV.Selected
  901. if (node~=nil) and (node.Level==4) and (node.Parent.Text=='methods') then
  902. local r,s=mono_getILCodeFromMethod(node.Data)
  903. if r~=nil then
  904. print(string.format("ILCode from %x to %x", r,r+s))
  905. end
  906. end
  907. end
  908. end
  909. function monoform_miDissectStaticStructureClick(sender)
  910. -- combine adding static to dissect and to table
  911. if (monoForm.TV.Selected~=nil) then
  912. local node=monoForm.TV.Selected
  913. if (node~=nil) and (node.Data~=nil) and (node.Level==2) then
  914. monoform_miAddStaticFieldAddressClick(sender)
  915. local smap = monoform_getStructMap()
  916. local s = monoform_exportStruct(node.Data, nil, true, true, smap, true, false)
  917. end
  918. end
  919. end
  920. function monoform_miAddStructureClick(sender)
  921. if (monoForm.TV.Selected~=nil) then
  922. local node=monoForm.TV.Selected
  923. if (node~=nil) and (node.Data~=nil) and (node.Level==2) then
  924. local smap = monoform_getStructMap()
  925. local s = monoform_exportStruct(node.Data, nil, false, false, smap, true, false)
  926. s = monoform_exportStruct(node.Data, nil, false, true, smap, true, false)
  927. end
  928. end
  929. end
  930. function monoform_miAddStructureRecursiveClick(sender)
  931. if (monoForm.TV.Selected~=nil) then
  932. local node=monoForm.TV.Selected
  933. if (node~=nil) and (node.Data~=nil) and (node.Level==2) then
  934. local smap = monoform_getStructMap()
  935. local s = monoform_exportStruct(node.Data, nil, true, false, smap, true, false)
  936. s = monoform_exportStruct(node.Data, nil, true, true, smap, true, false)
  937. end
  938. end
  939. end
  940. -- Add the script for locating static data pointer for a class and adding records
  941. function monoform_AddStaticClass(domain, image, class)
  942. if domain==nil or image==nil or class==nil then
  943. return
  944. end
  945. local addrs = getAddressList()
  946. local classname=mono_class_getName(class)
  947. local namespace=mono_class_getNamespace(class)
  948. local assemblyname=mono_image_get_name(image)
  949. local prefix, rootmr, mr
  950. prefix = ''
  951. rootmr=addresslist_createMemoryRecord(addrs)
  952. rootmr.Description = "Resolve "..classname
  953. rootmr.Type = vtAutoAssembler
  954. local symclassname = classname:gsub("([^A-Za-z0-9%.,_$`<>%[%]])", "")
  955. local script = {}
  956. script[#script+1] = '[ENABLE]'
  957. script[#script+1] = monoAA_GETMONOSTATICDATA(assemblyname, namespace, classname, symclassname, true)
  958. script[#script+1] = '[DISABLE]'
  959. script[#script+1] = monoAA_GETMONOSTATICDATA(assemblyname, namespace, classname, symclassname, false)
  960. rootmr.Script = table.concat(script,"\n")
  961. memoryrecord_setColor(rootmr, 0xFF0000)
  962. --local data = mono_class_getStaticFieldAddress(domain, class)
  963. --rootmr.Address = string.format("%08X",data)
  964. --rootmr.Type = vtPointer
  965. mr=addresslist_createMemoryRecord(addrs)
  966. mr.Description=classname..'.Static'
  967. mr.Address='['..symclassname..".Static]"
  968. mr.Type=vtPointer
  969. mr.appendToEntry(rootmr)
  970. mr=addresslist_createMemoryRecord(addrs)
  971. mr.Description=classname..'.Class'
  972. mr.Address='['..symclassname..".Class]"
  973. mr.Type=vtPointer
  974. mr.appendToEntry(rootmr)
  975. local i
  976. local fields=mono_class_enumFields(class)
  977. for i=1, #fields do
  978. if fields[i].isStatic and not fields[i].isConst and (field==nil or fields[i].field==field) then
  979. local fieldName = fields[i].name:gsub("([^A-Za-z0-9%.,_$`<>%[%]])", "")
  980. local offset = fields[i].offset
  981. if fieldName==nil or fieldName:len()==0 then
  982. fieldName = string.format("Offset %x", offset)
  983. end
  984. mr=addresslist_createMemoryRecord(addrs)
  985. mr.Description=prefix..fieldName
  986. if fields[i].monotype==MONO_TYPE_STRING then
  987. -- mr.Address=string.format("[[%s.Static]+%X]+C",symclassname,offset)
  988. mr.Address=symclassname..'.Static'
  989. mr.OffsetCount=2
  990. mr.Offset[0]=0xC
  991. mr.Offset[1]=offset
  992. mr.Type=vtString
  993. memoryrecord_string_setUnicode(mr, true)
  994. memoryrecord_string_setSize(mr, 80)
  995. else
  996. mr.Address=symclassname..'.Static'
  997. mr.OffsetCount=1
  998. mr.Offset[0]=offset
  999. mr.Type=monoTypeToVarType(fields[i].monotype)
  1000. end
  1001. if rootmr~=nil then
  1002. mr.appendToEntry(rootmr)
  1003. else
  1004. break
  1005. end
  1006. end
  1007. end
  1008. end
  1009. function monoform_AddStaticClassField(domain, image, class, fieldclass, field)
  1010. if domain==nil or image==nil or class==nil or fieldclass==nil or field==nil then
  1011. return
  1012. end
  1013. local i
  1014. local fields=mono_class_enumFields(fieldclass)
  1015. for i=1, #fields do
  1016. if fields[i].field==field then
  1017. local fieldname = fields[i].name
  1018. local offset = fields[i].offset
  1019. if fieldname==nil or fieldname:len()==0 then
  1020. fieldname = string.format("Offset %x", offset)
  1021. end
  1022. local addrs = getAddressList()
  1023. local classname=mono_class_getName(class)
  1024. local namespace=mono_class_getNamespace(class)
  1025. local assemblyname=mono_image_get_name(image)
  1026. local rootmr, mr
  1027. rootmr=addresslist_createMemoryRecord(addrs)
  1028. rootmr.Description = "Resolve "..classname.."."..fieldname
  1029. rootmr.Type = vtAutoAssembler
  1030. local symclassname = classname:gsub("[^A-Za-z0-9._]", "")
  1031. local symfieldname = fieldname:gsub("[^A-Za-z0-9._]", "")
  1032. local script = {}
  1033. script[#script+1] = '[ENABLE]'
  1034. script[#script+1] = monoAA_GETMONOSTATICFIELDDATA(assemblyname, namespace, classname, fieldname, symclassname, true)
  1035. script[#script+1] = '[DISABLE]'
  1036. script[#script+1] = monoAA_GETMONOSTATICFIELDDATA(assemblyname, namespace, classname, fieldname, symclassname, false)
  1037. rootmr.Script = table.concat(script,"\n")
  1038. memoryrecord_setColor(rootmr, 0xFF0000)
  1039. mr=addresslist_createMemoryRecord(addrs)
  1040. mr.Description=classname..'.'..fieldname
  1041. mr.appendToEntry(rootmr)
  1042. if fields[i].monotype==MONO_TYPE_STRING then
  1043. mr.Address=symclassname..'.'..symfieldname
  1044. mr.OffsetCount=1
  1045. mr.Offset[0]=0xC
  1046. mr.Type=vtString
  1047. memoryrecord_string_setUnicode(mr, true)
  1048. memoryrecord_string_setSize(mr, 80)
  1049. else
  1050. mr.Address="["..symclassname..'.'..symfieldname.."]"
  1051. mr.Type=monoTypeToVarType(fields[i].monotype)
  1052. end
  1053. break
  1054. end
  1055. end
  1056. end
  1057. function monoform_miAddStaticFieldAddressClick(sender)
  1058. if (monoForm.TV.Selected~=nil) then
  1059. local node=monoForm.TV.Selected
  1060. local domain, image, class, field
  1061. if (node~=nil) and (node.Data~=nil) then
  1062. if (node.Level>=4) and (node.Parent.Text=='static fields') then
  1063. local inode = node.Parent.Parent.Parent
  1064. local cnode = node.Parent.Parent
  1065. local fieldclass = cnode.Data
  1066. while inode.Text == 'base class' do
  1067. cnode = inode.Parent
  1068. inode = cnode.Parent
  1069. end
  1070. domain = inode.Parent.Data
  1071. image = inode.Data
  1072. class = cnode.Data
  1073. field = node.Data
  1074. monoform_AddStaticClassField(domain, image, class, fieldclass, field)
  1075. elseif (node~=nil) and (node.Data~=nil) and (node.Level==2) then
  1076. domain = node.Parent.Parent.Data
  1077. image = node.Parent.Data
  1078. class = node.Data
  1079. monoform_AddStaticClass(domain, image, class)
  1080. elseif (node~=nil) and (node.Data~=nil) and (node.Level==3) then
  1081. domain = node.Parent.Parent.Parent.Data
  1082. image = node.Parent.Parent.Data
  1083. class = node.Parent.Data
  1084. monoform_AddStaticClass(domain, image, class)
  1085. end
  1086. end
  1087. end
  1088. end
  1089. function monoform_context_onpopup(sender)
  1090. local node=monoForm.TV.Selected
  1091. local methodsEnabled = (node~=nil) and (node.Level==4) and (node.Parent.Text=='methods')
  1092. monoForm.miRejit.Enabled = methodsEnabled
  1093. monoForm.miGetILCode.Enabled = methodsEnabled
  1094. monoForm.miShowILDisassembly.Enabled = methodsEnabled
  1095. local structuresEnabled = (node~=nil) and (node.Data~=nil) and (node.Level==2)
  1096. monoForm.miExportStructure.Enabled = structuresEnabled
  1097. local fieldsEnabled = (node~=nil) and (node.Data~=nil)
  1098. and ( (node.Level==2)
  1099. or ((node.Level>=3) and (node.Text=='static fields'))
  1100. or ((node.Level>=4) and (node.Parent.Text=='static fields')))
  1101. monoForm.miFieldsMenu.Enabled = fieldsEnabled
  1102. monoForm.miAddStaticFieldAddress.Enabled = fieldsEnabled
  1103. end
  1104. function monoform_EnumImages(node)
  1105. --print("monoform_EnumImages")
  1106. local i
  1107. local domain=node.Data
  1108. --mono_setCurrentDomain(domain)
  1109. local assemblies=mono_enumAssemblies()
  1110. for i=1, #assemblies do
  1111. local image=mono_getImageFromAssembly(assemblies[i])
  1112. local imagename=mono_image_get_name(image)
  1113. local n=node.add(string.format("%x : %s", image, imagename))
  1114. n.HasChildren=true;
  1115. n.Data=image
  1116. end
  1117. end
  1118. function monoform_AddClass(node, klass, namespace, classname, fqname)
  1119. local desc=string.format("%x : %s", klass, fqname)
  1120. local n=node.add(desc)
  1121. n.Data=klass
  1122. local nf=n.add("static fields")
  1123. nf.Data=klass
  1124. nf.HasChildren=true
  1125. local nf=n.add("fields")
  1126. nf.Data=klass
  1127. nf.HasChildren=true
  1128. local nm=n.add("methods")
  1129. nm.Data=klass
  1130. nm.HasChildren=true
  1131. local p = mono_class_getParent(klass)
  1132. if p~=nil then
  1133. local np=n.add("base class")
  1134. np.Data=p
  1135. np.HasChildren=true
  1136. end
  1137. end
  1138. function monoform_EnumClasses(node)
  1139. --print("monoform_EnumClasses")
  1140. local image=node.Data
  1141. local classes=mono_image_enumClasses(image)
  1142. local i
  1143. if classes~=nil then
  1144. for i=1, #classes do
  1145. classes[i].fqname = mono_class_getFullName(classes[i].class)
  1146. end
  1147. local monoform_class_compare = function (a,b)
  1148. if a.namespace < b.namespace then
  1149. return true
  1150. elseif b.namespace < a.namespace then
  1151. return false
  1152. end
  1153. if a.fqname < b.fqname then
  1154. return true
  1155. elseif b.fqname < a.fqname then
  1156. return false
  1157. end
  1158. return a.class < b.class
  1159. end
  1160. table.sort(classes, monoform_class_compare)
  1161. for i=1, #classes do
  1162. monoform_AddClass(node, classes[i].class, classes[i].namespace, classes[i].classname, classes[i].fqname)
  1163. end
  1164. end
  1165. end;
  1166. function monoform_EnumFields(node, static)
  1167. -- print("monoform_EnumFields")
  1168. local i
  1169. local class=node.Data;
  1170. local fields=mono_class_enumFields(class)
  1171. for i=1, #fields do
  1172. if fields[i].isStatic == static and not fields[i].isConst then
  1173. local n=node.add(string.format("%x : %s (type: %s)", fields[i].offset, fields[i].name, fields[i].typename))
  1174. n.Data=fields[i].field
  1175. end
  1176. end
  1177. end
  1178. function monoform_EnumMethods(node)
  1179. --print("monoform_EnumMethods")
  1180. local i
  1181. local class=node.Data;
  1182. local methods=mono_class_enumMethods(class)
  1183. for i=1, #methods do
  1184. local n=node.add(string.format("%x : %s", methods[i].method, methods[i].name))
  1185. n.Data=methods[i].method
  1186. end
  1187. end
  1188. function mono_TVExpanding(sender, node)
  1189. --print("mono_TVExpanding")
  1190. --print("node.Count="..node.Count)
  1191. --print("node.Level="..node.Level)
  1192. local allow=true
  1193. if (node.Count==0) then
  1194. if (node.Level==0) then --images
  1195. monoform_EnumImages(node)
  1196. elseif (node.Level==1) then --classes
  1197. monoform_EnumClasses(node)
  1198. elseif (node.Level>=3) and (node.Text=='static fields') then --static fields
  1199. monoform_EnumFields(node, true)
  1200. elseif (node.Level>=3) and (node.Text=='fields') then --fields
  1201. monoform_EnumFields(node, false)
  1202. elseif (node.Level>=3) and (node.Text=='methods') then --methods
  1203. monoform_EnumMethods(node)
  1204. elseif (node.Level>=3) and (node.Text=='base class') then
  1205. if (monoForm.autoExpanding==nil) or (monoForm.autoExpanding==false) then
  1206. local klass = node.Data
  1207. if (klass ~= 0) then
  1208. local classname=mono_class_getName(klass)
  1209. local namespace=mono_class_getNamespace(klass)
  1210. local fqname=mono_class_getFullName(klass)
  1211. monoform_AddClass(node, klass, namespace, classname, fqname)
  1212. end
  1213. else
  1214. allow=false --don't auto expand the base classes
  1215. end
  1216. end
  1217. end
  1218. return allow
  1219. end
  1220. function mono_TVCollapsing(sender, node)
  1221. local allow=true
  1222. return allow
  1223. end
  1224. function monoform_FindDialogFind(sender)
  1225. local texttofind=string.lower(monoForm.FindDialog.FindText)
  1226. local tv=monoForm.TV
  1227. local startindex=0
  1228. if tv.Selected~=nil then
  1229. startindex=tv.Selected.AbsoluteIndex+1
  1230. end
  1231. local i
  1232. if string.find(monoForm.FindDialog.Options, 'frEntireScope') then
  1233. --deep scan
  1234. tv.beginUpdate()
  1235. i=startindex
  1236. while i<tv.Items.Count do
  1237. local node=monoForm.TV.items[i]
  1238. local text=string.lower(node.Text)
  1239. if string.find(text, texttofind)~=nil then
  1240. --found it
  1241. tv.Selected=node
  1242. break
  1243. end
  1244. if node.HasChildren then
  1245. node.Expand(false)
  1246. end
  1247. i=i+1
  1248. end
  1249. tv.endUpdate()
  1250. else
  1251. --just the already scanned stuff
  1252. for i=startindex, tv.Items.Count-1 do
  1253. local node=monoForm.TV.items[i]
  1254. local text=string.lower(node.Text)
  1255. if string.find(text, texttofind)~=nil then
  1256. --found it
  1257. tv.Selected=node
  1258. return
  1259. end
  1260. end
  1261. end
  1262. end
  1263. function monoform_miFindClick(sender)
  1264. monoForm.FindDialog.execute()
  1265. end
  1266. function monoform_miExpandAllClick(sender)
  1267. if messageDialog("Are you sure you wish to expand the whole tree? This can take a while and Cheat Engine may look like it has crashed (It has not)", mtConfirmation, mbYes, mbNo)==mrYes then
  1268. monoForm.TV.beginUpdate()
  1269. monoForm.autoExpanding=true --special feature where a base object can contain extra lua variables
  1270. monoForm.TV.fullExpand()
  1271. monoForm.autoExpanding=false
  1272. monoForm.TV.endUpdate()
  1273. end
  1274. end
  1275. function monoform_miSaveClick(sender)
  1276. if monoForm.SaveDialog.execute() then
  1277. monoForm.TV.saveToFile(monoForm.SaveDialog.Filename)
  1278. end
  1279. end
  1280. function mono_dissect()
  1281. --shows a form with a treeview that holds all the data nicely formatted.
  1282. --only fetches the data when requested
  1283. if (monopipe==nil) then
  1284. LaunchMonoDataCollector()
  1285. end
  1286. if (monoForm==nil) then
  1287. monoForm=createFormFromFile(getCheatEngineDir()..[[\autorun\forms\MonoDataCollector.frm]])
  1288. end
  1289. monoForm.show()
  1290. monoForm.TV.Items.clear()
  1291. local domains=mono_enumDomains()
  1292. local i
  1293. if (domains~=nil) then
  1294. for i=1, #domains do
  1295. n=monoForm.TV.Items.add(string.format("%x", domains[i]))
  1296. n.Data=domains[i]
  1297. monoForm.TV.Items[i-1].HasChildren=true
  1298. end
  1299. end
  1300. end
  1301. function miMonoActivateClick(sender)
  1302. if LaunchMonoDataCollector()==0 then
  1303. showMessage("Failure to launch")
  1304. end
  1305. end
  1306. function miMonoDissectClick(sender)
  1307. mono_dissect()
  1308. end
  1309. function mono_OpenProcessMT(t)
  1310. if t~=nil then
  1311. t.destroy()
  1312. end
  1313. --enumModules is faster than getAddress at OpenProcess time (No waiting for all symbols to be loaded first)
  1314. local usesmono=false
  1315. local m=enumModules()
  1316. local i
  1317. for i=1, #m do
  1318. if (m[i].Name=='mono.dll') or (string.sub(m[i].Name,1,5)=='mono-') then
  1319. usesmono=true
  1320. break
  1321. end
  1322. end
  1323. if usesmono then
  1324. --create a menu item if needed
  1325. if (miMonoTopMenuItem==nil) then
  1326. local mfm=getMainForm().Menu
  1327. if (mfm) then
  1328. local mi
  1329. miMonoTopMenuItem=createMenuItem(mfm)
  1330. miMonoTopMenuItem.Caption="Mono"
  1331. mfm.Items.insert(mfm.Items.Count-1, miMonoTopMenuItem) --add it before help
  1332. mi=createMenuItem(miMonoTopMenuItem)
  1333. mi.Caption="Activate mono features"
  1334. mi.OnClick=miMonoActivateClick
  1335. miMonoTopMenuItem.Add(mi)
  1336. mi=createMenuItem(miMonoTopMenuItem)
  1337. mi.Caption="Dissect mono"
  1338. mi.Shortcut="Ctrl+Alt+M"
  1339. mi.OnClick=miMonoDissectClick
  1340. miMonoTopMenuItem.Add(mi)
  1341. end
  1342. end
  1343. else
  1344. --destroy the menu item if needed
  1345. if miMonoTopMenuItem~=nil then
  1346. miMonoTopMenuItem.destroy() --also destroys the subitems as they are owned by this menuitem
  1347. miMonoTopMenuItem=nil
  1348. end
  1349. if monopipe~=nil then
  1350. monopipe.destroy()
  1351. monopipe=nil
  1352. if mono_AddressLookupID~=nil then
  1353. unregisterAddressLookupCallback(mono_AddressLookupID)
  1354. mono_AddressLookupID=nil
  1355. end
  1356. if mono_SymbolLookupID~=nil then
  1357. unregisterSymbolLookupCallback(mono_SymbolLookupID)
  1358. mono_SymbolLookupID=nil
  1359. end
  1360. end
  1361. end
  1362. if (monopipe~=nil) and (monopipe.ProcessID~=getOpenedProcessID()) then
  1363. --different process
  1364. monopipe.destroy()
  1365. monopipe=nil
  1366. if mono_AddressLookupID~=nil then
  1367. unregisterAddressLookupCallback(mono_AddressLookupID)
  1368. mono_AddressLookupID=nil
  1369. end
  1370. if mono_SymbolLookupID~=nil then
  1371. unregisterSymbolLookupCallback(mono_SymbolLookupID)
  1372. mono_SymbolLookupID=nil
  1373. end
  1374. if mono_StructureNameLookupID~=nil then
  1375. unregisterStructureNameLookup(mono_StructureNameLookupID)
  1376. mono_StructureNameLookupID=nil
  1377. end
  1378. if mono_StructureDissectOverrideID~=nil then
  1379. unregisterStructureDissectOverride(mono_StructureDissectOverrideID)
  1380. mono_StructureDissectOverrideID=nil
  1381. end
  1382. end
  1383. end
  1384. function mono_OpenProcess(processid)
  1385. --call the original onOpenProcess if there was one
  1386. if mono_oldOnOpenProcess~=nil then
  1387. mono_oldOnOpenProcess(processid)
  1388. end
  1389. synchronize("mono_OpenProcessMT")
  1390. --t=createTimer()
  1391. --t.Interval=1000
  1392. --t.OnTimer="mono_OpenProcessEpilogue"
  1393. --t.Enabled=true
  1394. end
  1395. function monoAA_USEMONO(parameters, syntaxcheckonly)
  1396. --called whenever an auto assembler script encounters the USEMONO() line
  1397. --the value you return will be placed instead of the given line
  1398. --In this case, returning a empty string is fine
  1399. --Special behaviour: Returning nil, with a secondary parameter being a string, will raise an exception on the auto assembler with that string
  1400. --another example:
  1401. --return parameters..":\nnop\nnop\nnop\n"
  1402. --you'd then call it using usemono(00400500) for example
  1403. if (syntaxcheckonly==false) and (LaunchMonoDataCollector()==0) then
  1404. return nil,"The mono handler failed to initialize"
  1405. end
  1406. return "" --return an empty string (removes it from the internal aa assemble list)
  1407. end
  1408. function monoAA_FINDMONOMETHOD(parameters, syntaxcheckonly)
  1409. --called whenever an auto assembler script encounters the MONOMETHOD() line
  1410. --parameters: name, fullmethodnamestring
  1411. --turns into a define that sets up name as an address to this method
  1412. local name, fullmethodnamestring, namespace, classname, methodname, methodaddress
  1413. local c,d,e
  1414. --parse the parameters
  1415. c=string.find(parameters,",")
  1416. if c~=nil then
  1417. name=string.sub(parameters, 1,c-1)
  1418. fullmethodnamestring=string.sub(parameters, c+1, #parameters)
  1419. c=string.find(fullmethodnamestring,":")
  1420. if (c~=nil) then
  1421. namespace=string.sub(fullmethodnamestring, 1,c-1)
  1422. else
  1423. namespace='';
  1424. end
  1425. d=string.find(fullmethodnamestring,":",c)
  1426. if (d~=nil) then
  1427. e=string.find(fullmethodnamestring,":",d+1)
  1428. if e~=nil then
  1429. classname=string.sub(fullmethodnamestring, c+1, e-1)
  1430. methodname=string.sub(fullmethodnamestring, e+1, #fullmethodnamestring)
  1431. else
  1432. return nil,"Invalid parameters (Methodname could not be determined)"
  1433. end
  1434. else
  1435. return nil,"Invalid parameters (Classname could not be determined)"
  1436. end
  1437. else
  1438. return nil,"Invalid parameters (name could not be determined)"
  1439. end
  1440. classname=classname:match "^%s*(.-)%s*$" --trim
  1441. methodname=methodname:match "^%s*(.-)%s*$" --trim
  1442. if syntaxcheckonly then
  1443. return "define("..name..",00000000)"
  1444. end
  1445. if (monopipe==nil) or (monopipe.Connected==false) then
  1446. LaunchMonoDataCollector()
  1447. end
  1448. if (monopipe==nil) or (monopipe.Connected==false) then
  1449. return nil,"The mono handler failed to initialize"
  1450. end
  1451. local method=mono_findMethod(namespace, classname, methodname)
  1452. if (method==0) then
  1453. return nil,fullmethodnamestring.." could not be found"
  1454. end
  1455. methodaddress=mono_compile_method(method)
  1456. if (methodaddress==0) then
  1457. return nil,fullmethodnamestring.." could not be jitted"
  1458. end
  1459. local result="define("..name..","..string.format("%x", methodaddress)..")"
  1460. -- showMessage(result)
  1461. return result
  1462. end
  1463. function monoform_getStructMap()
  1464. -- TODO: bug check for getStructureCount which does not return value correctly in older CE
  1465. local structmap={}
  1466. local n=getStructureCount()
  1467. if n==nil then
  1468. showMessage("Sorry this feature does not work yet. getStructureCount needs patching first.")
  1469. return nil
  1470. end
  1471. local fillChildStruct = function (struct, structmap)
  1472. local i, e, s
  1473. if struct==nil then return end
  1474. for i=0, struct.Count-1 do
  1475. e = struct.Element
  1476. if e.Vartype == vtPointer then
  1477. s = e.ChildStruct
  1478. if s~=nil then fillChildStruct(s, structmap) end
  1479. end
  1480. end
  1481. end
  1482. for i=0, n-1 do
  1483. local s = getStructure(i)
  1484. structmap[s.Name]=s
  1485. fillChildStruct(s, structmap)
  1486. end
  1487. return structmap
  1488. end
  1489. function mono_purgeDuplicateGlobalStructures()
  1490. local smap = monoform_getStructMap()
  1491. local n=getStructureCount()
  1492. local slist = {}
  1493. for i=0, n-1 do
  1494. local s1 = getStructure(i)
  1495. local s2 = smap[s1.Name]
  1496. if s1 ~= s2 then
  1497. slist[s1.Name] = s1
  1498. end
  1499. end
  1500. local name
  1501. local s
  1502. for name, s in pairs(slist) do
  1503. print("Removing "..name)
  1504. structure_removeFromGlobalStructureList(s)
  1505. end
  1506. end
  1507. function mono_reloadGlobalStructures(imagename)
  1508. local smap = monoform_getStructMap()
  1509. local classmap = {}
  1510. local staticmap = {}
  1511. local arraymap = {}
  1512. local imageclasses = {}
  1513. local i, j
  1514. local fqclass, caddr
  1515. local assemblies=mono_enumAssemblies()
  1516. for i=1, #assemblies do
  1517. local image=mono_getImageFromAssembly(assemblies[i])
  1518. local iname=mono_image_get_name(image)
  1519. if imagename==nil or imagename==iname then
  1520. local classes=mono_image_enumClasses(image)
  1521. -- purge classes
  1522. for j=1, #classes do
  1523. local fqclass = monoform_getfqclassname(classes[j].class, false)
  1524. local s = smap[fqclass]
  1525. if s ~= nil then
  1526. structure_removeFromGlobalStructureList(s)
  1527. classmap[fqclass] = classes[j].class
  1528. end
  1529. s = smap[fqclass..'[]']
  1530. if s ~= nil then
  1531. structure_removeFromGlobalStructureList(s)
  1532. arraymap[fqclass..'[]'] = classes[j].class
  1533. end
  1534. -- check for static section
  1535. fqclass = fqclass..'.Static'
  1536. s = smap[fqclass]
  1537. if s ~= nil then
  1538. structure_removeFromGlobalStructureList(s)
  1539. staticmap[fqclass] = classes[j].class
  1540. end
  1541. end
  1542. -- if order function given, sort by it by passing the table and keys a, b, otherwise just sort the keys
  1543. local spairs = function(t, order)
  1544. local keys = {}
  1545. for k in pairs(t) do keys[#keys+1] = k end
  1546. if order then
  1547. table.sort(keys, function(a,b) return order(t, a, b) end)
  1548. else
  1549. table.sort(keys)
  1550. end
  1551. local i = 0
  1552. return function() -- return the iterator function
  1553. i = i + 1
  1554. if keys[i] then
  1555. return keys[i], t[keys[i]]
  1556. end
  1557. end
  1558. end
  1559. local merge=function(...)
  1560. local i,k,v
  1561. local result={}
  1562. i=1
  1563. while true do
  1564. local args = select(i,...)
  1565. if args==nil then break end
  1566. for k,v in pairs(args) do result[k]=v end
  1567. i=i+1
  1568. end
  1569. return result
  1570. end
  1571. for fqclass, caddr in spairs(merge(classmap, arraymap, staticmap)) do
  1572. s = createStructure(fqclass)
  1573. structure_addToGlobalStructureList(s)
  1574. smap[fqclass] = s
  1575. end
  1576. end
  1577. end
  1578. for fqclass, caddr in pairs(classmap) do
  1579. print("Reloading Structure "..fqclass)
  1580. monoform_exportStruct(caddr, fqclass, true, false, smap, false, true)
  1581. end
  1582. for fqclass, caddr in pairs(arraymap) do
  1583. print("Reloading Structure "..fqclass)
  1584. monoform_exportArrayStruct(nil, caddr, fqclass, true, false, smap, false, true)
  1585. end
  1586. for fqclass, caddr in pairs(staticmap) do
  1587. print("Reloading Structure "..fqclass)
  1588. monoform_exportStruct(caddr, fqclass, true, true, smap, false, true)
  1589. end
  1590. end
  1591. function monoform_escapename(value)
  1592. if value~=nil then
  1593. return value:gsub("([^A-Za-z0-9%+%.,_$`<>%[%]])", "")
  1594. end
  1595. return nil
  1596. end
  1597. function monoform_getfqclassname(caddr, static)
  1598. if (caddr==nil or caddr==0) then return nil end
  1599. --local classname=mono_class_getName(caddr)
  1600. --local namespace=mono_class_getNamespace(caddr)
  1601. local classname=mono_class_getFullName(caddr)
  1602. local namespace=nil
  1603. local fqclass = monoform_escapename(classname)
  1604. if fqclass==nil or string.len(fqclass) == 0 then
  1605. return nil
  1606. end
  1607. if namespace~=nil and string.len(namespace) ~= 0 then
  1608. fqclass = namespace.."."..fqclass
  1609. end
  1610. if static then
  1611. fqclass = fqclass..".Static"
  1612. end
  1613. return fqclass
  1614. end
  1615. function monoform_exportStruct(caddr, typename, recursive, static, structmap, makeglobal, reload)
  1616. local fqclass = monoform_getfqclassname(caddr, static)
  1617. if typename==nil then
  1618. typename = fqclass
  1619. end
  1620. if typename == nil then
  1621. return nil
  1622. end
  1623. -- check if existing. exit early if already present
  1624. local s = structmap[typename]
  1625. if s == nil then
  1626. -- print("Creating Structure "..typename)
  1627. s = createStructure(typename)
  1628. structmap[typename] = s
  1629. if makeglobal then
  1630. structure_addToGlobalStructureList(s)
  1631. end
  1632. else
  1633. if not reload==true then
  1634. return s
  1635. end
  1636. -- TODO: cannot clear fields here but would like to
  1637. end
  1638. makeglobal = false
  1639. return monoform_exportStructInternal(s, caddr, recursive, static, structmap, makeglobal)
  1640. end
  1641. mono_StringStruct=nil
  1642. function monoform_exportStructInternal(s, caddr, recursive, static, structmap, makeglobal)
  1643. --print("a")
  1644. if caddr==0 or caddr==nil then return nil end
  1645. -- print("b")
  1646. local className = mono_class_getFullName(caddr)
  1647. --print('Populating '..className)
  1648. -- handle Array as separate case
  1649. if string.sub(className,-2)=='[]' then
  1650. local elemtype = mono_class_getArrayElementClass(caddr)
  1651. return monoform_exportArrayStructInternal(s, caddr, elemtype, recursive, structmap, makeglobal, true)
  1652. end
  1653. local hasStatic = false
  1654. structure_beginUpdate(s)
  1655. local fields=mono_class_enumFields(caddr)
  1656. local str -- string struct
  1657. local childstructs = {}
  1658. local i
  1659. for i=1, #fields do
  1660. hasStatic = hasStatic or fields[i].isStatic
  1661. if fields[i].isStatic==static and not fields[i].isConst then
  1662. local e=s.addElement()
  1663. local ft = fields[i].monotype
  1664. local fieldname = monoform_escapename(fields[i].name)
  1665. if fieldname~=nil then
  1666. e.Name=fieldname
  1667. end
  1668. e.Offset=fields[i].offset
  1669. e.Vartype=monoTypeToVarType(ft)
  1670. --print(string.format(" Field: %d: %d: %d: %s", e.Offset, e.Vartype, ft, fieldname))
  1671. if ft==MONO_TYPE_STRING then
  1672. --print(string.format(" Field: %d: %d: %d: %s", e.Offset, e.Vartype, ft, fieldname))
  1673. if mono_StringStruct==nil then
  1674. -- print("Creating string object")
  1675. mono_StringStruct = createStructure("String")
  1676. mono_StringStruct.beginUpdate()
  1677. local ce=mono_StringStruct.addElement()
  1678. ce.Name="Length"
  1679. if targetIs64Bit() then
  1680. ce.Offset=0x10
  1681. else
  1682. ce.Offset=0x8
  1683. end
  1684. ce.Vartype=vtDword
  1685. ce=mono_StringStruct.addElement()
  1686. ce.Name="Value"
  1687. if targetIs64Bit() then
  1688. ce.Offset=0x14
  1689. else
  1690. ce.Offset=0xC
  1691. end
  1692. ce.Vartype=vtUnicodeString
  1693. ce.Bytesize=128
  1694. mono_StringStruct.endUpdate()
  1695. mono_StringStruct.addToGlobalStructureList()
  1696. end
  1697. e.setChildStruct(mono_StringStruct)
  1698. --[[
  1699. elseif ft == MONO_TYPE_PTR or ft == MONO_TYPE_CLASS or ft == MONO_TYPE_BYREF
  1700. or ft == MONO_TYPE_GENERICINST then
  1701. --print("bla")
  1702. local typename = monoform_escapename(fields[i].typename)
  1703. if typename ~= nil then
  1704. local typeval = mono_type_getClass(fields[i].field)
  1705. --print(string.format("PTR: %X: %s", typeval, typename))
  1706. cs = monoform_exportStruct(typeval, typename, recursive, false, structmap, makeglobal)
  1707. if cs~=nil then e.setChildStruct(cs) end
  1708. end
  1709. elseif ft == MONO_TYPE_SZARRAY then
  1710. --print("bla2")
  1711. local typename = monoform_escapename(fields[i].typename)
  1712. local arraytype = mono_type_getClass(fields[i].field)
  1713. local elemtype = mono_class_getArrayElementClass(arraytype)
  1714. --print(typename)
  1715. --local acs = monoform_exportArrayStruct(arraytype, elemtype, typename, recursive, static, structmap, makeglobal, false)
  1716. --if acs~=nil then e.setChildStruct(acs) end --]]
  1717. end
  1718. end
  1719. end
  1720. structure_endUpdate(s)
  1721. return s
  1722. end
  1723. function monoform_exportArrayStruct(arraytype, elemtype, typename, recursive, static, structmap, makeglobal, reload)
  1724. local acs=nil
  1725. if typename~=nil then
  1726. acs = structmap[typename]
  1727. if acs==nil and arraytype~=nil then
  1728. acs = monoform_exportStruct(arraytype, typename, recursive, false, structmap, makeglobal)
  1729. reload = true
  1730. end
  1731. end
  1732. return monoform_exportArrayStructInternal(acs, arraytype, elemtype, recursive, structmap, makeglobal, reload)
  1733. end
  1734. function monoform_exportArrayStructInternal(acs, arraytype, elemtype, recursive, structmap, makeglobal, reload)
  1735. if acs~=nil then
  1736. cs = monoform_exportStruct(elemtype, nil, recursive, false, structmap, makeglobal)
  1737. if cs~=nil and reload then
  1738. structure_beginUpdate(acs)
  1739. local ce=acs.addElement()
  1740. ce.Name='Count'
  1741. ce.Offset=0xC
  1742. ce.Vartype=vtDword
  1743. ce.setChildStruct(cs)
  1744. local j
  1745. local psize
  1746. if targetIs64Bit() then
  1747. psize=8
  1748. else
  1749. psize=4
  1750. end
  1751. for j=0, 9 do -- Arbitrarily add 10 elements
  1752. ce=acs.addElement()
  1753. ce.Name=string.format("Item[%d]",j)
  1754. ce.Offset=j*psize+0x10
  1755. ce.Vartype=vtPointer
  1756. ce.setChildStruct(cs)
  1757. end
  1758. structure_endUpdate(acs)
  1759. end
  1760. end
  1761. return acs
  1762. end
  1763. function monoAA_GETMONOSTRUCT(parameters, syntaxcheckonly)
  1764. --called whenever an auto assembler script encounters the GETMONOSTRUCT() line
  1765. --parameters: classname or classname,namespace:classname (or classname,classname)
  1766. --turns into a struct define
  1767. local c,name,classname,namespace
  1768. c=string.find(parameters,",")
  1769. if c==nil then
  1770. --just find this class
  1771. name=parameters
  1772. classname=parameters
  1773. namespace=''
  1774. --print("Format 1")
  1775. --print("name="..name)
  1776. --print("classname="..classname)
  1777. --print("namespace="..namespace)
  1778. else
  1779. --this is a name,namespace:classname notation
  1780. print("Format 2")
  1781. name=string.sub(parameters, 1, c-1)
  1782. parameters=string.sub(parameters, c+1, #parameters)
  1783. c=string.find(parameters,":")
  1784. if (c~=nil) then
  1785. namespace=string.sub(parameters, 1,c-1)
  1786. classname=string.sub(parameters, c+1, #parameters)
  1787. else
  1788. namespace='';
  1789. classname=parameters
  1790. end
  1791. --print("name="..name)
  1792. --print("classname="..classname)
  1793. --print("namespace="..namespace)
  1794. end
  1795. name=name:match "^%s*(.-)%s*$"
  1796. classname=classname:match "^%s*(.-)%s*$"
  1797. namespace=namespace:match "^%s*(.-)%s*$"
  1798. local class=mono_findClass(namespace, classname)
  1799. if (class==0) then
  1800. return nil,"The class "..namespace..":"..classname.." could not be found"
  1801. end
  1802. local fields=mono_class_enumFields(class)
  1803. if (fields==nil) or (#fields==0) then
  1804. return nil,namespace..":"..classname.." has no fields"
  1805. end
  1806. local offsets={}
  1807. local i
  1808. for i=1, #fields do
  1809. if fields[i].offset~=0 then
  1810. offsets[fields[i].offset]=fields[i].name
  1811. end
  1812. end
  1813. local sortedindex={}
  1814. for c in pairs(offsets) do
  1815. table.insert(sortedindex, c)
  1816. end
  1817. table.sort(sortedindex)
  1818. local result="struct "..name.."\n"
  1819. local fieldsize
  1820. if #sortedindex>0 then
  1821. fieldsize=sortedindex[1]-0;
  1822. result=result.."vtable: resb "..fieldsize
  1823. end
  1824. result=result.."\n"
  1825. for i=1, #sortedindex do
  1826. local offset=sortedindex[i]
  1827. local name=offsets[offset]
  1828. result=result..name..": "
  1829. if sortedindex[i+1]~=nil then
  1830. fieldsize=sortedindex[i+1]-offset
  1831. else
  1832. --print("last one")
  1833. fieldsize=1 --last one
  1834. end
  1835. result=result.." resb "..fieldsize.."\n"
  1836. end
  1837. result=result.."ends\n"
  1838. --showMessage(result)
  1839. return result
  1840. end
  1841. function monoAA_GETMONOSTATICDATA(assemblyname, namespace, classname, symbolprefix, enable)
  1842. --parameters: assemblyname = partial name match of assembly
  1843. -- namespace = namespace of class (empty string if no namespace)
  1844. -- classname = name of class
  1845. -- symbolprefix = name of symbol prefix (sanitized classname used if nil)
  1846. -- returns AA script for locating static data location for given structure
  1847. local SYMCLASSNAME
  1848. if assemblyname==nil or namespace==nil or classname==nil then
  1849. return ''
  1850. end
  1851. if symbolprefix~=nil then
  1852. SYMCLASSNAME = symbolprefix:gsub("[^A-Za-z0-9._]", "")
  1853. else
  1854. SYMCLASSNAME = classname:gsub("[^A-Za-z0-9._]", "")
  1855. end
  1856. -- Populates ###.Static and ###.Class where ### the symbol prefix
  1857. local script_tmpl
  1858. if enable then
  1859. script_tmpl = [===[
  1860. label($SYMCLASSNAME$.threadexit)
  1861. label(classname)
  1862. label(namespace)
  1863. label(assemblyname)
  1864. label(status)
  1865. label(domain)
  1866. label(assembly)
  1867. label($SYMCLASSNAME$.Static)
  1868. label($SYMCLASSNAME$.Class)
  1869. alloc($SYMCLASSNAME$.threadstart, 2048)
  1870. registersymbol($SYMCLASSNAME$.Static)
  1871. registersymbol($SYMCLASSNAME$.Class)
  1872. $SYMCLASSNAME$.threadstart:
  1873. mov [$SYMCLASSNAME$.Class],0
  1874. mov [$SYMCLASSNAME$.Static],0
  1875. call mono.mono_get_root_domain
  1876. cmp eax,0
  1877. je $SYMCLASSNAME$.threadexit
  1878. mov [domain],eax
  1879. push [domain]
  1880. call mono.mono_thread_attach
  1881. add esp,4
  1882. push status
  1883. push assemblyname
  1884. call mono.mono_assembly_load_with_partial_name
  1885. add esp,8
  1886. cmp eax,0
  1887. je $SYMCLASSNAME$.threadexit
  1888. push eax
  1889. call mono.mono_assembly_get_image
  1890. add esp,4
  1891. cmp eax,0
  1892. je $SYMCLASSNAME$.threadexit
  1893. mov [assembly], eax
  1894. push classname
  1895. push namespace
  1896. push eax
  1897. call mono.mono_class_from_name_case
  1898. add esp,C
  1899. cmp eax,0
  1900. je $SYMCLASSNAME$.threadexit
  1901. mov [$SYMCLASSNAME$.Class],eax
  1902. push eax
  1903. push [domain]
  1904. call mono.mono_class_vtable
  1905. add esp,8
  1906. cmp eax,0
  1907. je $SYMCLASSNAME$.threadexit
  1908. push eax
  1909. call mono.mono_vtable_get_static_field_data
  1910. add esp,4
  1911. mov [$SYMCLASSNAME$.Static],eax
  1912. jmp $SYMCLASSNAME$.threadexit
  1913. ///////////////////////////////////////////////////////
  1914. // Data section
  1915. $SYMCLASSNAME$.Static:
  1916. dd 0
  1917. $SYMCLASSNAME$.Class:
  1918. dd 0
  1919. assemblyname:
  1920. db '$ASSEMBLYNAME$',0
  1921. namespace:
  1922. db '$NAMESPACE$',0
  1923. classname:
  1924. db '$CLASSNAME$',0
  1925. status:
  1926. dd 0
  1927. domain:
  1928. dd 0
  1929. assembly:
  1930. dd 0
  1931. $SYMCLASSNAME$.threadexit:
  1932. ret
  1933. createthread($SYMCLASSNAME$.threadstart)
  1934. ]===]
  1935. else
  1936. script_tmpl = [===[
  1937. unregistersymbol($SYMCLASSNAME$.Static)
  1938. unregistersymbol($SYMCLASSNAME$.Class)
  1939. dealloc($SYMCLASSNAME$.threadstart)
  1940. ]===]
  1941. end
  1942. return script_tmpl
  1943. :gsub('($CLASSNAME$)', classname)
  1944. :gsub('($SYMCLASSNAME$)', SYMCLASSNAME)
  1945. :gsub('($NAMESPACE$)', namespace)
  1946. :gsub('($ASSEMBLYNAME$)', assemblyname)
  1947. end
  1948. function monoAA_GETMONOSTATICFIELDDATA(assemblyname, namespace, classname, fieldname, symbolprefix, enable)
  1949. --parameters: assemblyname = partial name match of assembly
  1950. -- namespace = namespace of class (empty string if no namespace)
  1951. -- classname = name of class
  1952. -- fieldname = name of field
  1953. -- symbolprefix = name of symbol prefix (sanitized classname used if nil)
  1954. -- returns AA script for locating static data location for given structure
  1955. local SYMCLASSNAME
  1956. if assemblyname==nil or namespace==nil or classname==nil or fieldname==nil then
  1957. return ''
  1958. end
  1959. if symbolprefix~=nil then
  1960. SYMCLASSNAME = symbolprefix:gsub("[^A-Za-z0-9._]", "")
  1961. else
  1962. SYMCLASSNAME = classname:gsub("[^A-Za-z0-9._]", "")
  1963. end
  1964. local SYMFIELDNAME = fieldname:gsub("[^A-Za-z0-9._]", "")
  1965. -- Populates ###.Static and ###.Class where ### the symbol prefix
  1966. local script_tmpl
  1967. if enable then
  1968. script_tmpl = [===[
  1969. label(classname)
  1970. label(namespace)
  1971. label(assemblyname)
  1972. label(fieldname)
  1973. label(status)
  1974. label(domain)
  1975. label(assembly)
  1976. label(field)
  1977. label($SYMCLASSNAME$.$SYMFIELDNAME$)
  1978. label($SYMCLASSNAME$.$SYMFIELDNAME$.threadexit)
  1979. alloc($SYMCLASSNAME$.$SYMFIELDNAME$.threadstart, 2048)
  1980. registersymbol($SYMCLASSNAME$.$SYMFIELDNAME$)
  1981. $SYMCLASSNAME$.$SYMFIELDNAME$.threadstart:
  1982. mov [$SYMCLASSNAME$.$SYMFIELDNAME$],0
  1983. call mono.mono_get_root_domain
  1984. cmp eax,0
  1985. je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  1986. mov [domain],eax
  1987. push [domain]
  1988. call mono.mono_thread_attach
  1989. add esp,4
  1990. push status
  1991. push assemblyname
  1992. call mono.mono_assembly_load_with_partial_name
  1993. add esp,8
  1994. cmp eax,0
  1995. je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  1996. push eax
  1997. call mono.mono_assembly_get_image
  1998. add esp,4
  1999. cmp eax,0
  2000. je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  2001. mov [assembly], eax
  2002. push classname
  2003. push namespace
  2004. push eax
  2005. call mono.mono_class_from_name_case
  2006. add esp,C
  2007. cmp eax,0
  2008. je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  2009. push fieldname
  2010. push eax
  2011. call mono.mono_class_get_field_from_name
  2012. add esp,8
  2013. cmp eax,0
  2014. je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  2015. mov [field], eax
  2016. push eax
  2017. call mono.mono_field_get_parent
  2018. add esp,4
  2019. cmp eax,0
  2020. je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  2021. push eax
  2022. push [domain]
  2023. call mono.mono_class_vtable
  2024. add esp,8
  2025. cmp eax,0
  2026. je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  2027. push eax
  2028. call mono.mono_vtable_get_static_field_data
  2029. add esp,4
  2030. cmp eax,0
  2031. je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  2032. push eax // save data on stack
  2033. push [field]
  2034. call mono.mono_field_get_offset
  2035. add esp,4
  2036. pop ebx // restore data
  2037. add eax,ebx
  2038. mov [$SYMCLASSNAME$.$SYMFIELDNAME$],eax
  2039. jmp $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
  2040. ///////////////////////////////////////////////////////
  2041. // Data section
  2042. $SYMCLASSNAME$.$SYMFIELDNAME$:
  2043. dd 0
  2044. assemblyname:
  2045. db '$ASSEMBLYNAME$',0
  2046. namespace:
  2047. db '$NAMESPACE$',0
  2048. classname:
  2049. db '$CLASSNAME$',0
  2050. fieldname:
  2051. db '$FIELDNAME$',0
  2052. status:
  2053. dd 0
  2054. domain:
  2055. dd 0
  2056. assembly:
  2057. dd 0
  2058. field:
  2059. dd 0
  2060. $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit:
  2061. ret
  2062. createthread($SYMCLASSNAME$.$SYMFIELDNAME$.threadstart)
  2063. ]===]
  2064. else
  2065. script_tmpl = [===[
  2066. unregistersymbol($SYMCLASSNAME$.$SYMFIELDNAME$)
  2067. dealloc($SYMCLASSNAME$.$SYMFIELDNAME$.threadstart)
  2068. ]===]
  2069. end
  2070. return script_tmpl
  2071. :gsub('($CLASSNAME$)', classname)
  2072. :gsub('($SYMCLASSNAME$)', SYMCLASSNAME)
  2073. :gsub('($FIELDNAME$)', fieldname)
  2074. :gsub('($SYMFIELDNAME$)', SYMFIELDNAME)
  2075. :gsub('($NAMESPACE$)', namespace)
  2076. :gsub('($ASSEMBLYNAME$)', assemblyname)
  2077. end
  2078. function mono_initialize()
  2079. --register a function to be called when a process is opened
  2080. if (mono_init1==nil) then
  2081. mono_init1=true
  2082. mono_oldOnOpenProcess=onOpenProcess
  2083. onOpenProcess=mono_OpenProcess
  2084. registerAutoAssemblerCommand("USEMONO", monoAA_USEMONO)
  2085. registerAutoAssemblerCommand("FINDMONOMETHOD", monoAA_FINDMONOMETHOD)
  2086. registerAutoAssemblerCommand("GETMONOSTRUCT", monoAA_GETMONOSTRUCT)
  2087. end
  2088. end
  2089. mono_initialize()