History

Fix symbol versions with shared libs

ELF files that refer to shared libs containing sym-versions, but don't refer to any dynamic symbols with symbol versions (should happen only with very simple shared libs) would generate an empty .gnu.version_r section. Some dynamic linker contain bugs in that they don't check the section size or DT_VERNEEDNUM (which are both zero for such files we generate) before accessing the first entry, and then bail out with a message like ./a.exe: error while loading shared libraries: ./a1.so: unsupported version 25960 of Verneed record (where the "version number" actually comes from neighboring bytes from different sections). So, there's not much choice, we simply must not generate such section.

Michael Matz committed 6 years ago

Commit fdeeb621 parent d79e1de1 file · +47 −41Browse files

Unified · Split

tccelf.c+47−41
@@ -558,9 +558,7 @@ version_add (TCCState *s1) · 557 unmodified lines
558 return;558 return;
559 versym_section = new_section(s1, ".gnu.version", SHT_GNU_versym, SHF_ALLOC);559 versym_section = new_section(s1, ".gnu.version", SHT_GNU_versym, SHF_ALLOC);
560 versym_section->sh_entsize = sizeof(ElfW(Half));560 versym_section->sh_entsize = sizeof(ElfW(Half));
561 verneed_section = new_section(s1, ".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC);
562 versym_section->link = s1->dynsym;561 versym_section->link = s1->dynsym;
563 verneed_section->link = s1->dynsym->link;
564 562
565 /* add needed symbols */563 /* add needed symbols */
566 symtab = s1->dynsym;564 symtab = s1->dynsym;
@@ -580,43 +578,50 @@ version_add (TCCState *s1) · 13 unmodified lines
580 } else578 } else
581 versym[sym_index] = 0;579 versym[sym_index] = 0;
582 }580 }
583 /* generate verneed section */581 /* generate verneed section, but not when it will be empty. Some
584 for (i = nb_sym_versions; i-- > 0;) {582 dynamic linkers look at their contents even when DTVERNEEDNUM and
585 struct sym_version *sv = &sym_versions[i];583 section size is zero. */
586 int n_same_libs = 0, prev;584 if (nb_versions > 2) {
587 size_t vnofs;585 verneed_section = new_section(s1, ".gnu.version_r",
588 ElfW(Vernaux) *vna = 0;586 SHT_GNU_verneed, SHF_ALLOC);
589 if (sv->out_index < 1)587 verneed_section->link = s1->dynsym->link;
590 continue;588 for (i = nb_sym_versions; i-- > 0;) {
591 vnofs = section_add(verneed_section, sizeof(*vn), 1);589 struct sym_version *sv = &sym_versions[i];
592 vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);590 int n_same_libs = 0, prev;
593 vn->vn_version = 1;591 size_t vnofs;
594 vn->vn_file = put_elf_str(verneed_section->link, sv->lib);592 ElfW(Vernaux) *vna = 0;
595 vn->vn_aux = sizeof (*vn);593 if (sv->out_index < 1)
596 do {594 continue;
597 prev = sv->prev_same_lib;595 vnofs = section_add(verneed_section, sizeof(*vn), 1);
598 if (sv->out_index > 0) {596 vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);
599 vna = section_ptr_add(verneed_section, sizeof(*vna));597 vn->vn_version = 1;
600 vna->vna_hash = elf_hash ((const unsigned char *)sv->version);598 vn->vn_file = put_elf_str(verneed_section->link, sv->lib);
601 vna->vna_flags = 0;599 vn->vn_aux = sizeof (*vn);
602 vna->vna_other = sv->out_index;600 do {
603 sv->out_index = -2;601 prev = sv->prev_same_lib;
604 vna->vna_name = put_elf_str(verneed_section->link, sv->version);602 if (sv->out_index > 0) {
605 vna->vna_next = sizeof (*vna);603 vna = section_ptr_add(verneed_section, sizeof(*vna));
606 n_same_libs++;604 vna->vna_hash = elf_hash ((const unsigned char *)sv->version);
607 }605 vna->vna_flags = 0;
608 if (prev >= 0)606 vna->vna_other = sv->out_index;
609 sv = &sym_versions[prev];607 sv->out_index = -2;
610 } while(prev >= 0);608 vna->vna_name = put_elf_str(verneed_section->link, sv->version);
611 vna->vna_next = 0;609 vna->vna_next = sizeof (*vna);
612 vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);610 n_same_libs++;
613 vn->vn_cnt = n_same_libs;611 }
614 vn->vn_next = sizeof(*vn) + n_same_libs * sizeof(*vna);612 if (prev >= 0)
615 nb_entries++;613 sv = &sym_versions[prev];
616 }614 } while(prev >= 0);
617 if (vn)615 vna->vna_next = 0;
618 vn->vn_next = 0;616 vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);
619 verneed_section->sh_info = nb_entries;617 vn->vn_cnt = n_same_libs;
618 vn->vn_next = sizeof(*vn) + n_same_libs * sizeof(*vna);
619 nb_entries++;
620 }
621 if (vn)
622 vn->vn_next = 0;
623 verneed_section->sh_info = nb_entries;
624 }
620 dt_verneednum = nb_entries;625 dt_verneednum = nb_entries;
621}626}
622#endif627#endif
@@ -2045,10 +2050,11 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) · 1422 unmodified lines
2045 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));2050 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2046#endif2051#endif
2047#endif2052#endif
2048 if (versym_section) {2053 if (versym_section)
2054 put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
2055 if (verneed_section) {
2049 put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);2056 put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
2050 put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);2057 put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
2051 put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
2052 }2058 }
2053 s = find_section_create (s1, ".preinit_array", 0);2059 s = find_section_create (s1, ".preinit_array", 0);
2054 if (s && s->data_offset) {2060 if (s && s->data_offset) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t