RPA Toolkit
RJS prop access changes... continued.
[rpatk.git] / rvm / rvmrelocmap.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/rvmrelocmap.h"
22 #include "rlib/rmem.h"
23
24 rvm_relocmap_t *rvm_relocmap_create()
25 {
26         rvm_relocmap_t *relocmap;
27
28         relocmap = (rvm_relocmap_t*)r_zmalloc(sizeof(*relocmap));
29         if (!relocmap)
30                 return NULL;
31         relocmap->records = r_array_create(sizeof(rvm_relocrecord_t));
32         return relocmap;
33 }
34
35
36 void rvm_relocmap_destroy(rvm_relocmap_t *relocmap)
37 {
38         r_object_destroy((robject_t*)relocmap->records);
39         r_free(relocmap);
40 }
41
42
43 void rvm_relocmap_clear(rvm_relocmap_t *relocmap)
44 {
45         r_array_setlength(relocmap->records, 0);
46 }
47
48
49 long rvm_relocmap_add(rvm_relocmap_t *relocmap, rvm_reloctarget_t target, rvm_reloctype_t type, unsigned long offset, unsigned long label)
50 {
51         rvm_relocrecord_t record;
52         record.target = target;
53         record.type = type;
54         record.offset = offset;
55         record.label = label;
56
57         return r_array_add(relocmap->records, &record);
58 }
59
60
61 rvm_relocrecord_t *rvm_relocmap_get(rvm_relocmap_t *relocmap, unsigned long index)
62 {
63         if (index >= r_array_length(relocmap->records))
64                 return NULL;
65         return (rvm_relocrecord_t *)r_array_slot(relocmap->records, index);
66 }
67
68
69 unsigned long rvm_relocmap_length(rvm_relocmap_t *relocmap)
70 {
71         return r_array_length(relocmap->records);
72 }
73
74
75 int rvm_relocmap_relocate(rvm_relocmap_t *relocmap, rvm_codemap_t *codemap, rvm_asmins_t *code, rvm_codelabel_t **err)
76 {
77         unsigned long index;
78         rvm_relocrecord_t *reloc;
79         ruword value;
80
81         for (index = 0; index < r_array_length(relocmap->records); index++) {
82                 reloc = rvm_relocmap_get(relocmap, index);
83                 value = rvm_codemap_resolve(codemap, reloc->label, err);
84                 if (value == (ruword)-1)
85                         return -1;
86                 if (reloc->target == RVM_RELOC_CODE) {
87                         if (reloc->type == RVM_RELOC_BRANCH) {
88                                 code[reloc->offset].data.v.w = RVM_BYTE2CODE_OFFSET(value - (ruword)&code[reloc->offset]);
89                         } else if (reloc->type == RVM_RELOC_JUMP) {
90                                 code[reloc->offset].data.v.w = value - RVM_CODE2BYTE_OFFSET(1);
91                         } else if (reloc->type == RVM_RELOC_STRING) {
92                                 code[reloc->offset].data.v.w = value;
93                                 code[reloc->offset].data.size = r_strlen((char*)value);
94                         } else if (reloc->type == RVM_RELOC_BLOB) {
95                                 code[reloc->offset].data.v.w = value;
96                         } else {
97                                 code[reloc->offset].data.v.w = value;
98                         }
99                 } else if (reloc->target == RVM_RELOC_DATA){
100                         /*
101                          * TBD: No support for data relocation yet.
102                          */
103                 }
104         }
105         return 0;
106 }