2 * Regular Pattern Analyzer (RPA)
3 * Copyright (c) 2009-2010 Martin Stoilov
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.
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.
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/>.
18 * Martin Stoilov <martin@rpasearch.com>
21 #include "rvm/rvmcodemap.h"
22 #include "rlib/rstring.h"
23 #include "rlib/rmem.h"
26 rvm_codemap_t *rvm_codemap_create()
28 rvm_codemap_t *codemap;
30 codemap = (rvm_codemap_t*)r_malloc(sizeof(*codemap));
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);
40 void rvm_codemap_destroy(rvm_codemap_t *codemap)
42 rvm_codelabel_t *label;
43 unsigned long i, len = r_array_length(codemap->labels);
45 for (i = 0; i < len; i++) {
46 label = (rvm_codelabel_t*)r_array_slot(codemap->labels, i);
49 r_object_destroy((robject_t*)codemap->labels);
50 r_object_destroy((robject_t*)codemap->hash);
55 void rvm_codemap_clear(rvm_codemap_t *codemap)
58 rvm_codelabel_t *label;
60 for (i = 0; i < r_array_length(codemap->labels); i++) {
61 label = (rvm_codelabel_t*)r_array_slot(codemap->labels, i);
64 r_array_setlength(codemap->labels, 0);
65 r_hash_removeall(codemap->hash);
69 rvm_codelabel_t *rvm_codemap_label(rvm_codemap_t *codemap, long index)
71 if (index < 0 || index >= (long)r_array_length(codemap->labels))
73 return (rvm_codelabel_t*)r_array_slot(codemap->labels, index);
77 static long rvm_codemap_dolookup(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
79 rstr_t lookupstr = {(char*)name, namesize};
80 return r_hash_lookup_indexval(codemap->hash, &lookupstr);
84 static long rvm_codemap_add(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
86 rvm_codelabel_t *label = NULL;
89 labelidx = rvm_codemap_dolookup(codemap, name, namesize);
91 labelidx = (long)r_array_add(codemap->labels, NULL);
92 label = rvm_codemap_label(codemap, labelidx);
94 label->name = r_rstrdup(name, namesize);
95 r_hash_insert_indexval(codemap->hash, label->name, labelidx);
102 void rvm_codelabel_setoffset(rvm_codelabel_t *label, unsigned long base, unsigned long offset)
105 label->value = offset;
106 label->type = RVM_CODELABEL_OFFSET;
110 void rvm_codelabel_setpointer(rvm_codelabel_t *label, rpointer ptr)
113 label->value = (ruword)ptr;
114 label->type = RVM_CODELABEL_POINTER;
118 void rvm_codelabel_setinvalid(rvm_codelabel_t *label)
122 label->type = RVM_CODELABEL_INVALID;
126 long rvm_codemap_addoffset(rvm_codemap_t *codemap, const char *name, unsigned int namesize, unsigned long base, unsigned long offset)
128 long labelidx = rvm_codemap_add(codemap, name, namesize);
129 rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
131 rvm_codelabel_setoffset(label, base, offset);
136 long rvm_codemap_addoffset_s(rvm_codemap_t *codemap, const char *name, unsigned long base, unsigned long offset)
138 return rvm_codemap_addoffset(codemap, name, (unsigned int)r_strlen(name), base, offset);
142 long rvm_codemap_addpointer(rvm_codemap_t *codemap, const char *name, unsigned int namesize, rpointer ptr)
144 long labelidx = rvm_codemap_add(codemap, name, namesize);
145 rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
148 rvm_codelabel_setpointer(label, ptr);
154 long rvm_codemap_addpointer_s(rvm_codemap_t *codemap, const char *name, rpointer ptr)
156 return rvm_codemap_addpointer(codemap, name, (unsigned int)r_strlen(name), ptr);
160 long rvm_codemap_invalid_add(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
162 long labelidx = rvm_codemap_add(codemap, name, namesize);
163 rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
166 rvm_codelabel_setinvalid(label);
172 long rvm_codemap_validindex(rvm_codemap_t *codemap, long labelidx)
174 rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
176 if (label && label->type != RVM_CODELABEL_INVALID)
182 long rvm_codemap_invalid_add_s(rvm_codemap_t *codemap, const char *name)
184 return rvm_codemap_invalid_add(codemap, name, (unsigned int)r_strlen(name));
188 long rvm_codemap_lastlabel(rvm_codemap_t *codemap)
190 return (long)(r_array_length(codemap->labels) - 1);
194 long rvm_codemap_lookupadd(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
196 rstr_t lookupstr = {(char*)name, namesize};
197 long labelidx = r_hash_lookup_indexval(codemap->hash, &lookupstr);
200 labelidx = rvm_codemap_invalid_add(codemap, name, namesize);
205 long rvm_codemap_lookupadd_s(rvm_codemap_t *codemap, const char *name)
207 return rvm_codemap_lookupadd(codemap, name, (unsigned int)r_strlen(name));
211 long rvm_codemap_lookup(rvm_codemap_t *codemap, const char *name, unsigned int namesize)
213 rstr_t lookupstr = {(char*)name, namesize};
214 long labelidx = r_hash_lookup_indexval(codemap->hash, &lookupstr);
220 long rvm_codemap_lookup_s(rvm_codemap_t *codemap, const char *name)
222 return rvm_codemap_lookup(codemap, name, (unsigned int)r_strlen(name));
226 ruword rvm_codemap_resolve(rvm_codemap_t *codemap, long index, rvm_codelabel_t **err)
228 rvm_codelabel_t *label = rvm_codemap_label(codemap, index);
233 if (label->type == RVM_CODELABEL_POINTER) {
235 } else if (label->type == RVM_CODELABEL_OFFSET) {
236 value = rvm_codemap_resolve(codemap, label->base, err);
237 if (value == (ruword)-1)
239 return value + label->value;
247 void rvm_codemap_dump(rvm_codemap_t *codemap)
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);