1
1
import { injectable } from "inversify" ;
2
2
import { WasmBinary } from "./WasmBinary" ;
3
3
import { BytesReader } from "./BytesReader" ;
4
- import { WasmSection , WasmTypeSectionPayload , WasmSectionPayload , WasmExportSectionPayload , WasmCodeSectionPayload , WasmImportSectionPayload } from "./WasmSection" ;
4
+ import { WasmSection , WasmTypeSectionPayload , WasmSectionPayload , WasmExportSectionPayload , WasmCodeSectionPayload , WasmImportSectionPayload , WasmFunctionSectionPayload , findSection } from "./WasmSection" ;
5
5
import { WasmSectionType , WasmType , WasmValueType , getWasmValueType , getExternalType , WasmExternalKind } from "./wasmTypes" ;
6
- import { FuncType } from "./FuncType" ;
6
+ import { FuncType , printSignature } from "./FuncType" ;
7
7
import { FunctionBody , FunctionLocal , formatOpcodes } from "./FunctionBody" ;
8
8
import { WasmOpcode , WasmOpcodeDefinition , WasmOpcodes , Immediate } from "./WasmOpcodes" ;
9
9
import { OpcodeImmediateType } from "./OpcodeImmediateType" ;
@@ -22,6 +22,7 @@ export class WasmBinaryParser {
22
22
this . sectionParsers . set ( WasmSectionType . Export , this . parseExportSection )
23
23
this . sectionParsers . set ( WasmSectionType . Code , this . parseCodeSection )
24
24
this . sectionParsers . set ( WasmSectionType . Import , this . parseImportSection )
25
+ this . sectionParsers . set ( WasmSectionType . Function , this . parseFunctionSection )
25
26
}
26
27
27
28
parse ( binary : Buffer ) : WasmBinary {
@@ -30,7 +31,7 @@ export class WasmBinaryParser {
30
31
const magicNumberRead : string = reader . readBytesToHex ( 4 )
31
32
32
33
if ( magicNumberRead !== this . WASM_MAGIC_NUMBER ) {
33
- throw new Error ( `WASM Magic number not found` )
34
+ throw new Error ( `WASM Magic number not found: ${ magicNumberRead } ` )
34
35
}
35
36
const version = reader . readBytesToHex ( 4 )
36
37
@@ -53,24 +54,55 @@ export class WasmBinaryParser {
53
54
} )
54
55
}
55
56
56
- // removeme
57
- const sec = sections . find ( section => {
58
- return section . sectionType . toString ( ) == WasmSectionType [ WasmSectionType . Code . toString ( ) ]
59
- } ) ;
60
-
61
- const imp = sections . find ( section => {
62
- return section . sectionType . toString ( ) == WasmSectionType [ WasmSectionType . Import . toString ( ) ]
63
- } ) ;
64
- console . log ( JSON . stringify ( imp ) )
65
- // const outp: WasmCodeSectionPayload = sec.payload as WasmCodeSectionPayload;
66
- // console.log(JSON.stringify(outp.functions[1]))
67
- // const mapp = outp.functions[3].opcodes.map(p => `[0x${p.opcode.code.toString(16)}] ${p.opcode.name} ${p.immediates}`)
68
- // console.log(mapp)
69
- // console.log(outp.functions[2].formattedOpcodes)
70
- // console.log(JSON.stringify(wasmSections))
71
- return {
57
+ const wasmBinary : WasmBinary = {
72
58
sections
59
+ } ;
60
+ const wasmPostProcessed = this . postProcess ( wasmBinary ) ;
61
+ // console.log(JSON.stringify(wasmPostProcessed))
62
+ return wasmPostProcessed
63
+ }
64
+
65
+ postProcess ( wasmBinary : WasmBinary ) : WasmBinary {
66
+ const functionSection = findSection ( wasmBinary . sections , WasmSectionType . Function )
67
+ const functionSectionPayload : WasmFunctionSectionPayload = functionSection . payload as WasmFunctionSectionPayload
68
+
69
+ const typeSection = findSection ( wasmBinary . sections , WasmSectionType . Type )
70
+ const typeSectionPayload : WasmTypeSectionPayload = typeSection . payload as WasmTypeSectionPayload
71
+ const codeSection = findSection ( wasmBinary . sections , WasmSectionType . Code )
72
+ const codeSectionPayload : WasmCodeSectionPayload = codeSection . payload as WasmCodeSectionPayload
73
+ const exportSection = findSection ( wasmBinary . sections , WasmSectionType . Export )
74
+ const exportSectionPayload : WasmExportSectionPayload = exportSection . payload as WasmExportSectionPayload
75
+
76
+ const importSection = findSection ( wasmBinary . sections , WasmSectionType . Import )
77
+ const importSectionPayload : WasmImportSectionPayload = importSection . payload as WasmImportSectionPayload
78
+
79
+ // adding function signatures & name
80
+ for ( let i = 0 ; i < functionSectionPayload . functionsTypes . length ; i ++ ) {
81
+ const fun = functionSectionPayload . functionsTypes [ i ]
82
+ const funCode = codeSectionPayload . functions [ i ]
83
+ const typ = typeSectionPayload . functions [ fun ]
84
+ const signature = printSignature ( i , typ )
85
+ funCode . functionSignature = signature
86
+ funCode . name = `func_${ i } `
87
+ }
88
+ const numOfImports = importSectionPayload . imports . length
89
+ // adding export names to functions
90
+ for ( const exp of exportSectionPayload . exports ) {
91
+ if ( exp . kind !== getExternalType ( WasmExternalKind . Function . toString ( ) ) ) {
92
+ continue
93
+ }
94
+ const index = exp . index - numOfImports
95
+ const fun = codeSectionPayload . functions [ index ]
96
+ fun . exportedName = exp . name
73
97
}
98
+ // formatting opcodes
99
+ for ( const fun of codeSectionPayload . functions ) {
100
+ const formattedOpcodes = formatOpcodes ( fun . opcodes , importSectionPayload , codeSectionPayload )
101
+ fun . formattedOpcodes = formattedOpcodes
102
+ // deleting opcodes for now, not really needed in the response, maybe in the future
103
+ delete fun . opcodes
104
+ }
105
+ return wasmBinary
74
106
}
75
107
76
108
parseSectionPayload ( payload : Buffer , sectionId : number ) : WasmSectionPayload {
@@ -91,7 +123,7 @@ export class WasmBinaryParser {
91
123
const numberOfElements = reader . readVarUint32 ( )
92
124
let index = 0 ;
93
125
while ( index < numberOfElements ) {
94
- const funcType : FuncType = self . parseFuncType ( reader , index )
126
+ const funcType : FuncType = self . parseFuncType ( reader )
95
127
sectionPayload . functions . push ( funcType )
96
128
index ++
97
129
}
@@ -185,13 +217,27 @@ export class WasmBinaryParser {
185
217
return limits
186
218
}
187
219
220
+ parseFunctionSection ( payload : Buffer , self : any ) : WasmFunctionSectionPayload {
221
+ const reader = new BytesReader ( payload )
222
+ const numberOfElements = reader . readVarUint32 ( )
223
+ const functionSection : WasmFunctionSectionPayload = {
224
+ functionsTypes : [ ]
225
+ }
226
+ let functionsCounter = 0
227
+ while ( functionsCounter < numberOfElements ) {
228
+ const functionTypeIndex = reader . readVarUint32 ( )
229
+ functionSection . functionsTypes . push ( functionTypeIndex )
230
+ functionsCounter ++
231
+ }
232
+ return functionSection
233
+ }
234
+
188
235
parseCodeSection ( payload : Buffer , self : any ) : WasmCodeSectionPayload {
189
236
const reader = new BytesReader ( payload )
190
237
const numberOfElements = reader . readVarUint32 ( )
191
238
const codeSection : WasmCodeSectionPayload = {
192
239
functions : [ ]
193
240
}
194
- console . log ( `ParsingCodeSection, noElements=${ numberOfElements } ` )
195
241
let bodiesCounter = 0
196
242
while ( bodiesCounter < numberOfElements ) {
197
243
const functionBody = self . parseFunctionCode ( reader )
@@ -226,12 +272,10 @@ export class WasmBinaryParser {
226
272
const bytecodeBuffer : Buffer = reader . readBytes ( body . length - reader . getPointer ( ) )
227
273
const opcodes : WasmOpcode [ ] = this . parseFunctionBytecode ( bytecodeBuffer )
228
274
const bytecodeHex : string = bytecodeBuffer . toString ( 'hex' )
229
- const formattedOpcodes = formatOpcodes ( opcodes )
230
275
return {
231
276
bytecodeHex,
232
277
locals,
233
- opcodes,
234
- formattedOpcodes
278
+ opcodes
235
279
}
236
280
}
237
281
@@ -246,7 +290,7 @@ export class WasmBinaryParser {
246
290
throw new Error ( `Opcode not implemented: ${ opcodeByte } [${ opcodeByte . toString ( 16 ) } ]` )
247
291
}
248
292
for ( const immediate of opcodeDefinition . immediates ) {
249
- // TODO refactor
293
+ // TODO refactor this shit
250
294
if ( immediate . type === OpcodeImmediateType . U32 ) {
251
295
const immediateValue = reader . readVarUint32 ( )
252
296
const valueFormatted = immediateValue < 0 ? `-0x${ ( immediateValue * - 1 ) . toString ( 16 ) } ` : `0x${ immediateValue . toString ( 16 ) } `
@@ -263,6 +307,18 @@ export class WasmBinaryParser {
263
307
const immediateValue = reader . readBytesToNumber ( 1 )
264
308
const valueFormatted = immediateValue < 0 ? `-0x${ ( immediateValue * - 1 ) . toString ( 16 ) } ` : `0x${ immediateValue . toString ( 16 ) } `
265
309
immediates . push ( valueFormatted )
310
+ } else if ( immediate . type === OpcodeImmediateType . VECTOR_U32 ) {
311
+ const vectorLength = reader . readVarUint32 ( )
312
+ let vectorCounter = 0
313
+ while ( vectorCounter < vectorLength ) {
314
+ const immediateValue = reader . readVarUint32 ( )
315
+ const valueFormatted = immediateValue < 0 ? `-0x${ ( immediateValue * - 1 ) . toString ( 16 ) } ` : `0x${ immediateValue . toString ( 16 ) } `
316
+ immediates . push ( valueFormatted )
317
+ vectorCounter ++
318
+ }
319
+ const defaultTarget = reader . readVarUint32 ( )
320
+ const valueFormatted = defaultTarget < 0 ? `-0x${ ( defaultTarget * - 1 ) . toString ( 16 ) } ` : `0x${ defaultTarget . toString ( 16 ) } `
321
+ immediates . push ( valueFormatted )
266
322
}
267
323
}
268
324
opcodes . push ( {
@@ -273,7 +329,7 @@ export class WasmBinaryParser {
273
329
return opcodes
274
330
}
275
331
276
- parseFuncType ( reader : BytesReader , index : number ) : FuncType {
332
+ parseFuncType ( reader : BytesReader ) : FuncType {
277
333
const typeByte = reader . readBytesToNumber ( 1 )
278
334
if ( typeByte !== WasmType . FunctionType ) {
279
335
throw new Error ( `Error parsing FuncType - type=${ typeByte } not function ` )
@@ -297,7 +353,6 @@ export class WasmBinaryParser {
297
353
resultsCounter ++
298
354
}
299
355
return {
300
- index,
301
356
params,
302
357
results
303
358
}
0 commit comments