-
Notifications
You must be signed in to change notification settings - Fork 5
/
Program.fs
103 lines (93 loc) · 3.2 KB
/
Program.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
module Fint.CLI
open System
open System.IO
open Fint.Enums
open Fint.MethodBody
open Fint.Types
open Fint.MetaReader
open Fint.PEImage
open Fint.Interpreter
let resolvePath path =
match path with
| "corlib" -> (typeof<string>).Assembly.Location
| t -> t
let dumpPE path =
use input = File.OpenRead(resolvePath path)
let reader = new BinaryReader(input)
let data = ReadPE(reader)
printfn "%A" data
()
let dumpMeta path =
use input = File.OpenRead(resolvePath path)
let reader = new BinaryReader(input)
let meta = MetaReader(reader)
printfn "%A" (meta.dump())
let tables = meta.tables |> List.filter (fun t -> t.IsSome)
printfn "%A" tables.Length
()
let ildasm path =
use input = File.OpenRead(resolvePath path)
let reader = new BinaryReader(input)
let meta = MetaReader(reader)
let methodCount = meta.rowCount TableId.MethodDef
let methods = [ 0 .. methodCount - 1 ] |> List.map meta.readMethod
let withBody = methods |> List.filter (fun m -> m.body() <> None)
let dumpCode (body: MethodBody) =
let dumpOperand v =
match v with
| Int32Operand t -> t.ToString()
| Int64Operand t -> t.ToString()
| Float32Operand t -> t.ToString()
| Float64Operand t -> t.ToString()
| SwitchTarget t -> sprintf "%A" t
| BranchTarget t -> t.ToString()
| MetadataToken t ->
let result = meta.resolveToken (uint32 t)
match result with
| StringToken s -> sprintf "0x%X=%A" t s
| RowToken r ->
let table = meta.findTable r.table
let cells =
Array.zip table.columns r.cells
|> Array.map (fun (c, v) -> sprintf "%s=%s" c.name (meta.dumpCell v))
sprintf "0x%X=%A(%s)" t r.table (String.Join(";", cells))
| _ -> ""
let lines =
Array.zip body.code [| 0 .. body.code.Length - 1 |]
|> Array.map (fun (i, k) -> sprintf "%d: %A %s" k i.opCode (dumpOperand i.operand))
String.Join("\n", lines)
let dumpMethod (m: MethodDef) =
match m.body() with
| Some body ->
let sep = new String('-', m.name.Length)
sprintf "%s\n%s\n%s\n%s" sep m.name sep (dumpCode body)
| None -> failwith "expect method body"
printfn "methods with body: %d" withBody.Length
for m in withBody do
printfn "%s" (dumpMethod (m))
()
[<EntryPoint>]
let main argv =
let cmd = argv.[0]
match cmd with
| "pe" ->
dumpPE argv.[1]
0
| "meta" ->
dumpMeta argv.[1]
0
| "ildasm" ->
ildasm argv.[1]
0
| "run" ->
use input = File.OpenRead(argv.[1])
let reader = new BinaryReader(input)
run reader |> ignore
0
| s ->
printfn "unknown command %s, available commands:" s
printfn "pe <input> - dumps PE data of given assembly"
printfn "meta <input> - dumps metadata tables of given assembly"
printfn "methods <input> - dumps methods of given assembly"
printfn "run <input> - executes given assembly"
-1