1179187Sjb/*-
2179187Sjb * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3179187Sjb * All rights reserved.
4179187Sjb *
5179187Sjb * Redistribution and use in source and binary forms, with or without
6179187Sjb * modification, are permitted provided that the following conditions
7179187Sjb * are met:
8179187Sjb * 1. Redistributions of source code must retain the above copyright
9179187Sjb *    notice, this list of conditions and the following disclaimer.
10179187Sjb * 2. Redistributions in binary form must reproduce the above copyright
11179187Sjb *    notice, this list of conditions and the following disclaimer in the
12179187Sjb *    documentation and/or other materials provided with the distribution.
13179187Sjb *
14179187Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15179187Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16179187Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17179187Sjb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18179187Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19179187Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20179187Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21179187Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22179187Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23179187Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24179187Sjb * SUCH DAMAGE.
25179187Sjb *
26179187Sjb * $FreeBSD$
27179187Sjb */
28179187Sjb
29179187Sjb#include <stdlib.h>
30179187Sjb#include "_libdwarf.h"
31179187Sjb
32179187Sjbint
33179187Sjbdwarf_die_add(Dwarf_CU cu, int level, uint64_t offset, uint64_t abnum, Dwarf_Abbrev a, Dwarf_Die *diep, Dwarf_Error *err)
34179187Sjb{
35179187Sjb	Dwarf_Die die;
36179187Sjb	uint64_t key;
37179187Sjb	int ret = DWARF_E_NONE;
38179187Sjb
39179187Sjb	if (err == NULL)
40179187Sjb		return DWARF_E_ERROR;
41179187Sjb
42179187Sjb	if (cu == NULL || a == NULL) {
43179187Sjb		DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
44179187Sjb		return DWARF_E_ARGUMENT;
45179187Sjb	}
46179187Sjb
47179187Sjb	if ((die = malloc(sizeof(struct _Dwarf_Die))) == NULL) {
48179187Sjb		DWARF_SET_ERROR(err, DWARF_E_MEMORY);
49179187Sjb		return DWARF_E_MEMORY;
50179187Sjb	}
51179187Sjb
52179187Sjb	/* Initialise the abbrev structure. */
53179187Sjb	die->die_level	= level;
54179187Sjb	die->die_offset	= offset;
55179187Sjb	die->die_abnum	= abnum;
56179187Sjb	die->die_a	= a;
57179187Sjb	die->die_cu	= cu;
58248641Savg	die->die_name	= "";
59179187Sjb
60179187Sjb	/* Initialise the list of attribute values. */
61179187Sjb	STAILQ_INIT(&die->die_attrval);
62179187Sjb
63179187Sjb	/* Add the die to the list in the compilation unit. */
64179187Sjb	STAILQ_INSERT_TAIL(&cu->cu_die, die, die_next);
65179187Sjb
66179187Sjb	/* Add the die to the hash table in the compilation unit. */
67179187Sjb	key = offset % DWARF_DIE_HASH_SIZE;
68179187Sjb	STAILQ_INSERT_TAIL(&cu->cu_die_hash[key], die, die_hash);
69179187Sjb
70179187Sjb	if (diep != NULL)
71179187Sjb		*diep = die;
72179187Sjb
73179187Sjb	return ret;
74179187Sjb}
75179187Sjb
76179187Sjbint
77179187Sjbdwarf_dieoffset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *err __unused)
78179187Sjb{
79179187Sjb	*ret_offset = die->die_offset;
80179187Sjb
81179187Sjb	return DWARF_E_NONE;
82179187Sjb}
83179187Sjb
84179187Sjbint
85179187Sjbdwarf_child(Dwarf_Die die, Dwarf_Die *ret_die, Dwarf_Error *err)
86179187Sjb{
87179187Sjb	Dwarf_Die next;
88179187Sjb	int ret = DWARF_E_NONE;
89179187Sjb
90179187Sjb	if (err == NULL)
91179187Sjb		return DWARF_E_ERROR;
92179187Sjb
93179187Sjb	if (die == NULL || ret_die == NULL) {
94179187Sjb		DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
95179187Sjb		return DWARF_E_ARGUMENT;
96179187Sjb	}
97179187Sjb
98179187Sjb	if ((next = STAILQ_NEXT(die, die_next)) == NULL ||
99179187Sjb	    next->die_level != die->die_level + 1) {
100179187Sjb		*ret_die = NULL;
101179187Sjb		DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
102179187Sjb		ret = DWARF_E_NO_ENTRY;
103179187Sjb	} else
104179187Sjb		*ret_die = next;
105179187Sjb
106179187Sjb	return ret;
107179187Sjb}
108179187Sjb
109179187Sjbint
110179187Sjbdwarf_tag(Dwarf_Die die, Dwarf_Half *tag, Dwarf_Error *err)
111179187Sjb{
112179187Sjb	Dwarf_Abbrev a;
113179187Sjb
114179187Sjb	if (err == NULL)
115179187Sjb		return DWARF_E_ERROR;
116179187Sjb
117179187Sjb	if (die == NULL || tag == NULL || (a = die->die_a) == NULL) {
118179187Sjb		DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
119179187Sjb		return DWARF_E_ARGUMENT;
120179187Sjb	}
121179187Sjb
122179187Sjb	*tag = a->a_tag;
123179187Sjb
124179187Sjb	return DWARF_E_NONE;
125179187Sjb}
126179187Sjb
127179187Sjbint
128179187Sjbdwarf_siblingof(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *caller_ret_die, Dwarf_Error *err)
129179187Sjb{
130179187Sjb	Dwarf_Die next;
131179187Sjb	Dwarf_CU cu;
132179187Sjb	int ret = DWARF_E_NONE;
133179187Sjb
134179187Sjb	if (err == NULL)
135179187Sjb		return DWARF_E_ERROR;
136179187Sjb
137179187Sjb	if (dbg == NULL || caller_ret_die == NULL) {
138179187Sjb		DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
139179187Sjb		return DWARF_E_ARGUMENT;
140179187Sjb	}
141179187Sjb
142179187Sjb	if ((cu = dbg->dbg_cu_current) == NULL) {
143179187Sjb		DWARF_SET_ERROR(err, DWARF_E_CU_CURRENT);
144179187Sjb		return DWARF_E_CU_CURRENT;
145179187Sjb	}
146179187Sjb
147179187Sjb	if (die == NULL) {
148179187Sjb		*caller_ret_die = STAILQ_FIRST(&cu->cu_die);
149179187Sjb
150179187Sjb		if (*caller_ret_die == NULL) {
151179187Sjb			DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
152179187Sjb			ret = DWARF_E_NO_ENTRY;
153179187Sjb		}
154179187Sjb	} else {
155179187Sjb		next = die;
156179187Sjb		while ((next = STAILQ_NEXT(next, die_next)) != NULL) {
157179187Sjb			if (next->die_level < die->die_level) {
158179187Sjb				next = NULL;
159179187Sjb				break;
160179187Sjb			}
161179187Sjb			if (next->die_level == die->die_level) {
162179187Sjb				*caller_ret_die = next;
163179187Sjb				break;
164179187Sjb			}
165179187Sjb		}
166179187Sjb
167179187Sjb		if (next == NULL) {
168179187Sjb			*caller_ret_die = NULL;
169179187Sjb			DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
170179187Sjb			ret = DWARF_E_NO_ENTRY;
171179187Sjb		}
172179187Sjb	}
173179187Sjb
174179187Sjb	return ret;
175179187Sjb}
176179187Sjb
177179187SjbDwarf_Die
178179187Sjbdwarf_die_find(Dwarf_Die die, Dwarf_Unsigned off)
179179187Sjb{
180179187Sjb	Dwarf_CU cu = die->die_cu;
181179187Sjb	Dwarf_Die die1;
182179187Sjb
183179187Sjb	STAILQ_FOREACH(die1, &cu->cu_die, die_next) {
184179187Sjb		if (die1->die_offset == off)
185179187Sjb			return (die1);
186179187Sjb	}
187179187Sjb
188179187Sjb	return (NULL);
189179187Sjb}
190