pedump 0.6.10 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,318 @@
1
+ #coding: binary
2
+
3
+ class PEdump
4
+ module CLR
5
+ class Signature
6
+ FIELD = 6
7
+ PROPERTY = 8
8
+
9
+ DEFAULT = 0
10
+ VARARG = 5
11
+ GENERIC = 0x10
12
+ HASTHIS = 0x20
13
+ EXPLICITTHIS = 0x40
14
+
15
+ SENTINEL = 0x41
16
+
17
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.1.16-element-types-used-in-signatures.md
18
+ ELEMENT_TYPE_END = 0
19
+ ELEMENT_TYPE_VOID = 1
20
+ ELEMENT_TYPE_BOOLEAN = 2
21
+ ELEMENT_TYPE_CHAR = 3
22
+ ELEMENT_TYPE_I1 = 4
23
+ ELEMENT_TYPE_U1 = 5
24
+ ELEMENT_TYPE_I2 = 6
25
+ ELEMENT_TYPE_U2 = 7
26
+ ELEMENT_TYPE_I4 = 8
27
+ ELEMENT_TYPE_U4 = 9
28
+ ELEMENT_TYPE_I8 = 0x0a
29
+ ELEMENT_TYPE_U8 = 0x0b
30
+ ELEMENT_TYPE_R4 = 0x0c
31
+ ELEMENT_TYPE_R8 = 0x0d
32
+ ELEMENT_TYPE_STRING = 0x0e
33
+ ELEMENT_TYPE_PTR = 0x0f # Followed by type
34
+ ELEMENT_TYPE_BYREF = 0x10 # Followed by type
35
+ ELEMENT_TYPE_VALUETYPE = 0x11 # Followed by TypeDef or TypeRef token
36
+ ELEMENT_TYPE_CLASS = 0x12 # Followed by TypeDef or TypeRef token
37
+ ELEMENT_TYPE_VAR = 0x13 # Generic parameter in a generic type definition, represented as number (compressed unsigned integer)
38
+ ELEMENT_TYPE_ARRAY = 0x14 # type rank boundsCount bound1 … loCount lo1 …
39
+ ELEMENT_TYPE_GENERICINST = 0x15 # Generic type instantiation. Followed by type type-arg-count type-1 … type-n
40
+ ELEMENT_TYPE_TYPEDBYREF = 0x16
41
+ ELEMENT_TYPE_I = 0x18 # System.IntPtr
42
+ ELEMENT_TYPE_U = 0x19 # System.UIntPtr
43
+ ELEMENT_TYPE_FNPTR = 0x1b # Followed by full method signature
44
+ ELEMENT_TYPE_OBJECT = 0x1c # System.Object
45
+ ELEMENT_TYPE_SZARRAY = 0x1d # Single-dim array with 0 lower bound
46
+ ELEMENT_TYPE_MVAR = 0x1e # Generic parameter in a generic method definition, represented as number (compressed unsigned integer)
47
+ ELEMENT_TYPE_CMOD_REQD = 0x1f # Required modifier: followed by a TypeDef or TypeRef token
48
+ ELEMENT_TYPE_CMOD_OPT = 0x20 # Optional modifier: followed by a TypeDef or TypeRef token
49
+ ELEMENT_TYPE_INTERNAL = 0x21 # Implemented within the CLI
50
+ # TODO: 0x40+
51
+
52
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.10-param.md
53
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.15.3-calling-convention.md
54
+ def to_s
55
+ a = []
56
+ a << 'instance' if @type & 0x20 != 0
57
+ a << 'explicit' if @type & 0x40 != 0
58
+ a << case @type & 0x0f
59
+ when DEFAULT
60
+ nil # default calling convention
61
+ when 1
62
+ 'cdecl'
63
+ when 2
64
+ 'stdcall'
65
+ when 3
66
+ 'thiscall'
67
+ when 4
68
+ 'fastcall'
69
+ when VARARG
70
+ 'vararg'
71
+ else
72
+ "0x%02x" % (@type)
73
+ end
74
+ a << @RetType
75
+ a.compact.join(' ')
76
+ end
77
+
78
+ def self.read(io, key)
79
+ klass =
80
+ case key
81
+ when :Field
82
+ FieldSig
83
+ when :Property
84
+ PropertySig
85
+ when :MethodDef
86
+ MethodDefSig
87
+ when :MemberRef
88
+ type = io.getbyte
89
+ io.ungetbyte(type)
90
+ if type == FIELD
91
+ FieldSig
92
+ else
93
+ MethodRefSig
94
+ end
95
+ when :StandAloneSig
96
+ StandAloneMethodSig
97
+ when :TypeSpec
98
+ TypeSpecBlob
99
+ else
100
+ raise "unknown key: #{key.inspect}"
101
+ end
102
+ klass.new(io)
103
+ end
104
+
105
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.10-param.md
106
+ def _read_Param io
107
+ _read_CustomMod(io)
108
+ case (b = io.getbyte)
109
+ when ELEMENT_TYPE_BYREF
110
+ # TODO "add byref"
111
+ _read_Type(io)
112
+ when ELEMENT_TYPE_TYPEDBYREF
113
+ "TYPEDBYREF"
114
+ else
115
+ io.ungetbyte(b)
116
+ _read_Type(io)
117
+ end
118
+ end
119
+
120
+ def _read_Type io
121
+ case b = io.getbyte
122
+ when ELEMENT_TYPE_BOOLEAN then "bool"
123
+ when ELEMENT_TYPE_CHAR then "char"
124
+ when ELEMENT_TYPE_CLASS
125
+ a = ['CLASS']
126
+ a << _read_TypeDefOrRefOrSpecEncoded(io).to_s(16)
127
+ a.join(' ')
128
+
129
+ when ELEMENT_TYPE_VALUETYPE
130
+ a = ['VALUE']
131
+ a << _read_TypeDefOrRefOrSpecEncoded(io).to_s(16)
132
+ a.join(' ')
133
+
134
+ when ELEMENT_TYPE_GENERICINST
135
+ # https://github.com/stakx/ecma-335/blob/f181e4696eebcbbc7c2b1e5d0a2ee289f2884d2d/docs/vi.b.4.3-metadata.md
136
+ a = []
137
+ a << _read_Type(io)
138
+ genArgCount = _read_compressed_uint(io)
139
+ nested_types = genArgCount.times.map{ _read_Type(io).to_s }
140
+ a << '<' + nested_types.join(', ') + '>'
141
+ a.join(' ')
142
+
143
+ when ELEMENT_TYPE_I then "nint"
144
+ when ELEMENT_TYPE_I1 then "sbyte"
145
+ when ELEMENT_TYPE_I2 then "short"
146
+ when ELEMENT_TYPE_I4 then "int"
147
+ when ELEMENT_TYPE_I8 then "long"
148
+
149
+ when ELEMENT_TYPE_R4 then "float"
150
+ when ELEMENT_TYPE_R8 then "double"
151
+
152
+ when ELEMENT_TYPE_U then "nuint"
153
+ when ELEMENT_TYPE_U1 then "byte"
154
+ when ELEMENT_TYPE_U2 then "ushort"
155
+ when ELEMENT_TYPE_U4 then "uint"
156
+ when ELEMENT_TYPE_U8 then "ulong"
157
+ when ELEMENT_TYPE_OBJECT then "object"
158
+ when ELEMENT_TYPE_STRING then "string"
159
+ when ELEMENT_TYPE_SZARRAY then "#{_read_Type(io)}[]"
160
+ when ELEMENT_TYPE_VALUETYPE then _read_TypeDefOrRefOrSpecEncoded(io)
161
+ when ELEMENT_TYPE_VAR, ELEMENT_TYPE_MVAR
162
+ _read_compressed_uint(io).to_s
163
+ when ELEMENT_TYPE_VOID then "void"
164
+ when ELEMENT_TYPE_END then "END"
165
+ else
166
+ "0x%02x" % b
167
+ end
168
+ end
169
+
170
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.11-rettype.md
171
+ def _read_RetType io
172
+ _read_CustomMod(io)
173
+ case (b = io.getbyte)
174
+ when ELEMENT_TYPE_BYREF
175
+ # TODO "add byref"
176
+ _read_Type(io)
177
+ when ELEMENT_TYPE_TYPEDBYREF
178
+ "TYPEDBYREF"
179
+ when ELEMENT_TYPE_VOID
180
+ "void"
181
+ else
182
+ io.ungetbyte(b)
183
+ _read_Type(io)
184
+ end
185
+ end
186
+
187
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.7-custommod.md
188
+ def _read_CustomMod io
189
+ b = io.getbyte
190
+ if b == ELEMENT_TYPE_CMOD_REQD || b == ELEMENT_TYPE_CMOD_OPT
191
+ @cmod = b
192
+ @cmod_type = _read_TypeDefOrRefOrSpecEncoded(io)
193
+ else
194
+ io.ungetbyte(b)
195
+ end
196
+ end
197
+
198
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.8-typedeforreforspecencoded.md
199
+ def _read_TypeDefOrRefOrSpecEncoded io
200
+ v = _read_compressed_uint(io)
201
+ table_id = (v & 3)
202
+ idx_in_table = (v >> 2)
203
+ table_id_hi =
204
+ case table_id
205
+ when 0
206
+ # TypeDef
207
+ 0x02_000000
208
+ when 1
209
+ # TypeRef
210
+ 0x01_000000
211
+ when 2
212
+ # TypeSpec
213
+ 0x1b_000000
214
+ else
215
+ # invalid
216
+ 0
217
+ end
218
+ table_id_hi | idx_in_table
219
+ end
220
+
221
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2-blobs-and-signatures.md
222
+ def _read_compressed_uint io
223
+ v = io.read(1).unpack1('C')
224
+ if v & 0x80 == 0
225
+ # 1 byte
226
+ v
227
+ elsif v & 0xC0 == 0x80
228
+ # 2 bytes
229
+ ((v & 0x3F) << 8) | io.read(1).unpack1('C')
230
+ elsif v & 0xE0 == 0xC0
231
+ # 4 bytes
232
+ ((v & 0x1F) << 24) | (io.read(3).unpack1('C') << 16) | (io.read(2).unpack1('C') << 8) | io.read(1).unpack1('C')
233
+ else
234
+ nil
235
+ end
236
+ end
237
+ end # class Signature
238
+
239
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.4-fieldsig.md
240
+ class FieldSig < Signature
241
+ attr_accessor :type
242
+
243
+ def initialize(io)
244
+ sig_type = io.getbyte
245
+ raise "unexpected sig_type #{sig_type}" if sig_type != FIELD
246
+
247
+ _read_CustomMod(io)
248
+ @type = _read_Type(io)
249
+ end
250
+ end
251
+
252
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.5-propertysig.md
253
+ class PropertySig < Signature
254
+ attr_accessor :type, :params
255
+
256
+ def initialize(io)
257
+ sig_type = io.getbyte
258
+ raise "unexpected sig_type #{sig_type}" if sig_type != PROPERTY && sig_type != PROPERTY|HASTHIS
259
+
260
+ @ParamCount = _read_compressed_uint(io)
261
+ _read_CustomMod(io) # FIXME
262
+ @type = _read_Type(io)
263
+ if @ParamCount < 255 # protect from malformed EXEs
264
+ @params = @ParamCount.times.map{ _read_Param(io) }
265
+ end
266
+ end
267
+ end
268
+
269
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.2-methodrefsig.md
270
+ class MethodRefSig < Signature
271
+ attr_accessor :ret_type, :params
272
+
273
+ def initialize io
274
+ # "The first byte of the Signature holds bits for HASTHIS, EXPLICITTHIS, and the calling convention VARARG. These are ORed together."
275
+ @type = io.read(1).unpack1('C')
276
+ @ParamCount = _read_compressed_uint(io)
277
+ @ret_type = _read_RetType(io)
278
+
279
+ if @ParamCount < 255 # protect from malformed EXEs
280
+ @params = @ParamCount.times.map{ _read_Param(io) }
281
+ end
282
+ end
283
+ end
284
+
285
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.1-methoddefsig.md
286
+ class MethodDefSig < Signature
287
+ attr_accessor :ret_type, :params
288
+
289
+ def initialize io
290
+ # "The first byte of the Signature holds bits for HASTHIS, EXPLICITTHIS, and the calling convention VARARG. These are ORed together."
291
+ @type = io.read(1).unpack1('C')
292
+
293
+ if @type & GENERIC == GENERIC
294
+ @GenParamCount = _read_compressed_uint(io)
295
+ end
296
+
297
+ @ParamCount = _read_compressed_uint(io)
298
+ @ret_type = _read_RetType(io)
299
+
300
+ if @ParamCount < 255 # protect from malformed EXEs
301
+ @params = @ParamCount.times.map{ _read_Param(io) }
302
+ end
303
+ end
304
+ end
305
+
306
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.3-standalonemethodsig.md
307
+ class StandAloneMethodSig < MethodRefSig
308
+ end
309
+
310
+ # https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.14-typespec.md
311
+ class TypeSpecBlob < Signature
312
+ def initialize io
313
+ @type = _read_Type(io)
314
+ end
315
+ end
316
+
317
+ end
318
+ end