libdwarf_rw.c revision 261246
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
30ELFTC_VCSID("$Id: libdwarf_rw.c 2952 2013-06-26 19:09:40Z kaiwang27 $");
31
32uint64_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
61uint64_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
90uint64_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
124uint64_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
160void
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
189int
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
210void
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
242int
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
263int64_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
286int
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
309int
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
332uint64_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
352int
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
372int
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
395int64_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
418uint64_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
438char *
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
456void
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
466int
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
489uint8_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
501void
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
512int
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
533void
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
544int
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