1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2010 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_sections.c 3041 2014-05-18 15:11:03Z kaiwang27 $");
30260684Skaiw
31260684Skaiw#define	_SECTION_INIT_SIZE	128
32260684Skaiw
33260684Skaiwint
34260684Skaiw_dwarf_section_init(Dwarf_P_Debug dbg, Dwarf_P_Section *dsp, const char *name,
35260684Skaiw    int pseudo, Dwarf_Error *error)
36260684Skaiw{
37260684Skaiw	Dwarf_P_Section ds;
38260684Skaiw
39260684Skaiw	assert(dbg != NULL && dsp != NULL && name != NULL);
40260684Skaiw
41260684Skaiw	if ((ds = calloc(1, sizeof(struct _Dwarf_P_Section))) == NULL) {
42260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
43260684Skaiw		return (DW_DLE_MEMORY);
44260684Skaiw	}
45260684Skaiw
46260684Skaiw	if ((ds->ds_name = strdup(name)) == NULL) {
47260684Skaiw		free(ds);
48260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
49260684Skaiw		return (DW_DLE_MEMORY);
50260684Skaiw	}
51260684Skaiw
52260684Skaiw	if (!pseudo) {
53260684Skaiw		ds->ds_cap = _SECTION_INIT_SIZE;
54260684Skaiw		if ((ds->ds_data = malloc((size_t) ds->ds_cap)) == NULL) {
55260684Skaiw			free(ds->ds_name);
56260684Skaiw			free(ds);
57260684Skaiw			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
58260684Skaiw			return (DW_DLE_MEMORY);
59260684Skaiw		}
60260684Skaiw		STAILQ_INSERT_TAIL(&dbg->dbgp_seclist, ds, ds_next);
61260684Skaiw		dbg->dbgp_seccnt++;
62260684Skaiw	}
63260684Skaiw
64260684Skaiw	*dsp = ds;
65260684Skaiw
66260684Skaiw	return (DW_DLE_NONE);
67260684Skaiw}
68260684Skaiw
69260684Skaiwvoid
70260684Skaiw_dwarf_section_free(Dwarf_P_Debug dbg, Dwarf_P_Section *dsp)
71260684Skaiw{
72260684Skaiw	Dwarf_P_Section ds, tds;
73260684Skaiw
74260684Skaiw	assert(dbg != NULL && dsp != NULL);
75260684Skaiw
76260684Skaiw	if (*dsp == NULL)
77260684Skaiw		return;
78260684Skaiw
79260684Skaiw	STAILQ_FOREACH_SAFE(ds, &dbg->dbgp_seclist, ds_next, tds) {
80260684Skaiw		if (ds == *dsp) {
81260684Skaiw			STAILQ_REMOVE(&dbg->dbgp_seclist, ds, _Dwarf_P_Section,
82260684Skaiw			    ds_next);
83260684Skaiw			dbg->dbgp_seccnt--;
84260684Skaiw			break;
85260684Skaiw		}
86260684Skaiw	}
87260684Skaiw	ds = *dsp;
88260684Skaiw	if (ds->ds_name)
89260684Skaiw		free(ds->ds_name);
90260684Skaiw	if (ds->ds_data)
91260684Skaiw		free(ds->ds_data);
92260684Skaiw	free(ds);
93260684Skaiw	*dsp = NULL;
94260684Skaiw}
95260684Skaiw
96260684Skaiwint
97260684Skaiw_dwarf_pro_callback(Dwarf_P_Debug dbg, char *name, int size,
98260684Skaiw    Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link,
99260684Skaiw    Dwarf_Unsigned info, Dwarf_Unsigned *symndx, int *error)
100260684Skaiw{
101260684Skaiw	int e, ret, isymndx;
102260684Skaiw
103260684Skaiw	assert(dbg != NULL && name != NULL && symndx != NULL);
104260684Skaiw
105260684Skaiw	if (dbg->dbgp_func_b)
106260684Skaiw		ret = dbg->dbgp_func_b(name, size, type, flags, link, info,
107260684Skaiw		    symndx, &e);
108260684Skaiw	else {
109260684Skaiw		ret = dbg->dbgp_func(name, size, type, flags, link, info,
110260684Skaiw		    &isymndx, &e);
111260684Skaiw		*symndx = isymndx;
112260684Skaiw	}
113260684Skaiw	if (ret < 0) {
114260684Skaiw		if (error)
115260684Skaiw			*error = e;
116260684Skaiw	}
117260684Skaiw
118260684Skaiw	return (ret);
119260684Skaiw}
120260684Skaiw
121260684Skaiwint
122260684Skaiw_dwarf_section_callback(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
123260684Skaiw    Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link,
124260684Skaiw    Dwarf_Unsigned info, Dwarf_Error *error)
125260684Skaiw{
126260684Skaiw	int ret, ndx;
127260684Skaiw
128260684Skaiw	ndx = _dwarf_pro_callback(dbg, ds->ds_name, (int) ds->ds_size,
129260684Skaiw	    type, flags, link, info, &ds->ds_symndx, NULL);
130260684Skaiw	if (ndx < 0) {
131260684Skaiw		ret = DW_DLE_ELF_SECT_ERR;
132260684Skaiw		DWARF_SET_ERROR(dbg, error, ret);
133260684Skaiw		return (ret);
134260684Skaiw	}
135260684Skaiw	ds->ds_ndx = ndx;
136260684Skaiw
137260684Skaiw	return (DW_DLE_NONE);
138260684Skaiw}
139260684Skaiw
140260684Skaiwint
141260684Skaiw_dwarf_generate_sections(Dwarf_P_Debug dbg, Dwarf_Error *error)
142260684Skaiw{
143260684Skaiw	int ret;
144260684Skaiw
145260684Skaiw	/* Produce .debug_info section. */
146260684Skaiw	if ((ret = _dwarf_info_gen(dbg, error)) != DW_DLE_NONE)
147260684Skaiw		return (ret);
148260684Skaiw
149260684Skaiw	/* Produce .debug_abbrev section. */
150260684Skaiw	if ((ret = _dwarf_abbrev_gen(dbg, error)) != DW_DLE_NONE)
151260684Skaiw		return (ret);
152260684Skaiw
153260684Skaiw	/* Produce .debug_line section. */
154260684Skaiw	if ((ret = _dwarf_lineno_gen(dbg, error)) != DW_DLE_NONE)
155260684Skaiw		return (ret);
156260684Skaiw
157260684Skaiw	/* Produce .debug_frame section. */
158260684Skaiw	if ((ret = _dwarf_frame_gen(dbg, error)) != DW_DLE_NONE)
159260684Skaiw		return (ret);
160260684Skaiw
161260684Skaiw	/* Produce .debug_aranges section. */
162260684Skaiw	if ((ret = _dwarf_arange_gen(dbg, error)) != DW_DLE_NONE)
163260684Skaiw		return (ret);
164260684Skaiw
165260684Skaiw	/* Produce .debug_macinfo section. */
166260684Skaiw	if ((ret = _dwarf_macinfo_gen(dbg, error)) != DW_DLE_NONE)
167260684Skaiw		return (ret);
168260684Skaiw
169260684Skaiw	/* Produce .debug_pubnames section. */
170260684Skaiw	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_pubnames", dbg->dbgp_pubs,
171260684Skaiw	    error)) != DW_DLE_NONE)
172260684Skaiw		return (ret);
173260684Skaiw
174260684Skaiw	/* Produce .debug_weaknames section. */
175260684Skaiw	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_weaknames", dbg->dbgp_weaks,
176260684Skaiw	    error)) != DW_DLE_NONE)
177260684Skaiw		return (ret);
178260684Skaiw
179260684Skaiw	/* Produce .debug_funcnames section. */
180260684Skaiw	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_funcnames", dbg->dbgp_funcs,
181260684Skaiw	    error)) != DW_DLE_NONE)
182260684Skaiw		return (ret);
183260684Skaiw
184260684Skaiw	/* Produce .debug_typenames section. */
185260684Skaiw	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_typenames", dbg->dbgp_types,
186260684Skaiw	    error)) != DW_DLE_NONE)
187260684Skaiw		return (ret);
188260684Skaiw
189260684Skaiw	/* Produce .debug_varnames section. */
190260684Skaiw	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_varnames", dbg->dbgp_vars,
191260684Skaiw	    error)) != DW_DLE_NONE)
192260684Skaiw		return (ret);
193260684Skaiw
194260684Skaiw	/* Produce .debug_str section. */
195260684Skaiw	if ((ret = _dwarf_strtab_gen(dbg, error)) != DW_DLE_NONE)
196260684Skaiw		return (ret);
197260684Skaiw
198260684Skaiw	/* Finally, update and generate all relocation sections. */
199260684Skaiw	if ((ret = _dwarf_reloc_gen(dbg, error)) != DW_DLE_NONE)
200260684Skaiw		return (ret);
201260684Skaiw
202260684Skaiw	/* Set section/relocation iterator to the first element. */
203260684Skaiw	dbg->dbgp_secpos = STAILQ_FIRST(&dbg->dbgp_seclist);
204260684Skaiw	dbg->dbgp_drspos = STAILQ_FIRST(&dbg->dbgp_drslist);
205260684Skaiw
206260684Skaiw	return (DW_DLE_NONE);
207260684Skaiw}
208260684Skaiw
209260684SkaiwDwarf_Section *
210260684Skaiw_dwarf_find_section(Dwarf_Debug dbg, const char *name)
211260684Skaiw{
212260684Skaiw	Dwarf_Section *ds;
213260684Skaiw	Dwarf_Half i;
214260684Skaiw
215276371Semaste	assert(dbg != NULL && name != NULL);
216260684Skaiw
217260684Skaiw	for (i = 0; i < dbg->dbg_seccnt; i++) {
218260684Skaiw		ds = &dbg->dbg_section[i];
219260684Skaiw		if (ds->ds_name != NULL && !strcmp(ds->ds_name, name))
220260684Skaiw			return (ds);
221260684Skaiw	}
222260684Skaiw
223260684Skaiw	return (NULL);
224260684Skaiw}
225260684Skaiw
226276371SemasteDwarf_Section *
227276371Semaste_dwarf_find_next_types_section(Dwarf_Debug dbg, Dwarf_Section *ds)
228276371Semaste{
229276371Semaste
230276371Semaste	assert(dbg != NULL);
231276371Semaste
232276371Semaste	if (ds == NULL)
233276371Semaste		return (_dwarf_find_section(dbg, ".debug_types"));
234276371Semaste
235276371Semaste	assert(ds->ds_name != NULL);
236276371Semaste
237276371Semaste	do {
238276371Semaste		ds++;
239276371Semaste		if (ds->ds_name != NULL &&
240276371Semaste		    !strcmp(ds->ds_name, ".debug_types"))
241276371Semaste			return (ds);
242276371Semaste	} while (ds->ds_name != NULL);
243276371Semaste
244276371Semaste	return (NULL);
245276371Semaste}
246276371Semaste
247260684SkaiwDwarf_P_Section
248260684Skaiw_dwarf_pro_find_section(Dwarf_P_Debug dbg, const char *name)
249260684Skaiw{
250260684Skaiw	Dwarf_P_Section ds;
251260684Skaiw
252260684Skaiw	assert(dbg != NULL && name != NULL);
253260684Skaiw
254260684Skaiw	STAILQ_FOREACH(ds, &dbg->dbgp_seclist, ds_next) {
255260684Skaiw		if (ds->ds_name != NULL && !strcmp(ds->ds_name ,name))
256260684Skaiw			return (ds);
257260684Skaiw	}
258260684Skaiw
259260684Skaiw	return (NULL);
260260684Skaiw}
261260684Skaiw
262260684Skaiwvoid
263260684Skaiw_dwarf_section_cleanup(Dwarf_P_Debug dbg)
264260684Skaiw{
265260684Skaiw	Dwarf_P_Section ds, tds;
266260684Skaiw
267260684Skaiw	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
268260684Skaiw
269260684Skaiw	STAILQ_FOREACH_SAFE(ds, &dbg->dbgp_seclist, ds_next, tds) {
270260684Skaiw		STAILQ_REMOVE(&dbg->dbgp_seclist, ds, _Dwarf_P_Section,
271260684Skaiw		    ds_next);
272260684Skaiw		if (ds->ds_name)
273260684Skaiw			free(ds->ds_name);
274260684Skaiw		if (ds->ds_data)
275260684Skaiw			free(ds->ds_data);
276260684Skaiw		free(ds);
277260684Skaiw	}
278260684Skaiw	dbg->dbgp_seccnt = 0;
279260684Skaiw	dbg->dbgp_secpos = 0;
280260684Skaiw}
281