comparison memory.c @ 0:d4bc23cb728b

Import from CVS (CVS_DB/member/atsuki/cbc/DPP)
author Yasutaka Higa <e115763@ie.u-ryukyu.ac.jp>
date Wed, 16 Dec 2015 15:16:11 +0900
parents
children 190dadd8405b
comparison
equal deleted inserted replaced
-1:000000000000 0:d4bc23cb728b
1 /*
2
3 memory fragment management library
4
5 Shinji Kono (2006)
6
7 usage:
8
9 MemoryPtr db = 0;
10 add_memory(address,length,&db);
11
12 memory pattern is copyied and stored in a binary tree in db.
13 All patterns are shared.
14
15 memory pattern database (binary tree by pattern)
16
17
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include "memory.h"
23 #include "crc32.h"
24 #include <string.h>
25
26 #define MEMORY_REPORT 1
27
28 #if MEMORY_REPORT
29 int memory_header;
30 int memcmp_count;
31 int memory_body;
32 int restore_count;
33 int restore_size;
34 int range_count;
35 int range_size;
36 #endif
37
38 extern void die_exit(char *);
39
40 void
41 die_exit(char *msg)
42 {
43 fprintf(stderr,"%s\n",msg);
44 exit(1);
45 }
46
47 // static MemoryPtr memory_root;
48
49
50 /*
51
52 make memory fragment as a part of the program state
53
54 */
55
56 MemoryPtr
57 create_memory(void *adr, int length)
58 {
59 MemoryPtr m = (MemoryPtr)malloc(sizeof(Memory));
60 if (!m) die_exit("Cann't alloc memory list.");
61 m->left = m->right = 0;
62 m->length = length;
63 m->adr = m->body = adr;
64 #if MEMORY_REPORT
65 memory_header++;
66 #endif
67 return m;
68 }
69
70 /*
71
72 Compute hash value of a memory fragment
73
74 */
75
76 void
77 compute_memory_hash1(MemoryPtr m)
78 {
79 m->hash = Get_CRC((unsigned char *)m->adr,m->length);
80 }
81
82 void
83 free_memory(MemoryPtr m)
84 {
85 m->left = m->right = 0;
86 m->adr = m->body = 0;
87 free(m);
88 }
89
90 /*
91
92 Compare memory contents ( doesn't care about its address )
93
94 */
95
96 int
97 cmp_content(MemoryPtr a,MemoryPtr b)
98 {
99 if (a->length != b->length) {
100 if (a->length > b->length) {
101 return 1;
102 } else {
103 return -1;
104 }
105 }
106 if (a->hash == b->hash) {
107 #if MEMORY_REPORT
108 memcmp_count ++;
109 #endif
110 return memcmp(a->body,b->body,a->length);
111 } else if (a->hash > b->hash) {
112 return 1;
113 } else {
114 return -1;
115 }
116 }
117
118 /*
119
120 Compare entire memory contents ( doesn't care about its address )
121
122 */
123
124 static int
125 cmp_memory1(MemoryPtr a,MemoryPtr b)
126 {
127 int r;
128 if ((r=cmp_content(a,b))) return r;
129
130 if (a->adr==b->adr) {
131 return 0;
132 }
133 return (a->adr > b->adr) ? 1 : -1;
134 }
135
136 int
137 cmp_memory(MemoryPtr a,MemoryPtr b)
138 {
139 int r;
140 while(1) {
141 if ((r=cmp_memory1(a,b))) return r;
142 if (a->left && b->left) {
143 if ((r=cmp_memory(a->left,b->left))) return r;
144 } else if (a->left || b->left) {
145 return (a->left > b->left)? 1 : -1;
146 }
147 if (a->right && b->right) {
148 a = a->right; b = b->right;
149 // recursive loop
150 } else if (a->right || b->right) {
151 return (a->right > b->right)? 1 : -1;
152 } else {
153 return 0; // singleton
154 }
155 }
156 }
157
158 /*
159 Make a copy of real memory fragments
160 */
161
162 MemoryPtr
163 copy_memory1(MemoryPtr m)
164 {
165 MemoryPtr new = create_memory(m->adr,m->length);
166 void *p = (void *)malloc(m->length);
167 if (!p) {
168 die_exit("can't alloc memory body");
169 return 0;
170 }
171 #if MEMORY_REPORT
172 memory_body += m->length;
173 #endif
174 memcpy(p,m->adr,m->length);
175 m->body = new->body = p; // abondon original memory pattern
176 new->hash = m->hash;
177 return new;
178 }
179
180 MemoryPtr
181 copy_memory(MemoryPtr m, MemoryPtr *db)
182 {
183 MemoryPtr new, out;
184 if (!m) return m;
185 new = create_memory(m->adr,m->length);
186 new->hash = m->hash;
187 // look up is necessary to share its memory pattern
188 memory_lookup(new, db, copy_memory1, &out);
189 if (m->left) new->left = copy_memory(m->left, db);
190 if (m->right) new->right = copy_memory(m->right, db);
191 return new;
192 }
193
194 /*
195 restore copied memory save to the original addresses
196 */
197
198 void
199 restore_memory(MemoryPtr m)
200 {
201 while (m) {
202 memcpy(m->adr,m->body,m->length);
203 #if MEMORY_REPORT
204 restore_count ++;
205 restore_size += m->length;
206 #endif
207 if (m->left) restore_memory(m->left);
208 m = m->right;
209 }
210 }
211
212
213 /*
214 get hash for all memeory fragments
215 initial value of hash should be zero
216 */
217
218 int
219 get_memory_hash(MemoryPtr m, int hash)
220 {
221 if (!m) return hash;
222 compute_memory_hash1(m);
223 if (m->left) hash = get_memory_hash(m->left, hash);
224 if (m->right) return get_memory_hash(m->right, hash);
225 return m->hash | hash;
226 }
227
228 /*
229 add modified memory fragments to the pattern database
230 */
231
232 MemoryPtr
233 add_memory(void *ptr,int length, MemoryPtr *parent)
234 {
235 Memory m, *out;
236 m.adr = m.body = ptr;
237 m.length = length;
238 m.left = m.right = 0;
239 compute_memory_hash1(&m);
240
241 memory_lookup(&m, parent, copy_memory1, &out);
242 return out;
243 }
244
245 int
246 memory_lookup(MemoryPtr m, MemoryPtr *parent,
247 MemoryPtr (*new_memory)(MemoryPtr), MemoryPtr *out)
248 {
249 MemoryPtr db;
250 int r;
251
252 while(1) {
253 db = *parent;
254 if (!db) {
255 /* not found */
256 if (new_memory && out) {
257 db = new_memory(m);
258 db->left = db->right = 0;
259 *out = *parent = db;
260 }
261 return 0;
262 }
263 if(!(r = cmp_memory1(m,db))) {
264 /* bingo */
265 if (out) {
266 *out = db;
267 }
268 return 1;
269 } else if (r>0) {
270 parent = &db->left;
271 } else if (r<0) {
272 parent = &db->right;
273 }
274 }
275 /* !NOT REACHED */
276 }
277
278 /*
279 memory range list management for state registration
280 this list points the real memory
281 */
282
283 MemoryPtr
284 add_memory_range(void *ptr,int length, MemoryPtr *parent)
285 {
286 Memory m, *out;
287 m.adr = ptr;
288 m.length = length;
289 m.left = m.right = 0;
290
291 memory_range_lookup(&m, parent, &out);
292 return out;
293 }
294
295 static int
296 cmp_range(MemoryPtr a,MemoryPtr b)
297 {
298 if (a->adr==b->adr) {
299 if (a->length != b->length)
300 die_exit("memory range inconsitency");
301 return 0;
302 }
303 return (a->adr > b->adr) ? 1 : -1;
304 }
305
306 int
307 memory_range_lookup(MemoryPtr m, MemoryPtr *parent, MemoryPtr *out)
308 {
309 MemoryPtr db;
310 int r;
311
312 while(1) {
313 db = *parent;
314 if (!db) {
315 /* not found */
316 if (out) {
317 db = create_memory(m->adr, m->length);
318 *out = *parent = db;
319 }
320 #if MEMORY_REPORT
321 range_count++;
322 range_size+=m->length;
323 #endif
324 return 0;
325 }
326 if(!(r = cmp_range(m,db))) {
327 /* bingo (actually an error) */
328 if (out) {
329 *out = db;
330 }
331 return 1;
332 } else if (r>0) {
333 parent = &db->left;
334 } else if (r<0) {
335 parent = &db->right;
336 }
337 }
338 /* !NOT REACHED */
339 }
340
341 /*
342 */
343
344 void
345 memory_usage()
346 {
347 #if MEMORY_REPORT
348 printf(" memory_header %d\n",memory_header);
349 printf(" memcmp_count %d\n",memcmp_count);
350 printf(" memory_body %d\n",memory_body);
351 printf(" restore_count %d\n",restore_count);
352 printf(" restore_size %d\n",restore_size);
353 printf(" range_count %d\n",range_count);
354 printf(" range_size %d\n",range_size);
355 #endif
356 }
357
358
359 /* end */