1 /* $NetBSD: libdwarf_rw.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
5 * Copyright (c) 2010 Kai Wang
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include "_libdwarf.h"
31
32 __RCSID("$NetBSD: libdwarf_rw.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
33 ELFTC_VCSID("Id: libdwarf_rw.c 2952 2013-06-26 19:09:40Z kaiwang27 ");
34
35 uint64_t
_dwarf_read_lsb(uint8_t * data,uint64_t * offsetp,int bytes_to_read)36 _dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
37 {
38 uint64_t ret;
39 uint8_t *src;
40
41 src = data + *offsetp;
42
43 ret = 0;
44 switch (bytes_to_read) {
45 case 8:
46 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
47 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
48 case 4:
49 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
50 case 2:
51 ret |= ((uint64_t) src[1]) << 8;
52 case 1:
53 ret |= src[0];
54 break;
55 default:
56 return (0);
57 }
58
59 *offsetp += bytes_to_read;
60
61 return (ret);
62 }
63
64 uint64_t
_dwarf_decode_lsb(uint8_t ** data,int bytes_to_read)65 _dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
66 {
67 uint64_t ret;
68 uint8_t *src;
69
70 src = *data;
71
72 ret = 0;
73 switch (bytes_to_read) {
74 case 8:
75 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
76 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
77 case 4:
78 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
79 case 2:
80 ret |= ((uint64_t) src[1]) << 8;
81 case 1:
82 ret |= src[0];
83 break;
84 default:
85 return (0);
86 }
87
88 *data += bytes_to_read;
89
90 return (ret);
91 }
92
93 uint64_t
_dwarf_read_msb(uint8_t * data,uint64_t * offsetp,int bytes_to_read)94 _dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
95 {
96 uint64_t ret;
97 uint8_t *src;
98
99 src = data + *offsetp;
100
101 switch (bytes_to_read) {
102 case 1:
103 ret = src[0];
104 break;
105 case 2:
106 ret = src[1] | ((uint64_t) src[0]) << 8;
107 break;
108 case 4:
109 ret = src[3] | ((uint64_t) src[2]) << 8;
110 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
111 break;
112 case 8:
113 ret = src[7] | ((uint64_t) src[6]) << 8;
114 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
115 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
116 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
117 break;
118 default:
119 return (0);
120 }
121
122 *offsetp += bytes_to_read;
123
124 return (ret);
125 }
126
127 uint64_t
_dwarf_decode_msb(uint8_t ** data,int bytes_to_read)128 _dwarf_decode_msb(uint8_t **data, int bytes_to_read)
129 {
130 uint64_t ret;
131 uint8_t *src;
132
133 src = *data;
134
135 ret = 0;
136 switch (bytes_to_read) {
137 case 1:
138 ret = src[0];
139 break;
140 case 2:
141 ret = src[1] | ((uint64_t) src[0]) << 8;
142 break;
143 case 4:
144 ret = src[3] | ((uint64_t) src[2]) << 8;
145 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
146 break;
147 case 8:
148 ret = src[7] | ((uint64_t) src[6]) << 8;
149 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
150 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
151 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
152 break;
153 default:
154 return (0);
155 break;
156 }
157
158 *data += bytes_to_read;
159
160 return (ret);
161 }
162
163 void
_dwarf_write_lsb(uint8_t * data,uint64_t * offsetp,uint64_t value,int bytes_to_write)164 _dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
165 int bytes_to_write)
166 {
167 uint8_t *dst;
168
169 dst = data + *offsetp;
170
171 switch (bytes_to_write) {
172 case 8:
173 dst[7] = (value >> 56) & 0xff;
174 dst[6] = (value >> 48) & 0xff;
175 dst[5] = (value >> 40) & 0xff;
176 dst[4] = (value >> 32) & 0xff;
177 case 4:
178 dst[3] = (value >> 24) & 0xff;
179 dst[2] = (value >> 16) & 0xff;
180 case 2:
181 dst[1] = (value >> 8) & 0xff;
182 case 1:
183 dst[0] = value & 0xff;
184 break;
185 default:
186 return;
187 }
188
189 *offsetp += bytes_to_write;
190 }
191
192 int
_dwarf_write_lsb_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t value,int bytes_to_write,Dwarf_Error * error)193 _dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
194 uint64_t value, int bytes_to_write, Dwarf_Error *error)
195 {
196
197 assert(*size > 0);
198
199 while (*offsetp + bytes_to_write > *size) {
200 *size *= 2;
201 *block = realloc(*block, (size_t) *size);
202 if (*block == NULL) {
203 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
204 return (DW_DLE_MEMORY);
205 }
206 }
207
208 _dwarf_write_lsb(*block, offsetp, value, bytes_to_write);
209
210 return (DW_DLE_NONE);
211 }
212
213 void
_dwarf_write_msb(uint8_t * data,uint64_t * offsetp,uint64_t value,int bytes_to_write)214 _dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
215 int bytes_to_write)
216 {
217 uint8_t *dst;
218
219 dst = data + *offsetp;
220
221 switch (bytes_to_write) {
222 case 8:
223 dst[7] = value & 0xff;
224 dst[6] = (value >> 8) & 0xff;
225 dst[5] = (value >> 16) & 0xff;
226 dst[4] = (value >> 24) & 0xff;
227 value >>= 32;
228 case 4:
229 dst[3] = value & 0xff;
230 dst[2] = (value >> 8) & 0xff;
231 value >>= 16;
232 case 2:
233 dst[1] = value & 0xff;
234 value >>= 8;
235 case 1:
236 dst[0] = value & 0xff;
237 break;
238 default:
239 return;
240 }
241
242 *offsetp += bytes_to_write;
243 }
244
245 int
_dwarf_write_msb_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t value,int bytes_to_write,Dwarf_Error * error)246 _dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
247 uint64_t value, int bytes_to_write, Dwarf_Error *error)
248 {
249
250 assert(*size > 0);
251
252 while (*offsetp + bytes_to_write > *size) {
253 *size *= 2;
254 *block = realloc(*block, (size_t) *size);
255 if (*block == NULL) {
256 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
257 return (DW_DLE_MEMORY);
258 }
259 }
260
261 _dwarf_write_msb(*block, offsetp, value, bytes_to_write);
262
263 return (DW_DLE_NONE);
264 }
265
266 int64_t
_dwarf_read_sleb128(uint8_t * data,uint64_t * offsetp)267 _dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp)
268 {
269 int64_t ret = 0;
270 uint8_t b;
271 int shift = 0;
272 uint8_t *src;
273
274 src = data + *offsetp;
275
276 do {
277 b = *src++;
278 ret |= ((b & 0x7f) << shift);
279 (*offsetp)++;
280 shift += 7;
281 } while ((b & 0x80) != 0);
282
283 if (shift < 64 && (b & 0x40) != 0)
284 ret |= (-1 << shift);
285
286 return (ret);
287 }
288
289 int
_dwarf_write_sleb128(uint8_t * data,uint8_t * end,int64_t val)290 _dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val)
291 {
292 uint8_t *p;
293
294 p = data;
295
296 for (;;) {
297 if (p >= end)
298 return (-1);
299 *p = val & 0x7f;
300 val >>= 7;
301 if ((val == 0 && (*p & 0x40) == 0) ||
302 (val == -1 && (*p & 0x40) != 0)) {
303 p++;
304 break;
305 }
306 *p++ |= 0x80;
307 }
308
309 return (p - data);
310 }
311
312 int
_dwarf_write_sleb128_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,int64_t val,Dwarf_Error * error)313 _dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
314 int64_t val, Dwarf_Error *error)
315 {
316 int len;
317
318 assert(*size > 0);
319
320 while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size,
321 val)) < 0) {
322 *size *= 2;
323 *block = realloc(*block, (size_t) *size);
324 if (*block == NULL) {
325 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
326 return (DW_DLE_MEMORY);
327 }
328 }
329
330 *offsetp += len;
331
332 return (DW_DLE_NONE);
333 }
334
335 uint64_t
_dwarf_read_uleb128(uint8_t * data,uint64_t * offsetp)336 _dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp)
337 {
338 uint64_t ret = 0;
339 uint8_t b;
340 int shift = 0;
341 uint8_t *src;
342
343 src = data + *offsetp;
344
345 do {
346 b = *src++;
347 ret |= ((b & 0x7f) << shift);
348 (*offsetp)++;
349 shift += 7;
350 } while ((b & 0x80) != 0);
351
352 return (ret);
353 }
354
355 int
_dwarf_write_uleb128(uint8_t * data,uint8_t * end,uint64_t val)356 _dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val)
357 {
358 uint8_t *p;
359
360 p = data;
361
362 do {
363 if (p >= end)
364 return (-1);
365 *p = val & 0x7f;
366 val >>= 7;
367 if (val > 0)
368 *p |= 0x80;
369 p++;
370 } while (val > 0);
371
372 return (p - data);
373 }
374
375 int
_dwarf_write_uleb128_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t val,Dwarf_Error * error)376 _dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
377 uint64_t val, Dwarf_Error *error)
378 {
379 int len;
380
381 assert(*size > 0);
382
383 while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size,
384 val)) < 0) {
385 *size *= 2;
386 *block = realloc(*block, (size_t) *size);
387 if (*block == NULL) {
388 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
389 return (DW_DLE_MEMORY);
390 }
391 }
392
393 *offsetp += len;
394
395 return (DW_DLE_NONE);
396 }
397
398 int64_t
_dwarf_decode_sleb128(uint8_t ** dp)399 _dwarf_decode_sleb128(uint8_t **dp)
400 {
401 int64_t ret = 0;
402 uint8_t b;
403 int shift = 0;
404
405 uint8_t *src = *dp;
406
407 do {
408 b = *src++;
409 ret |= ((b & 0x7f) << shift);
410 shift += 7;
411 } while ((b & 0x80) != 0);
412
413 if (shift < 64 && (b & 0x40) != 0)
414 ret |= (-1 << shift);
415
416 *dp = src;
417
418 return (ret);
419 }
420
421 uint64_t
_dwarf_decode_uleb128(uint8_t ** dp)422 _dwarf_decode_uleb128(uint8_t **dp)
423 {
424 uint64_t ret = 0;
425 uint8_t b;
426 int shift = 0;
427
428 uint8_t *src = *dp;
429
430 do {
431 b = *src++;
432 ret |= ((b & 0x7f) << shift);
433 shift += 7;
434 } while ((b & 0x80) != 0);
435
436 *dp = src;
437
438 return (ret);
439 }
440
441 char *
_dwarf_read_string(void * data,Dwarf_Unsigned size,uint64_t * offsetp)442 _dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp)
443 {
444 char *ret, *src;
445
446 ret = src = (char *) data + *offsetp;
447
448 while (*src != '\0' && *offsetp < size) {
449 src++;
450 (*offsetp)++;
451 }
452
453 if (*src == '\0' && *offsetp < size)
454 (*offsetp)++;
455
456 return (ret);
457 }
458
459 void
_dwarf_write_string(void * data,uint64_t * offsetp,char * string)460 _dwarf_write_string(void *data, uint64_t *offsetp, char *string)
461 {
462 char *dst;
463
464 dst = (char *) data + *offsetp;
465 strcpy(dst, string);
466 (*offsetp) += strlen(string) + 1;
467 }
468
469 int
_dwarf_write_string_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,char * string,Dwarf_Error * error)470 _dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
471 char *string, Dwarf_Error *error)
472 {
473 size_t len;
474
475 assert(*size > 0);
476
477 len = strlen(string) + 1;
478 while (*offsetp + len > *size) {
479 *size *= 2;
480 *block = realloc(*block, (size_t) *size);
481 if (*block == NULL) {
482 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
483 return (DW_DLE_MEMORY);
484 }
485 }
486
487 _dwarf_write_string(*block, offsetp, string);
488
489 return (DW_DLE_NONE);
490 }
491
492 uint8_t *
_dwarf_read_block(void * data,uint64_t * offsetp,uint64_t length)493 _dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length)
494 {
495 uint8_t *ret, *src;
496
497 ret = src = (uint8_t *) data + *offsetp;
498
499 (*offsetp) += length;
500
501 return (ret);
502 }
503
504 void
_dwarf_write_block(void * data,uint64_t * offsetp,uint8_t * blk,uint64_t length)505 _dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk,
506 uint64_t length)
507 {
508 uint8_t *dst;
509
510 dst = (uint8_t *) data + *offsetp;
511 memcpy(dst, blk, length);
512 (*offsetp) += length;
513 }
514
515 int
_dwarf_write_block_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint8_t * blk,uint64_t length,Dwarf_Error * error)516 _dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
517 uint8_t *blk, uint64_t length, Dwarf_Error *error)
518 {
519
520 assert(*size > 0);
521
522 while (*offsetp + length > *size) {
523 *size *= 2;
524 *block = realloc(*block, (size_t) *size);
525 if (*block == NULL) {
526 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
527 return (DW_DLE_MEMORY);
528 }
529 }
530
531 _dwarf_write_block(*block, offsetp, blk, length);
532
533 return (DW_DLE_NONE);
534 }
535
536 void
_dwarf_write_padding(void * data,uint64_t * offsetp,uint8_t byte,uint64_t length)537 _dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte,
538 uint64_t length)
539 {
540 uint8_t *dst;
541
542 dst = (uint8_t *) data + *offsetp;
543 memset(dst, byte, length);
544 (*offsetp) += length;
545 }
546
547 int
_dwarf_write_padding_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint8_t byte,uint64_t cnt,Dwarf_Error * error)548 _dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
549 uint8_t byte, uint64_t cnt, Dwarf_Error *error)
550 {
551 assert(*size > 0);
552
553 while (*offsetp + cnt > *size) {
554 *size *= 2;
555 *block = realloc(*block, (size_t) *size);
556 if (*block == NULL) {
557 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
558 return (DW_DLE_MEMORY);
559 }
560 }
561
562 _dwarf_write_padding(*block, offsetp, byte, cnt);
563
564 return (DW_DLE_NONE);
565 }
566