libdwarf_rw.c revision 295577
1273806Snp/*-
2319255Snp * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3319255Snp * Copyright (c) 2010 Kai Wang
4319255Snp * All rights reserved.
5319255Snp *
6273806Snp * Redistribution and use in source and binary forms, with or without
7273806Snp * modification, are permitted provided that the following conditions
8273806Snp * are met:
9273806Snp * 1. Redistributions of source code must retain the above copyright
10273806Snp *    notice, this list of conditions and the following disclaimer.
11273806Snp * 2. Redistributions in binary form must reproduce the above copyright
12273806Snp *    notice, this list of conditions and the following disclaimer in the
13273806Snp *    documentation and/or other materials provided with the distribution.
14273806Snp *
15273806Snp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16273806Snp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17273806Snp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18273806Snp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19273806Snp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20273806Snp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21273806Snp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22273806Snp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23273806Snp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24273806Snp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25273806Snp * SUCH DAMAGE.
26273806Snp */
27273806Snp
28273806Snp#include "_libdwarf.h"
29273806Snp
30273806SnpELFTC_VCSID("$Id: libdwarf_rw.c 3286 2015-12-31 16:45:46Z emaste $");
31273806Snp
32273806Snpuint64_t
33273806Snp_dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
34273806Snp{
35273806Snp	uint64_t ret;
36273806Snp	uint8_t *src;
37273806Snp
38273806Snp	src = data + *offsetp;
39273806Snp
40273806Snp	ret = 0;
41273806Snp	switch (bytes_to_read) {
42273806Snp	case 8:
43273806Snp		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
44273806Snp		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
45273806Snp		/* FALLTHROUGH */
46273806Snp	case 4:
47273806Snp		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
48273806Snp		/* FALLTHROUGH */
49273806Snp	case 2:
50273806Snp		ret |= ((uint64_t) src[1]) << 8;
51273806Snp		/* FALLTHROUGH */
52273806Snp	case 1:
53273806Snp		ret |= src[0];
54273806Snp		break;
55273806Snp	default:
56273806Snp		return (0);
57273806Snp	}
58273806Snp
59273806Snp	*offsetp += bytes_to_read;
60273806Snp
61273806Snp	return (ret);
62273806Snp}
63273806Snp
64273806Snpuint64_t
65273806Snp_dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
66273806Snp{
67273806Snp	uint64_t ret;
68273806Snp	uint8_t *src;
69273806Snp
70273806Snp	src = *data;
71273806Snp
72273806Snp	ret = 0;
73273806Snp	switch (bytes_to_read) {
74273806Snp	case 8:
75273806Snp		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
76273806Snp		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
77273806Snp		/* FALLTHROUGH */
78273806Snp	case 4:
79273806Snp		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
80273806Snp		/* FALLTHROUGH */
81273806Snp	case 2:
82273806Snp		ret |= ((uint64_t) src[1]) << 8;
83273806Snp		/* FALLTHROUGH */
84273806Snp	case 1:
85273806Snp		ret |= src[0];
86273806Snp		break;
87273806Snp	default:
88273806Snp		return (0);
89273806Snp	}
90273806Snp
91273806Snp	*data += bytes_to_read;
92273806Snp
93273806Snp	return (ret);
94273806Snp}
95273806Snp
96273806Snpuint64_t
97273806Snp_dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
98273806Snp{
99273806Snp	uint64_t ret;
100273806Snp	uint8_t *src;
101273806Snp
102273806Snp	src = data + *offsetp;
103273806Snp
104273806Snp	switch (bytes_to_read) {
105273806Snp	case 1:
106273806Snp		ret = src[0];
107273806Snp		break;
108273806Snp	case 2:
109273806Snp		ret = src[1] | ((uint64_t) src[0]) << 8;
110273806Snp		break;
111273806Snp	case 4:
112273806Snp		ret = src[3] | ((uint64_t) src[2]) << 8;
113273806Snp		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
114273806Snp		break;
115273806Snp	case 8:
116273806Snp		ret = src[7] | ((uint64_t) src[6]) << 8;
117273806Snp		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
118273806Snp		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
119273806Snp		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
120273806Snp		break;
121273806Snp	default:
122273806Snp		return (0);
123273806Snp	}
124273806Snp
125273806Snp	*offsetp += bytes_to_read;
126273806Snp
127273806Snp	return (ret);
128273806Snp}
129273806Snp
130273806Snpuint64_t
131273806Snp_dwarf_decode_msb(uint8_t **data, int bytes_to_read)
132273806Snp{
133273806Snp	uint64_t ret;
134273806Snp	uint8_t *src;
135273806Snp
136273806Snp	src = *data;
137273806Snp
138273806Snp	ret = 0;
139273806Snp	switch (bytes_to_read) {
140273806Snp	case 1:
141273806Snp		ret = src[0];
142273806Snp		break;
143273806Snp	case 2:
144273806Snp		ret = src[1] | ((uint64_t) src[0]) << 8;
145273806Snp		break;
146273806Snp	case 4:
147273806Snp		ret = src[3] | ((uint64_t) src[2]) << 8;
148273806Snp		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
149273806Snp		break;
150273806Snp	case 8:
151273806Snp		ret = src[7] | ((uint64_t) src[6]) << 8;
152273806Snp		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
153273806Snp		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
154273806Snp		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
155273806Snp		break;
156273806Snp	default:
157273806Snp		return (0);
158273806Snp		break;
159273806Snp	}
160273806Snp
161273806Snp	*data += bytes_to_read;
162273806Snp
163273806Snp	return (ret);
164273806Snp}
165273806Snp
166273806Snpvoid
167273806Snp_dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
168273806Snp    int bytes_to_write)
169273806Snp{
170273806Snp	uint8_t *dst;
171273806Snp
172273806Snp	dst = data + *offsetp;
173273806Snp
174273806Snp	switch (bytes_to_write) {
175273806Snp	case 8:
176273806Snp		dst[7] = (value >> 56) & 0xff;
177273806Snp		dst[6] = (value >> 48) & 0xff;
178273806Snp		dst[5] = (value >> 40) & 0xff;
179273806Snp		dst[4] = (value >> 32) & 0xff;
180273806Snp		/* FALLTHROUGH */
181273806Snp	case 4:
182273806Snp		dst[3] = (value >> 24) & 0xff;
183273806Snp		dst[2] = (value >> 16) & 0xff;
184273806Snp		/* FALLTHROUGH */
185273806Snp	case 2:
186273806Snp		dst[1] = (value >> 8) & 0xff;
187273806Snp		/* FALLTHROUGH */
188273806Snp	case 1:
189273806Snp		dst[0] = value & 0xff;
190273806Snp		break;
191273806Snp	default:
192273806Snp		return;
193273806Snp	}
194273806Snp
195273806Snp	*offsetp += bytes_to_write;
196273806Snp}
197273806Snp
198273806Snpint
199273806Snp_dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
200273806Snp    uint64_t value, int bytes_to_write, Dwarf_Error *error)
201273806Snp{
202273806Snp
203273806Snp	assert(*size > 0);
204273806Snp
205273806Snp	while (*offsetp + bytes_to_write > *size) {
206273806Snp		*size *= 2;
207273806Snp		*block = realloc(*block, (size_t) *size);
208273806Snp		if (*block == NULL) {
209273806Snp			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
210273806Snp			return (DW_DLE_MEMORY);
211273806Snp		}
212273806Snp	}
213273806Snp
214273806Snp	_dwarf_write_lsb(*block, offsetp, value, bytes_to_write);
215273806Snp
216273806Snp	return (DW_DLE_NONE);
217273806Snp}
218273806Snp
219273806Snpvoid
220273806Snp_dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
221273806Snp    int bytes_to_write)
222273806Snp{
223273806Snp	uint8_t *dst;
224273806Snp
225273806Snp	dst = data + *offsetp;
226273806Snp
227273806Snp	switch (bytes_to_write) {
228273806Snp	case 8:
229273806Snp		dst[7] = value & 0xff;
230273806Snp		dst[6] = (value >> 8) & 0xff;
231273806Snp		dst[5] = (value >> 16) & 0xff;
232273806Snp		dst[4] = (value >> 24) & 0xff;
233273806Snp		value >>= 32;
234273806Snp		/* FALLTHROUGH */
235273806Snp	case 4:
236273806Snp		dst[3] = value & 0xff;
237273806Snp		dst[2] = (value >> 8) & 0xff;
238273806Snp		value >>= 16;
239273806Snp		/* FALLTHROUGH */
240273806Snp	case 2:
241273806Snp		dst[1] = value & 0xff;
242273806Snp		value >>= 8;
243273806Snp		/* FALLTHROUGH */
244273806Snp	case 1:
245273806Snp		dst[0] = value & 0xff;
246273806Snp		break;
247273806Snp	default:
248273806Snp		return;
249273806Snp	}
250273806Snp
251273806Snp	*offsetp += bytes_to_write;
252273806Snp}
253273806Snp
254273806Snpint
255273806Snp_dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
256273806Snp    uint64_t value, int bytes_to_write, Dwarf_Error *error)
257273806Snp{
258273806Snp
259273806Snp	assert(*size > 0);
260273806Snp
261273806Snp	while (*offsetp + bytes_to_write > *size) {
262273806Snp		*size *= 2;
263273806Snp		*block = realloc(*block, (size_t) *size);
264273806Snp		if (*block == NULL) {
265273806Snp			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
266273806Snp			return (DW_DLE_MEMORY);
267273806Snp		}
268273806Snp	}
269273806Snp
270273806Snp	_dwarf_write_msb(*block, offsetp, value, bytes_to_write);
271273806Snp
272273806Snp	return (DW_DLE_NONE);
273273806Snp}
274273806Snp
275273806Snpint64_t
276273806Snp_dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp)
277273806Snp{
278273806Snp	int64_t ret = 0;
279273806Snp	uint8_t b;
280273806Snp	int shift = 0;
281273806Snp	uint8_t *src;
282273806Snp
283273806Snp	src = data + *offsetp;
284273806Snp
285273806Snp	do {
286273806Snp		b = *src++;
287273806Snp		ret |= ((b & 0x7f) << shift);
288273806Snp		(*offsetp)++;
289273806Snp		shift += 7;
290273806Snp	} while ((b & 0x80) != 0);
291273806Snp
292273806Snp	if (shift < 64 && (b & 0x40) != 0)
293273806Snp		ret |= (-1 << shift);
294273806Snp
295273806Snp	return (ret);
296273806Snp}
297273806Snp
298273806Snpint
299273806Snp_dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val)
300273806Snp{
301273806Snp	uint8_t *p;
302273806Snp
303273806Snp	p = data;
304273806Snp
305273806Snp	for (;;) {
306273806Snp		if (p >= end)
307273806Snp			return (-1);
308273806Snp		*p = val & 0x7f;
309273806Snp		val >>= 7;
310273806Snp		if ((val == 0 && (*p & 0x40) == 0) ||
311273806Snp		    (val == -1 && (*p & 0x40) != 0)) {
312273806Snp			p++;
313273806Snp			break;
314273806Snp		}
315273806Snp		*p++ |= 0x80;
316273806Snp	}
317273806Snp
318273806Snp	return (p - data);
319273806Snp}
320273806Snp
321273806Snpint
322273806Snp_dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
323273806Snp    int64_t val, Dwarf_Error *error)
324273806Snp{
325273806Snp	int len;
326273806Snp
327273806Snp	assert(*size > 0);
328273806Snp
329273806Snp	while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size,
330273806Snp	    val)) < 0) {
331273806Snp		*size *= 2;
332273806Snp		*block = realloc(*block, (size_t) *size);
333273806Snp		if (*block == NULL) {
334273806Snp			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
335273806Snp			return (DW_DLE_MEMORY);
336273806Snp		}
337273806Snp	}
338273806Snp
339273806Snp	*offsetp += len;
340273806Snp
341273806Snp	return (DW_DLE_NONE);
342273806Snp}
343273806Snp
344273806Snpuint64_t
345273806Snp_dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp)
346319255Snp{
347319255Snp	uint64_t ret = 0;
348319255Snp	uint8_t b;
349319255Snp	int shift = 0;
350319255Snp	uint8_t *src;
351319255Snp
352319255Snp	src = data + *offsetp;
353319255Snp
354319255Snp	do {
355319255Snp		b = *src++;
356319255Snp		ret |= ((b & 0x7f) << shift);
357319255Snp		(*offsetp)++;
358319255Snp		shift += 7;
359319255Snp	} while ((b & 0x80) != 0);
360319255Snp
361319255Snp	return (ret);
362319255Snp}
363319255Snp
364319255Snpint
365319255Snp_dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val)
366319255Snp{
367319255Snp	uint8_t *p;
368319255Snp
369319255Snp	p = data;
370319255Snp
371319255Snp	do {
372319255Snp		if (p >= end)
373319255Snp			return (-1);
374319255Snp		*p = val & 0x7f;
375319255Snp		val >>= 7;
376319255Snp		if (val > 0)
377319255Snp			*p |= 0x80;
378319255Snp		p++;
379319255Snp	} while (val > 0);
380319255Snp
381319255Snp	return (p - data);
382319255Snp}
383319255Snp
384319255Snpint
385319255Snp_dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
386319255Snp    uint64_t val, Dwarf_Error *error)
387319255Snp{
388319255Snp	int len;
389319255Snp
390319255Snp	assert(*size > 0);
391319255Snp
392319255Snp	while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size,
393319255Snp	    val)) < 0) {
394319255Snp		*size *= 2;
395319255Snp		*block = realloc(*block, (size_t) *size);
396319255Snp		if (*block == NULL) {
397319255Snp			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
398319255Snp			return (DW_DLE_MEMORY);
399319255Snp		}
400319255Snp	}
401319255Snp
402319255Snp	*offsetp += len;
403319255Snp
404319255Snp	return (DW_DLE_NONE);
405319255Snp}
406319255Snp
407319255Snpint64_t
408319255Snp_dwarf_decode_sleb128(uint8_t **dp)
409319255Snp{
410319255Snp	int64_t ret = 0;
411319255Snp	uint8_t b;
412319255Snp	int shift = 0;
413319255Snp
414319255Snp	uint8_t *src = *dp;
415319255Snp
416319255Snp	do {
417319255Snp		b = *src++;
418319255Snp		ret |= ((b & 0x7f) << shift);
419319255Snp		shift += 7;
420319255Snp	} while ((b & 0x80) != 0);
421319255Snp
422319255Snp	if (shift < 64 && (b & 0x40) != 0)
423319255Snp		ret |= (-1 << shift);
424319255Snp
425319255Snp	*dp = src;
426319255Snp
427319255Snp	return (ret);
428319255Snp}
429319255Snp
430319255Snpuint64_t
431319255Snp_dwarf_decode_uleb128(uint8_t **dp)
432319255Snp{
433319255Snp	uint64_t ret = 0;
434319255Snp	uint8_t b;
435319255Snp	int shift = 0;
436319255Snp
437319255Snp	uint8_t *src = *dp;
438319255Snp
439319255Snp	do {
440319255Snp		b = *src++;
441319255Snp		ret |= ((b & 0x7f) << shift);
442319255Snp		shift += 7;
443319255Snp	} while ((b & 0x80) != 0);
444319255Snp
445319255Snp	*dp = src;
446319255Snp
447319255Snp	return (ret);
448319255Snp}
449319255Snp
450319255Snpchar *
451319255Snp_dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp)
452319255Snp{
453319255Snp	char *ret, *src;
454319255Snp
455319255Snp	ret = src = (char *) data + *offsetp;
456319255Snp
457319255Snp	while (*src != '\0' && *offsetp < size) {
458319255Snp		src++;
459319255Snp		(*offsetp)++;
460319255Snp	}
461319255Snp
462319255Snp	if (*src == '\0' && *offsetp < size)
463319255Snp		(*offsetp)++;
464319255Snp
465319255Snp	return (ret);
466319255Snp}
467319255Snp
468319255Snpvoid
469319255Snp_dwarf_write_string(void *data, uint64_t *offsetp, char *string)
470319255Snp{
471319255Snp	char *dst;
472319255Snp
473319255Snp	dst = (char *) data + *offsetp;
474319255Snp	strcpy(dst, string);
475273806Snp	(*offsetp) += strlen(string) + 1;
476273806Snp}
477273806Snp
478319255Snpint
479319255Snp_dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
480319255Snp    char *string, Dwarf_Error *error)
481273806Snp{
482273806Snp	size_t len;
483273806Snp
484273806Snp	assert(*size > 0);
485273806Snp
486273806Snp	len = strlen(string) + 1;
487273806Snp	while (*offsetp + len > *size) {
488273806Snp		*size *= 2;
489273806Snp		*block = realloc(*block, (size_t) *size);
490273806Snp		if (*block == NULL) {
491273806Snp			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
492273806Snp			return (DW_DLE_MEMORY);
493273806Snp		}
494273806Snp	}
495273806Snp
496273806Snp	_dwarf_write_string(*block, offsetp, string);
497273806Snp
498273806Snp	return (DW_DLE_NONE);
499273806Snp}
500273806Snp
501273806Snpuint8_t *
502273806Snp_dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length)
503273806Snp{
504273806Snp	uint8_t *ret, *src;
505273806Snp
506273806Snp	ret = src = (uint8_t *) data + *offsetp;
507273806Snp
508273806Snp	(*offsetp) += length;
509273806Snp
510273806Snp	return (ret);
511319255Snp}
512319255Snp
513319255Snpvoid
514319255Snp_dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk,
515273806Snp    uint64_t length)
516273806Snp{
517273806Snp	uint8_t *dst;
518273806Snp
519273806Snp	dst = (uint8_t *) data + *offsetp;
520273806Snp	memcpy(dst, blk, length);
521273806Snp	(*offsetp) += length;
522273806Snp}
523273806Snp
524273806Snpint
525273806Snp_dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
526273806Snp    uint8_t *blk, uint64_t length, Dwarf_Error *error)
527273806Snp{
528273806Snp
529273806Snp	assert(*size > 0);
530273806Snp
531273806Snp	while (*offsetp + length > *size) {
532273806Snp		*size *= 2;
533273806Snp		*block = realloc(*block, (size_t) *size);
534273806Snp		if (*block == NULL) {
535273806Snp			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
536273806Snp			return (DW_DLE_MEMORY);
537273806Snp		}
538273806Snp	}
539273806Snp
540273806Snp	_dwarf_write_block(*block, offsetp, blk, length);
541273806Snp
542273806Snp	return (DW_DLE_NONE);
543273806Snp}
544273806Snp
545273806Snpvoid
546273806Snp_dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte,
547273806Snp    uint64_t length)
548273806Snp{
549273806Snp	uint8_t *dst;
550273806Snp
551273806Snp	dst = (uint8_t *) data + *offsetp;
552273806Snp	memset(dst, byte, length);
553273806Snp	(*offsetp) += length;
554273806Snp}
555273806Snp
556273806Snpint
557273806Snp_dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
558273806Snp    uint8_t byte, uint64_t cnt, Dwarf_Error *error)
559273806Snp{
560273806Snp	assert(*size > 0);
561273806Snp
562273806Snp	while (*offsetp + cnt > *size) {
563273806Snp		*size *= 2;
564273806Snp		*block = realloc(*block, (size_t) *size);
565273806Snp		if (*block == NULL) {
566273806Snp			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
567273806Snp			return (DW_DLE_MEMORY);
568273806Snp		}
569273806Snp	}
570273806Snp
571273806Snp	_dwarf_write_padding(*block, offsetp, byte, cnt);
572273806Snp
573273806Snp	return (DW_DLE_NONE);
574273806Snp}
575273806Snp