RPA Toolkit
Build system cleanup...
[rpatk.git] / rvm / rvmcodemap.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21 #include "rvm/rvmcodemap.h"
22 #include "rlib/rstring.h"
23 #include "rlib/rmem.h"
24
25
26 rvm_codemap_t *rvm_codemap_create()
27 {
28         rvm_codemap_t *codemap;
29
30         codemap = (rvm_codemap_t*)r_malloc(sizeof(*codemap));
31         if (!codemap)
32                 return NULL;
33         r_memset(codemap, 0, sizeof(*codemap));
34         codemap->labels = r_array_create(sizeof(rvm_codelabel_t));
35         codemap->hash = r_hash_create(5, r_hash_rstrequal, r_hash_rstrhash);
36         return codemap;
37 }
38
39
40 void rvm_codemap_destroy(rvm_codemap_t *codemap)
41 {
42         rvm_codelabel_t *label;
43         unsigned long i, len = r_array_length(codemap->labels);
44
45         for (i = 0; i < len; i++) {
46                 label = (rvm_codelabel_t*)r_array_slot(codemap->labels, i);
47                 r_free(label->name);
48         }
49         r_object_destroy((robject_t*)codemap->labels);
50         r_object_destroy((robject_t*)codemap->hash);
51         r_free(codemap);
52 }
53
54
55 void rvm_codemap_clear(rvm_codemap_t *codemap)
56 {
57         unsigned long i;
58         rvm_codelabel_t *label;
59
60         for (i = 0; i < r_array_length(codemap->labels); i++) {
61                 label = (rvm_codelabel_t*)r_array_slot(codemap->labels, i);
62                 r_free(label->name);
63         }
64         r_array_setlength(codemap->labels, 0);
65         r_hash_removeall(codemap->hash);
66 }
67
68
69 rvm_codelabel_t *rvm_codemap_label(rvm_codemap_t *codemap, long index)
70 {
71         if (index < 0 || index >= (long)r_array_length(codemap->labels))
72                 return NULL;
73         return (rvm_codelabel_t*)r_array_slot(codemap->labels, index);
74 }
75
76
77 static long rvm_codemap_dolookup(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
78 {
79         rstr_t lookupstr = {(char*)name, namesize};
80         return r_hash_lookup_indexval(codemap->hash, &lookupstr);
81 }
82
83
84 static long rvm_codemap_add(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
85 {
86         rvm_codelabel_t *label = NULL;
87         long labelidx = -1;
88
89         labelidx = rvm_codemap_dolookup(codemap, name, namesize);
90         if (labelidx < 0) {
91                 labelidx = (long)r_array_add(codemap->labels, NULL);
92                 label = rvm_codemap_label(codemap, labelidx);
93                 if (name) {
94                         label->name = r_rstrdup(name, namesize);
95                         r_hash_insert_indexval(codemap->hash, label->name, labelidx);
96                 }
97         }
98         return labelidx;
99 }
100
101
102 void rvm_codelabel_setoffset(rvm_codelabel_t *label, unsigned long base, unsigned long offset)
103 {
104         label->base = base;
105         label->value = offset;
106         label->type = RVM_CODELABEL_OFFSET;
107 }
108
109
110 void rvm_codelabel_setpointer(rvm_codelabel_t *label, rpointer ptr)
111 {
112         label->base = 0;
113         label->value = (ruword)ptr;
114         label->type = RVM_CODELABEL_POINTER;
115 }
116
117
118 void rvm_codelabel_setinvalid(rvm_codelabel_t *label)
119 {
120         label->base = 0;
121         label->value = 0;
122         label->type = RVM_CODELABEL_INVALID;
123 }
124
125
126 long rvm_codemap_addoffset(rvm_codemap_t *codemap, const char *name, unsigned int namesize, unsigned long base, unsigned long offset)
127 {
128         long labelidx = rvm_codemap_add(codemap, name, namesize);
129         rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
130         if (label)
131                 rvm_codelabel_setoffset(label, base, offset);
132         return labelidx;
133 }
134
135
136 long rvm_codemap_addoffset_s(rvm_codemap_t *codemap, const char *name, unsigned long base, unsigned long offset)
137 {
138         return rvm_codemap_addoffset(codemap, name, (unsigned int)r_strlen(name), base, offset);
139 }
140
141
142 long rvm_codemap_addpointer(rvm_codemap_t *codemap, const char *name, unsigned int namesize, rpointer ptr)
143 {
144         long labelidx = rvm_codemap_add(codemap, name, namesize);
145         rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
146
147         if (label) {
148                 rvm_codelabel_setpointer(label, ptr);
149         }
150         return labelidx;
151 }
152
153
154 long rvm_codemap_addpointer_s(rvm_codemap_t *codemap, const char *name, rpointer ptr)
155 {
156         return rvm_codemap_addpointer(codemap, name, (unsigned int)r_strlen(name), ptr);
157 }
158
159
160 long rvm_codemap_invalid_add(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
161 {
162         long labelidx = rvm_codemap_add(codemap, name, namesize);
163         rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
164
165         if (label) {
166                 rvm_codelabel_setinvalid(label);
167         }
168         return labelidx;
169 }
170
171
172 long rvm_codemap_validindex(rvm_codemap_t *codemap, long labelidx)
173 {
174         rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
175
176         if (label && label->type != RVM_CODELABEL_INVALID)
177                 return 1;
178         return 0;
179 }
180
181
182 long rvm_codemap_invalid_add_s(rvm_codemap_t *codemap, const char *name)
183 {
184         return rvm_codemap_invalid_add(codemap, name, (unsigned int)r_strlen(name));
185 }
186
187
188 long rvm_codemap_lastlabel(rvm_codemap_t *codemap)
189 {
190         return (long)(r_array_length(codemap->labels) - 1);
191 }
192
193
194 long rvm_codemap_lookupadd(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
195 {
196         rstr_t lookupstr = {(char*)name, namesize};
197         long labelidx = r_hash_lookup_indexval(codemap->hash, &lookupstr);
198
199         if (labelidx < 0)
200                 labelidx = rvm_codemap_invalid_add(codemap, name, namesize);
201         return labelidx;
202 }
203
204
205 long rvm_codemap_lookupadd_s(rvm_codemap_t *codemap, const char *name)
206 {
207         return rvm_codemap_lookupadd(codemap, name, (unsigned int)r_strlen(name));
208 }
209
210
211 long rvm_codemap_lookup(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
212 {
213         rstr_t lookupstr = {(char*)name, namesize};
214         long labelidx = r_hash_lookup_indexval(codemap->hash, &lookupstr);
215
216         return labelidx;
217 }
218
219
220 long rvm_codemap_lookup_s(rvm_codemap_t *codemap, const char *name)
221 {
222         return rvm_codemap_lookup(codemap, name, (unsigned int)r_strlen(name));
223 }
224
225
226 ruword rvm_codemap_resolve(rvm_codemap_t *codemap, long index, rvm_codelabel_t **err)
227 {
228         rvm_codelabel_t *label = rvm_codemap_label(codemap, index);
229         ruword value;
230
231         if (!label)
232                 return 0;
233         if (label->type == RVM_CODELABEL_POINTER) {
234                 return label->value;
235         } else if (label->type == RVM_CODELABEL_OFFSET) {
236                 value = rvm_codemap_resolve(codemap, label->base, err);
237                 if (value == (ruword)-1)
238                         return (ruword)-1;
239                 return value + label->value;
240         }
241         if (err)
242                 *err = label;
243         return (ruword)-1;
244 }
245
246
247 void rvm_codemap_dump(rvm_codemap_t *codemap)
248 {
249         long i = 0;
250
251         for (i = 0; i < (long)r_array_length(codemap->labels); i++) {
252                 rvm_codelabel_t *label = rvm_codemap_label(codemap, i);
253                 r_printf("%d: %s(%d), type: %d, base: %ld, value: %ld\n", i, label->name->str, label->name->size, label->type, label->base, label->value);
254         }
255 }
256