ilMetaTools.ml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. (*
  2. * This file is part of ilLib
  3. * Copyright (c)2004-2013 Haxe Foundation
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  18. *)
  19. open IlMeta;;
  20. open IlData;;
  21. open PeReader;;
  22. open ExtString;;
  23. let rec follow s = match s with
  24. | SReqModifier (_,s)
  25. | SOptModifier (_,s) ->
  26. follow s
  27. | SPinned s ->
  28. follow s
  29. | s -> s
  30. (* tells if a type_def_or_ref is of type `path` *)
  31. let rec is_type path = function
  32. | TypeDef td ->
  33. td.td_namespace = fst path && td.td_name = snd path
  34. | TypeRef tr ->
  35. tr.tr_namespace = fst path && tr.tr_name = snd path
  36. | TypeSpec ts -> (match follow ts.ts_signature with
  37. | SClass c | SValueType c ->
  38. is_type path c
  39. | SGenericInst(s,_) -> (match follow s with
  40. | SClass c | SValueType c ->
  41. is_type path c
  42. | _ -> false)
  43. | _ -> false)
  44. | _ -> assert false
  45. let rec get_path type_def_or_ref = match type_def_or_ref with
  46. | TypeDef td -> (match td.td_extra_enclosing with
  47. | None ->
  48. td.td_namespace,[], td.td_name
  49. | Some t2 ->
  50. let ns, nested = match get_path (TypeDef t2) with
  51. | ns,nested, name ->
  52. ns, nested @ [name]
  53. in
  54. ns,nested, td.td_name)
  55. | TypeRef tr -> (match tr.tr_resolution_scope with
  56. | TypeRef tr2 ->
  57. let ns, nested = match get_path (TypeRef tr2) with
  58. | ns,nested, name ->
  59. ns, nested @ [name]
  60. in
  61. ns,nested, tr.tr_name
  62. | _ ->
  63. tr.tr_namespace,[],tr.tr_name)
  64. | TypeSpec ts -> (match follow ts.ts_signature with
  65. | SClass c | SValueType c ->
  66. get_path c
  67. | SGenericInst(s,_) -> (match follow s with
  68. | SClass c | SValueType c ->
  69. get_path c
  70. | _ -> [],[],"")
  71. | _ -> [],[],"")
  72. | _ -> assert false
  73. let constant_s = function
  74. | IBool true -> "true"
  75. | IBool false -> "false"
  76. | IChar chr -> "'" ^ Char.escaped (Char.chr chr) ^ "'"
  77. | IByte i ->
  78. Printf.sprintf "(byte) 0x%x" i
  79. | IShort i ->
  80. Printf.sprintf "(short) 0x%x" i
  81. | IInt i ->
  82. Printf.sprintf "0x%lx" i
  83. | IInt64 i ->
  84. Printf.sprintf "0x%Lx" i
  85. | IFloat32 f ->
  86. Printf.sprintf "%ff" f
  87. | IFloat64 f ->
  88. Printf.sprintf "%fd" f
  89. | IString s -> "\"" ^ s ^ "\""
  90. | INull -> "null"
  91. let path_s = function
  92. | [],[], s -> s
  93. | ns,[], s -> String.concat "." ns ^ "." ^ s
  94. | [],enc, s -> String.concat "@" enc ^ "." ^ s
  95. | ns,enc,s -> String.concat "." ns ^ "." ^ String.concat "@" enc ^ "." ^ s
  96. let rec ilsig_s = function
  97. | SBoxed -> "boxed"
  98. | SEnum e -> "enum " ^ e
  99. | SType -> "System.Type"
  100. | SVoid -> "void"
  101. | SBool -> "bool"
  102. | SChar -> "char"
  103. | SInt8 -> "int8"
  104. | SUInt8 -> "uint8"
  105. | SInt16 -> "int16"
  106. | SUInt16 -> "uint16"
  107. | SInt32 -> "int32"
  108. | SUInt32 -> "uint32"
  109. | SInt64 -> "int64"
  110. | SUInt64 -> "uint64"
  111. | SFloat32 -> "float"
  112. | SFloat64 -> "double"
  113. | SString -> "string"
  114. | SPointer s -> ilsig_s s ^ "*"
  115. | SManagedPointer s -> ilsig_s s ^ "&"
  116. | SValueType td -> "valuetype " ^ path_s (get_path td)
  117. | SClass cl -> "classtype " ^ path_s (get_path cl)
  118. | STypeParam t | SMethodTypeParam t -> "!" ^ string_of_int t
  119. | SArray (s,opts) ->
  120. ilsig_s s ^ "[" ^ String.concat "," (List.map (function
  121. | Some i,None when i <> 0 ->
  122. string_of_int i ^ "..."
  123. | None, Some i when i <> 0 ->
  124. string_of_int i
  125. | Some s, Some b when b = 0 && s <> 0 ->
  126. string_of_int s ^ "..."
  127. | Some s, Some b when s <> 0 || b <> 0 ->
  128. let b = if b > 0 then b - 1 else b in
  129. string_of_int s ^ "..." ^ string_of_int (s + b)
  130. | _ ->
  131. ""
  132. ) (Array.to_list opts)) ^ "]"
  133. | SGenericInst (t,tl) ->
  134. "generic " ^ (ilsig_s t) ^ "<" ^ String.concat ", " (List.map ilsig_s tl) ^ ">"
  135. | STypedReference -> "typedreference"
  136. | SIntPtr -> "native int"
  137. | SUIntPtr -> "native unsigned int"
  138. | SFunPtr (callconv,ret,args) ->
  139. "function " ^ ilsig_s ret ^ "(" ^ String.concat ", " (List.map ilsig_s args) ^ ")"
  140. | SObject -> "object"
  141. | SVector s -> ilsig_s s ^ "[]"
  142. | SReqModifier (_,s) -> "modreq() " ^ ilsig_s s
  143. | SOptModifier (_,s) -> "modopt() " ^ ilsig_s s
  144. | SSentinel -> "..."
  145. | SPinned s -> "pinned " ^ ilsig_s s
  146. let rec instance_s = function
  147. | InstConstant c -> constant_s c
  148. | InstBoxed b -> "boxed " ^ instance_s b
  149. | InstType t -> "Type " ^ t
  150. | InstArray il -> "[" ^ String.concat ", " (List.map instance_s il) ^ "]"
  151. | InstEnum e -> "Enum " ^ string_of_int e
  152. let named_attribute_s (is_prop,name,inst) =
  153. (if is_prop then
  154. "/*prop*/ "
  155. else
  156. "")
  157. ^ name ^ " = " ^ instance_s inst
  158. let attributes_s (il,nal) =
  159. "(" ^ (String.concat ", " (List.map instance_s il)) ^ (if nal <> [] then ", " ^ (String.concat ", " (List.map named_attribute_s nal)) else "") ^")"
  160. let meta_root m : meta_root = match m with
  161. | Module r -> Obj.magic r
  162. | TypeRef r -> Obj.magic r
  163. | TypeDef r -> Obj.magic r
  164. | FieldPtr r -> Obj.magic r
  165. | Field r -> Obj.magic r
  166. | MethodPtr r -> Obj.magic r
  167. | Method r -> Obj.magic r
  168. | ParamPtr r -> Obj.magic r
  169. | Param r -> Obj.magic r
  170. | InterfaceImpl r -> Obj.magic r
  171. | MemberRef r -> Obj.magic r
  172. | Constant r -> Obj.magic r
  173. | CustomAttribute r -> Obj.magic r
  174. | FieldMarshal r -> Obj.magic r
  175. | DeclSecurity r -> Obj.magic r
  176. | ClassLayout r -> Obj.magic r
  177. | FieldLayout r -> Obj.magic r
  178. | StandAloneSig r -> Obj.magic r
  179. | EventMap r -> Obj.magic r
  180. | EventPtr r -> Obj.magic r
  181. | Event r -> Obj.magic r
  182. | PropertyMap r -> Obj.magic r
  183. | PropertyPtr r -> Obj.magic r
  184. | Property r -> Obj.magic r
  185. | MethodSemantics r -> Obj.magic r
  186. | MethodImpl r -> Obj.magic r
  187. | ModuleRef r -> Obj.magic r
  188. | TypeSpec r -> Obj.magic r
  189. | ImplMap r -> Obj.magic r
  190. | FieldRVA r -> Obj.magic r
  191. | ENCLog r -> Obj.magic r
  192. | ENCMap r -> Obj.magic r
  193. | Assembly r -> Obj.magic r
  194. | AssemblyProcessor r -> Obj.magic r
  195. | AssemblyOS r -> Obj.magic r
  196. | AssemblyRef r -> Obj.magic r
  197. | AssemblyRefProcessor r -> Obj.magic r
  198. | AssemblyRefOS r -> Obj.magic r
  199. | File r -> Obj.magic r
  200. | ExportedType r -> Obj.magic r
  201. | ManifestResource r -> Obj.magic r
  202. | NestedClass r -> Obj.magic r
  203. | GenericParam r -> Obj.magic r
  204. | MethodSpec r -> Obj.magic r
  205. | GenericParamConstraint r -> Obj.magic r
  206. | _ -> assert false
  207. let meta_root_ptr p : meta_root_ptr = match p with
  208. | FieldPtr r -> Obj.magic r
  209. | MethodPtr r -> Obj.magic r
  210. | ParamPtr r -> Obj.magic r
  211. | EventPtr r -> Obj.magic r
  212. | _ -> assert false
  213. let rec ilsig_norm = function
  214. | SVoid -> LVoid
  215. | SBool -> LBool
  216. | SChar -> LChar
  217. | SInt8 -> LInt8
  218. | SUInt8 -> LUInt8
  219. | SInt16 -> LInt16
  220. | SUInt16 -> LUInt16
  221. | SInt32 -> LInt32
  222. | SUInt32 -> LUInt32
  223. | SInt64 -> LInt64
  224. | SUInt64 -> LUInt64
  225. | SFloat32 -> LFloat32
  226. | SFloat64 -> LFloat64
  227. | SString -> LString
  228. | SPointer p -> LPointer (ilsig_norm p)
  229. | SManagedPointer p -> LManagedPointer (ilsig_norm p)
  230. | SValueType v -> LValueType (get_path v, [])
  231. | SClass v -> LClass (get_path v, [])
  232. | STypeParam i -> LTypeParam i
  233. | SArray (t, opts) -> LArray(ilsig_norm t, opts)
  234. | SGenericInst (p,args) -> (match follow p with
  235. | SClass v ->
  236. LClass(get_path v, List.map ilsig_norm args)
  237. | SValueType v ->
  238. LValueType(get_path v, List.map ilsig_norm args)
  239. | _ -> assert false)
  240. | STypedReference -> LTypedReference
  241. | SIntPtr -> LIntPtr
  242. | SUIntPtr -> LUIntPtr
  243. | SFunPtr(conv,ret,args) -> LMethod(conv,ilsig_norm ret,List.map ilsig_norm args)
  244. | SObject -> LObject
  245. | SVector s -> LVector (ilsig_norm s)
  246. | SMethodTypeParam i -> LMethodTypeParam i
  247. | SReqModifier (_,s) -> ilsig_norm s
  248. | SOptModifier (_,s) -> ilsig_norm s
  249. | SSentinel -> LSentinel
  250. | SPinned s -> ilsig_norm s
  251. | SType -> LClass( (["System"],[],"Type"), [])
  252. | SBoxed -> LObject
  253. | SEnum e ->
  254. let lst = String.nsplit e "." in
  255. let rev = List.rev lst in
  256. match rev with
  257. | hd :: tl -> LValueType( (List.rev tl,[],hd), [] )
  258. | _ -> assert false
  259. let ilsig_t s =
  260. {
  261. snorm = ilsig_norm s;
  262. ssig = s;
  263. }
  264. let ilsig_of_tdef_ref = function
  265. | TypeDef td ->
  266. SClass (TypeDef td)
  267. | TypeRef tr ->
  268. SClass (TypeRef tr)
  269. | TypeSpec ts ->
  270. ts.ts_signature
  271. | s ->
  272. (* error ("Invalid tdef_or_ref: " ^ ilsig_s s) *)
  273. error "Invalid tdef_or_ref"
  274. let convert_field ctx f =
  275. let constant = List.fold_left (fun c -> function
  276. | Constant c ->
  277. Some c.c_value
  278. | _ ->
  279. c
  280. ) None (Hashtbl.find_all ctx.il_relations (IField, f.f_id))
  281. in
  282. {
  283. fname = f.f_name;
  284. fflags = f.f_flags;
  285. fsig = ilsig_t f.f_signature;
  286. fconstant = constant;
  287. }
  288. let convert_generic ctx gp =
  289. let constraints = List.fold_left (fun c -> function
  290. | GenericParamConstraint gc ->
  291. ilsig_t (ilsig_of_tdef_ref gc.gc_constraint) :: c
  292. | _ ->
  293. c
  294. ) [] (Hashtbl.find_all ctx.il_relations (IGenericParam, gp.gp_id))
  295. in
  296. {
  297. tnumber = gp.gp_number;
  298. tflags = gp.gp_flags;
  299. tname = gp.gp_name;
  300. tconstraints = constraints;
  301. }
  302. let convert_method ctx m =
  303. let msig = ilsig_t m.m_signature in
  304. let ret, margs = match follow msig.ssig with
  305. | SFunPtr (_,ret,args) ->
  306. (* print_endline m.m_name; *)
  307. (* print_endline (Printf.sprintf "%d vs %d" (List.length args) (List.length m.m_param_list)); *)
  308. (* print_endline (String.concat ", " (List.map (fun p ->string_of_int p.p_sequence ^ ":" ^ p.p_name) m.m_param_list)); *)
  309. (* print_endline (String.concat ", " (List.map (ilsig_s) args)); *)
  310. (* print_endline "\n"; *)
  311. (* TODO: find out WHY this happens *)
  312. let param_list = List.filter (fun p -> p.p_sequence > 0) m.m_param_list in
  313. if List.length param_list <> List.length args then
  314. let i = ref 0 in
  315. ilsig_t ret, List.map (fun s ->
  316. incr i; "arg" ^ (string_of_int !i), { pf_io = []; pf_reserved = [] }, ilsig_t s) args
  317. else
  318. ilsig_t ret, List.map2 (fun p s ->
  319. p.p_name, p.p_flags, ilsig_t s
  320. ) param_list args
  321. | _ -> assert false
  322. in
  323. let override, types, semantics =
  324. List.fold_left (fun (override,types,semantics) -> function
  325. | MethodImpl mi ->
  326. let declaring = match mi.mi_method_declaration with
  327. | MemberRef mr ->
  328. Some (get_path mr.memr_class, mr.memr_name)
  329. | Method m -> (match m.m_declaring with
  330. | Some td ->
  331. Some (get_path (TypeDef td), m.m_name)
  332. | None -> override)
  333. | _ -> override
  334. in
  335. declaring, types, semantics
  336. | GenericParam gp ->
  337. override, (convert_generic ctx gp) :: types, semantics
  338. | MethodSemantics ms ->
  339. override, types, ms.ms_semantic @ semantics
  340. | _ ->
  341. override,types, semantics
  342. ) (None,[],[]) (Hashtbl.find_all ctx.il_relations (IMethod, m.m_id))
  343. in
  344. {
  345. mname = m.m_name;
  346. mflags = m.m_flags;
  347. msig = msig;
  348. margs = margs;
  349. mret = ret;
  350. moverride = override;
  351. mtypes = types;
  352. msemantics = semantics;
  353. }
  354. let convert_prop ctx prop =
  355. let name = prop.prop_name in
  356. let flags = prop.prop_flags in
  357. let psig = ilsig_t prop.prop_type in
  358. let pget, pset =
  359. List.fold_left (fun (get,set) -> function
  360. | MethodSemantics ms when List.mem SGetter ms.ms_semantic ->
  361. assert (get = None);
  362. Some (ms.ms_method.m_name, ms.ms_method.m_flags), set
  363. | MethodSemantics ms when List.mem SSetter ms.ms_semantic ->
  364. assert (set = None);
  365. get, Some (ms.ms_method.m_name,ms.ms_method.m_flags)
  366. | _ -> get,set
  367. )
  368. (None,None)
  369. (Hashtbl.find_all ctx.il_relations (IProperty, prop.prop_id))
  370. in
  371. {
  372. pname = name;
  373. psig = psig;
  374. pflags = flags;
  375. pget = pget;
  376. pset = pset;
  377. }
  378. let convert_event ctx event =
  379. let name = event.e_name in
  380. let flags = event.e_flags in
  381. let esig = ilsig_of_tdef_ref event.e_event_type in
  382. let esig = ilsig_t esig in
  383. let add, remove, eraise =
  384. List.fold_left (fun (add, remove, eraise) -> function
  385. | MethodSemantics ms when List.mem SAddOn ms.ms_semantic ->
  386. assert (add = None);
  387. Some (ms.ms_method.m_name, ms.ms_method.m_flags), remove, eraise
  388. | MethodSemantics ms when List.mem SRemoveOn ms.ms_semantic ->
  389. assert (remove = None);
  390. add, Some (ms.ms_method.m_name,ms.ms_method.m_flags), eraise
  391. | MethodSemantics ms when List.mem SFire ms.ms_semantic ->
  392. assert (eraise = None);
  393. add, remove, Some (ms.ms_method.m_name, ms.ms_method.m_flags)
  394. | _ -> add, remove, eraise
  395. )
  396. (None,None,None)
  397. (Hashtbl.find_all ctx.il_relations (IEvent, event.e_id))
  398. in
  399. {
  400. ename = name;
  401. eflags = flags;
  402. esig = esig;
  403. eadd = add;
  404. eremove = remove;
  405. eraise = eraise;
  406. }
  407. let convert_class ctx path =
  408. let td = Hashtbl.find ctx.il_typedefs path in
  409. let cpath = get_path (TypeDef td) in
  410. let cflags = td.td_flags in
  411. let csuper = Option.map (fun e -> ilsig_t (ilsig_of_tdef_ref e)) td.td_extends in
  412. let cfields = List.map (convert_field ctx) td.td_field_list in
  413. let cmethods = List.map (convert_method ctx) td.td_method_list in
  414. let enclosing = Option.map (fun t -> get_path (TypeDef t)) td.td_extra_enclosing in
  415. let impl, types, nested, props, events, attrs =
  416. List.fold_left (fun (impl,types,nested,props,events,attrs) -> function
  417. | InterfaceImpl ii ->
  418. (ilsig_t (ilsig_of_tdef_ref ii.ii_interface)) :: impl,types,nested, props, events, attrs
  419. | GenericParam gp ->
  420. (impl, (convert_generic ctx gp) :: types, nested, props,events, attrs)
  421. | NestedClass nc ->
  422. assert (nc.nc_enclosing.td_id = td.td_id);
  423. (impl,types,(get_path (TypeDef nc.nc_nested)) :: nested, props, events, attrs)
  424. | PropertyMap pm ->
  425. assert (props = []);
  426. impl,types,nested,List.map (convert_prop ctx) pm.pm_property_list, events, attrs
  427. | EventMap em ->
  428. assert (events = []);
  429. (impl,types,nested,props,List.map (convert_event ctx) em.em_event_list, attrs)
  430. | CustomAttribute a ->
  431. impl,types,nested,props,events,(a :: attrs)
  432. | _ ->
  433. (impl,types,nested,props,events,attrs)
  434. )
  435. ([],[],[],[],[],[])
  436. (Hashtbl.find_all ctx.il_relations (ITypeDef, td.td_id))
  437. in
  438. {
  439. cpath = cpath;
  440. cflags = cflags;
  441. csuper = csuper;
  442. cfields = cfields;
  443. cmethods = cmethods;
  444. cevents = events;
  445. cprops = props;
  446. cimplements = impl;
  447. ctypes = types;
  448. cenclosing = enclosing;
  449. cnested = nested;
  450. cattrs = attrs;
  451. }