RPA Toolkit
fixed the clear mechanism.
[rpatk.git] / rvm / rvmcodemap.c
1 #include "rvmcodemap.h"
2 #include "rstring.h"
3 #include "rmem.h"
4
5
6 rvm_codemap_t *rvm_codemap_create()
7 {
8         rvm_codemap_t *codemap;
9
10         codemap = (rvm_codemap_t*)r_malloc(sizeof(*codemap));
11         if (!codemap)
12                 return NULL;
13         r_memset(codemap, 0, sizeof(*codemap));
14         codemap->labels = r_array_create(sizeof(rvm_codelabel_t));
15         codemap->hash = r_hash_create(5, r_hash_rstrequal, r_hash_rstrhash);
16         return codemap;
17 }
18
19
20 void rvm_codemap_destroy(rvm_codemap_t *codemap)
21 {
22         rlong i;
23         rvm_codelabel_t *label;
24         rlong len = r_array_length(codemap->labels);
25
26         for (i = 0; i < len; i++) {
27                 label = (rvm_codelabel_t*)r_array_slot(codemap->labels, i);
28                 r_free(label->name);
29         }
30         r_object_destroy((robject_t*)codemap->labels);
31         r_object_destroy((robject_t*)codemap->hash);
32         r_free(codemap);
33 }
34
35
36 void rvm_codemap_clear(rvm_codemap_t *codemap)
37 {
38         rlong i;
39         rvm_codelabel_t *label;
40
41         for (i = 0; i < r_array_length(codemap->labels); i++) {
42                 label = (rvm_codelabel_t*)r_array_slot(codemap->labels, i);
43                 r_free(label->name);
44         }
45         r_array_setlength(codemap->labels, 0);
46         r_hash_removeall(codemap->hash);
47 }
48
49
50 rvm_codelabel_t *rvm_codemap_label(rvm_codemap_t *codemap, rlong index)
51 {
52         if (index < 0 || index >= r_array_length(codemap->labels))
53                 return NULL;
54         return (rvm_codelabel_t*)r_array_slot(codemap->labels, index);
55 }
56
57
58 static rlong rvm_codemap_dolookup(rvm_codemap_t *codemap, const rchar *name, ruint namesize)
59 {
60         rstr_t lookupstr = {(char*)name, namesize};
61         return r_hash_lookup_indexval(codemap->hash, &lookupstr);
62 }
63
64
65 static rlong rvm_codemap_add(rvm_codemap_t *codemap, const rchar *name, ruint namesize)
66 {
67         rvm_codelabel_t *label;
68         rlong labelidx = -1;
69
70         labelidx = rvm_codemap_dolookup(codemap, name, namesize);
71         if (labelidx < 0) {
72                 r_memset(&label, 0, sizeof(label));
73                 labelidx = r_array_add(codemap->labels, NULL);
74                 label = rvm_codemap_label(codemap, labelidx);
75                 if (name) {
76                         label->name = r_rstrdup(name, namesize);
77                         r_hash_insert_indexval(codemap->hash, label->name, labelidx);
78                 }
79         }
80         return labelidx;
81 }
82
83
84
85 rlong rvm_codemap_addoffset(rvm_codemap_t *codemap, const rchar *name, ruint namesize, rulong base, rulong offset)
86 {
87         rlong labelidx = rvm_codemap_add(codemap, name, namesize);
88         rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
89
90         if (label) {
91                 label->base = base;
92                 label->value = offset;
93                 label->type = RVM_CODELABEL_OFFSET;
94         }
95         return labelidx;
96 }
97
98
99 rlong rvm_codemap_addoffset_s(rvm_codemap_t *codemap, const rchar *name, rulong base, rulong offset)
100 {
101         return rvm_codemap_addoffset(codemap, name, r_strlen(name), base, offset);
102 }
103
104
105 rlong rvm_codemap_addpointer(rvm_codemap_t *codemap, const rchar *name, ruint namesize, rpointer ptr)
106 {
107         rlong labelidx = rvm_codemap_add(codemap, name, namesize);
108         rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
109
110         if (label) {
111                 label->value = (rword)ptr;
112                 label->type = RVM_CODELABEL_POINTER;
113         }
114         return labelidx;
115 }
116
117
118 rlong rvm_codemap_addpointer_s(rvm_codemap_t *codemap, const rchar *name, rpointer ptr)
119 {
120         return rvm_codemap_addpointer(codemap, name, r_strlen(name), ptr);
121 }
122
123
124 rlong rvm_codemap_invalid_add(rvm_codemap_t *codemap, const rchar *name, ruint namesize)
125 {
126         rlong labelidx = rvm_codemap_add(codemap, name, namesize);
127         rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
128
129         if (label) {
130                 label->type = RVM_CODELABEL_INVALID;
131         }
132         return labelidx;
133 }
134
135
136 rlong rvm_codemap_validindex(rvm_codemap_t *codemap, rlong labelidx)
137 {
138         rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
139
140         if (label && label->type != RVM_CODELABEL_INVALID)
141                 return 1;
142         return 0;
143 }
144
145
146 rlong rvm_codemap_invalid_add_s(rvm_codemap_t *codemap, const rchar *name)
147 {
148         return rvm_codemap_invalid_add(codemap, name, r_strlen(name));
149 }
150
151
152 rlong rvm_codemap_lastlabel(rvm_codemap_t *codemap)
153 {
154         return r_array_length(codemap->labels) - 1;
155 }
156
157
158 rlong rvm_codemap_lookupadd(rvm_codemap_t *codemap, const rchar *name, ruint namesize)
159 {
160         rstr_t lookupstr = {(char*)name, namesize};
161         rlong labelidx = r_hash_lookup_indexval(codemap->hash, &lookupstr);
162
163         if (labelidx < 0)
164                 labelidx = rvm_codemap_invalid_add(codemap, name, namesize);
165         return labelidx;
166 }
167
168
169 rlong rvm_codemap_lookupadd_s(rvm_codemap_t *codemap, const rchar *name)
170 {
171         return rvm_codemap_lookupadd(codemap, name, r_strlen(name));
172 }
173
174
175 rlong rvm_codemap_lookup(rvm_codemap_t *codemap, const rchar *name, ruint namesize)
176 {
177         rstr_t lookupstr = {(char*)name, namesize};
178         rlong labelidx = r_hash_lookup_indexval(codemap->hash, &lookupstr);
179
180         return labelidx;
181 }
182
183
184 rlong rvm_codemap_lookup_s(rvm_codemap_t *codemap, const rchar *name)
185 {
186         return rvm_codemap_lookup(codemap, name, r_strlen(name));
187 }
188
189
190 rword rvm_codemap_resolve(rvm_codemap_t *codemap, rlong index, rvm_codelabel_t **err)
191 {
192         rvm_codelabel_t *label = rvm_codemap_label(codemap, index);
193         rword value;
194
195         if (!label)
196                 return 0;
197         if (label->type == RVM_CODELABEL_POINTER) {
198                 return label->value;
199         } else if (label->type == RVM_CODELABEL_OFFSET) {
200                 value = rvm_codemap_resolve(codemap, label->base, err);
201                 if (value == (rword)-1)
202                         return (rword)-1;
203                 return value + label->value;
204         }
205         if (err)
206                 *err = label;
207         return (rword)-1;
208 }
209
210
211 void rvm_codemap_dump(rvm_codemap_t *codemap)
212 {
213         rint i = 0;
214
215         for (i = 0; i < r_array_length(codemap->labels); i++) {
216                 rvm_codelabel_t *label = rvm_codemap_label(codemap, i);
217                 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);
218         }
219 }
220