1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2009-2011 Kai Wang
3260684Skaiw * All rights reserved.
4260684Skaiw *
5260684Skaiw * Redistribution and use in source and binary forms, with or without
6260684Skaiw * modification, are permitted provided that the following conditions
7260684Skaiw * are met:
8260684Skaiw * 1. Redistributions of source code must retain the above copyright
9260684Skaiw *    notice, this list of conditions and the following disclaimer.
10260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
11260684Skaiw *    notice, this list of conditions and the following disclaimer in the
12260684Skaiw *    documentation and/or other materials provided with the distribution.
13260684Skaiw *
14260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17260684Skaiw * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24260684Skaiw * SUCH DAMAGE.
25260684Skaiw */
26260684Skaiw
27260684Skaiw#include "_libdwarf.h"
28260684Skaiw
29276371SemasteELFTC_VCSID("$Id: libdwarf_arange.c 3029 2014-04-21 23:26:02Z kaiwang27 $");
30260684Skaiw
31260684Skaiwvoid
32260684Skaiw_dwarf_arange_cleanup(Dwarf_Debug dbg)
33260684Skaiw{
34260684Skaiw	Dwarf_ArangeSet as, tas;
35260684Skaiw	Dwarf_Arange ar, tar;
36260684Skaiw
37260684Skaiw	STAILQ_FOREACH_SAFE(as, &dbg->dbg_aslist, as_next, tas) {
38260684Skaiw		STAILQ_FOREACH_SAFE(ar, &as->as_arlist, ar_next, tar) {
39260684Skaiw			STAILQ_REMOVE(&as->as_arlist, ar, _Dwarf_Arange,
40260684Skaiw			    ar_next);
41260684Skaiw			free(ar);
42260684Skaiw		}
43260684Skaiw		STAILQ_REMOVE(&dbg->dbg_aslist, as, _Dwarf_ArangeSet, as_next);
44260684Skaiw		free(as);
45260684Skaiw	}
46260684Skaiw
47260684Skaiw	if (dbg->dbg_arange_array)
48260684Skaiw		free(dbg->dbg_arange_array);
49260684Skaiw
50260684Skaiw	dbg->dbg_arange_array = NULL;
51260684Skaiw	dbg->dbg_arange_cnt = 0;
52260684Skaiw}
53260684Skaiw
54260684Skaiwint
55260684Skaiw_dwarf_arange_init(Dwarf_Debug dbg, Dwarf_Error *error)
56260684Skaiw{
57260684Skaiw	Dwarf_CU cu;
58260684Skaiw	Dwarf_ArangeSet as;
59260684Skaiw	Dwarf_Arange ar;
60260684Skaiw	Dwarf_Section *ds;
61260684Skaiw	uint64_t offset, dwarf_size, length, addr, range;
62260684Skaiw	int i, ret;
63260684Skaiw
64260684Skaiw	ret = DW_DLE_NONE;
65260684Skaiw
66260684Skaiw	if ((ds = _dwarf_find_section(dbg, ".debug_aranges")) == NULL)
67260684Skaiw		return (DW_DLE_NONE);
68260684Skaiw
69260684Skaiw	if (!dbg->dbg_info_loaded) {
70276371Semaste		ret = _dwarf_info_load(dbg, 1, 1, error);
71260684Skaiw		if (ret != DW_DLE_NONE)
72260684Skaiw			return (ret);
73260684Skaiw	}
74260684Skaiw
75260684Skaiw	offset = 0;
76260684Skaiw	while (offset < ds->ds_size) {
77260684Skaiw
78260684Skaiw		if ((as = malloc(sizeof(struct _Dwarf_ArangeSet))) == NULL) {
79260684Skaiw			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
80260684Skaiw			return (DW_DLE_MEMORY);
81260684Skaiw		}
82260684Skaiw		STAILQ_INIT(&as->as_arlist);
83260684Skaiw		STAILQ_INSERT_TAIL(&dbg->dbg_aslist, as, as_next);
84260684Skaiw
85260684Skaiw		/* Read in the table header. */
86260684Skaiw		length = dbg->read(ds->ds_data, &offset, 4);
87260684Skaiw		if (length == 0xffffffff) {
88260684Skaiw			dwarf_size = 8;
89260684Skaiw			length = dbg->read(ds->ds_data, &offset, 8);
90260684Skaiw		} else
91260684Skaiw			dwarf_size = 4;
92260684Skaiw
93260684Skaiw		as->as_length = length;
94260684Skaiw		as->as_version = dbg->read(ds->ds_data, &offset, 2);
95260684Skaiw		if (as->as_version != 2) {
96260684Skaiw			DWARF_SET_ERROR(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
97260684Skaiw			ret = DW_DLE_VERSION_STAMP_ERROR;
98260684Skaiw			goto fail_cleanup;
99260684Skaiw		}
100260684Skaiw
101260684Skaiw		as->as_cu_offset = dbg->read(ds->ds_data, &offset, dwarf_size);
102260684Skaiw		STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
103260684Skaiw			if (cu->cu_offset == as->as_cu_offset)
104260684Skaiw				break;
105260684Skaiw		}
106260684Skaiw		if (cu == NULL) {
107260684Skaiw			DWARF_SET_ERROR(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
108260684Skaiw			ret = DW_DLE_ARANGE_OFFSET_BAD;
109260684Skaiw			goto fail_cleanup;
110260684Skaiw		}
111260684Skaiw		as->as_cu = cu;
112260684Skaiw
113260684Skaiw		as->as_addrsz = dbg->read(ds->ds_data, &offset, 1);
114260684Skaiw		as->as_segsz = dbg->read(ds->ds_data, &offset, 1);
115260684Skaiw
116260684Skaiw		/* Skip the padding bytes.  */
117260684Skaiw		offset = roundup(offset, 2 * as->as_addrsz);
118260684Skaiw
119260684Skaiw		/* Read in address range descriptors. */
120260684Skaiw		while (offset < ds->ds_size) {
121260684Skaiw			addr = dbg->read(ds->ds_data, &offset, as->as_addrsz);
122260684Skaiw			range = dbg->read(ds->ds_data, &offset, as->as_addrsz);
123260684Skaiw			if (addr == 0 && range == 0)
124260684Skaiw				break;
125260684Skaiw			if ((ar = calloc(1, sizeof(struct _Dwarf_Arange))) ==
126260684Skaiw			    NULL) {
127260684Skaiw				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
128260684Skaiw				goto fail_cleanup;
129260684Skaiw			}
130260684Skaiw			ar->ar_as = as;
131260684Skaiw			ar->ar_address = addr;
132260684Skaiw			ar->ar_range = range;
133260684Skaiw			STAILQ_INSERT_TAIL(&as->as_arlist, ar, ar_next);
134260684Skaiw			dbg->dbg_arange_cnt++;
135260684Skaiw		}
136260684Skaiw	}
137260684Skaiw
138260684Skaiw	/* Build arange array. */
139260684Skaiw	if (dbg->dbg_arange_cnt > 0) {
140276371Semaste		if ((dbg->dbg_arange_array = malloc(dbg->dbg_arange_cnt *
141276371Semaste		    sizeof(Dwarf_Arange))) == NULL) {
142260684Skaiw			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
143260684Skaiw			ret = DW_DLE_MEMORY;
144260684Skaiw			goto fail_cleanup;
145260684Skaiw		}
146260684Skaiw
147260684Skaiw		i = 0;
148260684Skaiw		STAILQ_FOREACH(as, &dbg->dbg_aslist, as_next) {
149260684Skaiw			STAILQ_FOREACH(ar, &as->as_arlist, ar_next)
150260684Skaiw				dbg->dbg_arange_array[i++] = ar;
151260684Skaiw		}
152260684Skaiw		assert((Dwarf_Unsigned)i == dbg->dbg_arange_cnt);
153260684Skaiw	}
154260684Skaiw
155260684Skaiw	return (DW_DLE_NONE);
156260684Skaiw
157260684Skaiwfail_cleanup:
158260684Skaiw
159260684Skaiw	_dwarf_arange_cleanup(dbg);
160260684Skaiw
161260684Skaiw	return (ret);
162260684Skaiw}
163260684Skaiw
164260684Skaiwint
165260684Skaiw_dwarf_arange_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
166260684Skaiw{
167260684Skaiw	Dwarf_P_Section ds;
168260684Skaiw	Dwarf_Rel_Section drs;
169260684Skaiw	Dwarf_ArangeSet as;
170260684Skaiw	Dwarf_Arange ar;
171260684Skaiw	uint64_t offset;
172260684Skaiw	int ret;
173260684Skaiw
174260684Skaiw	as = dbg->dbgp_as;
175260684Skaiw	assert(as != NULL);
176260684Skaiw	if (STAILQ_EMPTY(&as->as_arlist))
177260684Skaiw		return (DW_DLE_NONE);
178260684Skaiw
179260684Skaiw	as->as_length = 0;
180260684Skaiw	as->as_version = 2;
181260684Skaiw	as->as_cu_offset = 0;	/* We have only one CU. */
182260684Skaiw	as->as_addrsz = dbg->dbg_pointer_size;
183260684Skaiw	as->as_segsz = 0;	/* XXX */
184260684Skaiw
185260684Skaiw	/* Create .debug_arange section. */
186260684Skaiw	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_aranges", 0, error)) !=
187260684Skaiw	    DW_DLE_NONE)
188260684Skaiw		goto gen_fail0;
189260684Skaiw
190260684Skaiw	/* Create relocation section for .debug_aranges */
191260684Skaiw	RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error));
192260684Skaiw
193260684Skaiw	/* Write section header. */
194260684Skaiw	RCHECK(WRITE_VALUE(as->as_length, 4));
195260684Skaiw	RCHECK(WRITE_VALUE(as->as_version, 2));
196260684Skaiw	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
197260684Skaiw	    ds->ds_size, 0, as->as_cu_offset, ".debug_info", error));
198260684Skaiw	RCHECK(WRITE_VALUE(as->as_addrsz, 1));
199260684Skaiw	RCHECK(WRITE_VALUE(as->as_segsz, 1));
200260684Skaiw
201260684Skaiw	/* Pad to (2 * address_size) */
202260684Skaiw	offset = roundup(ds->ds_size, 2 * as->as_addrsz);
203260684Skaiw	if (offset > ds->ds_size)
204260684Skaiw		RCHECK(WRITE_PADDING(0, offset - ds->ds_size));
205260684Skaiw
206260684Skaiw	/* Write tuples. */
207260684Skaiw	STAILQ_FOREACH(ar, &as->as_arlist, ar_next) {
208260684Skaiw		RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds,
209260684Skaiw		    dwarf_drt_data_reloc, dbg->dbg_pointer_size, ds->ds_size,
210260684Skaiw		    ar->ar_symndx, ar->ar_address, NULL, error));
211260684Skaiw		if (ar->ar_esymndx > 0)
212260684Skaiw			RCHECK(_dwarf_reloc_entry_add_pair(dbg, drs, ds,
213260684Skaiw			    dbg->dbg_pointer_size, ds->ds_size, ar->ar_symndx,
214260684Skaiw			    ar->ar_esymndx, ar->ar_address, ar->ar_eoff, error));
215260684Skaiw		else
216260684Skaiw			RCHECK(WRITE_VALUE(ar->ar_range, dbg->dbg_pointer_size));
217260684Skaiw	}
218260684Skaiw	RCHECK(WRITE_VALUE(0, dbg->dbg_pointer_size));
219260684Skaiw	RCHECK(WRITE_VALUE(0, dbg->dbg_pointer_size));
220260684Skaiw
221260684Skaiw	/* Fill in the length field. */
222260684Skaiw	as->as_length = ds->ds_size - 4;
223260684Skaiw	offset = 0;
224260684Skaiw	dbg->write(ds->ds_data, &offset, as->as_length, 4);
225260684Skaiw
226260684Skaiw	/* Inform application the creation of .debug_aranges ELF section. */
227260684Skaiw	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
228260684Skaiw
229260684Skaiw	/* Finalize relocation section for .debug_aranges */
230260684Skaiw	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
231260684Skaiw
232260684Skaiw	return (DW_DLE_NONE);
233260684Skaiw
234260684Skaiwgen_fail:
235260684Skaiw	_dwarf_reloc_section_free(dbg, &drs);
236260684Skaiw
237260684Skaiwgen_fail0:
238260684Skaiw	_dwarf_section_free(dbg, &ds);
239260684Skaiw
240260684Skaiw	return (ret);
241260684Skaiw}
242260684Skaiw
243260684Skaiwvoid
244260684Skaiw_dwarf_arange_pro_cleanup(Dwarf_P_Debug dbg)
245260684Skaiw{
246260684Skaiw	Dwarf_ArangeSet as;
247260684Skaiw	Dwarf_Arange ar, tar;
248260684Skaiw
249260684Skaiw	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
250260684Skaiw	if (dbg->dbgp_as == NULL)
251260684Skaiw		return;
252260684Skaiw
253260684Skaiw	as = dbg->dbgp_as;
254260684Skaiw	STAILQ_FOREACH_SAFE(ar, &as->as_arlist, ar_next, tar) {
255260684Skaiw		STAILQ_REMOVE(&as->as_arlist, ar, _Dwarf_Arange, ar_next);
256260684Skaiw		free(ar);
257260684Skaiw	}
258260684Skaiw	free(as);
259260684Skaiw	dbg->dbgp_as = NULL;
260260684Skaiw}
261