1
/*
2
 * $Id$
3
 *
4
 * Copyright (C) 2003-2009 JNode.org
5
 *
6
 * This library is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful, but 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
14
 * License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this library; If not, write to the Free Software Foundation, Inc., 
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20
 
21
package org.jnode.vm;
22
23
import org.jnode.system.MemoryScanner;
24
import org.jnode.annotation.MagicPermission;
25
import org.vmmagic.unboxed.Address;
26
import org.vmmagic.unboxed.Offset;
27
28
29
/**
30
 * @author Ewout Prangsma (epr@users.sourceforge.net)
31
 */
32
@MagicPermission
33
final class MemoryScannerImpl implements MemoryScanner {
34
35
    /**
36
     * @see org.jnode.system.MemoryScanner#findInt16(org.jnode.vm.Address, int, int, int)
37
     */
38
    public Address findInt16(Address start, int size, int match, int stepSize) {
39
        int offset = 0;
40
        match &= 0xFFFF;
41
        size -= 1;
42
        while (offset < size) {
43
            if ((start.loadShort(Offset.fromIntSignExtend(offset)) & 0xFFFF) == match) {
44
                return start.add(offset);
45
            } else {
46
                offset += stepSize;
47
            }
48
        }
49
        return null;
50
    }
51
52
    /**
53
     * @see org.jnode.system.MemoryScanner#findInt32(org.jnode.vm.Address, int, int, int)
54
     */
55
    public Address findInt32(Address start, int size, int match, int stepSize) {
56
        int offset = 0;
57
        size -= 3;
58
        while (offset < size) {
59
            if (start.loadInt(Offset.fromIntSignExtend(offset)) == match) {
60
                return start.add(offset);
61
            } else {
62
                offset += stepSize;
63
            }
64
        }
65
        return null;
66
    }
67
68
    /**
69
     * @see org.jnode.system.MemoryScanner#findInt64(org.jnode.vm.Address, int, long, int)
70
     */
71
    public Address findInt64(Address start, int size, long match, int stepSize) {
72
        int offset = 0;
73
        size -= 7;
74
        while (offset < size) {
75
            if (start.loadLong(Offset.fromIntSignExtend(offset)) == match) {
76
                return start.add(offset);
77
            } else {
78
                offset += stepSize;
79
            }
80
        }
81
        return null;
82
    }
83
84
    /**
85
     * @see org.jnode.system.MemoryScanner#findInt8(org.jnode.vm.Address, int, int, int)
86
     */
87
    public Address findInt8(Address start, int size, int match, int stepSize) {
88
        int offset = 0;
89
        match &= 0xFF;
90
        while (offset < size) {
91
            if ((start.loadByte(Offset.fromIntSignExtend(offset)) & 0xFF) == match) {
92
                return start.add(offset);
93
            } else {
94
                offset += stepSize;
95
            }
96
        }
97
        return null;
98
    }
99
100
    /**
101
     * @see org.jnode.system.MemoryScanner#findInt8Array(org.jnode.vm.Address, int, byte[], int, int, int)
102
     */
103
    public Address findInt8Array(Address start, int size, byte[] match,
104
                                 int matchOffset, int matchLength, int stepSize) {
105
        int offset = 0;
106
        size -= (matchLength - 1);
107
        final int match0 = match[matchOffset] & 0xFF;
108
        while (offset < size) {
109
            if ((start.loadByte(Offset.fromIntSignExtend(offset)) & 0xFF) == match0) {
110
                if (isMatch(start, offset, match, matchOffset, matchLength)) {
111
                    return start.add(offset);
112
                }
113
            }
114
            offset += stepSize;
115
        }
116
        return null;
117
    }
118
119
    /**
120
     * @see org.jnode.system.MemoryScanner#findInt16Array(org.jnode.vm.Address, int, char[], int, int, int)
121
     */
122
    public Address findInt16Array(Address start, int size, char[] match,
123
                                  int matchOffset, int matchLength, int stepSize) {
124
        int offset = 0;
125
        size -= ((matchLength * 2) - 1);
126
        final int match0 = match[matchOffset] & 0xFFFF;
127
        while (offset < size) {
128
            if ((start.loadChar(Offset.fromIntSignExtend(offset)) & 0xFFFF) == match0) {
129
                if (isMatch(start, offset, match, matchOffset, matchLength)) {
130
                    return start.add(offset);
131
                }
132
            }
133
            offset += stepSize;
134
        }
135
        return null;
136
    }
137
138
    /**
139
     * @see org.jnode.system.MemoryScanner#findInt16Array(org.jnode.vm.Address, int, short[], int, int, int)
140
     */
141
    public Address findInt16Array(Address start, int size, short[] match,
142
                                  int matchOffset, int matchLength, int stepSize) {
143
        int offset = 0;
144
        size -= ((matchLength * 2) - 1);
145
        final int match0 = match[matchOffset] & 0xFFFF;
146
        while (offset < size) {
147
            if ((start.loadShort(Offset.fromIntSignExtend(offset)) & 0xFFFF) == match0) {
148
                if (isMatch(start, offset, match, matchOffset, matchLength)) {
149
                    return start.add(offset);
150
                }
151
            }
152
            offset += stepSize;
153
        }
154
        return null;
155
    }
156
157
    /**
158
     * @see org.jnode.system.MemoryScanner#findInt32Array(org.jnode.vm.Address, int, int[], int, int, int)
159
     */
160
    public Address findInt32Array(Address start, int size, int[] match,
161
                                  int matchOffset, int matchLength, int stepSize) {
162
        int offset = 0;
163
        size -= ((matchLength * 4) - 1);
164
        final int match0 = match[matchOffset];
165
        while (offset < size) {
166
            if (start.loadInt(Offset.fromIntSignExtend(offset)) == match0) {
167
                if (isMatch(start, offset, match, matchOffset, matchLength)) {
168
                    return start.add(offset);
169
                }
170
            }
171
            offset += stepSize;
172
        }
173
        return null;
174
    }
175
176
    /**
177
     * @see org.jnode.system.MemoryScanner#findInt64Array(org.jnode.vm.Address, int, long[], int, int, int)
178
     */
179
    public Address findInt64Array(Address start, int size, long[] match,
180
                                  int matchOffset, int matchLength, int stepSize) {
181
        int offset = 0;
182
        size -= ((matchLength * 8) - 1);
183
        final long match0 = match[matchOffset];
184
        while (offset < size) {
185
            if (start.loadLong(Offset.fromIntSignExtend(offset)) == match0) {
186
                if (isMatch(start, offset, match, matchOffset, matchLength)) {
187
                    return start.add(offset);
188
                }
189
            }
190
            offset += stepSize;
191
        }
192
        return null;
193
    }
194
195
    private final boolean isMatch(Address start, int offset, byte[] match,
196
                                  int matchOffset, int matchLength) {
197
        for (int i = 0; i < matchLength; i++) {
198
            if ((start.loadByte(Offset.fromIntSignExtend(offset + i)) & 0xFF) != (match[matchOffset + i] & 0xFF)) {
199
                return false;
200
            }
201
        }
202
        return true;
203
    }
204
205
    private final boolean isMatch(Address start, int offset, char[] match,
206
                                  int matchOffset, int matchLength) {
207
        for (int i = 0; i < matchLength; i++) {
208
            if ((start.loadChar(Offset.fromIntSignExtend(offset + (i * 2))) & 0xFFFF) !=
209
                (match[matchOffset + i] & 0xFFFF)) {
210
                return false;
211
            }
212
        }
213
        return true;
214
    }
215
216
    private final boolean isMatch(Address start, int offset, short[] match,
217
                                  int matchOffset, int matchLength) {
218
        for (int i = 0; i < matchLength; i++) {
219
            if ((start.loadShort(Offset.fromIntSignExtend(offset + (i * 2))) & 0xFFFF) !=
220
                (match[matchOffset + i] & 0xFFFF)) {
221
                return false;
222
            }
223
        }
224
        return true;
225
    }
226
227
    private final boolean isMatch(Address start, int offset, int[] match,
228
                                  int matchOffset, int matchLength) {
229
        for (int i = 0; i < matchLength; i++) {
230
            if (start.loadInt(Offset.fromIntSignExtend(offset + (i * 4))) != match[matchOffset + i]) {
231
                return false;
232
            }
233
        }
234
        return true;
235
    }
236
237
    private final boolean isMatch(Address start, int offset, long[] match,
238
                                  int matchOffset, int matchLength) {
239
        for (int i = 0; i < matchLength; i++) {
240
            if (start.loadLong(Offset.fromIntSignExtend(offset + (i * 8))) != match[matchOffset + i]) {
241
                return false;
242
            }
243
        }
244
        return true;
245
    }
246
}