Fix: don't perform unaligned integer read/writes
[babeltrace.git] / formats / ctf / types / integer.c
CommitLineData
6dc2ca62
MD
1/*
2 * Common Trace Format
3 *
4 * Integers read/write functions.
5 *
64fa3fec
MD
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6dc2ca62 9 *
ccd7e1c8
MD
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
de0ba614 16 *
ccd7e1c8
MD
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
c462e188
MD
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
6dc2ca62
MD
27 */
28
4c8bfb7e
MD
29#include <babeltrace/ctf/types.h>
30#include <babeltrace/bitfield.h>
6dc2ca62
MD
31#include <stdint.h>
32#include <glib.h>
9b0422a0 33#include <babeltrace/endian.h>
6dc2ca62 34
5385cf15
MD
35/*
36 * The aligned read/write functions are expected to be faster than the
37 * bitfield variants. They will be enabled eventually as an
38 * optimisation.
39 */
40
7fe00194 41static
1cf393f6 42int _aligned_integer_read(struct bt_stream_pos *ppos,
0d69b916 43 struct bt_definition *definition)
6dc2ca62 44{
d11e9c49
MD
45 struct definition_integer *integer_definition =
46 container_of(definition, struct definition_integer, p);
47 const struct declaration_integer *integer_declaration =
48 integer_definition->declaration;
46322b33 49 struct ctf_stream_pos *pos = ctf_pos(ppos);
f6625916 50 int rbo = (integer_declaration->byte_order != BYTE_ORDER); /* reverse byte order */
6dc2ca62 51
70fd5a51
MD
52 if (!ctf_align_pos(pos, integer_declaration->p.alignment))
53 return -EFAULT;
6dc2ca62 54
c5e74408
MD
55 if (!ctf_pos_access_ok(pos, integer_declaration->len))
56 return -EFAULT;
57
670977d3 58 assert(!(pos->offset % CHAR_BIT));
d11e9c49
MD
59 if (!integer_declaration->signedness) {
60 switch (integer_declaration->len) {
61 case 8:
62 {
63 uint8_t v;
64
190e4503 65 memcpy(&v, ctf_get_pos_addr(pos), sizeof(v));
d11e9c49
MD
66 integer_definition->value._unsigned = v;
67 break;
68 }
69 case 16:
70 {
71 uint16_t v;
72
190e4503 73 memcpy(&v, ctf_get_pos_addr(pos), sizeof(v));
d11e9c49
MD
74 integer_definition->value._unsigned =
75 rbo ? GUINT16_SWAP_LE_BE(v) : v;
76 break;
77 }
78 case 32:
79 {
80 uint32_t v;
81
190e4503 82 memcpy(&v, ctf_get_pos_addr(pos), sizeof(v));
d11e9c49
MD
83 integer_definition->value._unsigned =
84 rbo ? GUINT32_SWAP_LE_BE(v) : v;
85 break;
86 }
87 case 64:
88 {
89 uint64_t v;
90
190e4503 91 memcpy(&v, ctf_get_pos_addr(pos), sizeof(v));
d11e9c49
MD
92 integer_definition->value._unsigned =
93 rbo ? GUINT64_SWAP_LE_BE(v) : v;
94 break;
95 }
96 default:
97 assert(0);
98 }
99 } else {
100 switch (integer_declaration->len) {
101 case 8:
102 {
103 int8_t v;
104
190e4503 105 memcpy(&v, ctf_get_pos_addr(pos), sizeof(v));
d11e9c49
MD
106 integer_definition->value._signed = v;
107 break;
108 }
109 case 16:
110 {
111 int16_t v;
112
190e4503 113 memcpy(&v, ctf_get_pos_addr(pos), sizeof(v));
d11e9c49 114 integer_definition->value._signed =
27265cb3 115 rbo ? (int16_t) GUINT16_SWAP_LE_BE(v) : v;
d11e9c49
MD
116 break;
117 }
118 case 32:
119 {
120 int32_t v;
121
190e4503 122 memcpy(&v, ctf_get_pos_addr(pos), sizeof(v));
d11e9c49 123 integer_definition->value._signed =
27265cb3 124 rbo ? (int32_t) GUINT32_SWAP_LE_BE(v) : v;
d11e9c49
MD
125 break;
126 }
127 case 64:
128 {
129 int64_t v;
130
190e4503 131 memcpy(&v, ctf_get_pos_addr(pos), sizeof(v));
d11e9c49 132 integer_definition->value._signed =
27265cb3 133 rbo ? (int64_t) GUINT64_SWAP_LE_BE(v) : v;
d11e9c49
MD
134 break;
135 }
136 default:
137 assert(0);
138 }
6dc2ca62 139 }
70fd5a51
MD
140 if (!ctf_move_pos(pos, integer_declaration->len))
141 return -EFAULT;
c5e74408 142 return 0;
6dc2ca62
MD
143}
144
7fe00194 145static
1cf393f6 146int _aligned_integer_write(struct bt_stream_pos *ppos,
0d69b916 147 struct bt_definition *definition)
6dc2ca62 148{
d11e9c49
MD
149 struct definition_integer *integer_definition =
150 container_of(definition, struct definition_integer, p);
151 const struct declaration_integer *integer_declaration =
152 integer_definition->declaration;
46322b33 153 struct ctf_stream_pos *pos = ctf_pos(ppos);
f6625916 154 int rbo = (integer_declaration->byte_order != BYTE_ORDER); /* reverse byte order */
6dc2ca62 155
70fd5a51
MD
156 if (!ctf_align_pos(pos, integer_declaration->p.alignment))
157 return -EFAULT;
6dc2ca62 158
c5e74408
MD
159 if (!ctf_pos_access_ok(pos, integer_declaration->len))
160 return -EFAULT;
161
670977d3 162 assert(!(pos->offset % CHAR_BIT));
bed864a7 163 if (pos->dummy)
6dc2ca62 164 goto end;
d11e9c49 165 if (!integer_declaration->signedness) {
d11e9c49 166 switch (integer_declaration->len) {
190e4503
MD
167 case 8:
168 {
169 uint8_t v = integer_definition->value._unsigned;
170
171 memcpy(ctf_get_pos_addr(pos), &v, sizeof(v));
d11e9c49 172 break;
190e4503 173 }
d11e9c49 174 case 16:
190e4503
MD
175 {
176 uint16_t v = integer_definition->value._unsigned;
177
178 if (rbo)
179 v = GUINT16_SWAP_LE_BE(v);
180 memcpy(ctf_get_pos_addr(pos), &v, sizeof(v));
d11e9c49 181 break;
190e4503 182 }
d11e9c49 183 case 32:
190e4503
MD
184 {
185 uint32_t v = integer_definition->value._unsigned;
186
187 if (rbo)
188 v = GUINT32_SWAP_LE_BE(v);
189 memcpy(ctf_get_pos_addr(pos), &v, sizeof(v));
d11e9c49 190 break;
190e4503 191 }
d11e9c49 192 case 64:
190e4503
MD
193 {
194 uint64_t v = integer_definition->value._unsigned;
195
196 if (rbo)
197 v = GUINT64_SWAP_LE_BE(v);
198 memcpy(ctf_get_pos_addr(pos), &v, sizeof(v));
d11e9c49 199 break;
190e4503 200 }
d11e9c49
MD
201 default:
202 assert(0);
203 }
204 } else {
d11e9c49 205 switch (integer_declaration->len) {
190e4503
MD
206 case 8:
207 {
208 uint8_t v = integer_definition->value._signed;
209
210 memcpy(ctf_get_pos_addr(pos), &v, sizeof(v));
d11e9c49 211 break;
190e4503 212 }
d11e9c49 213 case 16:
190e4503
MD
214 {
215 int16_t v = integer_definition->value._signed;
216
217 if (rbo)
218 v = GUINT16_SWAP_LE_BE(v);
219 memcpy(ctf_get_pos_addr(pos), &v, sizeof(v));
d11e9c49 220 break;
190e4503 221 }
d11e9c49 222 case 32:
190e4503
MD
223 {
224 int32_t v = integer_definition->value._signed;
225
226 if (rbo)
227 v = GUINT32_SWAP_LE_BE(v);
228 memcpy(ctf_get_pos_addr(pos), &v, sizeof(v));
d11e9c49 229 break;
190e4503 230 }
d11e9c49 231 case 64:
190e4503
MD
232 {
233 int64_t v = integer_definition->value._signed;
234
235 if (rbo)
236 v = GUINT64_SWAP_LE_BE(v);
237 memcpy(ctf_get_pos_addr(pos), &v, sizeof(v));
d11e9c49 238 break;
190e4503 239 }
d11e9c49
MD
240 default:
241 assert(0);
242 }
6dc2ca62
MD
243 }
244end:
70fd5a51
MD
245 if (!ctf_move_pos(pos, integer_declaration->len))
246 return -EFAULT;
c5e74408 247 return 0;
6dc2ca62
MD
248}
249
0d69b916 250int ctf_integer_read(struct bt_stream_pos *ppos, struct bt_definition *definition)
6dc2ca62 251{
d11e9c49
MD
252 struct definition_integer *integer_definition =
253 container_of(definition, struct definition_integer, p);
254 const struct declaration_integer *integer_declaration =
255 integer_definition->declaration;
46322b33 256 struct ctf_stream_pos *pos = ctf_pos(ppos);
6dc2ca62 257
5385cf15
MD
258 if (!(integer_declaration->p.alignment % CHAR_BIT)
259 && !(integer_declaration->len % CHAR_BIT)) {
c5e74408 260 return _aligned_integer_read(ppos, definition);
5385cf15
MD
261 }
262
70fd5a51
MD
263 if (!ctf_align_pos(pos, integer_declaration->p.alignment))
264 return -EFAULT;
c5e74408
MD
265
266 if (!ctf_pos_access_ok(pos, integer_declaration->len))
267 return -EFAULT;
268
d11e9c49
MD
269 if (!integer_declaration->signedness) {
270 if (integer_declaration->byte_order == LITTLE_ENDIAN)
47415068 271 bt_bitfield_read_le(mmap_align_addr(pos->base_mma) +
190e4503 272 pos->mmap_base_offset, unsigned char,
d11e9c49
MD
273 pos->offset, integer_declaration->len,
274 &integer_definition->value._unsigned);
275 else
47415068 276 bt_bitfield_read_be(mmap_align_addr(pos->base_mma) +
190e4503 277 pos->mmap_base_offset, unsigned char,
d11e9c49
MD
278 pos->offset, integer_declaration->len,
279 &integer_definition->value._unsigned);
280 } else {
281 if (integer_declaration->byte_order == LITTLE_ENDIAN)
47415068 282 bt_bitfield_read_le(mmap_align_addr(pos->base_mma) +
190e4503 283 pos->mmap_base_offset, unsigned char,
d11e9c49
MD
284 pos->offset, integer_declaration->len,
285 &integer_definition->value._signed);
286 else
47415068 287 bt_bitfield_read_be(mmap_align_addr(pos->base_mma) +
190e4503 288 pos->mmap_base_offset, unsigned char,
d11e9c49
MD
289 pos->offset, integer_declaration->len,
290 &integer_definition->value._signed);
6dc2ca62 291 }
70fd5a51
MD
292 if (!ctf_move_pos(pos, integer_declaration->len))
293 return -EFAULT;
c5e74408 294 return 0;
6dc2ca62 295}
7fe00194 296
0d69b916 297int ctf_integer_write(struct bt_stream_pos *ppos, struct bt_definition *definition)
7fe00194 298{
d11e9c49
MD
299 struct definition_integer *integer_definition =
300 container_of(definition, struct definition_integer, p);
301 const struct declaration_integer *integer_declaration =
302 integer_definition->declaration;
46322b33
MD
303 struct ctf_stream_pos *pos = ctf_pos(ppos);
304
5385cf15
MD
305 if (!(integer_declaration->p.alignment % CHAR_BIT)
306 && !(integer_declaration->len % CHAR_BIT)) {
c5e74408 307 return _aligned_integer_write(ppos, definition);
5385cf15
MD
308 }
309
70fd5a51
MD
310 if (!ctf_align_pos(pos, integer_declaration->p.alignment))
311 return -EFAULT;
c5e74408
MD
312
313 if (!ctf_pos_access_ok(pos, integer_declaration->len))
314 return -EFAULT;
315
7fe00194
MD
316 if (pos->dummy)
317 goto end;
d11e9c49
MD
318 if (!integer_declaration->signedness) {
319 if (integer_declaration->byte_order == LITTLE_ENDIAN)
47415068 320 bt_bitfield_write_le(mmap_align_addr(pos->base_mma) +
190e4503 321 pos->mmap_base_offset, unsigned char,
d11e9c49
MD
322 pos->offset, integer_declaration->len,
323 integer_definition->value._unsigned);
324 else
47415068 325 bt_bitfield_write_be(mmap_align_addr(pos->base_mma) +
190e4503 326 pos->mmap_base_offset, unsigned char,
d11e9c49
MD
327 pos->offset, integer_declaration->len,
328 integer_definition->value._unsigned);
329 } else {
330 if (integer_declaration->byte_order == LITTLE_ENDIAN)
47415068 331 bt_bitfield_write_le(mmap_align_addr(pos->base_mma) +
190e4503 332 pos->mmap_base_offset, unsigned char,
d11e9c49
MD
333 pos->offset, integer_declaration->len,
334 integer_definition->value._signed);
335 else
47415068 336 bt_bitfield_write_be(mmap_align_addr(pos->base_mma) +
190e4503 337 pos->mmap_base_offset, unsigned char,
d11e9c49
MD
338 pos->offset, integer_declaration->len,
339 integer_definition->value._signed);
340 }
7fe00194 341end:
70fd5a51
MD
342 if (!ctf_move_pos(pos, integer_declaration->len))
343 return -EFAULT;
c5e74408 344 return 0;
7fe00194 345}
This page took 0.047768 seconds and 4 git commands to generate.