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