Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Hack to workaround weird/unexpected DWARF
[simgrid.git] / src / mc / mc_diff.cpp
1 /* Copyright (c) 2008-2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /* mc_diff - Memory snapshooting and comparison                             */
8
9 #include "src/xbt/ex_interface.h"   /* internals of backtrace setup */
10 #include "xbt/str.h"
11 #include "mc/mc.h"
12 #include "xbt/mmalloc.h"
13 #include "src/mc/mc_object_info.h"
14 #include "mc/datatypes.h"
15 #include "src/mc/mc_private.h"
16 #include "src/mc/mc_snapshot.h"
17 #include "src/mc/mc_dwarf.hpp"
18 #include "src/mc/Type.hpp"
19
20 using simgrid::mc::remote;
21
22 extern "C" {
23
24 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_diff, xbt,
25                                 "Logging specific to mc_diff in mc");
26
27 /*********************************** Heap comparison ***********************************/
28 /***************************************************************************************/
29
30 typedef char *type_name;
31
32 struct XBT_PRIVATE s_mc_diff {
33   s_xbt_mheap_t std_heap_copy;
34   std::size_t heaplimit;
35   // Number of blocks in the heaps:
36   std::size_t heapsize1, heapsize2;
37   std::vector<simgrid::mc::IgnoredHeapRegion>* to_ignore1;
38   std::vector<simgrid::mc::IgnoredHeapRegion>* to_ignore2;
39   s_heap_area_t *equals_to1, *equals_to2;
40   simgrid::mc::Type **types1;
41   simgrid::mc::Type **types2;
42   std::size_t available;
43 };
44
45 #define equals_to1_(i,j) equals_to1[ MAX_FRAGMENT_PER_BLOCK*(i) + (j)]
46 #define equals_to2_(i,j) equals_to2[ MAX_FRAGMENT_PER_BLOCK*(i) + (j)]
47 #define types1_(i,j) types1[ MAX_FRAGMENT_PER_BLOCK*(i) + (j)]
48 #define types2_(i,j) types2[ MAX_FRAGMENT_PER_BLOCK*(i) + (j)]
49
50 static __thread struct s_mc_diff *mc_diff_info = nullptr;
51
52 /*********************************** Free functions ************************************/
53
54 static void heap_area_pair_free(heap_area_pair_t pair)
55 {
56   xbt_free(pair);
57   pair = NULL;
58 }
59
60 static void heap_area_pair_free_voidp(void *d)
61 {
62   heap_area_pair_free((heap_area_pair_t) * (void **) d);
63 }
64
65 static void heap_area_free(heap_area_t area)
66 {
67   xbt_free(area);
68   area = NULL;
69 }
70
71 /************************************************************************************/
72
73 static s_heap_area_t make_heap_area(int block, int fragment)
74 {
75   s_heap_area_t area;
76   area.valid = 1;
77   area.block = block;
78   area.fragment = fragment;
79   return area;
80 }
81
82
83 static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1,
84                                  int block2, int fragment2)
85 {
86
87   unsigned int cursor = 0;
88   heap_area_pair_t current_pair;
89
90   xbt_dynar_foreach(list, cursor, current_pair) {
91     if (current_pair->block1 == block1 && current_pair->block2 == block2
92         && current_pair->fragment1 == fragment1
93         && current_pair->fragment2 == fragment2)
94       return 0;
95   }
96
97   return 1;
98 }
99
100 static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1,
101                               int block2, int fragment2)
102 {
103
104   if (is_new_heap_area_pair(list, block1, fragment1, block2, fragment2)) {
105     heap_area_pair_t pair = NULL;
106     pair = xbt_new0(s_heap_area_pair_t, 1);
107     pair->block1 = block1;
108     pair->fragment1 = fragment1;
109     pair->block2 = block2;
110     pair->fragment2 = fragment2;
111
112     xbt_dynar_push(list, &pair);
113
114     return 1;
115   }
116
117   return 0;
118 }
119
120 static ssize_t heap_comparison_ignore_size(
121   std::vector<simgrid::mc::IgnoredHeapRegion>* ignore_list,
122   const void *address)
123 {
124   int start = 0;
125   int end = ignore_list->size() - 1;
126
127   while (start <= end) {
128     unsigned int cursor = (start + end) / 2;
129     simgrid::mc::IgnoredHeapRegion const& region = (*ignore_list)[cursor];
130     if (region.address == address)
131       return region.size;
132     if (region.address < address)
133       start = cursor + 1;
134     if (region.address > address)
135       end = cursor - 1;
136   }
137
138   return -1;
139 }
140
141 static bool is_stack(const void *address)
142 {
143   for (auto const& stack : mc_model_checker->process().stack_areas())
144     if (address == stack.address)
145       return true;
146   return false;
147 }
148
149 // TODO, this should depend on the snapshot?
150 static bool is_block_stack(int block)
151 {
152   for (auto const& stack : mc_model_checker->process().stack_areas())
153     if (block == stack.block)
154       return true;
155   return false;
156 }
157
158 static void match_equals(struct s_mc_diff *state, xbt_dynar_t list)
159 {
160
161   unsigned int cursor = 0;
162   heap_area_pair_t current_pair;
163
164   xbt_dynar_foreach(list, cursor, current_pair) {
165
166     if (current_pair->fragment1 != -1) {
167
168       state->equals_to1_(current_pair->block1, current_pair->fragment1) =
169           make_heap_area(current_pair->block2, current_pair->fragment2);
170       state->equals_to2_(current_pair->block2, current_pair->fragment2) =
171           make_heap_area(current_pair->block1, current_pair->fragment1);
172
173     } else {
174
175       state->equals_to1_(current_pair->block1, 0) =
176           make_heap_area(current_pair->block2, current_pair->fragment2);
177       state->equals_to2_(current_pair->block2, 0) =
178           make_heap_area(current_pair->block1, current_pair->fragment1);
179
180     }
181
182   }
183 }
184
185 /** Check whether two blocks are known to be matching
186  *
187  *  @param state  State used
188  *  @param b1     Block of state 1
189  *  @param b2     Block of state 2
190  *  @return       if the blocks are known to be matching
191  */
192 static int equal_blocks(struct s_mc_diff *state, int b1, int b2)
193 {
194
195   if (state->equals_to1_(b1, 0).block == b2
196       && state->equals_to2_(b2, 0).block == b1)
197     return 1;
198
199   return 0;
200 }
201
202 /** Check whether two fragments are known to be matching
203  *
204  *  @param state  State used
205  *  @param b1     Block of state 1
206  *  @param f1     Fragment of state 1
207  *  @param b2     Block of state 2
208  *  @param f2     Fragment of state 2
209  *  @return       if the fragments are known to be matching
210  */
211 static int equal_fragments(struct s_mc_diff *state, int b1, int f1, int b2,
212                            int f2)
213 {
214
215   if (state->equals_to1_(b1, f1).block == b2
216       && state->equals_to1_(b1, f1).fragment == f2
217       && state->equals_to2_(b2, f2).block == b1
218       && state->equals_to2_(b2, f2).fragment == f1)
219     return 1;
220
221   return 0;
222 }
223
224 }
225
226 int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2,
227                           std::vector<simgrid::mc::IgnoredHeapRegion>* i1,
228                           std::vector<simgrid::mc::IgnoredHeapRegion>* i2)
229 {
230   if (mc_diff_info == NULL) {
231     mc_diff_info = xbt_new0(struct s_mc_diff, 1);
232     mc_diff_info->equals_to1 = NULL;
233     mc_diff_info->equals_to2 = NULL;
234     mc_diff_info->types1 = NULL;
235     mc_diff_info->types2 = NULL;
236   }
237   struct s_mc_diff *state = mc_diff_info;
238
239   if ((((struct mdesc *) heap1)->heaplimit !=
240        ((struct mdesc *) heap2)->heaplimit)
241       ||
242       ((((struct mdesc *) heap1)->heapsize !=
243         ((struct mdesc *) heap2)->heapsize)))
244     return -1;
245
246   state->heaplimit = ((struct mdesc *) heap1)->heaplimit;
247   
248   state->std_heap_copy = *mc_model_checker->process().get_heap();
249
250   state->heapsize1 = heap1->heapsize;
251   state->heapsize2 = heap2->heapsize;
252
253   state->to_ignore1 = i1;
254   state->to_ignore2 = i2;
255
256   if (state->heaplimit > state->available) {
257     state->equals_to1 = (s_heap_area_t*)
258         realloc(state->equals_to1,
259                 state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
260                 sizeof(s_heap_area_t));
261     state->types1 = (simgrid::mc::Type**)
262         realloc(state->types1,
263                 state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
264                 sizeof(simgrid::mc::Type*));
265     state->equals_to2 = (s_heap_area_t*)
266         realloc(state->equals_to2,
267                 state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
268                 sizeof(s_heap_area_t));
269     state->types2 = (simgrid::mc::Type**)
270         realloc(state->types2,
271                 state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
272                 sizeof(simgrid::mc::Type*));
273     state->available = state->heaplimit;
274   }
275
276   memset(state->equals_to1, 0,
277          state->heaplimit * MAX_FRAGMENT_PER_BLOCK * sizeof(s_heap_area_t));
278   memset(state->equals_to2, 0,
279          state->heaplimit * MAX_FRAGMENT_PER_BLOCK * sizeof(s_heap_area_t));
280   memset(state->types1, 0,
281          state->heaplimit * MAX_FRAGMENT_PER_BLOCK * sizeof(type_name *));
282   memset(state->types2, 0,
283          state->heaplimit * MAX_FRAGMENT_PER_BLOCK * sizeof(type_name *));
284
285   return 0;
286
287 }
288
289 extern "C" {
290
291 void reset_heap_information()
292 {
293
294 }
295
296 // TODO, have a robust way to find it in O(1)
297 static inline
298 mc_mem_region_t MC_get_heap_region(mc_snapshot_t snapshot)
299 {
300   size_t n = snapshot->snapshot_regions.size();
301   for (size_t i=0; i!=n; ++i) {
302     mc_mem_region_t region = snapshot->snapshot_regions[i].get();
303     if (region->region_type() == simgrid::mc::RegionType::Heap)
304       return region;
305   }
306   xbt_die("No heap region");
307 }
308
309 int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
310 {
311   simgrid::mc::Process* process = &mc_model_checker->process();
312   struct s_mc_diff *state = mc_diff_info;
313
314   /* Start comparison */
315   size_t i1, i2, j1, j2, k;
316   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
317   int nb_diff1 = 0, nb_diff2 = 0;
318
319   int equal, res_compare = 0;
320
321   /* Check busy blocks */
322
323   i1 = 1;
324
325   malloc_info heapinfo_temp1, heapinfo_temp2;
326   malloc_info heapinfo_temp2b;
327
328   mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
329   mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
330
331   // This is the address of std_heap->heapinfo in the application process:
332   void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
333
334   // This is in snapshot do not use them directly:
335   const malloc_info* heapinfos1 = snapshot1->read<malloc_info*>(
336     (std::uint64_t)heapinfo_address, simgrid::mc::ProcessIndexMissing);
337   const malloc_info* heapinfos2 = snapshot2->read<malloc_info*>(
338     (std::uint64_t)heapinfo_address, simgrid::mc::ProcessIndexMissing);
339
340   while (i1 < state->heaplimit) {
341
342     const malloc_info* heapinfo1 = (const malloc_info*) MC_region_read(heap_region1, &heapinfo_temp1, &heapinfos1[i1], sizeof(malloc_info));
343     const malloc_info* heapinfo2 = (const malloc_info*) MC_region_read(heap_region2, &heapinfo_temp2, &heapinfos2[i1], sizeof(malloc_info));
344
345     if (heapinfo1->type == MMALLOC_TYPE_FREE || heapinfo1->type == MMALLOC_TYPE_HEAPINFO) {      /* Free block */
346       i1 ++;
347       continue;
348     }
349
350     if (heapinfo1->type < 0) {
351       fprintf(stderr, "Unkown mmalloc block type.\n");
352       abort();
353     }
354
355     addr_block1 =
356         ((void *) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE +
357                    (char *) state->std_heap_copy.heapbase));
358
359     if (heapinfo1->type == MMALLOC_TYPE_UNFRAGMENTED) {       /* Large block */
360
361       if (is_stack(addr_block1)) {
362         for (k = 0; k < heapinfo1->busy_block.size; k++)
363           state->equals_to1_(i1 + k, 0) = make_heap_area(i1, -1);
364         for (k = 0; k < heapinfo2->busy_block.size; k++)
365           state->equals_to2_(i1 + k, 0) = make_heap_area(i1, -1);
366         i1 += heapinfo1->busy_block.size;
367         continue;
368       }
369
370       if (state->equals_to1_(i1, 0).valid) {
371         i1++;
372         continue;
373       }
374
375       i2 = 1;
376       equal = 0;
377       res_compare = 0;
378
379       /* Try first to associate to same block in the other heap */
380       if (heapinfo2->type == heapinfo1->type) {
381
382         if (state->equals_to2_(i1, 0).valid == 0) {
383
384           addr_block2 = (ADDR2UINT(i1) - 1) * BLOCKSIZE +
385                          (char *) state->std_heap_copy.heapbase;
386
387           res_compare =
388               compare_heap_area(simgrid::mc::ProcessIndexMissing, addr_block1, addr_block2, snapshot1, snapshot2,
389                                 NULL, NULL, 0);
390
391           if (res_compare != 1) {
392             for (k = 1; k < heapinfo2->busy_block.size; k++)
393               state->equals_to2_(i1 + k, 0) = make_heap_area(i1, -1);
394             for (k = 1; k < heapinfo1->busy_block.size; k++)
395               state->equals_to1_(i1 + k, 0) = make_heap_area(i1, -1);
396             equal = 1;
397             i1 += heapinfo1->busy_block.size;
398           }
399
400         }
401
402       }
403
404       while (i2 < state->heaplimit && !equal) {
405
406         addr_block2 = (ADDR2UINT(i2) - 1) * BLOCKSIZE +
407                        (char *) state->std_heap_copy.heapbase;
408
409         if (i2 == i1) {
410           i2++;
411           continue;
412         }
413
414         const malloc_info* heapinfo2b = (const malloc_info*) MC_region_read(heap_region2, &heapinfo_temp2b, &heapinfos2[i2], sizeof(malloc_info));
415
416         if (heapinfo2b->type != MMALLOC_TYPE_UNFRAGMENTED) {
417           i2++;
418           continue;
419         }
420
421         if (state->equals_to2_(i2, 0).valid) {
422           i2++;
423           continue;
424         }
425
426         res_compare =
427             compare_heap_area(simgrid::mc::ProcessIndexMissing, addr_block1, addr_block2, snapshot1, snapshot2,
428                               NULL, NULL, 0);
429
430         if (res_compare != 1) {
431           for (k = 1; k < heapinfo2b->busy_block.size; k++)
432             state->equals_to2_(i2 + k, 0) = make_heap_area(i1, -1);
433           for (k = 1; k < heapinfo1->busy_block.size; k++)
434             state->equals_to1_(i1 + k, 0) = make_heap_area(i2, -1);
435           equal = 1;
436           i1 += heapinfo1->busy_block.size;
437         }
438
439         i2++;
440
441       }
442
443       if (!equal) {
444         XBT_DEBUG("Block %zu not found (size_used = %zu, addr = %p)", i1,
445                   heapinfo1->busy_block.busy_size, addr_block1);
446         i1 = state->heaplimit + 1;
447         nb_diff1++;
448         //i1++;
449       }
450
451     } else {                    /* Fragmented block */
452
453       for (j1 = 0; j1 < (size_t) (BLOCKSIZE >> heapinfo1->type); j1++) {
454
455         if (heapinfo1->busy_frag.frag_size[j1] == -1) /* Free fragment */
456           continue;
457
458         if (state->equals_to1_(i1, j1).valid)
459           continue;
460
461         addr_frag1 =
462             (void *) ((char *) addr_block1 + (j1 << heapinfo1->type));
463
464         i2 = 1;
465         equal = 0;
466
467         /* Try first to associate to same fragment in the other heap */
468         if (heapinfo2->type == heapinfo1->type) {
469
470           if (state->equals_to2_(i1, j1).valid == 0) {
471
472             addr_block2 = (ADDR2UINT(i1) - 1) * BLOCKSIZE +
473                            (char *) state->std_heap_copy.heapbase;
474             addr_frag2 =
475                 (void *) ((char *) addr_block2 +
476                           (j1 << heapinfo2->type));
477
478             res_compare =
479                 compare_heap_area(simgrid::mc::ProcessIndexMissing, addr_frag1, addr_frag2, snapshot1, snapshot2,
480                                   NULL, NULL, 0);
481
482             if (res_compare != 1)
483               equal = 1;
484
485           }
486
487         }
488
489         while (i2 < state->heaplimit && !equal) {
490
491           const malloc_info* heapinfo2b = (const malloc_info*) MC_region_read(
492             heap_region2, &heapinfo_temp2b, &heapinfos2[i2],
493             sizeof(malloc_info));
494
495           if (heapinfo2b->type == MMALLOC_TYPE_FREE || heapinfo2b->type == MMALLOC_TYPE_HEAPINFO) {
496             i2 ++;
497             continue;
498           }
499
500           // We currently do not match fragments with unfragmented blocks (maybe we should).
501           if (heapinfo2b->type == MMALLOC_TYPE_UNFRAGMENTED) {
502             i2++;
503             continue;
504           }
505
506           if (heapinfo2b->type < 0) {
507             fprintf(stderr, "Unkown mmalloc block type.\n");
508             abort();
509           }
510
511           for (j2 = 0; j2 < (size_t) (BLOCKSIZE >> heapinfo2b->type);
512                j2++) {
513
514             if (i2 == i1 && j2 == j1)
515               continue;
516
517             if (state->equals_to2_(i2, j2).valid)
518               continue;
519
520             addr_block2 = (ADDR2UINT(i2) - 1) * BLOCKSIZE +
521                            (char *) state->std_heap_copy.heapbase;
522             addr_frag2 =
523                 (void *) ((char *) addr_block2 +
524                           (j2 << heapinfo2b->type));
525
526             res_compare =
527                 compare_heap_area(simgrid::mc::ProcessIndexMissing, addr_frag1, addr_frag2, snapshot2, snapshot2,
528                                   NULL, NULL, 0);
529
530             if (res_compare != 1) {
531               equal = 1;
532               break;
533             }
534
535           }
536
537           i2++;
538
539         }
540
541         if (!equal) {
542           XBT_DEBUG
543               ("Block %zu, fragment %zu not found (size_used = %zd, address = %p)\n",
544                i1, j1, heapinfo1->busy_frag.frag_size[j1],
545                addr_frag1);
546           i2 = state->heaplimit + 1;
547           i1 = state->heaplimit + 1;
548           nb_diff1++;
549           break;
550         }
551
552       }
553
554       i1++;
555
556     }
557
558   }
559
560   /* All blocks/fragments are equal to another block/fragment ? */
561   size_t i = 1, j = 0;
562
563   for(i = 1; i < state->heaplimit; i++) {
564     const malloc_info* heapinfo1 = (const malloc_info*) MC_region_read(
565       heap_region1, &heapinfo_temp1, &heapinfos1[i], sizeof(malloc_info));
566     if (heapinfo1->type == MMALLOC_TYPE_UNFRAGMENTED) {
567       if (i1 == state->heaplimit) {
568         if (heapinfo1->busy_block.busy_size > 0) {
569           if (state->equals_to1_(i, 0).valid == 0) {
570             if (XBT_LOG_ISENABLED(mc_diff, xbt_log_priority_debug)) {
571               // TODO, add address
572               XBT_DEBUG("Block %zu not found (size used = %zu)", i,
573                         heapinfo1->busy_block.busy_size);
574               //mmalloc_backtrace_block_display((void*)heapinfo1, i);
575             }
576             nb_diff1++;
577           }
578         }
579       }
580     }
581     if (heapinfo1->type > 0) {
582       for (j = 0; j < (size_t) (BLOCKSIZE >> heapinfo1->type); j++) {
583         if (i1 == state->heaplimit) {
584           if (heapinfo1->busy_frag.frag_size[j] > 0) {
585             if (state->equals_to1_(i, j).valid == 0) {
586               if (XBT_LOG_ISENABLED(mc_diff, xbt_log_priority_debug)) {
587                 // TODO, print fragment address
588                 XBT_DEBUG
589                     ("Block %zu, Fragment %zu not found (size used = %zd)",
590                      i, j,
591                      heapinfo1->busy_frag.frag_size[j]);
592                 //mmalloc_backtrace_fragment_display((void*)heapinfo1, i, j);
593               }
594               nb_diff1++;
595             }
596           }
597         }
598       }
599     }
600   }
601
602   if (i1 == state->heaplimit)
603     XBT_DEBUG("Number of blocks/fragments not found in heap1 : %d", nb_diff1);
604
605   for (i=1; i < state->heaplimit; i++) {
606     const malloc_info* heapinfo2 = (const malloc_info*) MC_region_read(
607       heap_region2, &heapinfo_temp2, &heapinfos2[i], sizeof(malloc_info));
608     if (heapinfo2->type == MMALLOC_TYPE_UNFRAGMENTED) {
609       if (i1 == state->heaplimit) {
610         if (heapinfo2->busy_block.busy_size > 0) {
611           if (state->equals_to2_(i, 0).valid == 0) {
612             if (XBT_LOG_ISENABLED(mc_diff, xbt_log_priority_debug)) {
613               // TODO, print address of the block
614               XBT_DEBUG("Block %zu not found (size used = %zu)", i,
615                         heapinfo2->busy_block.busy_size);
616               //mmalloc_backtrace_block_display((void*)heapinfo2, i);
617             }
618             nb_diff2++;
619           }
620         }
621       }
622     }
623     if (heapinfo2->type > 0) {
624       for (j = 0; j < (size_t) (BLOCKSIZE >> heapinfo2->type); j++) {
625         if (i1 == state->heaplimit) {
626           if (heapinfo2->busy_frag.frag_size[j] > 0) {
627             if (state->equals_to2_(i, j).valid == 0) {
628               if (XBT_LOG_ISENABLED(mc_diff, xbt_log_priority_debug)) {
629                 // TODO, print address of the block
630                 XBT_DEBUG
631                     ("Block %zu, Fragment %zu not found (size used = %zd)",
632                      i, j,
633                      heapinfo2->busy_frag.frag_size[j]);
634                 //mmalloc_backtrace_fragment_display((void*)heapinfo2, i, j);
635               }
636               nb_diff2++;
637             }
638           }
639         }
640       }
641     }
642   }
643
644   if (i1 == state->heaplimit)
645     XBT_DEBUG("Number of blocks/fragments not found in heap2 : %d", nb_diff2);
646
647   return ((nb_diff1 > 0) || (nb_diff2 > 0));
648 }
649
650 /**
651  *
652  * @param state
653  * @param real_area1     Process address for state 1
654  * @param real_area2     Process address for state 2
655  * @param snapshot1      Snapshot of state 1
656  * @param snapshot2      Snapshot of state 2
657  * @param previous
658  * @param size
659  * @param check_ignore
660  */
661 static int compare_heap_area_without_type(struct s_mc_diff *state, int process_index,
662                                           const void *real_area1, const void *real_area2,
663                                           mc_snapshot_t snapshot1,
664                                           mc_snapshot_t snapshot2,
665                                           xbt_dynar_t previous, int size,
666                                           int check_ignore)
667 {
668   simgrid::mc::Process* process = &mc_model_checker->process();
669
670   int i = 0;
671   const void *addr_pointed1, *addr_pointed2;
672   int pointer_align, res_compare;
673   ssize_t ignore1, ignore2;
674
675   mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
676   mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
677
678   while (i < size) {
679
680     if (check_ignore > 0) {
681       if ((ignore1 =
682            heap_comparison_ignore_size(state->to_ignore1,
683                                        (char *) real_area1 + i)) != -1) {
684         if ((ignore2 =
685              heap_comparison_ignore_size(state->to_ignore2,
686                                          (char *) real_area2 + i)) == ignore1) {
687           if (ignore1 == 0) {
688             check_ignore--;
689             return 0;
690           } else {
691             i = i + ignore2;
692             check_ignore--;
693             continue;
694           }
695         }
696       }
697     }
698
699     if (MC_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
700
701       pointer_align = (i / sizeof(void *)) * sizeof(void *);
702       addr_pointed1 = snapshot1->read(
703         remote((void**)((char *) real_area1 + pointer_align)), process_index);
704       addr_pointed2 = snapshot2->read(
705         remote((void**)((char *) real_area2 + pointer_align)), process_index);
706
707       if (process->in_maestro_stack(remote(addr_pointed1))
708         && process->in_maestro_stack(remote(addr_pointed2))) {
709         i = pointer_align + sizeof(void *);
710         continue;
711       } else if (addr_pointed1 > state->std_heap_copy.heapbase
712                  && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
713                  && addr_pointed2 > state->std_heap_copy.heapbase
714                  && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)) {
715         // Both addreses are in the heap:
716         res_compare =
717             compare_heap_area(process_index, addr_pointed1, addr_pointed2, snapshot1,
718                               snapshot2, previous, NULL, 0);
719         if (res_compare == 1) {
720           return res_compare;
721         }
722         i = pointer_align + sizeof(void *);
723         continue;
724       } else {
725         return 1;
726       }
727
728     }
729
730     i++;
731
732   }
733
734   return 0;
735
736 }
737
738 /**
739  *
740  * @param state
741  * @param real_area1     Process address for state 1
742  * @param real_area2     Process address for state 2
743  * @param snapshot1      Snapshot of state 1
744  * @param snapshot2      Snapshot of state 2
745  * @param previous
746  * @param type_id
747  * @param area_size      either a byte_size or an elements_count (?)
748  * @param check_ignore
749  * @param pointer_level
750  * @return               0 (same), 1 (different), -1 (unknown)
751  */
752 static int compare_heap_area_with_type(struct s_mc_diff *state, int process_index,
753                                        const void *real_area1, const void *real_area2,
754                                        mc_snapshot_t snapshot1,
755                                        mc_snapshot_t snapshot2,
756                                        xbt_dynar_t previous, simgrid::mc::Type* type,
757                                        int area_size, int check_ignore,
758                                        int pointer_level)
759 {
760 top:
761   // HACK: This should not happen but in pratice, there is some
762   // DW_TAG_typedef without DW_AT_type. We should fix this somehow.
763   if (type == nullptr)
764     return 0;
765
766   if (is_stack(real_area1) && is_stack(real_area2))
767     return 0;
768   ssize_t ignore1, ignore2;
769
770   if ((check_ignore > 0)
771       && ((ignore1 = heap_comparison_ignore_size(state->to_ignore1, real_area1))
772           > 0)
773       && ((ignore2 = heap_comparison_ignore_size(state->to_ignore2, real_area2))
774           == ignore1)) {
775     return 0;
776   }
777
778   simgrid::mc::Type *subtype, *subsubtype;
779   int res, elm_size;
780   const void *addr_pointed1, *addr_pointed2;
781
782   mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
783   mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
784
785   switch (type->type) {
786   case DW_TAG_unspecified_type:
787     return 1;
788
789   case DW_TAG_base_type:
790     if (!type->name.empty() && type->name == "char") {        /* String, hence random (arbitrary ?) size */
791       if (real_area1 == real_area2)
792         return -1;
793       else
794         return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0);
795     } else {
796       if (area_size != -1 && type->byte_size != area_size)
797         return -1;
798       else {
799         return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
800       }
801     }
802     break;
803   case DW_TAG_enumeration_type:
804     if (area_size != -1 && type->byte_size != area_size)
805       return -1;
806     else
807       return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
808     break;
809   case DW_TAG_typedef:
810   case DW_TAG_const_type:
811   case DW_TAG_volatile_type:
812     // Poor man's TCO:
813     type = type->subtype;
814     goto top;
815     break;
816   case DW_TAG_array_type:
817     subtype = type->subtype;
818     switch (subtype->type) {
819     case DW_TAG_unspecified_type:
820       return 1;
821
822     case DW_TAG_base_type:
823     case DW_TAG_enumeration_type:
824     case DW_TAG_pointer_type:
825     case DW_TAG_reference_type:
826     case DW_TAG_rvalue_reference_type:
827     case DW_TAG_structure_type:
828     case DW_TAG_class_type:
829     case DW_TAG_union_type:
830       if (subtype->full_type)
831         subtype = subtype->full_type;
832       elm_size = subtype->byte_size;
833       break;
834       // TODO, just remove the type indirection?
835     case DW_TAG_const_type:
836     case DW_TAG_typedef:
837     case DW_TAG_volatile_type:
838       subsubtype = subtype->subtype;
839       if (subsubtype->full_type)
840         subsubtype = subsubtype->full_type;
841       elm_size = subsubtype->byte_size;
842       break;
843     default:
844       return 0;
845       break;
846     }
847     for (int i = 0; i < type->element_count; i++) {
848       // TODO, add support for variable stride (DW_AT_byte_stride)
849       res =
850           compare_heap_area_with_type(state, process_index,
851                                       (char *) real_area1 + (i * elm_size),
852                                       (char *) real_area2 + (i * elm_size),
853                                       snapshot1, snapshot2, previous,
854                                       type->subtype, subtype->byte_size,
855                                       check_ignore, pointer_level);
856       if (res == 1)
857         return res;
858     }
859     break;
860   case DW_TAG_reference_type:
861   case DW_TAG_rvalue_reference_type:
862   case DW_TAG_pointer_type:
863     if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
864       addr_pointed1 = snapshot1->read(remote((void**)real_area1), process_index);
865       addr_pointed2 = snapshot2->read(remote((void**)real_area2), process_index);
866       return (addr_pointed1 != addr_pointed2);;
867     } else {
868       pointer_level++;
869       if (pointer_level > 1) {  /* Array of pointers */
870         for (size_t i = 0; i < (area_size / sizeof(void *)); i++) {
871           addr_pointed1 = snapshot1->read(
872             remote((void**)((char*) real_area1 + i * sizeof(void *))),
873             process_index);
874           addr_pointed2 = snapshot2->read(
875             remote((void**)((char*) real_area2 + i * sizeof(void *))),
876             process_index);
877           if (addr_pointed1 > state->std_heap_copy.heapbase
878               && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
879               && addr_pointed2 > state->std_heap_copy.heapbase
880               && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
881             res =
882                 compare_heap_area(process_index, addr_pointed1, addr_pointed2, snapshot1,
883                                   snapshot2, previous, type->subtype,
884                                   pointer_level);
885           else
886             res = (addr_pointed1 != addr_pointed2);
887           if (res == 1)
888             return res;
889         }
890       } else {
891         addr_pointed1 = snapshot1->read(remote((void**)real_area1), process_index);
892         addr_pointed2 = snapshot2->read(remote((void**)real_area2), process_index);
893         if (addr_pointed1 > state->std_heap_copy.heapbase
894             && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
895             && addr_pointed2 > state->std_heap_copy.heapbase
896             && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
897           return compare_heap_area(process_index, addr_pointed1, addr_pointed2, snapshot1,
898                                    snapshot2, previous, type->subtype,
899                                    pointer_level);
900         else
901           return (addr_pointed1 != addr_pointed2);
902       }
903     }
904     break;
905   case DW_TAG_structure_type:
906   case DW_TAG_class_type:
907     if (type->full_type)
908       type = type->full_type;
909     if (area_size != -1 && type->byte_size != area_size) {
910       if (area_size > type->byte_size && area_size % type->byte_size == 0) {
911         for (size_t i = 0; i < (size_t)(area_size / type->byte_size); i++) {
912           res =
913               compare_heap_area_with_type(state, process_index,
914                                           (char *) real_area1 + i * type->byte_size,
915                                           (char *) real_area2 + i * type->byte_size,
916                                           snapshot1, snapshot2, previous, type, -1,
917                                           check_ignore, 0);
918           if (res == 1)
919             return res;
920         }
921       } else {
922         return -1;
923       }
924     } else {
925       for(simgrid::mc::Member& member : type->members) {
926         // TODO, optimize this? (for the offset case)
927         void *real_member1 = simgrid::dwarf::resolve_member(
928           real_area1, type, &member, (simgrid::mc::AddressSpace*) snapshot1, process_index);
929         void *real_member2 = simgrid::dwarf::resolve_member(
930             real_area2, type, &member, (simgrid::mc::AddressSpace*) snapshot2, process_index);
931         res =
932           compare_heap_area_with_type(state, process_index, real_member1, real_member2,
933                                         snapshot1, snapshot2,
934                                         previous, member.type, -1,
935                                         check_ignore, 0);
936         if (res == 1) {
937           return res;
938         }
939       }
940     }
941     break;
942   case DW_TAG_union_type:
943     return compare_heap_area_without_type(state, process_index, real_area1, real_area2,
944                                           snapshot1, snapshot2, previous,
945                                           type->byte_size, check_ignore);
946     break;
947   default:
948     break;
949   }
950
951   return 0;
952
953 }
954
955 /** Infer the type of a part of the block from the type of the block
956  *
957  * TODO, handle DW_TAG_array_type as well as arrays of the object ((*p)[5], p[5])
958  *
959  * TODO, handle subfields ((*p).bar.foo, (*p)[5].bar…)
960  *
961  * @param  type_id            DWARF type ID of the root address
962  * @param  area_size
963  * @return                    DWARF type ID for given offset
964  */
965 static simgrid::mc::Type* get_offset_type(void *real_base_address, simgrid::mc::Type* type,
966                                  int offset, int area_size,
967                                  mc_snapshot_t snapshot, int process_index)
968 {
969
970   // Beginning of the block, the infered variable type if the type of the block:
971   if (offset == 0)
972     return type;
973
974   switch (type->type) {
975   case DW_TAG_structure_type:
976   case DW_TAG_class_type:
977     if (type->full_type)
978       type = type->full_type;
979
980     if (area_size != -1 && type->byte_size != area_size) {
981       if (area_size > type->byte_size && area_size % type->byte_size == 0)
982         return type;
983       else
984         return NULL;
985     } else {
986       for(simgrid::mc::Member& member : type->members) {
987
988         if (member.has_offset_location()) {
989           // We have the offset, use it directly (shortcut):
990           if (member.offset() == offset)
991             return member.type;
992         } else {
993           void *real_member = simgrid::dwarf::resolve_member(
994             real_base_address, type, &member, snapshot, process_index);
995           if ((char*) real_member - (char *) real_base_address == offset)
996             return member.type;
997         }
998
999       }
1000       return NULL;
1001     }
1002     break;
1003   default:
1004     /* FIXME : other cases ? */
1005     return NULL;
1006     break;
1007   }
1008 }
1009
1010 /**
1011  *
1012  * @param area1          Process address for state 1
1013  * @param area2          Process address for state 2
1014  * @param snapshot1      Snapshot of state 1
1015  * @param snapshot2      Snapshot of state 2
1016  * @param previous       Pairs of blocks already compared on the current path (or NULL)
1017  * @param type_id        Type of variable
1018  * @param pointer_level
1019  * @return 0 (same), 1 (different), -1
1020  */
1021 int compare_heap_area(int process_index, const void *area1, const void *area2, mc_snapshot_t snapshot1,
1022                       mc_snapshot_t snapshot2, xbt_dynar_t previous,
1023                       simgrid::mc::Type* type, int pointer_level)
1024 {
1025   simgrid::mc::Process* process = &mc_model_checker->process();
1026
1027   struct s_mc_diff *state = mc_diff_info;
1028
1029   int res_compare;
1030   ssize_t block1, frag1, block2, frag2;
1031   ssize_t size;
1032   int check_ignore = 0;
1033
1034   void *real_addr_block1, *real_addr_block2, *real_addr_frag1, *real_addr_frag2;
1035   int type_size = -1;
1036   int offset1 = 0, offset2 = 0;
1037   int new_size1 = -1, new_size2 = -1;
1038   simgrid::mc::Type *new_type1 = NULL, *new_type2 = NULL;
1039
1040   int match_pairs = 0;
1041
1042   // This is the address of std_heap->heapinfo in the application process:
1043   void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
1044
1045   const malloc_info* heapinfos1 = snapshot1->read(
1046     remote((const malloc_info**)heapinfo_address), process_index);
1047   const malloc_info* heapinfos2 = snapshot2->read(
1048     remote((const malloc_info**)heapinfo_address), process_index);
1049
1050   malloc_info heapinfo_temp1, heapinfo_temp2;
1051
1052   if (previous == NULL) {
1053     previous =
1054         xbt_dynar_new(sizeof(heap_area_pair_t), heap_area_pair_free_voidp);
1055     match_pairs = 1;
1056   }
1057   // Get block number:
1058   block1 =
1059       ((char *) area1 -
1060        (char *) state->std_heap_copy.heapbase) / BLOCKSIZE + 1;
1061   block2 =
1062       ((char *) area2 -
1063        (char *) state->std_heap_copy.heapbase) / BLOCKSIZE + 1;
1064
1065   // If either block is a stack block:
1066   if (is_block_stack((int) block1) && is_block_stack((int) block2)) {
1067     add_heap_area_pair(previous, block1, -1, block2, -1);
1068     if (match_pairs) {
1069       match_equals(state, previous);
1070       xbt_dynar_free(&previous);
1071     }
1072     return 0;
1073   }
1074   // If either block is not in the expected area of memory:
1075   if (((char *) area1 < (char *) state->std_heap_copy.heapbase)
1076       || (block1 > (ssize_t) state->heapsize1) || (block1 < 1)
1077       || ((char *) area2 < (char *) state->std_heap_copy.heapbase)
1078       || (block2 > (ssize_t) state->heapsize2) || (block2 < 1)) {
1079     if (match_pairs) {
1080       xbt_dynar_free(&previous);
1081     }
1082     return 1;
1083   }
1084
1085   // Process address of the block:
1086   real_addr_block1 = (ADDR2UINT(block1) - 1) * BLOCKSIZE +
1087                  (char *) state->std_heap_copy.heapbase;
1088   real_addr_block2 = (ADDR2UINT(block2) - 1) * BLOCKSIZE +
1089                  (char *) state->std_heap_copy.heapbase;
1090
1091   if (type) {
1092
1093     if (type->full_type)
1094       type = type->full_type;
1095
1096     // This assume that for "boring" types (volatile ...) byte_size is absent:
1097     while (type->byte_size == 0 && type->subtype != NULL)
1098       type = type->subtype;
1099
1100     // Find type_size:
1101     if ((type->type == DW_TAG_pointer_type)
1102         || ((type->type == DW_TAG_base_type) && !type->name.empty()
1103             && type->name == "char"))
1104       type_size = -1;
1105     else
1106       type_size = type->byte_size;
1107
1108   }
1109
1110   mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
1111   mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
1112
1113   const malloc_info* heapinfo1 = (const malloc_info*) MC_region_read(
1114     heap_region1, &heapinfo_temp1, &heapinfos1[block1], sizeof(malloc_info));
1115   const malloc_info* heapinfo2 = (const malloc_info*) MC_region_read(
1116     heap_region2, &heapinfo_temp2, &heapinfos2[block2], sizeof(malloc_info));
1117
1118   if ((heapinfo1->type == MMALLOC_TYPE_FREE || heapinfo1->type==MMALLOC_TYPE_HEAPINFO)
1119     && (heapinfo2->type == MMALLOC_TYPE_FREE || heapinfo2->type ==MMALLOC_TYPE_HEAPINFO)) {
1120
1121     /* Free block */
1122     if (match_pairs) {
1123       match_equals(state, previous);
1124       xbt_dynar_free(&previous);
1125     }
1126     return 0;
1127
1128   } else if (heapinfo1->type == MMALLOC_TYPE_UNFRAGMENTED
1129     && heapinfo2->type == MMALLOC_TYPE_UNFRAGMENTED) {
1130     /* Complete block */
1131
1132     // TODO, lookup variable type from block type as done for fragmented blocks
1133
1134     offset1 = (char *) area1 - (char *) real_addr_block1;
1135     offset2 = (char *) area2 - (char *) real_addr_block2;
1136
1137     if (state->equals_to1_(block1, 0).valid
1138         && state->equals_to2_(block2, 0).valid) {
1139       if (equal_blocks(state, block1, block2)) {
1140         if (match_pairs) {
1141           match_equals(state, previous);
1142           xbt_dynar_free(&previous);
1143         }
1144         return 0;
1145       }
1146     }
1147
1148     if (type_size != -1) {
1149       if (type_size != (ssize_t) heapinfo1->busy_block.busy_size
1150           && type_size != (ssize_t)   heapinfo2->busy_block.busy_size
1151           && (type->name.empty() || type->name == "struct s_smx_context")) {
1152         if (match_pairs) {
1153           match_equals(state, previous);
1154           xbt_dynar_free(&previous);
1155         }
1156         return -1;
1157       }
1158     }
1159
1160     if (heapinfo1->busy_block.size !=
1161         heapinfo2->busy_block.size) {
1162       if (match_pairs) {
1163         xbt_dynar_free(&previous);
1164       }
1165       return 1;
1166     }
1167
1168     if (heapinfo1->busy_block.busy_size !=
1169         heapinfo2->busy_block.busy_size) {
1170       if (match_pairs) {
1171         xbt_dynar_free(&previous);
1172       }
1173       return 1;
1174     }
1175
1176     if (!add_heap_area_pair(previous, block1, -1, block2, -1)) {
1177       if (match_pairs) {
1178         match_equals(state, previous);
1179         xbt_dynar_free(&previous);
1180       }
1181       return 0;
1182     }
1183
1184     size = heapinfo1->busy_block.busy_size;
1185
1186     // Remember (basic) type inference.
1187     // The current data structure only allows us to do this for the whole block.
1188     if (type != NULL && area1 == real_addr_block1) {
1189       state->types1_(block1, 0) = type;
1190     }
1191     if (type != NULL && area2 == real_addr_block2) {
1192       state->types2_(block2, 0) = type;
1193     }
1194
1195     if (size <= 0) {
1196       if (match_pairs) {
1197         match_equals(state, previous);
1198         xbt_dynar_free(&previous);
1199       }
1200       return 0;
1201     }
1202
1203     frag1 = -1;
1204     frag2 = -1;
1205
1206     if ((heapinfo1->busy_block.ignore > 0)
1207         && (heapinfo2->busy_block.ignore ==
1208             heapinfo1->busy_block.ignore))
1209       check_ignore = heapinfo1->busy_block.ignore;
1210
1211   } else if ((heapinfo1->type > 0) && (heapinfo2->type > 0)) {      /* Fragmented block */
1212
1213     // Fragment number:
1214     frag1 =
1215         ((uintptr_t) (ADDR2UINT(area1) % (BLOCKSIZE))) >> heapinfo1->type;
1216     frag2 =
1217         ((uintptr_t) (ADDR2UINT(area2) % (BLOCKSIZE))) >> heapinfo2->type;
1218
1219     // Process address of the fragment:
1220     real_addr_frag1 =
1221         (void *) ((char *) real_addr_block1 +
1222                   (frag1 << heapinfo1->type));
1223     real_addr_frag2 =
1224         (void *) ((char *) real_addr_block2 +
1225                   (frag2 << heapinfo2->type));
1226
1227     // Check the size of the fragments against the size of the type:
1228     if (type_size != -1) {
1229       if (heapinfo1->busy_frag.frag_size[frag1] == -1
1230           || heapinfo2->busy_frag.frag_size[frag2] == -1) {
1231         if (match_pairs) {
1232           match_equals(state, previous);
1233           xbt_dynar_free(&previous);
1234         }
1235         return -1;
1236       }
1237       // ?
1238       if (type_size != heapinfo1->busy_frag.frag_size[frag1]
1239           || type_size != heapinfo2->busy_frag.frag_size[frag2]) {
1240         if (match_pairs) {
1241           match_equals(state, previous);
1242           xbt_dynar_free(&previous);
1243         }
1244         return -1;
1245       }
1246     }
1247
1248     // Check if the blocks are already matched together:
1249     if (state->equals_to1_(block1, frag1).valid
1250         && state->equals_to2_(block2, frag2).valid) {
1251       if (offset1==offset2 && equal_fragments(state, block1, frag1, block2, frag2)) {
1252         if (match_pairs) {
1253           match_equals(state, previous);
1254           xbt_dynar_free(&previous);
1255         }
1256         return 0;
1257       }
1258     }
1259     // Compare the size of both fragments:
1260     if (heapinfo1->busy_frag.frag_size[frag1] !=
1261         heapinfo2->busy_frag.frag_size[frag2]) {
1262       if (type_size == -1) {
1263         if (match_pairs) {
1264           match_equals(state, previous);
1265           xbt_dynar_free(&previous);
1266         }
1267         return -1;
1268       } else {
1269         if (match_pairs) {
1270           xbt_dynar_free(&previous);
1271         }
1272         return 1;
1273       }
1274     }
1275
1276     // Size of the fragment:
1277     size = heapinfo1->busy_frag.frag_size[frag1];
1278
1279     // Remember (basic) type inference.
1280     // The current data structure only allows us to do this for the whole fragment.
1281     if (type != NULL && area1 == real_addr_frag1) {
1282       state->types1_(block1, frag1) = type;
1283     }
1284     if (type != NULL && area2 == real_addr_frag2) {
1285       state->types2_(block2, frag2) = type;
1286     }
1287     // The type of the variable is already known:
1288     if (type) {
1289       new_type1 = type;
1290       new_type2 = type;
1291     }
1292     // Type inference from the block type.
1293     else if (state->types1_(block1, frag1) != NULL
1294              || state->types2_(block2, frag2) != NULL) {
1295
1296       offset1 = (char *) area1 - (char *) real_addr_frag1;
1297       offset2 = (char *) area2 - (char *) real_addr_frag2;
1298
1299       if (state->types1_(block1, frag1) != NULL
1300           && state->types2_(block2, frag2) != NULL) {
1301         new_type1 =
1302             get_offset_type(real_addr_frag1, state->types1_(block1, frag1),
1303                             offset1, size, snapshot1, process_index);
1304         new_type2 =
1305             get_offset_type(real_addr_frag2, state->types2_(block2, frag2),
1306                             offset1, size, snapshot2, process_index);
1307       } else if (state->types1_(block1, frag1) != NULL) {
1308         new_type1 =
1309             get_offset_type(real_addr_frag1, state->types1_(block1, frag1),
1310                             offset1, size, snapshot1, process_index);
1311         new_type2 =
1312             get_offset_type(real_addr_frag2, state->types1_(block1, frag1),
1313                             offset2, size, snapshot2, process_index);
1314       } else if (state->types2_(block2, frag2) != NULL) {
1315         new_type1 =
1316             get_offset_type(real_addr_frag1, state->types2_(block2, frag2),
1317                             offset1, size, snapshot1, process_index);
1318         new_type2 =
1319             get_offset_type(real_addr_frag2, state->types2_(block2, frag2),
1320                             offset2, size, snapshot2, process_index);
1321       } else {
1322         if (match_pairs) {
1323           match_equals(state, previous);
1324           xbt_dynar_free(&previous);
1325         }
1326         return -1;
1327       }
1328
1329       if (new_type1 != NULL && new_type2 != NULL && new_type1 != new_type2) {
1330
1331         type = new_type1;
1332         while (type->byte_size == 0 && type->subtype != NULL)
1333           type = type->subtype;
1334         new_size1 = type->byte_size;
1335
1336         type = new_type2;
1337         while (type->byte_size == 0 && type->subtype != NULL)
1338           type = type->subtype;
1339         new_size2 = type->byte_size;
1340
1341       } else {
1342         if (match_pairs) {
1343           match_equals(state, previous);
1344           xbt_dynar_free(&previous);
1345         }
1346         return -1;
1347       }
1348     }
1349
1350     if (new_size1 > 0 && new_size1 == new_size2) {
1351       type = new_type1;
1352       size = new_size1;
1353     }
1354
1355     if (offset1 == 0 && offset2 == 0) {
1356       if (!add_heap_area_pair(previous, block1, frag1, block2, frag2)) {
1357         if (match_pairs) {
1358           match_equals(state, previous);
1359           xbt_dynar_free(&previous);
1360         }
1361         return 0;
1362       }
1363     }
1364
1365     if (size <= 0) {
1366       if (match_pairs) {
1367         match_equals(state, previous);
1368         xbt_dynar_free(&previous);
1369       }
1370       return 0;
1371     }
1372
1373     if ((heapinfo1->busy_frag.ignore[frag1] > 0)
1374         && (heapinfo2->busy_frag.ignore[frag2] ==
1375             heapinfo1->busy_frag.ignore[frag1]))
1376       check_ignore = heapinfo1->busy_frag.ignore[frag1];
1377
1378   } else {
1379
1380     if (match_pairs) {
1381       xbt_dynar_free(&previous);
1382     }
1383     return 1;
1384
1385   }
1386
1387
1388   /* Start comparison */
1389   if (type) {
1390     res_compare =
1391         compare_heap_area_with_type(state, process_index, area1, area2, snapshot1, snapshot2,
1392                                     previous, type, size, check_ignore,
1393                                     pointer_level);
1394   } else {
1395     res_compare =
1396         compare_heap_area_without_type(state, process_index, area1, area2, snapshot1, snapshot2,
1397                                        previous, size, check_ignore);
1398   }
1399   if (res_compare == 1) {
1400     if (match_pairs)
1401       xbt_dynar_free(&previous);
1402     return res_compare;
1403   }
1404
1405   if (match_pairs) {
1406     match_equals(state, previous);
1407     xbt_dynar_free(&previous);
1408   }
1409
1410   return 0;
1411 }
1412
1413 /*********************************************** Miscellaneous ***************************************************/
1414 /****************************************************************************************************************/
1415
1416 // Not used and broken code:
1417 # if 0
1418
1419 // Not used:
1420 static int get_pointed_area_size(void *area, int heap)
1421 {
1422
1423   struct s_mc_diff *state = mc_diff_info;
1424
1425   int block, frag;
1426   malloc_info *heapinfo;
1427
1428   if (heap == 1)
1429     heapinfo = state->heapinfo1;
1430   else
1431     heapinfo = state->heapinfo2;
1432
1433   block =
1434       ((char *) area -
1435        (char *) state->std_heap_copy.heapbase) / BLOCKSIZE + 1;
1436
1437   if (((char *) area < (char *) state->std_heap_copy.heapbase)
1438       || (block > state->heapsize1) || (block < 1))
1439     return -1;
1440
1441   if (heapinfo[block].type == MMALLOC_TYPE_FREE || heapinfo[block].type == MMALLOC_TYPE_HEAPINFO) {     /* Free block */
1442     return -1;
1443   } else if (heapinfo[block].type == MMALLOC_TYPE_UNFRAGMENTED) {       /* Complete block */
1444     return (int) heapinfo[block].busy_block.busy_size;
1445   } else {
1446     frag =
1447         ((uintptr_t) (ADDR2UINT(area) % (BLOCKSIZE))) >> heapinfo[block].type;
1448     return (int) heapinfo[block].busy_frag.frag_size[frag];
1449   }
1450 }
1451
1452 #ifndef max
1453 #define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
1454 #endif
1455
1456 // Not used:
1457 int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2)
1458 {
1459
1460   struct s_mc_diff *state = mc_diff_info;
1461
1462   if (heap1 == NULL && heap1 == NULL) {
1463     XBT_DEBUG("Malloc descriptors null");
1464     return 0;
1465   }
1466
1467   if (heap1->heaplimit != heap2->heaplimit) {
1468     XBT_DEBUG("Different limit of valid info table indices");
1469     return 1;
1470   }
1471
1472   /* Heap information */
1473   state->heaplimit = ((struct mdesc *) heap1)->heaplimit;
1474
1475   state->std_heap_copy = *mc_model_checker->process().get_heap();
1476
1477   state->heapbase1 = (char *) heap1 + BLOCKSIZE;
1478   state->heapbase2 = (char *) heap2 + BLOCKSIZE;
1479
1480   state->heapinfo1 =
1481       (malloc_info *) ((char *) heap1 +
1482                        ((uintptr_t)
1483                         ((char *) heap1->heapinfo - (char *) state->s_heap)));
1484   state->heapinfo2 =
1485       (malloc_info *) ((char *) heap2 +
1486                        ((uintptr_t)
1487                         ((char *) heap2->heapinfo - (char *) state->s_heap)));
1488
1489   state->heapsize1 = heap1->heapsize;
1490   state->heapsize2 = heap2->heapsize;
1491
1492   /* Start comparison */
1493   size_t i, j, k;
1494   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
1495
1496   int distance = 0;
1497
1498   /* Check busy blocks */
1499
1500   i = 1;
1501
1502   while (i <= state->heaplimit) {
1503
1504     addr_block1 =
1505         ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
1506                    (char *) state->heapbase1));
1507     addr_block2 =
1508         ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
1509                    (char *) state->heapbase2));
1510
1511     if (state->heapinfo1[i].type != state->heapinfo2[i].type) {
1512
1513       distance += BLOCKSIZE;
1514       XBT_DEBUG("Different type of blocks (%zu) : %d - %d -> distance = %d", i,
1515                 state->heapinfo1[i].type, state->heapinfo2[i].type, distance);
1516       i++;
1517
1518     } else {
1519
1520       if (state->heapinfo1[i].type == MMALLOC_TYPE_FREE
1521         || state->heapinfo1[i].type == MMALLOC_TYPE_HAPINFO) {     /* Free block */
1522         i++;
1523         continue;
1524       }
1525
1526       if (state->heapinfo1[i].type == MMALLOC_TYPE_UNFRAGMENTED) {      /* Large block */
1527
1528         if (state->heapinfo1[i].busy_block.size !=
1529             state->heapinfo2[i].busy_block.size) {
1530           distance +=
1531               BLOCKSIZE * max(state->heapinfo1[i].busy_block.size,
1532                               state->heapinfo2[i].busy_block.size);
1533           i += max(state->heapinfo1[i].busy_block.size,
1534                    state->heapinfo2[i].busy_block.size);
1535           XBT_DEBUG
1536               ("Different larger of cluster at block %zu : %zu - %zu -> distance = %d",
1537                i, state->heapinfo1[i].busy_block.size,
1538                state->heapinfo2[i].busy_block.size, distance);
1539           continue;
1540         }
1541
1542         /*if(heapinfo1[i].busy_block.busy_size != heapinfo2[i].busy_block.busy_size){
1543            distance += max(heapinfo1[i].busy_block.busy_size, heapinfo2[i].busy_block.busy_size);
1544            i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
1545            XBT_DEBUG("Different size used oin large cluster at block %zu : %zu - %zu -> distance = %d", i, heapinfo1[i].busy_block.busy_size, heapinfo2[i].busy_block.busy_size, distance);
1546            continue;
1547            } */
1548
1549         k = 0;
1550
1551         //while(k < (heapinfo1[i].busy_block.busy_size)){
1552         while (k < state->heapinfo1[i].busy_block.size * BLOCKSIZE) {
1553           if (memcmp((char *) addr_block1 + k, (char *) addr_block2 + k, 1) !=
1554               0) {
1555             distance++;
1556           }
1557           k++;
1558         }
1559
1560         i++;
1561
1562       } else {                  /* Fragmented block */
1563
1564         for (j = 0; j < (size_t) (BLOCKSIZE >> state->heapinfo1[i].type); j++) {
1565
1566           addr_frag1 =
1567               (void *) ((char *) addr_block1 + (j << state->heapinfo1[i].type));
1568           addr_frag2 =
1569               (void *) ((char *) addr_block2 + (j << state->heapinfo2[i].type));
1570
1571           if (state->heapinfo1[i].busy_frag.frag_size[j] == 0
1572               && state->heapinfo2[i].busy_frag.frag_size[j] == 0) {
1573             continue;
1574           }
1575
1576
1577           /*if(heapinfo1[i].busy_frag.frag_size[j] != heapinfo2[i].busy_frag.frag_size[j]){
1578              distance += max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j]);
1579              XBT_DEBUG("Different size used in fragment %zu in block %zu : %d - %d -> distance = %d", j, i, heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j], distance); 
1580              continue;
1581              } */
1582
1583           k = 0;
1584
1585           //while(k < max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j])){
1586           while (k < (BLOCKSIZE / (BLOCKSIZE >> state->heapinfo1[i].type))) {
1587             if (memcmp((char *) addr_frag1 + k, (char *) addr_frag2 + k, 1) !=
1588                 0) {
1589               distance++;
1590             }
1591             k++;
1592           }
1593
1594         }
1595
1596         i++;
1597
1598       }
1599
1600     }
1601
1602   }
1603
1604   return distance;
1605
1606 }
1607 #endif
1608
1609 }