52
52
* {@link #createVirtualTable(CategoryPath, String, Address, TaskMonitor)} methods demangle
53
53
* the strings and created tables within a owner/parentage tree based on the demangled information.
54
54
* <p><p>
55
- * The {@link #findVbt(ClassID, List)} and {@link #findVft(ClassID, List)} methods attempt
56
- * to find the VF/VB tables by finding the appropriate node in the tree based upon owner and
57
- * at-times-mismatched parentage information from the user. This mismatch is not necessarily
55
+ * The {@link #findVbt(ClassID, List, Integer )} and {@link #findVft(ClassID, List, Integer )} methods
56
+ * attempt to find the VF/VB tables by finding the appropriate node in the tree based upon owner
57
+ * and at-times-mismatched parentage information from the user. This mismatch is not necessarily
58
58
* the fault of the user, but more due to what parentage is incorporated into the mangled name.
59
59
* <p><p>
60
60
* <B> DESIGN of find mechanism</B>
@@ -127,6 +127,12 @@ public class MsftVxtManager extends VxtManager {
127
127
private Map <ClassID , List <VirtualBaseTable >> vbtsByOwner ;
128
128
private Map <ClassID , List <VirtualFunctionTable >> vftsByOwner ;
129
129
130
+ // A new interim solution using the address order per owner.
131
+ private Map <ClassID , Map <Address , VirtualBaseTable >> vbtByAddressByOwner ;
132
+ private Map <ClassID , Map <Address , VirtualFunctionTable >> vftByAddressByOwner ;
133
+ private Map <ClassID , Map <Integer , VirtualBaseTable >> vbtByPtrOrdinalByOwner ;
134
+ private Map <ClassID , Map <Integer , VirtualFunctionTable >> vftByPtrOrdinalByOwner ;
135
+
130
136
// Used for locating vft and vbt
131
137
// These are explicitly used for storing/retrieving the "program" versions which result from
132
138
// locating and parsing the mangled strings for these tables. It is possible that these
@@ -149,6 +155,10 @@ public MsftVxtManager(ClassTypeManager ctm, Program program) {
149
155
parentageNodeByMangled = new HashMap <>();
150
156
vbtsByOwner = new HashMap <>();
151
157
vftsByOwner = new HashMap <>();
158
+ vbtByAddressByOwner = new HashMap <>();
159
+ vftByAddressByOwner = new HashMap <>();
160
+ vbtByPtrOrdinalByOwner = new HashMap <>();
161
+ vftByPtrOrdinalByOwner = new HashMap <>();
152
162
vbtRoot = new ParentageNode (null );
153
163
vftRoot = new ParentageNode (null );
154
164
vbtsByOwnerParentage = new HashMap <>();
@@ -295,23 +305,63 @@ public VirtualFunctionTable[] getVfts(ClassID owner) {
295
305
* @param parentage the parentage for the desired table. The parentage must start with the
296
306
* parent that contains the pointer to the table and should include the ordered lineage from
297
307
* that class through all of its decendents to the owner, excluding the owner
308
+ * @param ordinal ordinal of table for owner as sorted by address
298
309
* @return the table
299
310
*/
300
- public VirtualBaseTable findVbt (ClassID owner , List <ClassID > parentage ) {
311
+ public VirtualBaseTable findVbt (ClassID owner , List <ClassID > parentage , Integer ordinal ) {
301
312
OwnerParentage op = new OwnerParentage (owner , parentage );
302
313
VirtualBaseTable vbt = vbtsByOwnerParentage .get (op );
303
314
if (vbt != null ) {
304
315
return vbt ;
305
316
}
306
- vbt = searchVbtTree (owner , parentage );
317
+ vbt = getVbtByAddressOrdinal (owner , ordinal );
307
318
if (vbt == null ) {
308
- vbt = new PlaceholderVirtualBaseTable (owner , parentage );
319
+ vbt = searchVbtTree (owner , parentage );
320
+ if (vbt == null ) {
321
+ vbt = new PlaceholderVirtualBaseTable (owner , parentage );
322
+ }
309
323
}
310
324
vbtsByOwnerParentage .put (op , vbt );
311
- storeVbt (owner , vbt );
325
+ storeVbt (owner , ordinal , vbt );
312
326
return vbt ;
313
327
}
314
328
329
+ private VirtualBaseTable getVbtByAddressOrdinal (ClassID owner , Integer ordinal ) {
330
+ if (ordinal == null ) {
331
+ return null ;
332
+ }
333
+ Map <Address , VirtualBaseTable > map = vbtByAddressByOwner .get (owner );
334
+ if (map == null ) {
335
+ return null ;
336
+ }
337
+ int count = 0 ;
338
+ for (Map .Entry <Address , VirtualBaseTable > entry : map .entrySet ()) {
339
+ if (count == ordinal ) {
340
+ return entry .getValue ();
341
+ }
342
+ count ++;
343
+ }
344
+ return null ;
345
+ }
346
+
347
+ private VirtualFunctionTable getVftByAddressOrdinal (ClassID owner , Integer ordinal ) {
348
+ if (ordinal == null ) {
349
+ return null ;
350
+ }
351
+ Map <Address , VirtualFunctionTable > map = vftByAddressByOwner .get (owner );
352
+ if (map == null ) {
353
+ return null ;
354
+ }
355
+ int count = 0 ;
356
+ for (Map .Entry <Address , VirtualFunctionTable > entry : map .entrySet ()) {
357
+ if (count == ordinal ) {
358
+ return entry .getValue ();
359
+ }
360
+ count ++;
361
+ }
362
+ return null ;
363
+ }
364
+
315
365
private VirtualBaseTable searchVbtTree (ClassID owner , List <ClassID > parentage ) {
316
366
ParentageNode node = findNode (owner , parentage , vbtRoot );
317
367
if (node == null ) {
@@ -341,20 +391,24 @@ private VirtualBaseTable searchVbtTree(ClassID owner, List<ClassID> parentage) {
341
391
* @param parentage the parentage for the desired table. The parentage must start with the
342
392
* parent that contains the pointer to the table and should include the ordered lineage from
343
393
* that class through all of its decendents to the owner, excluding the owner
394
+ * @param ordinal ordinal of table for owner as sorted by address
344
395
* @return the table
345
396
*/
346
- public VirtualFunctionTable findVft (ClassID owner , List <ClassID > parentage ) {
397
+ public VirtualFunctionTable findVft (ClassID owner , List <ClassID > parentage , Integer ordinal ) {
347
398
OwnerParentage op = new OwnerParentage (owner , parentage );
348
399
VirtualFunctionTable vft = vftsByOwnerParentage .get (op );
349
400
if (vft != null ) {
350
401
return vft ;
351
402
}
352
- vft = searchVftTree (owner , parentage );
403
+ vft = getVftByAddressOrdinal (owner , ordinal );
353
404
if (vft == null ) {
354
- vft = new PlaceholderVirtualFunctionTable (owner , parentage );
405
+ vft = searchVftTree (owner , parentage );
406
+ if (vft == null ) {
407
+ vft = new PlaceholderVirtualFunctionTable (owner , parentage );
408
+ }
355
409
}
356
410
vftsByOwnerParentage .put (op , vft );
357
- storeVft (owner , vft );
411
+ storeVft (owner , ordinal , vft );
358
412
return vft ;
359
413
}
360
414
@@ -463,7 +517,7 @@ public boolean createVirtualTable(CategoryPath categoryPath, String mangled, Add
463
517
}
464
518
node .setVBTable (prvbt );
465
519
vbtByAddress .put (address , prvbt );
466
- storeVbt (owner , prvbt ); // temp solution?
520
+ storeVbt (owner , address , prvbt ); // temp solution?
467
521
break ;
468
522
469
523
case VFT :
@@ -475,7 +529,7 @@ public boolean createVirtualTable(CategoryPath categoryPath, String mangled, Add
475
529
}
476
530
node .setVFTable (vft );
477
531
vftByAddress .put (address , vft );
478
- storeVft (owner , vft ); // temp solution?
532
+ storeVft (owner , address , vft ); // temp solution?
479
533
break ;
480
534
481
535
default :
@@ -484,9 +538,37 @@ public boolean createVirtualTable(CategoryPath categoryPath, String mangled, Add
484
538
return true ;
485
539
}
486
540
487
- private void storeVbt (ClassID owner , VirtualBaseTable vbt ) {
488
- ClassID own = vbt .getOwner ();
489
- List <VirtualBaseTable > list = vbtsByOwner .get (own );
541
+ private void storeVbt (ClassID owner , Address address , VirtualBaseTable vbt ) {
542
+ List <VirtualBaseTable > list = vbtsByOwner .get (owner );
543
+ if (list == null ) {
544
+ list = new ArrayList <>();
545
+ vbtsByOwner .put (owner , list );
546
+ }
547
+ List <ClassID > parentage = vbt .getParentage ();
548
+ for (VirtualBaseTable table : list ) {
549
+ if (isEqual (table .getParentage (), parentage )) {
550
+ return ; // return without saving
551
+ }
552
+ }
553
+ list .add (vbt );
554
+
555
+ // Part of next interim solution
556
+ Map <Address , VirtualBaseTable > map = vbtByAddressByOwner .get (owner );
557
+ if (map == null ) {
558
+ map = new TreeMap <>();
559
+ vbtByAddressByOwner .put (owner , map );
560
+ }
561
+ if (map .containsKey (address )) {
562
+ Msg .warn (this , String .format ("VBT already exists for owner/address %s/%s" ,
563
+ owner .getSymbolPath ().toString (), address .toString ()));
564
+ return ;
565
+ }
566
+ map .put (address , vbt );
567
+
568
+ }
569
+
570
+ private void storeVbt (ClassID owner , Integer ordinal , VirtualBaseTable vbt ) {
571
+ List <VirtualBaseTable > list = vbtsByOwner .get (owner );
490
572
if (list == null ) {
491
573
list = new ArrayList <>();
492
574
vbtsByOwner .put (owner , list );
@@ -498,9 +580,26 @@ private void storeVbt(ClassID owner, VirtualBaseTable vbt) {
498
580
}
499
581
}
500
582
list .add (vbt );
583
+
584
+ // Part of next interim solution
585
+ if (ordinal == null ) {
586
+ return ;
587
+ }
588
+ Map <Integer , VirtualBaseTable > map = vbtByPtrOrdinalByOwner .get (owner );
589
+ if (map == null ) {
590
+ map = new TreeMap <>();
591
+ vbtByPtrOrdinalByOwner .put (owner , map );
592
+ }
593
+ if (map .containsKey (ordinal )) {
594
+ Msg .warn (this , String .format ("VBT already exists for owner/ordinal %s/%d " ,
595
+ owner .getSymbolPath ().toString (), ordinal ));
596
+ return ;
597
+ }
598
+ map .put (ordinal , vbt );
599
+
501
600
}
502
601
503
- private void storeVft (ClassID owner , VirtualFunctionTable vft ) {
602
+ private void storeVft (ClassID owner , Address address , VirtualFunctionTable vft ) {
504
603
List <VirtualFunctionTable > list = vftsByOwner .get (owner );
505
604
if (list == null ) {
506
605
list = new ArrayList <>();
@@ -513,6 +612,52 @@ private void storeVft(ClassID owner, VirtualFunctionTable vft) {
513
612
}
514
613
}
515
614
list .add (vft );
615
+
616
+ // Part of next interim solution
617
+ Map <Address , VirtualFunctionTable > map = vftByAddressByOwner .get (owner );
618
+ if (map == null ) {
619
+ map = new TreeMap <>();
620
+ vftByAddressByOwner .put (owner , map );
621
+ }
622
+ if (map .containsKey (address )) {
623
+ Msg .warn (this , String .format ("VFT already exists for owner/address %s/%s" ,
624
+ owner .getSymbolPath ().toString (), address .toString ()));
625
+ return ;
626
+ }
627
+ map .put (address , vft );
628
+
629
+ }
630
+
631
+ private void storeVft (ClassID owner , Integer ordinal , VirtualFunctionTable vft ) {
632
+ List <VirtualFunctionTable > list = vftsByOwner .get (owner );
633
+ if (list == null ) {
634
+ list = new ArrayList <>();
635
+ vftsByOwner .put (owner , list );
636
+ }
637
+ List <ClassID > parentage = vft .getParentage ();
638
+ for (VirtualFunctionTable table : list ) {
639
+ if (isEqual (table .getParentage (), parentage )) {
640
+ return ; // return without saving
641
+ }
642
+ }
643
+ list .add (vft );
644
+
645
+ // Part of next interim solution
646
+ if (ordinal == null ) {
647
+ return ;
648
+ }
649
+ Map <Integer , VirtualFunctionTable > map = vftByPtrOrdinalByOwner .get (owner );
650
+ if (map == null ) {
651
+ map = new TreeMap <>();
652
+ vftByPtrOrdinalByOwner .put (owner , map );
653
+ }
654
+ if (map .containsKey (ordinal )) {
655
+ Msg .warn (this , String .format ("VFT already exists for owner/ptrOffset %s/%d" ,
656
+ owner .getSymbolPath ().toString (), ordinal ));
657
+ return ;
658
+ }
659
+ map .put (ordinal , vft );
660
+
516
661
}
517
662
518
663
private boolean isEqual (List <ClassID > parentage1 , List <ClassID > parentage2 ) {
0 commit comments