xref: /minix3/libexec/ld.elf_so/symver.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: symver.c,v 1.4 2013/05/09 15:38:14 christos Exp $	*/
2f14fb602SLionel Sambuc 
3f14fb602SLionel Sambuc /*-
4f14fb602SLionel Sambuc  * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra.
5f14fb602SLionel Sambuc  * Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>.
6f14fb602SLionel Sambuc  * Copyright 2009, 2010, 2011 Konstantin Belousov <kib@FreeBSD.ORG>.
7f14fb602SLionel Sambuc  * All rights reserved.
8f14fb602SLionel Sambuc  *
9f14fb602SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
10f14fb602SLionel Sambuc  * modification, are permitted provided that the following conditions
11f14fb602SLionel Sambuc  * are met:
12f14fb602SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13f14fb602SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14f14fb602SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
15f14fb602SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
16f14fb602SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
17f14fb602SLionel Sambuc  *
18f14fb602SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19f14fb602SLionel Sambuc  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20f14fb602SLionel Sambuc  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21f14fb602SLionel Sambuc  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22f14fb602SLionel Sambuc  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23f14fb602SLionel Sambuc  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24f14fb602SLionel Sambuc  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25f14fb602SLionel Sambuc  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26f14fb602SLionel Sambuc  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27f14fb602SLionel Sambuc  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28f14fb602SLionel Sambuc  *
29f14fb602SLionel Sambuc  * $FreeBSD: head/libexec/rtld-elf/rtld.c 220004 2011-03-25 18:23:10Z avg $
30f14fb602SLionel Sambuc  */
31f14fb602SLionel Sambuc 
32f14fb602SLionel Sambuc /*-
33f14fb602SLionel Sambuc  * Copyright (c) 2011 The NetBSD Foundation, Inc.
34f14fb602SLionel Sambuc  * All rights reserved.
35f14fb602SLionel Sambuc  *
36f14fb602SLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
37f14fb602SLionel Sambuc  * by NONAKA Kimihiro.
38f14fb602SLionel Sambuc  *
39f14fb602SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
40f14fb602SLionel Sambuc  * modification, are permitted provided that the following conditions
41f14fb602SLionel Sambuc  * are met:
42f14fb602SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
43f14fb602SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
44f14fb602SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
45f14fb602SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
46f14fb602SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
47f14fb602SLionel Sambuc  *
48f14fb602SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
49f14fb602SLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
50f14fb602SLionel Sambuc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51f14fb602SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
52f14fb602SLionel Sambuc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53f14fb602SLionel Sambuc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54f14fb602SLionel Sambuc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55f14fb602SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56f14fb602SLionel Sambuc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57f14fb602SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58f14fb602SLionel Sambuc  * POSSIBILITY OF SUCH DAMAGE.
59f14fb602SLionel Sambuc  */
60f14fb602SLionel Sambuc 
61f14fb602SLionel Sambuc #include <sys/cdefs.h>
62*84d9c625SLionel Sambuc __RCSID("$NetBSD: symver.c,v 1.4 2013/05/09 15:38:14 christos Exp $");
63f14fb602SLionel Sambuc 
64f14fb602SLionel Sambuc #include <sys/param.h>
65f14fb602SLionel Sambuc #include <sys/exec_elf.h>
66f14fb602SLionel Sambuc #include <string.h>
67f14fb602SLionel Sambuc 
68f14fb602SLionel Sambuc #include "debug.h"
69f14fb602SLionel Sambuc #include "rtld.h"
70f14fb602SLionel Sambuc 
71*84d9c625SLionel Sambuc void
_rtld_object_add_name(Obj_Entry * obj,const char * name)72*84d9c625SLionel Sambuc _rtld_object_add_name(Obj_Entry *obj, const char *name)
73*84d9c625SLionel Sambuc {
74*84d9c625SLionel Sambuc     Name_Entry *entry;
75*84d9c625SLionel Sambuc     size_t len;
76*84d9c625SLionel Sambuc 
77*84d9c625SLionel Sambuc     len = strlen(name);
78*84d9c625SLionel Sambuc     entry = xmalloc(sizeof(Name_Entry) + len);
79*84d9c625SLionel Sambuc 
80*84d9c625SLionel Sambuc     if (entry != NULL) {
81*84d9c625SLionel Sambuc 	strcpy(entry->name, name);
82*84d9c625SLionel Sambuc 	SIMPLEQ_INSERT_TAIL(&obj->names, entry, link);
83*84d9c625SLionel Sambuc     }
84*84d9c625SLionel Sambuc }
85f14fb602SLionel Sambuc 
86f14fb602SLionel Sambuc int
_rtld_object_match_name(const Obj_Entry * obj,const char * name)87f14fb602SLionel Sambuc _rtld_object_match_name(const Obj_Entry *obj, const char *name)
88f14fb602SLionel Sambuc {
89f14fb602SLionel Sambuc 	Name_Entry *entry;
90f14fb602SLionel Sambuc 
91*84d9c625SLionel Sambuc 	SIMPLEQ_FOREACH(entry, &obj->names, link) {
92f14fb602SLionel Sambuc 		dbg(("name: %s, entry->name: %s", name, entry->name));
93f14fb602SLionel Sambuc 		if (strcmp(name, entry->name) == 0)
94f14fb602SLionel Sambuc 			return 1;
95f14fb602SLionel Sambuc 	}
96f14fb602SLionel Sambuc 	return 0;
97f14fb602SLionel Sambuc }
98f14fb602SLionel Sambuc 
99*84d9c625SLionel Sambuc #ifdef RTLD_LOADER
100f14fb602SLionel Sambuc static Obj_Entry *
locate_dependency(const Obj_Entry * obj,const char * name)101f14fb602SLionel Sambuc locate_dependency(const Obj_Entry *obj, const char *name)
102f14fb602SLionel Sambuc {
103f14fb602SLionel Sambuc 	const Objlist_Entry *entry;
104f14fb602SLionel Sambuc 	const Needed_Entry *needed;
105f14fb602SLionel Sambuc 
106f14fb602SLionel Sambuc 	SIMPLEQ_FOREACH(entry, &_rtld_list_main, link) {
107f14fb602SLionel Sambuc 		if (_rtld_object_match_name(entry->obj, name))
108f14fb602SLionel Sambuc 			return entry->obj;
109f14fb602SLionel Sambuc 	}
110f14fb602SLionel Sambuc 
111f14fb602SLionel Sambuc 	for (needed = obj->needed; needed != NULL; needed = needed->next) {
112f14fb602SLionel Sambuc 		dbg(("needed: name: %s, str: %s", name,
113f14fb602SLionel Sambuc 		    &obj->strtab[needed->name]));
114f14fb602SLionel Sambuc 		if (strcmp(name, &obj->strtab[needed->name]) == 0 ||
115f14fb602SLionel Sambuc 		    (needed->obj != NULL && _rtld_object_match_name(needed->obj, name))) {
116f14fb602SLionel Sambuc 			/*
117f14fb602SLionel Sambuc 			 * If there is DT_NEEDED for the name we are looking
118f14fb602SLionel Sambuc 			 * for, we are all set.  Note that object might not be
119f14fb602SLionel Sambuc 			 * found if dependency was not loaded yet, so the
120f14fb602SLionel Sambuc 			 * function can return NULL here.  This is expected
121f14fb602SLionel Sambuc 			 * and handled properly by the caller.
122f14fb602SLionel Sambuc 			 */
123f14fb602SLionel Sambuc 			return needed->obj;
124f14fb602SLionel Sambuc 		}
125f14fb602SLionel Sambuc 	}
126f14fb602SLionel Sambuc 
127f14fb602SLionel Sambuc 	_rtld_error("%s: Unexpected inconsistency: dependency %s not found",
128f14fb602SLionel Sambuc 	    obj->path, name);
129f14fb602SLionel Sambuc 	return NULL;
130f14fb602SLionel Sambuc }
131f14fb602SLionel Sambuc 
132f14fb602SLionel Sambuc static int
check_object_provided_version(Obj_Entry * refobj,const Obj_Entry * depobj,const Elf_Vernaux * vna)133f14fb602SLionel Sambuc check_object_provided_version(Obj_Entry *refobj, const Obj_Entry *depobj,
134f14fb602SLionel Sambuc     const Elf_Vernaux *vna)
135f14fb602SLionel Sambuc {
136f14fb602SLionel Sambuc 	const char *vername = &refobj->strtab[vna->vna_name];
137f14fb602SLionel Sambuc 	const char *depstrtab = depobj->strtab;
138f14fb602SLionel Sambuc 	const Elf_Verdef *vd = depobj->verdef;
139f14fb602SLionel Sambuc 	const Elf_Word hash = vna->vna_hash;
140f14fb602SLionel Sambuc 
141f14fb602SLionel Sambuc 	if (vd == NULL) {
142f14fb602SLionel Sambuc 		_rtld_error("%s: version %s required by %s not defined",
143f14fb602SLionel Sambuc 		    depobj->path, vername, refobj->path);
144f14fb602SLionel Sambuc 		return -1;
145f14fb602SLionel Sambuc 	}
146f14fb602SLionel Sambuc 
147f14fb602SLionel Sambuc 	for (;; vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) {
148f14fb602SLionel Sambuc 		if (vd->vd_version != VER_DEF_CURRENT) {
149f14fb602SLionel Sambuc 			_rtld_error(
150f14fb602SLionel Sambuc 			    "%s: Unsupported version %d of Elf_Verdef entry",
151f14fb602SLionel Sambuc 			    depobj->path, vd->vd_version);
152f14fb602SLionel Sambuc 			return -1;
153f14fb602SLionel Sambuc 		}
154f14fb602SLionel Sambuc 		dbg(("hash: 0x%x, vd_hash: 0x%x", hash, vd->vd_hash));
155f14fb602SLionel Sambuc 		if (hash == vd->vd_hash) {
156f14fb602SLionel Sambuc 			const Elf_Verdaux *vda = (const Elf_Verdaux *)
157f14fb602SLionel Sambuc 			    ((const char *)vd + vd->vd_aux);
158f14fb602SLionel Sambuc 			dbg(("vername: %s, str: %s", vername,
159f14fb602SLionel Sambuc 			    &depstrtab[vda->vda_name]));
160f14fb602SLionel Sambuc 			if (strcmp(vername, &depstrtab[vda->vda_name]) == 0)
161f14fb602SLionel Sambuc 				return 0;
162f14fb602SLionel Sambuc 		}
163f14fb602SLionel Sambuc 		if (vd->vd_next == 0)
164f14fb602SLionel Sambuc 			break;
165f14fb602SLionel Sambuc 	}
166f14fb602SLionel Sambuc 	if (vna->vna_flags & VER_FLG_WEAK)
167f14fb602SLionel Sambuc 		return 0;
168f14fb602SLionel Sambuc 
169f14fb602SLionel Sambuc 	_rtld_error("%s: version %s required by %s not found", depobj->path,
170f14fb602SLionel Sambuc 	    vername, refobj->path);
171f14fb602SLionel Sambuc 	return -1;
172f14fb602SLionel Sambuc }
173f14fb602SLionel Sambuc 
174f14fb602SLionel Sambuc int
_rtld_verify_object_versions(Obj_Entry * obj)175f14fb602SLionel Sambuc _rtld_verify_object_versions(Obj_Entry *obj)
176f14fb602SLionel Sambuc {
177f14fb602SLionel Sambuc 	const char *strtab = obj->strtab;
178f14fb602SLionel Sambuc 	const Elf_Verneed *vn;
179f14fb602SLionel Sambuc 	const Elf_Vernaux *vna;
180f14fb602SLionel Sambuc 	const Elf_Verdef *vd;
181f14fb602SLionel Sambuc 	const Elf_Verdaux *vda;
182f14fb602SLionel Sambuc 	const Obj_Entry *depobj;
183f14fb602SLionel Sambuc 	int maxvertab, vernum;
184f14fb602SLionel Sambuc 
185f14fb602SLionel Sambuc 	dbg(("obj->path: %s", obj->path));
186f14fb602SLionel Sambuc 
187f14fb602SLionel Sambuc 	/*
188f14fb602SLionel Sambuc 	 * If we don't have string table or objects that have their version
189f14fb602SLionel Sambuc 	 * requirements already checked, we must be ok.
190f14fb602SLionel Sambuc 	 */
191f14fb602SLionel Sambuc 	if (strtab == NULL || obj->vertab != NULL)
192f14fb602SLionel Sambuc 		return 0;
193f14fb602SLionel Sambuc 
194f14fb602SLionel Sambuc 	maxvertab = 0;
195f14fb602SLionel Sambuc 
196f14fb602SLionel Sambuc 	/*
197f14fb602SLionel Sambuc 	 * Walk over defined and required version records and figure out
198f14fb602SLionel Sambuc 	 * max index used by any of them. Do very basic sanity checking
199f14fb602SLionel Sambuc 	 * while there.
200f14fb602SLionel Sambuc 	 */
201f14fb602SLionel Sambuc 	for (vn = obj->verneed;
202f14fb602SLionel Sambuc 	     vn != NULL;
203f14fb602SLionel Sambuc 	     vn = (const Elf_Verneed *)((const char *)vn + vn->vn_next)) {
204f14fb602SLionel Sambuc 
205f14fb602SLionel Sambuc 		if (vn->vn_version != VER_NEED_CURRENT) {
206f14fb602SLionel Sambuc 			_rtld_error(
207f14fb602SLionel Sambuc 			    "%s: Unsupported version %d of Elf_Verneed entry",
208f14fb602SLionel Sambuc 			    obj->path, vn->vn_version);
209f14fb602SLionel Sambuc 			return -1;
210f14fb602SLionel Sambuc 		}
211f14fb602SLionel Sambuc 
212f14fb602SLionel Sambuc 		dbg(("verneed: vn_file: %d, str: %s",
213f14fb602SLionel Sambuc 		    vn->vn_file, &strtab[vn->vn_file]));
214f14fb602SLionel Sambuc 		depobj = locate_dependency(obj, &strtab[vn->vn_file]);
215f14fb602SLionel Sambuc 		assert(depobj != NULL);
216f14fb602SLionel Sambuc 
217f14fb602SLionel Sambuc 		for (vna = (const Elf_Vernaux *)((const char *)vn + vn->vn_aux);
218f14fb602SLionel Sambuc 		     /*CONSTCOND*/1;
219f14fb602SLionel Sambuc 		     vna = (const Elf_Vernaux *)((const char *)vna + vna->vna_next)) {
220f14fb602SLionel Sambuc 
221f14fb602SLionel Sambuc 			if (check_object_provided_version(obj, depobj, vna) == -1)
222f14fb602SLionel Sambuc 				return -1;
223f14fb602SLionel Sambuc 
224f14fb602SLionel Sambuc 			vernum = VER_NEED_IDX(vna->vna_other);
225f14fb602SLionel Sambuc 			if (vernum > maxvertab)
226f14fb602SLionel Sambuc 				maxvertab = vernum;
227f14fb602SLionel Sambuc 
228f14fb602SLionel Sambuc 			if (vna->vna_next == 0) {
229f14fb602SLionel Sambuc 				/* No more symbols. */
230f14fb602SLionel Sambuc 				break;
231f14fb602SLionel Sambuc 			}
232f14fb602SLionel Sambuc 		}
233f14fb602SLionel Sambuc 
234f14fb602SLionel Sambuc 		if (vn->vn_next == 0) {
235f14fb602SLionel Sambuc 			/* No more dependencies. */
236f14fb602SLionel Sambuc 			break;
237f14fb602SLionel Sambuc 		}
238f14fb602SLionel Sambuc 	}
239f14fb602SLionel Sambuc 
240f14fb602SLionel Sambuc 	for (vd = obj->verdef;
241f14fb602SLionel Sambuc 	     vd != NULL;
242f14fb602SLionel Sambuc 	     vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) {
243f14fb602SLionel Sambuc 
244f14fb602SLionel Sambuc 		if (vd->vd_version != VER_DEF_CURRENT) {
245f14fb602SLionel Sambuc 			_rtld_error(
246f14fb602SLionel Sambuc 			    "%s: Unsupported version %d of Elf_Verdef entry",
247f14fb602SLionel Sambuc 			    obj->path, vd->vd_version);
248f14fb602SLionel Sambuc 			return -1;
249f14fb602SLionel Sambuc 		}
250f14fb602SLionel Sambuc 
251f14fb602SLionel Sambuc 		dbg(("verdef: vn_ndx: 0x%x", vd->vd_ndx));
252f14fb602SLionel Sambuc 		vernum = VER_DEF_IDX(vd->vd_ndx);
253f14fb602SLionel Sambuc 		if (vernum > maxvertab)
254f14fb602SLionel Sambuc 			maxvertab = vernum;
255f14fb602SLionel Sambuc 
256f14fb602SLionel Sambuc 		if (vd->vd_next == 0) {
257f14fb602SLionel Sambuc 			/* No more definitions. */
258f14fb602SLionel Sambuc 			break;
259f14fb602SLionel Sambuc 		}
260f14fb602SLionel Sambuc 	}
261f14fb602SLionel Sambuc 
262f14fb602SLionel Sambuc 	dbg(("maxvertab: %d", maxvertab));
263f14fb602SLionel Sambuc 	if (maxvertab == 0)
264f14fb602SLionel Sambuc 		return 0;
265f14fb602SLionel Sambuc 
266f14fb602SLionel Sambuc 	/*
267f14fb602SLionel Sambuc 	 * Store version information in array indexable by version index.
268f14fb602SLionel Sambuc 	 * Verify that object version requirements are satisfied along the
269f14fb602SLionel Sambuc 	 * way.
270f14fb602SLionel Sambuc 	 */
271f14fb602SLionel Sambuc 	obj->vertabnum = maxvertab + 1;
272f14fb602SLionel Sambuc 	obj->vertab = (Ver_Entry *)xcalloc(obj->vertabnum * sizeof(Ver_Entry));
273f14fb602SLionel Sambuc 
274f14fb602SLionel Sambuc 	for (vn = obj->verneed;
275f14fb602SLionel Sambuc 	     vn != NULL;
276f14fb602SLionel Sambuc 	     vn = (const Elf_Verneed *)((const char *)vn + vn->vn_next)) {
277f14fb602SLionel Sambuc 
278f14fb602SLionel Sambuc 		for (vna = (const Elf_Vernaux *)((const char *)vn + vn->vn_aux);
279f14fb602SLionel Sambuc 		     /*CONSTCOND*/1;
280f14fb602SLionel Sambuc 		     vna = (const Elf_Vernaux *)((const char *)vna + vna->vna_next)) {
281f14fb602SLionel Sambuc 
282f14fb602SLionel Sambuc 			vernum = VER_NEED_IDX(vna->vna_other);
283f14fb602SLionel Sambuc 			assert(vernum <= maxvertab);
284f14fb602SLionel Sambuc 			obj->vertab[vernum].hash = vna->vna_hash;
285f14fb602SLionel Sambuc 			obj->vertab[vernum].name = &strtab[vna->vna_name];
286f14fb602SLionel Sambuc 			obj->vertab[vernum].file = &strtab[vn->vn_file];
287f14fb602SLionel Sambuc 			obj->vertab[vernum].flags =
288f14fb602SLionel Sambuc 			    (vna->vna_other & VER_NEED_HIDDEN)
289f14fb602SLionel Sambuc 			      ? VER_INFO_HIDDEN : 0;
290f14fb602SLionel Sambuc 			dbg(("verneed: vernum: %d, hash: 0x%x, name: %s, "
291f14fb602SLionel Sambuc 			    "file: %s, flags: 0x%x", vernum,
292f14fb602SLionel Sambuc 			    obj->vertab[vernum].hash, obj->vertab[vernum].name,
293f14fb602SLionel Sambuc 			    obj->vertab[vernum].file,
294f14fb602SLionel Sambuc 			    obj->vertab[vernum].flags));
295f14fb602SLionel Sambuc 
296f14fb602SLionel Sambuc 			if (vna->vna_next == 0) {
297f14fb602SLionel Sambuc 				/* No more symbols. */
298f14fb602SLionel Sambuc 				break;
299f14fb602SLionel Sambuc 			}
300f14fb602SLionel Sambuc 		}
301f14fb602SLionel Sambuc 		if (vn->vn_next == 0) {
302f14fb602SLionel Sambuc 			/* No more dependencies. */
303f14fb602SLionel Sambuc 			break;
304f14fb602SLionel Sambuc 		}
305f14fb602SLionel Sambuc 	}
306f14fb602SLionel Sambuc 
307f14fb602SLionel Sambuc 	for (vd = obj->verdef;
308f14fb602SLionel Sambuc 	     vd != NULL;
309f14fb602SLionel Sambuc 	     vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) {
310f14fb602SLionel Sambuc 
311f14fb602SLionel Sambuc 		if ((vd->vd_flags & VER_FLG_BASE) == 0) {
312f14fb602SLionel Sambuc 			vernum = VER_DEF_IDX(vd->vd_ndx);
313f14fb602SLionel Sambuc 			assert(vernum <= maxvertab);
314f14fb602SLionel Sambuc 			vda = (const Elf_Verdaux *)
315f14fb602SLionel Sambuc 			    ((const char *)vd + vd->vd_aux);
316f14fb602SLionel Sambuc 			obj->vertab[vernum].hash = vd->vd_hash;
317f14fb602SLionel Sambuc 			obj->vertab[vernum].name = &strtab[vda->vda_name];
318f14fb602SLionel Sambuc 			obj->vertab[vernum].file = NULL;
319f14fb602SLionel Sambuc 			obj->vertab[vernum].flags = 0;
320f14fb602SLionel Sambuc 			dbg(("verdef: vernum: %d, hash: 0x%x, name: %s",
321f14fb602SLionel Sambuc 			    vernum, obj->vertab[vernum].hash,
322f14fb602SLionel Sambuc 			    obj->vertab[vernum].name));
323f14fb602SLionel Sambuc 		}
324f14fb602SLionel Sambuc 
325f14fb602SLionel Sambuc 		if (vd->vd_next == 0) {
326f14fb602SLionel Sambuc 			/* No more definitions. */
327f14fb602SLionel Sambuc 			break;
328f14fb602SLionel Sambuc 		}
329f14fb602SLionel Sambuc 	}
330f14fb602SLionel Sambuc 
331f14fb602SLionel Sambuc 	return 0;
332f14fb602SLionel Sambuc }
333*84d9c625SLionel Sambuc #endif
334