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