1 /*-
2  * Copyright (c) 2010-2013 Kai Wang
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include "ld.h"
28 #include "ld_input.h"
29 #include "ld_layout.h"
30 #include "ld_output.h"
31 #include "ld_script.h"
32 #include "ld_symbols.h"
33 #include "ld_symver.h"
34 #include "ld_strtab.h"
35 
36 ELFTC_VCSID("$Id: ld_symver.c 2917 2013-02-16 07:16:02Z kaiwang27 $");
37 
38 /*
39  * Symbol versioning sections are the same for 32bit and 64bit
40  * ELF objects.
41  */
42 #define Elf_Verdef	Elf32_Verdef
43 #define	Elf_Verdaux	Elf32_Verdaux
44 #define	Elf_Verneed	Elf32_Verneed
45 #define	Elf_Vernaux	Elf32_Vernaux
46 
47 static void _add_version_name(struct ld *ld, struct ld_input *li, int ndx,
48     const char *name);
49 static struct ld_symver_vda *_alloc_vda(struct ld *ld, const char *name,
50     struct ld_symver_verdef *svd);
51 static struct ld_symver_vna *_alloc_vna(struct ld *ld, const char *name,
52     struct ld_symver_verneed *svn);
53 static struct ld_symver_verdef *_alloc_verdef(struct ld *ld,
54     struct ld_symver_verdef_head *head);
55 static struct ld_symver_verneed *_alloc_verneed(struct ld *ld,
56     struct ld_input *li, struct ld_symver_verneed_head *head);
57 static struct ld_symver_verdef *_load_verdef(struct ld *ld,
58     struct ld_input *li, Elf_Verdef *vd);
59 static void _load_verdef_section(struct ld *ld, struct ld_input *li, Elf *e,
60     Elf_Scn *verdef);
61 static void _load_verneed_section(struct ld *ld, struct ld_input *li, Elf *e,
62     Elf_Scn *verneed);
63 
64 void
ld_symver_load_symbol_version_info(struct ld * ld,struct ld_input * li,Elf * e,Elf_Scn * versym,Elf_Scn * verneed,Elf_Scn * verdef)65 ld_symver_load_symbol_version_info(struct ld *ld, struct ld_input *li, Elf *e,
66     Elf_Scn *versym, Elf_Scn *verneed, Elf_Scn *verdef)
67 {
68 	Elf_Data *d_vs;
69 	int elferr;
70 
71 	if (versym == NULL)
72 		return;
73 
74 	(void) elf_errno();
75 	if ((d_vs = elf_getdata(versym, NULL)) == NULL) {
76 		elferr = elf_errno();
77 		if (elferr != 0)
78 			ld_fatal(ld, "%s: elf_getdata failed: %s", li->li_name,
79 			    elf_errmsg(elferr));
80 		return;
81 	}
82 	if (d_vs->d_size == 0)
83 		return;
84 
85 	if ((li->li_versym = malloc(d_vs->d_size)) == NULL)
86 		ld_fatal_std(ld, "malloc");
87 	memcpy(li->li_versym, d_vs->d_buf, d_vs->d_size);
88 	li->li_versym_sz = d_vs->d_size / sizeof(uint16_t);
89 
90 	_add_version_name(ld, li, 0, "*local*");
91 	_add_version_name(ld, li, 1, "*global*");
92 
93 	if (verneed != NULL)
94 		_load_verneed_section(ld, li, e, verneed);
95 
96 	if (verdef != NULL)
97 		_load_verdef_section(ld, li, e, verdef);
98 }
99 
100 void
ld_symver_create_verneed_section(struct ld * ld)101 ld_symver_create_verneed_section(struct ld *ld)
102 {
103 	struct ld_input *li;
104 	struct ld_output *lo;
105 	struct ld_output_section *os;
106 	struct ld_output_data_buffer *odb;
107 	struct ld_symver_verdef *svd;
108 	struct ld_symver_verneed *svn;
109 	struct ld_symver_vda *sda;
110 	struct ld_symver_vna *sna;
111 	char verneed_name[] = ".gnu.version_r";
112 	Elf_Verneed *vn;
113 	Elf_Vernaux *vna;
114 	uint8_t *buf, *buf2, *end;
115 	size_t sz;
116 
117 	lo = ld->ld_output;
118 	assert(lo != NULL);
119 	assert(lo->lo_dynstr != NULL);
120 
121 	/*
122 	 * Create .gnu.version_r section.
123 	 */
124 	HASH_FIND_STR(lo->lo_ostbl, verneed_name, os);
125 	if (os == NULL)
126 		os = ld_layout_insert_output_section(ld, verneed_name,
127 		    SHF_ALLOC);
128 	os->os_type = SHT_GNU_verneed;
129 	os->os_flags = SHF_ALLOC;
130 	os->os_entsize = 0;
131 	if (lo->lo_ec == ELFCLASS32)
132 		os->os_align = 4;
133 	else
134 		os->os_align = 8;
135 
136 	if ((os->os_link = strdup(".dynstr")) == NULL)
137 		ld_fatal_std(ld, "strdup");
138 
139 	lo->lo_verneed = os;
140 
141 	/*
142 	 * Build Verneed/Vernaux structures.
143 	 */
144 	sz = 0;
145 	STAILQ_FOREACH(li, &ld->ld_lilist, li_next) {
146 		if (li->li_type != LIT_DSO || li->li_dso_refcnt == 0 ||
147 		    li->li_verdef == NULL)
148 			continue;
149 
150 		svn = NULL;
151 		STAILQ_FOREACH(svd, li->li_verdef, svd_next) {
152 			if (svd->svd_flags & VER_FLG_BASE)
153 				continue;
154 
155 			/* Skip version definition that is never ref'ed. */
156 			if (svd->svd_ref == 0)
157 				continue;
158 
159 			/* Invalid Verdef? */
160 			if ((sda = STAILQ_FIRST(&svd->svd_aux)) == NULL)
161 				continue;
162 
163 			if (lo->lo_vnlist == NULL) {
164 				lo->lo_vnlist = calloc(1,
165 				    sizeof(*lo->lo_vnlist));
166 				if (lo->lo_vnlist == NULL)
167 					ld_fatal_std(ld, "calloc");
168 				STAILQ_INIT(lo->lo_vnlist);
169 			}
170 
171 			/* Allocate Verneed entry. */
172 			if (svn == NULL) {
173 				svn = _alloc_verneed(ld, li, lo->lo_vnlist);
174 				svn->svn_version = VER_NEED_CURRENT;
175 				svn->svn_cnt = 0;
176 				svn->svn_fileindex =
177 				    ld_strtab_insert_no_suffix(ld,
178 					ld->ld_dynstr, svn->svn_file);
179 				sz += sizeof(Elf_Verneed);
180 				lo->lo_verneed_num++;
181 			}
182 
183 			/* Allocate Vernaux entry. */
184 			sna = _alloc_vna(ld, sda->sda_name, svn);
185 			sna->sna_other = lo->lo_version_index++;
186 			sna->sna_nameindex = ld_strtab_insert_no_suffix(ld,
187 			    ld->ld_dynstr, sna->sna_name);
188 			/* TODO: flags? VER_FLG_WEAK */
189 			svn->svn_cnt++;
190 
191 			sz += sizeof(Elf_Vernaux);
192 
193 			/*
194 			 * Store the index in Verdef structure, so later we can
195 			 * quickly find the version index for a dynamic symbol,
196 			 * when we build the .gnu.version section.
197 			 */
198 			svd->svd_ndx_output = sna->sna_other;
199 		}
200 	}
201 
202 	if (lo->lo_verneed_num == 0)
203 		return;
204 
205 	/* Store the number of verneed entries in the sh_info field. */
206 	os->os_info_val = lo->lo_verneed_num;
207 
208 	/*
209 	 * Write Verneed/Vernaux structures.
210 	 */
211 	if ((buf = malloc(sz)) == NULL)
212 		ld_fatal_std(ld, "malloc");
213 
214 	if ((odb = calloc(1, sizeof(*odb))) == NULL)
215 		ld_fatal_std(ld, "calloc");
216 
217 	odb->odb_buf = buf;
218 	odb->odb_size = sz;
219 	odb->odb_align = os->os_align;
220 	odb->odb_type = ELF_T_VNEED; /* enable libelf translation */
221 
222 	end = buf + sz;
223 	vn = NULL;
224 	STAILQ_FOREACH(svn, lo->lo_vnlist, svn_next){
225 		vn = (Elf_Verneed *) (uintptr_t) buf;
226 		vn->vn_version = VER_NEED_CURRENT;
227 		vn->vn_cnt = svn->svn_cnt;
228 		vn->vn_file = svn->svn_fileindex;
229 		vn->vn_aux = sizeof(Elf_Verneed);
230 		vn->vn_next = sizeof(Elf_Verneed) +
231 		    svn->svn_cnt * sizeof(Elf_Vernaux);
232 
233 		/*
234 		 * Write Vernaux entries.
235 		 */
236 		buf2 = buf + sizeof(Elf_Verneed);
237 		vna = NULL;
238 		STAILQ_FOREACH(sna, &svn->svn_aux, sna_next) {
239 			vna = (Elf_Vernaux *) (uintptr_t) buf2;
240 			vna->vna_hash = sna->sna_hash;
241 			vna->vna_flags = 0; /* TODO: VER_FLG_WEAK? */
242 			vna->vna_other = sna->sna_other;
243 			vna->vna_name = sna->sna_nameindex;
244 			vna->vna_next = sizeof(Elf_Vernaux);
245 			buf2 += sizeof(Elf_Vernaux);
246 		}
247 
248 		/* Set last Vernaux entry's vna_next to 0. */
249 		if (vna != NULL)
250 			vna->vna_next = 0;
251 
252 		buf += vn->vn_next;
253 	}
254 
255 	/* Set last Verneed entry's vn_next to 0 */
256 	if (vn != NULL)
257 		vn->vn_next = 0;
258 
259 	assert(buf == end);
260 
261 	(void) ld_output_create_section_element(ld, os, OET_DATA_BUFFER,
262 	    odb, NULL);
263 }
264 
265 void
ld_symver_create_verdef_section(struct ld * ld)266 ld_symver_create_verdef_section(struct ld *ld)
267 {
268 	struct ld_script *lds;
269 	struct ld_output *lo;
270 	struct ld_output_section *os;
271 	struct ld_output_data_buffer *odb;
272 	struct ld_script_version_node *ldvn;
273 	char verdef_name[] = ".gnu.version_d";
274 	Elf_Verdef *vd;
275 	Elf_Verdaux *vda;
276 	uint8_t *buf, *end;
277 	char *soname;
278 	size_t sz;
279 
280 	lo = ld->ld_output;
281 	assert(lo != NULL);
282 	assert(lo->lo_dynstr != NULL);
283 
284 	lds = ld->ld_scp;
285 	if (STAILQ_EMPTY(&lds->lds_vn))
286 		return;
287 
288 	/*
289 	 * Create .gnu.version_d section.
290 	 */
291 	HASH_FIND_STR(lo->lo_ostbl, verdef_name, os);
292 	if (os == NULL)
293 		os = ld_layout_insert_output_section(ld, verdef_name,
294 		    SHF_ALLOC);
295 	os->os_type = SHT_GNU_verdef;
296 	os->os_flags = SHF_ALLOC;
297 	os->os_entsize = 0;
298 	if (lo->lo_ec == ELFCLASS32)
299 		os->os_align = 4;
300 	else
301 		os->os_align = 8;
302 
303 	if ((os->os_link = strdup(".dynstr")) == NULL)
304 		ld_fatal_std(ld, "strdup");
305 
306 	lo->lo_verdef = os;
307 
308 	/*
309 	 * Calculate verdef section size: .gnu.version_d section consists
310 	 * of one file version entry and several symbol version definition
311 	 * entries (with corresponding) auxiliary entries.
312 	 */
313 	lo->lo_verdef_num = 1;
314 	sz = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
315 	STAILQ_FOREACH(ldvn, &lds->lds_vn, ldvn_next) {
316 		sz += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
317 		if (ldvn->ldvn_dep != NULL)
318 			sz += sizeof(Elf_Verdaux);
319 		lo->lo_verdef_num++;
320 	}
321 
322 	/* Store the number of verdef entries in the sh_info field. */
323 	os->os_info_val = lo->lo_verdef_num;
324 
325 	/* Allocate buffer for Verdef/Verdaux entries. */
326 	if ((buf = malloc(sz)) == NULL)
327 		ld_fatal_std(ld, "malloc");
328 
329 	end = buf + sz;
330 
331 	if ((odb = calloc(1, sizeof(*odb))) == NULL)
332 		ld_fatal_std(ld, "calloc");
333 
334 	odb->odb_buf = buf;
335 	odb->odb_size = sz;
336 	odb->odb_align = os->os_align;
337 	odb->odb_type = ELF_T_VDEF; /* enable libelf translation */
338 
339 	/*
340 	 * Set file version name to `soname' if it is provided,
341 	 * otherwise set version name to output file name.
342 	 */
343 	if (ld->ld_soname != NULL)
344 		soname = ld->ld_soname;
345 	else {
346 		if ((soname = strrchr(ld->ld_output_file, '/')) == NULL)
347 			soname = ld->ld_output_file;
348 		else
349 			soname++;
350 	}
351 
352 	/* Write file version entry. */
353 	vd = (Elf_Verdef *) (uintptr_t) buf;
354 	vd->vd_version = VER_DEF_CURRENT;
355 	vd->vd_flags |= VER_FLG_BASE;
356 	vd->vd_ndx = 1;
357 	vd->vd_cnt = 1;
358 	vd->vd_hash = elf_hash(soname);
359 	vd->vd_aux = sizeof(Elf_Verdef);
360 	vd->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
361 	buf += sizeof(Elf_Verdef);
362 
363 	/* Write file version auxiliary entry. */
364 	vda = (Elf_Verdaux *) (uintptr_t) buf;
365 	vda->vda_name = ld_strtab_insert_no_suffix(ld, ld->ld_dynstr,
366 	    soname);
367 	vda->vda_next = 0;
368 	buf += sizeof(Elf_Verdaux);
369 
370 	/* Write symbol version definition entries. */
371 	STAILQ_FOREACH(ldvn, &lds->lds_vn, ldvn_next) {
372 		vd = (Elf_Verdef *) (uintptr_t) buf;
373 		vd->vd_version = VER_DEF_CURRENT;
374 		vd->vd_flags = 0;
375 		vd->vd_ndx = lo->lo_version_index++;
376 		vd->vd_cnt = (ldvn->ldvn_dep == NULL) ? 1 : 2;
377 		vd->vd_hash = elf_hash(ldvn->ldvn_name);
378 		vd->vd_aux = sizeof(Elf_Verdef);
379 		if (STAILQ_NEXT(ldvn, ldvn_next) == NULL)
380 			vd->vd_next = 0;
381 		else
382 			vd->vd_next = sizeof(Elf_Verdef) +
383 			    ((ldvn->ldvn_dep == NULL) ? 1 : 2) *
384 				sizeof(Elf_Verdaux);
385 		buf += sizeof(Elf_Verdef);
386 
387 		/* Write version name auxiliary entry. */
388 		vda = (Elf_Verdaux *) (uintptr_t) buf;
389 		vda->vda_name = ld_strtab_insert_no_suffix(ld, ld->ld_dynstr,
390 		    ldvn->ldvn_name);
391 		vda->vda_next = ldvn->ldvn_dep == NULL ? 0 :
392 		    sizeof(Elf_Verdaux);
393 		buf += sizeof(Elf_Verdaux);
394 
395 		if (ldvn->ldvn_dep == NULL)
396 			continue;
397 
398 		/* Write version dependency auxiliary entry. */
399 		vda = (Elf_Verdaux *) (uintptr_t) buf;
400 		vda->vda_name = ld_strtab_insert_no_suffix(ld, ld->ld_dynstr,
401 		    ldvn->ldvn_dep);
402 		vda->vda_next = 0;
403 		buf += sizeof(Elf_Verdaux);
404 	}
405 
406 	assert(buf == end);
407 
408 	(void) ld_output_create_section_element(ld, os, OET_DATA_BUFFER,
409 	    odb, NULL);
410 }
411 
412 void
ld_symver_create_versym_section(struct ld * ld)413 ld_symver_create_versym_section(struct ld *ld)
414 {
415 	struct ld_output *lo;
416 	struct ld_output_section *os;
417 	struct ld_output_data_buffer *odb;
418 	struct ld_symbol *lsb;
419 	char versym_name[] = ".gnu.version";
420 	uint16_t *buf;
421 	size_t sz;
422 	int i;
423 
424 	lo = ld->ld_output;
425 	assert(lo != NULL);
426 	assert(lo->lo_dynsym != NULL);
427 	assert(ld->ld_dynsym != NULL);
428 
429 	/*
430 	 * Create .gnu.version section.
431 	 */
432 	HASH_FIND_STR(lo->lo_ostbl, versym_name, os);
433 	if (os == NULL)
434 		os = ld_layout_insert_output_section(ld, versym_name,
435 		    SHF_ALLOC);
436 	os->os_type = SHT_GNU_versym;
437 	os->os_flags = SHF_ALLOC;
438 	os->os_entsize = 2;
439 	os->os_align = 2;
440 
441 	if ((os->os_link = strdup(".dynsym")) == NULL)
442 		ld_fatal_std(ld, "strdup");
443 
444 	lo->lo_versym = os;
445 
446 	/*
447 	 * Write versym table.
448 	 */
449 	sz = ld->ld_dynsym->sy_size * sizeof(*buf);
450 	if ((buf = malloc(sz)) == NULL)
451 		ld_fatal_std(ld, "malloc");
452 
453 	buf[0] = 0;		/* special index 0 symbol */
454 	i = 1;
455 	STAILQ_FOREACH(lsb, ld->ld_dyn_symbols, lsb_dyn) {
456 		/*
457 		 * Assign version index according to the following rules:
458 		 *
459 		 * 1. If the symbol is local, the version is *local*.
460 		 *
461 		 * 2. If the symbol is defined in shared libraries and there
462 		 *    exists a version definition for this symbol, use the
463 		 *    version defined by the shared library.
464 		 *
465 		 * 3. If the symbol is defined in regular objects and the
466 		 *    linker creates a shared library, use the version
467 		 *    defined in the version script, if provided.
468 		 *
469 		 * 4. Otherwise, the version is *global*.
470 		 */
471 		if (lsb->lsb_bind == STB_LOCAL)
472 			buf[i] = 0; /* Version is *local* */
473 		else if (lsb->lsb_vd != NULL)
474 			buf[i] = lsb->lsb_vd->svd_ndx_output;
475 		else if (ld->ld_dso && ld_symbols_in_regular(lsb))
476 			buf[i] = ld_symver_search_version_script(ld, lsb);
477 		else {
478 			buf[i] = 1; /* Version is *global* */
479 		}
480 		i++;
481 	}
482 	assert((size_t) i == ld->ld_dynsym->sy_size);
483 
484 	if ((odb = calloc(1, sizeof(*odb))) == NULL)
485 		ld_fatal_std(ld, "calloc");
486 
487 	odb->odb_buf = (void *) buf;
488 	odb->odb_size = sz;
489 	odb->odb_align = os->os_align;
490 	odb->odb_type = ELF_T_HALF; /* enable libelf translation */
491 
492 	(void) ld_output_create_section_element(ld, os, OET_DATA_BUFFER,
493 	    odb, NULL);
494 }
495 
496 void
ld_symver_add_verdef_refcnt(struct ld * ld,struct ld_symbol * lsb)497 ld_symver_add_verdef_refcnt(struct ld *ld, struct ld_symbol *lsb)
498 {
499 	struct ld_symbol_defver *dv;
500 	struct ld_symver_verdef *svd;
501 	struct ld_symver_vda *sda;
502 	struct ld_input *li;
503 	const char *ver;
504 
505 	li = lsb->lsb_input;
506 	assert(li != NULL);
507 
508 	if (li->li_verdef == NULL)
509 		return;
510 
511 	if (lsb->lsb_ver != NULL)
512 		ver = lsb->lsb_ver;
513 	else {
514 		HASH_FIND_STR(ld->ld_defver, lsb->lsb_name, dv);
515 		if (dv == NULL || dv->dv_ver == NULL)
516 			return;
517 		ver = dv->dv_ver;
518 	}
519 
520 	STAILQ_FOREACH(svd, li->li_verdef, svd_next) {
521 		if (svd->svd_flags & VER_FLG_BASE)
522 			continue;
523 
524 		/* Invalid Verdef? */
525 		if ((sda = STAILQ_FIRST(&svd->svd_aux)) == NULL)
526 			continue;
527 
528 		if (!strcmp(ver, sda->sda_name))
529 			break;
530 	}
531 
532 	if (svd != NULL) {
533 		svd->svd_ref++;
534 		lsb->lsb_vd = svd;
535 	}
536 }
537 
538 static void
_add_version_name(struct ld * ld,struct ld_input * li,int ndx,const char * name)539 _add_version_name(struct ld *ld, struct ld_input *li, int ndx,
540     const char *name)
541 {
542 	int i;
543 
544 	assert(name != NULL);
545 
546 	if (ndx <= 1)
547 		return;
548 
549 	if (li->li_vername == NULL) {
550 		li->li_vername_sz = 10;
551 		li->li_vername = calloc(li->li_vername_sz,
552 		    sizeof(*li->li_vername));
553 		if (li->li_vername == NULL)
554 			ld_fatal_std(ld, "calloc");
555 	}
556 
557 	if ((size_t) ndx >= li->li_vername_sz) {
558 		li->li_vername = realloc(li->li_vername,
559 		    sizeof(*li->li_vername) * li->li_vername_sz * 2);
560 		if (li->li_vername == NULL)
561 			ld_fatal_std(ld, "realloc");
562 		for (i = li->li_vername_sz; (size_t) i < li->li_vername_sz * 2;
563 		     i++)
564 			li->li_vername[i] = NULL;
565 		li->li_vername_sz *= 2;
566 	}
567 
568 	if (li->li_vername[ndx] == NULL) {
569 		li->li_vername[ndx] = strdup(name);
570 		if (li->li_vername[ndx] == NULL)
571 			ld_fatal_std(ld, "strdup");
572 	}
573 }
574 
575 static struct ld_symver_vna *
_alloc_vna(struct ld * ld,const char * name,struct ld_symver_verneed * svn)576 _alloc_vna(struct ld *ld, const char *name, struct ld_symver_verneed *svn)
577 {
578 	struct ld_symver_vna *sna;
579 
580 	assert(name != NULL);
581 
582 	if ((sna = calloc(1, sizeof(*sna))) == NULL)
583 		ld_fatal_std(ld, "calloc");
584 
585 	if ((sna->sna_name = strdup(name)) == NULL)
586 		ld_fatal_std(ld, "strdup");
587 
588 	sna->sna_hash = (uint32_t) elf_hash(sna->sna_name);
589 
590 	if (svn != NULL)
591 		STAILQ_INSERT_TAIL(&svn->svn_aux, sna, sna_next);
592 
593 	return (sna);
594 }
595 
596 static struct ld_symver_vda *
_alloc_vda(struct ld * ld,const char * name,struct ld_symver_verdef * svd)597 _alloc_vda(struct ld *ld, const char *name, struct ld_symver_verdef *svd)
598 {
599 	struct ld_symver_vda *sda;
600 
601 	if ((sda = calloc(1, sizeof(*sda))) == NULL)
602 		ld_fatal_std(ld, "calloc");
603 
604 	if ((sda->sda_name = strdup(name)) == NULL)
605 		ld_fatal_std(ld, "strdup");
606 
607 	if (svd != NULL)
608 		STAILQ_INSERT_TAIL(&svd->svd_aux, sda, sda_next);
609 
610 	return (sda);
611 }
612 
613 static struct ld_symver_verneed *
_alloc_verneed(struct ld * ld,struct ld_input * li,struct ld_symver_verneed_head * head)614 _alloc_verneed(struct ld *ld, struct ld_input *li,
615     struct ld_symver_verneed_head *head)
616 {
617 	struct ld_symver_verneed *svn;
618 	const char *bn;
619 
620 	if ((svn = calloc(1, sizeof(*svn))) == NULL)
621 		ld_fatal_std(ld, "calloc");
622 
623 	if (li->li_soname != NULL)
624 		bn = li->li_soname;
625 	else {
626 		if ((bn = strrchr(li->li_name, '/')) == NULL)
627 			bn = li->li_name;
628 		else
629 			bn++;
630 	}
631 
632 	if ((svn->svn_file = strdup(bn)) == NULL)
633 		ld_fatal_std(ld, "strdup");
634 
635 	STAILQ_INIT(&svn->svn_aux);
636 
637 	if (head != NULL)
638 		STAILQ_INSERT_TAIL(head, svn, svn_next);
639 
640 	return (svn);
641 }
642 
643 static struct ld_symver_verdef *
_alloc_verdef(struct ld * ld,struct ld_symver_verdef_head * head)644 _alloc_verdef(struct ld *ld, struct ld_symver_verdef_head *head)
645 {
646 	struct ld_symver_verdef *svd;
647 
648 	if ((svd = calloc(1, sizeof(*svd))) == NULL)
649 		ld_fatal_std(ld, "calloc");
650 
651 	STAILQ_INIT(&svd->svd_aux);
652 
653 	if (head != NULL)
654 		STAILQ_INSERT_TAIL(head, svd, svd_next);
655 
656 	return (svd);
657 }
658 
659 static void
_load_verneed_section(struct ld * ld,struct ld_input * li,Elf * e,Elf_Scn * verneed)660 _load_verneed_section(struct ld *ld, struct ld_input *li, Elf *e,
661     Elf_Scn *verneed)
662 {
663 	Elf_Data *d_vn;
664 	Elf_Verneed *vn;
665 	Elf_Vernaux *vna;
666 	GElf_Shdr sh_vn;
667 	uint8_t *buf, *end, *buf2;
668 	char *name;
669 	int elferr, i;
670 
671 	if (gelf_getshdr(verneed, &sh_vn) != &sh_vn)
672 		ld_fatal(ld, "%s: gelf_getshdr failed: %s", li->li_name,
673 		    elf_errmsg(-1));
674 
675 	(void) elf_errno();
676 	if ((d_vn = elf_getdata(verneed, NULL)) == NULL) {
677 		elferr = elf_errno();
678 		if (elferr != 0)
679 			ld_fatal(ld, "%s: elf_getdata failed: %s", li->li_name,
680 			    elf_errmsg(elferr));
681 		return;
682 	}
683 	if (d_vn->d_size == 0)
684 		return;
685 
686 	buf = d_vn->d_buf;
687 	end = buf + d_vn->d_size;
688 	while (buf + sizeof(Elf_Verneed) <= end) {
689 		vn = (Elf_Verneed *) (uintptr_t) buf;
690 		buf2 = buf + vn->vn_aux;
691 		i = 0;
692 		while (buf2 + sizeof(Elf_Vernaux) <= end && i < vn->vn_cnt) {
693 			vna = (Elf32_Vernaux *) (uintptr_t) buf2;
694 			name = elf_strptr(e, sh_vn.sh_link,
695 			    vna->vna_name);
696 			if (name != NULL)
697 				_add_version_name(ld, li, (int) vna->vna_other,
698 				    name);
699 			buf2 += vna->vna_next;
700 			i++;
701 		}
702 		if (vn->vn_next == 0)
703 			break;
704 		buf += vn->vn_next;
705 	}
706 }
707 
708 static void
_load_verdef_section(struct ld * ld,struct ld_input * li,Elf * e,Elf_Scn * verdef)709 _load_verdef_section(struct ld *ld, struct ld_input *li, Elf *e,
710     Elf_Scn *verdef)
711 {
712 	struct ld_symver_verdef *svd;
713 	Elf_Data *d_vd;
714 	Elf_Verdef *vd;
715 	Elf_Verdaux *vda;
716 	GElf_Shdr sh_vd;
717 	uint8_t *buf, *end, *buf2;
718 	char *name;
719 	int elferr, i;
720 
721 	if (gelf_getshdr(verdef, &sh_vd) != &sh_vd)
722 		ld_fatal(ld, "%s: gelf_getshdr failed: %s", li->li_name,
723 		    elf_errmsg(-1));
724 
725 	(void) elf_errno();
726 	if ((d_vd = elf_getdata(verdef, NULL)) == NULL) {
727 		elferr = elf_errno();
728 		if (elferr != 0)
729 			ld_fatal(ld, "%s: elf_getdata failed: %s", li->li_name,
730 			    elf_errmsg(elferr));
731 		return;
732 	}
733 	if (d_vd->d_size == 0)
734 		return;
735 
736 	buf = d_vd->d_buf;
737 	end = buf + d_vd->d_size;
738 	while (buf + sizeof(Elf_Verdef) <= end) {
739 		vd = (Elf_Verdef *) (uintptr_t) buf;
740 		svd = _load_verdef(ld, li, vd);
741 		buf2 = buf + vd->vd_aux;
742 		i = 0;
743 		while (buf2 + sizeof(Elf_Verdaux) <= end && i < vd->vd_cnt) {
744 			vda = (Elf_Verdaux *) (uintptr_t) buf2;
745 			name = elf_strptr(e, sh_vd.sh_link, vda->vda_name);
746 			if (name != NULL) {
747 				_add_version_name(ld, li, (int) vd->vd_ndx,
748 				    name);
749 				(void) _alloc_vda(ld, name, svd);
750 			}
751 			if (vda->vda_next == 0)
752 				break;
753 			buf2 += vda->vda_next;
754 			i++;
755 		}
756 		if (vd->vd_next == 0)
757 			break;
758 		buf += vd->vd_next;
759 	}
760 }
761 
762 static struct ld_symver_verdef *
_load_verdef(struct ld * ld,struct ld_input * li,Elf_Verdef * vd)763 _load_verdef(struct ld *ld, struct ld_input *li, Elf_Verdef *vd)
764 {
765 	struct ld_symver_verdef *svd;
766 
767 	if (li->li_verdef == NULL) {
768 		if ((li->li_verdef = calloc(1, sizeof(*li->li_verdef))) ==
769 		    NULL)
770 			ld_fatal_std(ld, "calloc");
771 		STAILQ_INIT(li->li_verdef);
772 	}
773 
774 	svd = _alloc_verdef(ld, li->li_verdef);
775 	svd->svd_version = vd->vd_version;
776 	svd->svd_flags = vd->vd_flags;
777 	svd->svd_ndx = vd->vd_ndx;
778 	svd->svd_cnt = vd->vd_cnt;
779 	svd->svd_hash = vd->vd_hash;
780 
781 	return (svd);
782 }
783 
784 uint16_t
ld_symver_search_version_script(struct ld * ld,struct ld_symbol * lsb)785 ld_symver_search_version_script(struct ld *ld, struct ld_symbol *lsb)
786 {
787 	struct ld_script *lds;
788 	struct ld_script_version_node *ldvn;
789 	struct ld_script_version_entry *ldve, *ldve_g;
790 	uint16_t ndx, ret_ndx, ret_ndx_g;
791 
792 	/* If the symbol version index was known, return it directly. */
793 	if (lsb->lsb_vndx_known)
794 		return (lsb->lsb_vndx);
795 
796 	/* The symbol version index will be known after searching. */
797 	lsb->lsb_vndx_known = 1;
798 
799 	lds = ld->ld_scp;
800 
801 	/* If there isn't a version script, the default version is *global* */
802 	if (STAILQ_EMPTY(&lds->lds_vn)) {
803 		lsb->lsb_vndx = 1;
804 		return (1);
805 	}
806 
807 	/* Search for a match in the version patterns. */
808 	ndx = 2;
809 	ldve_g = NULL;
810 	ret_ndx_g = 0;
811 	STAILQ_FOREACH(ldvn, &lds->lds_vn, ldvn_next) {
812 		STAILQ_FOREACH(ldve, ldvn->ldvn_e, ldve_next) {
813 			assert(ldve->ldve_sym != NULL);
814 			if (fnmatch(ldve->ldve_sym, lsb->lsb_name, 0) == 0) {
815 				if (ldve->ldve_local)
816 					ret_ndx = 0;
817 				else if (ldvn->ldvn_name != NULL)
818 					ret_ndx = ndx;
819 				else
820 					ret_ndx = 1;
821 
822 				/*
823 				 * If the version name is a globbing pattern,
824 				 * we only consider it is a match when there
825 				 * doesn't exist a exact match.
826 				 */
827 				if (ldve->ldve_glob) {
828 					if (ldve_g == NULL) {
829 						ldve_g = ldve;
830 						ret_ndx_g = ret_ndx;
831 					}
832 				} else {
833 					lsb->lsb_vndx = ret_ndx;
834 					return (ret_ndx);
835 				}
836 			}
837 		}
838 		if (ldvn->ldvn_name != NULL)
839 			ndx++;
840 	}
841 
842 	/* There is no exact match, check if there is a globbing match. */
843 	if (ldve_g != NULL) {
844 		lsb->lsb_vndx = ret_ndx_g;
845 		return (ret_ndx_g);
846 	}
847 
848 	/*
849 	 * Symbol doesn't match any version definition, set version
850 	 * to *global*.
851 	 */
852 	lsb->lsb_vndx = 1;
853 	return (1);
854 }
855