1 /* Get public symbol information.
2 Copyright (C) 2002, 2003, 2004, 2005, 2008 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2002.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
9 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
19 or both in parallel, as here.
21 elfutils is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
37 #include <sys/param.h>
44 get_offsets (Dwarf *dbg)
48 struct pubnames_s *mem = NULL;
49 const size_t entsize = sizeof (struct pubnames_s);
50 unsigned char *const startp = dbg->sectiondata[IDX_debug_pubnames]->d_buf;
51 unsigned char *readp = startp;
52 unsigned char *endp = readp + dbg->sectiondata[IDX_debug_pubnames]->d_size;
54 while (readp + 14 < endp)
56 /* If necessary, allocate more entries. */
59 allocated = MAX (10, 2 * allocated);
60 struct pubnames_s *newmem
61 = (struct pubnames_s *) realloc (mem, allocated * entsize);
64 __libdw_seterrno (DWARF_E_NOMEM);
73 /* Read the set header. */
75 Dwarf_Off len = read_4ubyte_unaligned_inc (dbg, readp);
76 if (len == DWARF3_LENGTH_64_BIT)
78 len = read_8ubyte_unaligned_inc (dbg, readp);
81 else if (unlikely (len >= DWARF3_LENGTH_MIN_ESCAPE_CODE
82 && len <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
84 __libdw_seterrno (DWARF_E_INVALID_DWARF);
88 /* Now we know the offset of the first offset/name pair. */
89 mem[cnt].set_start = readp + 2 + 2 * len_bytes - startp;
90 mem[cnt].address_len = len_bytes;
91 size_t max_size = dbg->sectiondata[IDX_debug_pubnames]->d_size;
92 if (mem[cnt].set_start >= max_size
93 || len - (2 + 2 * len_bytes) > max_size - mem[cnt].set_start)
94 /* Something wrong, the first entry is beyond the end of
95 the section. Or the length of the whole unit is too big. */
98 /* Read the version. It better be two for now. */
99 uint16_t version = read_2ubyte_unaligned (dbg, readp);
100 if (unlikely (version != 2))
102 __libdw_seterrno (DWARF_E_INVALID_VERSION);
106 /* Get the CU offset. */
107 if (__libdw_read_offset (dbg, dbg, IDX_debug_pubnames,
108 readp + 2, len_bytes,
109 &mem[cnt].cu_offset, IDX_debug_info, 3))
110 /* Error has been already set in reader. */
113 /* Determine the size of the CU header. */
115 = ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf
116 + mem[cnt].cu_offset);
117 if (read_4ubyte_unaligned_noncvt (infop) == DWARF3_LENGTH_64_BIT)
118 mem[cnt].cu_header_size = 23;
120 mem[cnt].cu_header_size = 11;
124 /* Advance to the next set. */
128 if (mem == NULL || cnt == 0)
131 __libdw_seterrno (DWARF_E_NO_ENTRY);
135 dbg->pubnames_sets = (struct pubnames_s *) realloc (mem, cnt * entsize);
136 dbg->pubnames_nsets = cnt;
143 dwarf_getpubnames (Dwarf *dbg,
144 int (*callback) (Dwarf *, Dwarf_Global *, void *),
145 void *arg, ptrdiff_t offset)
150 if (unlikely (offset < 0))
152 __libdw_seterrno (DWARF_E_INVALID_OFFSET);
156 /* Make sure it is a valid offset. */
157 if (unlikely (dbg->sectiondata[IDX_debug_pubnames] == NULL
159 >= dbg->sectiondata[IDX_debug_pubnames]->d_size)))
160 /* No (more) entry. */
163 /* If necessary read the set information. */
164 if (dbg->pubnames_nsets == 0 && unlikely (get_offsets (dbg) != 0))
167 /* Find the place where to start. */
172 offset = dbg->pubnames_sets[0].set_start;
176 for (cnt = 0; cnt + 1 < dbg->pubnames_nsets; ++cnt)
177 if ((Dwarf_Off) offset >= dbg->pubnames_sets[cnt].set_start)
179 assert ((Dwarf_Off) offset
180 < dbg->pubnames_sets[cnt + 1].set_start);
183 assert (cnt + 1 < dbg->pubnames_nsets);
186 unsigned char *startp
187 = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf;
189 = startp + dbg->sectiondata[IDX_debug_pubnames]->d_size;
190 unsigned char *readp = startp + offset;
195 gl.cu_offset = (dbg->pubnames_sets[cnt].cu_offset
196 + dbg->pubnames_sets[cnt].cu_header_size);
200 /* READP points to the next offset/name pair. */
201 if (readp + dbg->pubnames_sets[cnt].address_len > endp)
203 if (dbg->pubnames_sets[cnt].address_len == 4)
204 gl.die_offset = read_4ubyte_unaligned_inc (dbg, readp);
206 gl.die_offset = read_8ubyte_unaligned_inc (dbg, readp);
208 /* If the offset is zero we reached the end of the set. */
209 if (gl.die_offset == 0)
212 /* Add the CU offset. */
213 gl.die_offset += dbg->pubnames_sets[cnt].cu_offset;
215 gl.name = (char *) readp;
216 readp = (unsigned char *) memchr (gl.name, '\0', endp - readp);
217 if (unlikely (readp == NULL))
220 __libdw_seterrno (DWARF_E_INVALID_DWARF);
225 /* We found name and DIE offset. Report it. */
226 if (callback (dbg, &gl, arg) != DWARF_CB_OK)
228 /* The user wants us to stop. Return the offset of the
230 return readp - startp;
234 if (++cnt == dbg->pubnames_nsets)
235 /* This was the last set. */
238 startp = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf;
239 readp = startp + dbg->pubnames_sets[cnt].set_start;
242 /* We are done. No more entries. */