@@ -305,17 +305,153 @@ private void DeleteRangeFromCache(DisassemblyBlock block)
305
305
}
306
306
}
307
307
308
+ private class DisasmAddressRange
309
+ {
310
+ public ulong StartAddress ;
311
+ public ulong EndAddress ;
312
+ Dictionary < ulong , DisasmInstruction > AddressToInstruction ;
313
+
314
+ public DisasmAddressRange ( DisasmInstruction instruction )
315
+ {
316
+ StartAddress = instruction . Addr ;
317
+ EndAddress = instruction . Addr ;
318
+ AddressToInstruction = new Dictionary < ulong , DisasmInstruction > ( )
319
+ {
320
+ { instruction . Addr , instruction }
321
+ } ;
322
+ }
323
+
324
+ public void UpdateEndAddress ( DisasmInstruction instruction )
325
+ {
326
+ EndAddress = instruction . Addr ;
327
+ AddressToInstruction . Add ( instruction . Addr , instruction ) ;
328
+ }
329
+
330
+ public void MapSourceToInstructions ( DebuggedProcess process , TupleValue [ ] src_and_asm_lines )
331
+ {
332
+ /* Example response
333
+ * [
334
+ * {
335
+ * line="15",
336
+ * file="main.cpp",
337
+ * fullname="/home/cpp/main.cpp",
338
+ * line_asm_insn=[
339
+ * {
340
+ * address="0x0000000008001485",
341
+ * func-name="main(int, char**)",
342
+ * offset="316",
343
+ * opcodes="83 bd 4c ff ff ff 00",
344
+ * inst="cmpl $0x0,-0xb4(%rbp)"
345
+ * },
346
+ * {
347
+ * address="0x000000000800148c",
348
+ * func-name="main(int, char**)",
349
+ * offset="323",
350
+ * opcodes="75 07",
351
+ * inst="jne 0x8001495 <main(int, char**)+332>"
352
+ * }
353
+ * ]
354
+ * }
355
+ * ]
356
+ */
357
+ foreach ( TupleValue src_and_asm_line in src_and_asm_lines )
358
+ {
359
+ uint line = src_and_asm_line . FindUint ( "line" ) ;
360
+ string file = process . GetMappedFileFromTuple ( src_and_asm_line ) ;
361
+ ValueListValue line_asm_instructions = src_and_asm_line . Find < ValueListValue > ( "line_asm_insn" ) ;
362
+ foreach ( ResultValue line_asm_insn in line_asm_instructions . Content )
363
+ {
364
+ ulong address = line_asm_insn . FindAddr ( "address" ) ;
365
+ AddressToInstruction [ address ] . File = file ;
366
+ AddressToInstruction [ address ] . Line = line ;
367
+ }
368
+ }
369
+ }
370
+ }
371
+
308
372
// this is inefficient so we try and grab everything in one gulp
309
373
internal static async Task < DisasmInstruction [ ] > Disassemble ( DebuggedProcess process , ulong startAddr , ulong endAddr )
310
374
{
375
+ // Due to GDB not returning source information when requesting outside of the range of user code.
376
+ // We first get disassembly with opcodes, then map each Symbol to an address range and attempt to retrieve source information per Symbol.
377
+
378
+ // Mode 2 - disassembly with raw opcodes
311
379
string cmd = "-data-disassemble -s " + EngineUtils . AsAddr ( startAddr , process . Is64BitArch ) + " -e " + EngineUtils . AsAddr ( endAddr , process . Is64BitArch ) + " -- 2" ;
312
380
Results results = await process . CmdAsync ( cmd , ResultClass . None ) ;
313
381
if ( results . ResultClass != ResultClass . done )
314
382
{
315
383
return null ;
316
384
}
317
385
318
- return DecodeDisassemblyInstructions ( results . Find < ValueListValue > ( "asm_insns" ) . AsArray < TupleValue > ( ) ) ;
386
+ DisasmInstruction [ ] instructions = DecodeDisassemblyInstructions ( results . Find < ValueListValue > ( "asm_insns" ) . AsArray < TupleValue > ( ) ) ;
387
+
388
+ if ( instructions != null && instructions . Length != 0 )
389
+ {
390
+ // Map 'Symbol' (Function Name) to Address Range
391
+ Dictionary < string , DisasmAddressRange > funcToAddressRange = new Dictionary < string , DisasmAddressRange > ( ) ;
392
+ for ( int i = 0 ; i < instructions . Length ; i ++ )
393
+ {
394
+ string functionName = instructions [ i ] . Symbol ;
395
+ if ( funcToAddressRange . ContainsKey ( functionName ) )
396
+ {
397
+ // Update the end address with this current instruction.
398
+ funcToAddressRange [ functionName ] . UpdateEndAddress ( instructions [ i ] ) ;
399
+ }
400
+ else
401
+ {
402
+ // Insert new function to keep track of.
403
+ funcToAddressRange . Add ( functionName , new DisasmAddressRange ( instructions [ i ] ) ) ;
404
+ }
405
+
406
+ // endAddr will not show up in instructions, so make the last instruction we get to get the range til the end.
407
+ if ( i == instructions . Length - 1 )
408
+ {
409
+ funcToAddressRange [ functionName ] . EndAddress = endAddr ;
410
+ }
411
+ }
412
+
413
+ foreach ( string functionName in funcToAddressRange . Keys )
414
+ {
415
+ DisasmAddressRange range = funcToAddressRange [ functionName ] ;
416
+
417
+ // Mode 5 - mixed source and disassembly with raw opcodes
418
+ cmd = "-data-disassemble -s " + EngineUtils . AsAddr ( range . StartAddress , process . Is64BitArch ) + " -e " + EngineUtils . AsAddr ( range . EndAddress , process . Is64BitArch ) + " -- 5" ;
419
+ results = await process . CmdAsync ( cmd , ResultClass . None ) ;
420
+ if ( results . ResultClass != ResultClass . done )
421
+ {
422
+ return null ;
423
+ }
424
+ try
425
+ {
426
+ /* Example response
427
+ * asm_insns=[
428
+ * src_and_asm_line={
429
+ * line="15",
430
+ * file="main.cpp",
431
+ * fullname="/home/cpp/main.cpp",
432
+ * line_asm_insn=[ ... ]
433
+ * }
434
+ * ]
435
+ */
436
+ ResultListValue asm_insns = results . Find < ResultListValue > ( "asm_insns" ) ;
437
+ if ( asm_insns != null )
438
+ {
439
+ TupleValue [ ] values = asm_insns . FindAll < TupleValue > ( "src_and_asm_line" ) ;
440
+ if ( values != null )
441
+ {
442
+ range . MapSourceToInstructions ( process , values ) ;
443
+ }
444
+ }
445
+ }
446
+ catch
447
+ {
448
+ // asm_insns can be ValueListValue if it does not contain source information.
449
+ }
450
+ }
451
+ }
452
+
453
+
454
+ return instructions ;
319
455
}
320
456
321
457
// this is inefficient so we try and grab everything in one gulp
0 commit comments