2

由于我似乎将 95% 的编码时间实际上花在了 F# 的 FSI 上,因此我绕道(参见:Distracted)并想编写一些实用函数。

我感兴趣的特定实用程序是一个“反汇编”(http://www.cons.org/cmucl/doc/reading-disassembly.html)函数,它可以为给定函数转储IL,稍后可能会计算指令,基本的静态分析等,通常这只是分散注意力的天堂。我已经编写了将 byteArrayIL 映射到 MSIL 名称的代码(几乎)。

这是用于从当前模块获取函数名称的代码段:

let dec_c = MethodBase.GetCurrentMethod().DeclaringType

System.Reflection.Assembly.GetAssembly(dec_c).GetTypes() 
|> Seq.map (fun x -> x.FullName) //, get_function_instructions x)

这几乎可以正常工作,因为 x.FullName 反映了实际的函数名称:

FSI_0001
<StartupCode$FSI_0001>.$FSI_0001
FSI_0002
FSI_0002+instructions_of_bytes@24
FSI_0002+remove_null_function_body_bytes@32
FSI_0002+remove_null_function_body_bytes@31-1
FSI_0002+resolve_IL_from_bytes@38
FSI_0002+resolve_IL_from_bytes@36-1
FSI_0002+it@49
FSI_0002+it@50-1
<StartupCode$FSI_0002>.$FSI_0002
FSI_0003
FSI_0003+it@49-2
FSI_0003+it@50-3
<StartupCode$FSI_0003>.$FSI_0003

所以我们可以很容易地编写一个函数来根据我们的函数名进行过滤。

不幸的是(可能由于我的误解),似乎并非所有函数都以这种方式可用,例如,如果我们定义以下简单函数然后重新运行转储:

(* reload FSI *)
let simple_add x = x + 1
(* rerun the function name dumping *)

FSI_0001
<StartupCode$FSI_0001>.$FSI_0001
FSI_0002
FSI_0002+instructions_of_bytes@24
FSI_0002+remove_null_function_body_bytes@32
FSI_0002+remove_null_function_body_bytes@31-1
FSI_0002+resolve_IL_from_bytes@38
FSI_0002+resolve_IL_from_bytes@36-1
FSI_0002+it@50
FSI_0002+it@51-1
<StartupCode$FSI_0002>.$FSI_0002

奇怪的是,结果文本中不存在“simple_add”函数。

思考: 1. 可能simple_add这个函数不是通过反射实现的,直到看到被使用?听起来很奇怪。2. 可能是那些“FSI_0002+it”字符串之一实际上是我们的函数。

问题: 1. 为什么输出没有反映所有的函数名?2.有没有更好的方法来做到这一点?

4

1 回答 1

3

我想我在答案上睡了(半睡),我做错了,没有必要列出每个函数字符串名称......

let get_function_instructions (mb : System.Type) = 
  mb.GetMethods() 
  |> Seq.map ...

let find_func_print_instructions f =
  f.GetType()
  |> get_function_instructions 
  |> print_instruction_text
于 2012-11-21T19:27:12.680 回答