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 2952 2013-06-26 19:09:40Z kaiwang27 $");
31 
32 uint64_t
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 	case 4:
46 		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
47 	case 2:
48 		ret |= ((uint64_t) src[1]) << 8;
49 	case 1:
50 		ret |= src[0];
51 		break;
52 	default:
53 		return (0);
54 	}
55 
56 	*offsetp += bytes_to_read;
57 
58 	return (ret);
59 }
60 
61 uint64_t
62 _dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
63 {
64 	uint64_t ret;
65 	uint8_t *src;
66 
67 	src = *data;
68 
69 	ret = 0;
70 	switch (bytes_to_read) {
71 	case 8:
72 		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
73 		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
74 	case 4:
75 		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
76 	case 2:
77 		ret |= ((uint64_t) src[1]) << 8;
78 	case 1:
79 		ret |= src[0];
80 		break;
81 	default:
82 		return (0);
83 	}
84 
85 	*data += bytes_to_read;
86 
87 	return (ret);
88 }
89 
90 uint64_t
91 _dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
92 {
93 	uint64_t ret;
94 	uint8_t *src;
95 
96 	src = data + *offsetp;
97 
98 	switch (bytes_to_read) {
99 	case 1:
100 		ret = src[0];
101 		break;
102 	case 2:
103 		ret = src[1] | ((uint64_t) src[0]) << 8;
104 		break;
105 	case 4:
106 		ret = src[3] | ((uint64_t) src[2]) << 8;
107 		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
108 		break;
109 	case 8:
110 		ret = src[7] | ((uint64_t) src[6]) << 8;
111 		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
112 		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
113 		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
114 		break;
115 	default:
116 		return (0);
117 	}
118 
119 	*offsetp += bytes_to_read;
120 
121 	return (ret);
122 }
123 
124 uint64_t
125 _dwarf_decode_msb(uint8_t **data, int bytes_to_read)
126 {
127 	uint64_t ret;
128 	uint8_t *src;
129 
130 	src = *data;
131 
132 	ret = 0;
133 	switch (bytes_to_read) {
134 	case 1:
135 		ret = src[0];
136 		break;
137 	case 2:
138 		ret = src[1] | ((uint64_t) src[0]) << 8;
139 		break;
140 	case 4:
141 		ret = src[3] | ((uint64_t) src[2]) << 8;
142 		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
143 		break;
144 	case 8:
145 		ret = src[7] | ((uint64_t) src[6]) << 8;
146 		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
147 		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
148 		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
149 		break;
150 	default:
151 		return (0);
152 		break;
153 	}
154 
155 	*data += bytes_to_read;
156 
157 	return (ret);
158 }
159 
160 void
161 _dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
162     int bytes_to_write)
163 {
164 	uint8_t *dst;
165 
166 	dst = data + *offsetp;
167 
168 	switch (bytes_to_write) {
169 	case 8:
170 		dst[7] = (value >> 56) & 0xff;
171 		dst[6] = (value >> 48) & 0xff;
172 		dst[5] = (value >> 40) & 0xff;
173 		dst[4] = (value >> 32) & 0xff;
174 	case 4:
175 		dst[3] = (value >> 24) & 0xff;
176 		dst[2] = (value >> 16) & 0xff;
177 	case 2:
178 		dst[1] = (value >> 8) & 0xff;
179 	case 1:
180 		dst[0] = value & 0xff;
181 		break;
182 	default:
183 		return;
184 	}
185 
186 	*offsetp += bytes_to_write;
187 }
188 
189 int
190 _dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
191     uint64_t value, int bytes_to_write, Dwarf_Error *error)
192 {
193 
194 	assert(*size > 0);
195 
196 	while (*offsetp + bytes_to_write > *size) {
197 		*size *= 2;
198 		*block = realloc(*block, (size_t) *size);
199 		if (*block == NULL) {
200 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
201 			return (DW_DLE_MEMORY);
202 		}
203 	}
204 
205 	_dwarf_write_lsb(*block, offsetp, value, bytes_to_write);
206 
207 	return (DW_DLE_NONE);
208 }
209 
210 void
211 _dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
212     int bytes_to_write)
213 {
214 	uint8_t *dst;
215 
216 	dst = data + *offsetp;
217 
218 	switch (bytes_to_write) {
219 	case 8:
220 		dst[7] = value & 0xff;
221 		dst[6] = (value >> 8) & 0xff;
222 		dst[5] = (value >> 16) & 0xff;
223 		dst[4] = (value >> 24) & 0xff;
224 		value >>= 32;
225 	case 4:
226 		dst[3] = value & 0xff;
227 		dst[2] = (value >> 8) & 0xff;
228 		value >>= 16;
229 	case 2:
230 		dst[1] = value & 0xff;
231 		value >>= 8;
232 	case 1:
233 		dst[0] = value & 0xff;
234 		break;
235 	default:
236 		return;
237 	}
238 
239 	*offsetp += bytes_to_write;
240 }
241 
242 int
243 _dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
244     uint64_t value, int bytes_to_write, Dwarf_Error *error)
245 {
246 
247 	assert(*size > 0);
248 
249 	while (*offsetp + bytes_to_write > *size) {
250 		*size *= 2;
251 		*block = realloc(*block, (size_t) *size);
252 		if (*block == NULL) {
253 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
254 			return (DW_DLE_MEMORY);
255 		}
256 	}
257 
258 	_dwarf_write_msb(*block, offsetp, value, bytes_to_write);
259 
260 	return (DW_DLE_NONE);
261 }
262 
263 int64_t
264 _dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp)
265 {
266 	int64_t ret = 0;
267 	uint8_t b;
268 	int shift = 0;
269 	uint8_t *src;
270 
271 	src = data + *offsetp;
272 
273 	do {
274 		b = *src++;
275 		ret |= ((b & 0x7f) << shift);
276 		(*offsetp)++;
277 		shift += 7;
278 	} while ((b & 0x80) != 0);
279 
280 	if (shift < 64 && (b & 0x40) != 0)
281 		ret |= (-1 << shift);
282 
283 	return (ret);
284 }
285 
286 int
287 _dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val)
288 {
289 	uint8_t *p;
290 
291 	p = data;
292 
293 	for (;;) {
294 		if (p >= end)
295 			return (-1);
296 		*p = val & 0x7f;
297 		val >>= 7;
298 		if ((val == 0 && (*p & 0x40) == 0) ||
299 		    (val == -1 && (*p & 0x40) != 0)) {
300 			p++;
301 			break;
302 		}
303 		*p++ |= 0x80;
304 	}
305 
306 	return (p - data);
307 }
308 
309 int
310 _dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
311     int64_t val, Dwarf_Error *error)
312 {
313 	int len;
314 
315 	assert(*size > 0);
316 
317 	while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size,
318 	    val)) < 0) {
319 		*size *= 2;
320 		*block = realloc(*block, (size_t) *size);
321 		if (*block == NULL) {
322 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
323 			return (DW_DLE_MEMORY);
324 		}
325 	}
326 
327 	*offsetp += len;
328 
329 	return (DW_DLE_NONE);
330 }
331 
332 uint64_t
333 _dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp)
334 {
335 	uint64_t ret = 0;
336 	uint8_t b;
337 	int shift = 0;
338 	uint8_t *src;
339 
340 	src = data + *offsetp;
341 
342 	do {
343 		b = *src++;
344 		ret |= ((b & 0x7f) << shift);
345 		(*offsetp)++;
346 		shift += 7;
347 	} while ((b & 0x80) != 0);
348 
349 	return (ret);
350 }
351 
352 int
353 _dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val)
354 {
355 	uint8_t *p;
356 
357 	p = data;
358 
359 	do {
360 		if (p >= end)
361 			return (-1);
362 		*p = val & 0x7f;
363 		val >>= 7;
364 		if (val > 0)
365 			*p |= 0x80;
366 		p++;
367 	} while (val > 0);
368 
369 	return (p - data);
370 }
371 
372 int
373 _dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
374     uint64_t val, Dwarf_Error *error)
375 {
376 	int len;
377 
378 	assert(*size > 0);
379 
380 	while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size,
381 	    val)) < 0) {
382 		*size *= 2;
383 		*block = realloc(*block, (size_t) *size);
384 		if (*block == NULL) {
385 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
386 			return (DW_DLE_MEMORY);
387 		}
388 	}
389 
390 	*offsetp += len;
391 
392 	return (DW_DLE_NONE);
393 }
394 
395 int64_t
396 _dwarf_decode_sleb128(uint8_t **dp)
397 {
398 	int64_t ret = 0;
399 	uint8_t b;
400 	int shift = 0;
401 
402 	uint8_t *src = *dp;
403 
404 	do {
405 		b = *src++;
406 		ret |= ((b & 0x7f) << shift);
407 		shift += 7;
408 	} while ((b & 0x80) != 0);
409 
410 	if (shift < 64 && (b & 0x40) != 0)
411 		ret |= (-1 << shift);
412 
413 	*dp = src;
414 
415 	return (ret);
416 }
417 
418 uint64_t
419 _dwarf_decode_uleb128(uint8_t **dp)
420 {
421 	uint64_t ret = 0;
422 	uint8_t b;
423 	int shift = 0;
424 
425 	uint8_t *src = *dp;
426 
427 	do {
428 		b = *src++;
429 		ret |= ((b & 0x7f) << shift);
430 		shift += 7;
431 	} while ((b & 0x80) != 0);
432 
433 	*dp = src;
434 
435 	return (ret);
436 }
437 
438 char *
439 _dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp)
440 {
441 	char *ret, *src;
442 
443 	ret = src = (char *) data + *offsetp;
444 
445 	while (*src != '\0' && *offsetp < size) {
446 		src++;
447 		(*offsetp)++;
448 	}
449 
450 	if (*src == '\0' && *offsetp < size)
451 		(*offsetp)++;
452 
453 	return (ret);
454 }
455 
456 void
457 _dwarf_write_string(void *data, uint64_t *offsetp, char *string)
458 {
459 	char *dst;
460 
461 	dst = (char *) data + *offsetp;
462 	strcpy(dst, string);
463 	(*offsetp) += strlen(string) + 1;
464 }
465 
466 int
467 _dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
468     char *string, Dwarf_Error *error)
469 {
470 	size_t len;
471 
472 	assert(*size > 0);
473 
474 	len = strlen(string) + 1;
475 	while (*offsetp + len > *size) {
476 		*size *= 2;
477 		*block = realloc(*block, (size_t) *size);
478 		if (*block == NULL) {
479 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
480 			return (DW_DLE_MEMORY);
481 		}
482 	}
483 
484 	_dwarf_write_string(*block, offsetp, string);
485 
486 	return (DW_DLE_NONE);
487 }
488 
489 uint8_t *
490 _dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length)
491 {
492 	uint8_t *ret, *src;
493 
494 	ret = src = (uint8_t *) data + *offsetp;
495 
496 	(*offsetp) += length;
497 
498 	return (ret);
499 }
500 
501 void
502 _dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk,
503     uint64_t length)
504 {
505 	uint8_t *dst;
506 
507 	dst = (uint8_t *) data + *offsetp;
508 	memcpy(dst, blk, length);
509 	(*offsetp) += length;
510 }
511 
512 int
513 _dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
514     uint8_t *blk, uint64_t length, Dwarf_Error *error)
515 {
516 
517 	assert(*size > 0);
518 
519 	while (*offsetp + length > *size) {
520 		*size *= 2;
521 		*block = realloc(*block, (size_t) *size);
522 		if (*block == NULL) {
523 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
524 			return (DW_DLE_MEMORY);
525 		}
526 	}
527 
528 	_dwarf_write_block(*block, offsetp, blk, length);
529 
530 	return (DW_DLE_NONE);
531 }
532 
533 void
534 _dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte,
535     uint64_t length)
536 {
537 	uint8_t *dst;
538 
539 	dst = (uint8_t *) data + *offsetp;
540 	memset(dst, byte, length);
541 	(*offsetp) += length;
542 }
543 
544 int
545 _dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
546     uint8_t byte, uint64_t cnt, Dwarf_Error *error)
547 {
548 	assert(*size > 0);
549 
550 	while (*offsetp + cnt > *size) {
551 		*size *= 2;
552 		*block = realloc(*block, (size_t) *size);
553 		if (*block == NULL) {
554 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
555 			return (DW_DLE_MEMORY);
556 		}
557 	}
558 
559 	_dwarf_write_padding(*block, offsetp, byte, cnt);
560 
561 	return (DW_DLE_NONE);
562 }
563