| @@ -58,6 +58,8 @@ ST_FUNC void tccelf_new(TCCState *s) · 57 unmodified lines |
| 58 | /* create standard sections */ | 58 | /* create standard sections */ |
| 59 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); | 59 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
| 60 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); | 60 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| | 61 | /* create ro data section (make ro after relocation done with GNU_RELRO) */ |
| | 62 | data_ro_section = new_section(s, ".data.ro", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 61 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); | 63 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); |
| 62 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); | 64 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); |
| 63 | common_section->sh_num = SHN_COMMON; | 65 | common_section->sh_num = SHN_COMMON; |
| @@ -79,11 +81,11 @@ ST_FUNC void tccelf_new(TCCState *s) · 15 unmodified lines |
| 79 | ST_FUNC void tccelf_bounds_new(TCCState *s) | 81 | ST_FUNC void tccelf_bounds_new(TCCState *s) |
| 80 | { | 82 | { |
| 81 | TCCState *s1 = s; | 83 | TCCState *s1 = s; |
| 82 | /* create bounds sections */ | 84 | /* create bounds sections (make ro after relocation done with GNU_RELRO) */ |
| 83 | bounds_section = new_section(s, ".bounds", | 85 | bounds_section = new_section(s, ".bounds", |
| 84 | SHT_PROGBITS, SHF_ALLOC); | 86 | SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 85 | lbounds_section = new_section(s, ".lbounds", | 87 | lbounds_section = new_section(s, ".lbounds", |
| 86 | SHT_PROGBITS, SHF_ALLOC); | 88 | SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 87 | } | 89 | } |
| 88 | #endif | 90 | #endif |
| 89 | | 91 | |
| @@ -1043,6 +1045,16 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 953 unmodified lines |
| 1043 | case R_386_PC32: | 1045 | case R_386_PC32: |
| 1044 | #elif defined(TCC_TARGET_X86_64) | 1046 | #elif defined(TCC_TARGET_X86_64) |
| 1045 | case R_X86_64_PC32: | 1047 | case R_X86_64_PC32: |
| | 1048 | { |
| | 1049 | ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; |
| | 1050 | |
| | 1051 | /* support __dso_handle in atexit() */ |
| | 1052 | if (sym->st_shndx != SHN_UNDEF && |
| | 1053 | ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN) { |
| | 1054 | rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PLT32); |
| | 1055 | break; |
| | 1056 | } |
| | 1057 | } |
| 1046 | #elif defined(TCC_TARGET_ARM64) | 1058 | #elif defined(TCC_TARGET_ARM64) |
| 1047 | case R_AARCH64_PREL32: | 1059 | case R_AARCH64_PREL32: |
| 1048 | #endif | 1060 | #endif |
| @@ -1828,11 +1840,20 @@ struct dyn_inf { · 779 unmodified lines |
| 1828 | addr_t rel_size; | 1840 | addr_t rel_size; |
| 1829 | }; | 1841 | }; |
| 1830 | | 1842 | |
| | 1843 | /* Info for GNU_RELRO */ |
| | 1844 | struct ro_inf { |
| | 1845 | addr_t sh_offset; |
| | 1846 | addr_t sh_addr; |
| | 1847 | addr_t sh_size; |
| | 1848 | }; |
| | 1849 | |
| 1831 | /* Assign sections to segments and decide how are sections laid out when loaded | 1850 | /* Assign sections to segments and decide how are sections laid out when loaded |
| 1832 | in memory. This function also fills corresponding program headers. */ | 1851 | in memory. This function also fills corresponding program headers. */ |
| 1833 | static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, | 1852 | static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, |
| | 1853 | int phnum, int phfill, |
| 1834 | Section *interp, Section* strsec, | 1854 | Section *interp, Section* strsec, |
| 1835 | struct dyn_inf *dyninf, int *sec_order) | 1855 | struct dyn_inf *dyninf, struct ro_inf *roinf, |
| | 1856 | int *sec_order) |
| 1836 | { | 1857 | { |
| 1837 | int i, sh_order_index, file_offset; | 1858 | int i, sh_order_index, file_offset; |
| 1838 | Section *s; | 1859 | Section *s; |
| @@ -1883,7 +1904,10 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 44 unmodified lines |
| 1883 | /* dynamic relocation table information, for .dynamic section */ | 1904 | /* dynamic relocation table information, for .dynamic section */ |
| 1884 | dyninf->rel_addr = dyninf->rel_size = 0; | 1905 | dyninf->rel_addr = dyninf->rel_size = 0; |
| 1885 | | 1906 | |
| 1886 | for(j = 0; j < (phnum == 6 ? 3 : 2); j++) { | 1907 | /* read only segment mapping for GNU_RELRO */ |
| | 1908 | roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0; |
| | 1909 | |
| | 1910 | for(j = 0; j < phfill; j++) { |
| 1887 | Section *relocplt = s1->got ? s1->got->relocplt : NULL; | 1911 | Section *relocplt = s1->got ? s1->got->relocplt : NULL; |
| 1888 | | 1912 | |
| 1889 | ph->p_type = j == 2 ? PT_TLS : PT_LOAD; | 1913 | ph->p_type = j == 2 ? PT_TLS : PT_LOAD; |
| @@ -1898,7 +1922,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 8 unmodified lines |
| 1898 | info about the layout. We do the following ordering: interp, | 1922 | info about the layout. We do the following ordering: interp, |
| 1899 | symbol tables, relocations, progbits, nobits */ | 1923 | symbol tables, relocations, progbits, nobits */ |
| 1900 | /* XXX: do faster and simpler sorting */ | 1924 | /* XXX: do faster and simpler sorting */ |
| 1901 | for(k = 0; k < 6; k++) { | 1925 | for(k = 0; k < 7; k++) { |
| 1902 | for(i = 1; i < s1->nb_sections; i++) { | 1926 | for(i = 1; i < s1->nb_sections; i++) { |
| 1903 | s = s1->sections[i]; | 1927 | s = s1->sections[i]; |
| 1904 | /* compute if section should be included */ | 1928 | /* compute if section should be included */ |
| @@ -1930,12 +1954,17 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 25 unmodified lines |
| 1930 | else if (k != 3 && s == relocplt) | 1954 | else if (k != 3 && s == relocplt) |
| 1931 | continue; | 1955 | continue; |
| 1932 | } else if (s->sh_type == SHT_NOBITS) { | 1956 | } else if (s->sh_type == SHT_NOBITS) { |
| 1933 | if (k != 5) | 1957 | if (k != 6) |
| 1934 | continue; | 1958 | continue; |
| 1935 | } else { | 1959 | } else if (s == data_ro_section || |
| | 1960 | s == bounds_section || |
| | 1961 | s == lbounds_section) { |
| 1936 | if (k != 4) | 1962 | if (k != 4) |
| 1937 | continue; | 1963 | continue; |
| 1938 | } | 1964 | } else { |
| | 1965 | if (k != 5) |
| | 1966 | continue; |
| | 1967 | } |
| 1939 | sec_order[sh_order_index++] = i; | 1968 | sec_order[sh_order_index++] = i; |
| 1940 | | 1969 | |
| 1941 | /* section matches: we align it and add its size */ | 1970 | /* section matches: we align it and add its size */ |
| @@ -1956,8 +1985,17 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 14 unmodified lines |
| 1956 | if (s->sh_type == SHT_RELX && s != relocplt) { | 1985 | if (s->sh_type == SHT_RELX && s != relocplt) { |
| 1957 | if (dyninf->rel_size == 0) | 1986 | if (dyninf->rel_size == 0) |
| 1958 | dyninf->rel_addr = addr; | 1987 | dyninf->rel_addr = addr; |
| 1959 | dyninf->rel_size += s->sh_size; | 1988 | dyninf->rel_size = (addr - dyninf->rel_addr) + s->sh_size; |
| 1960 | } | 1989 | } |
| | 1990 | if (s == data_ro_section || |
| | 1991 | s == bounds_section || |
| | 1992 | s == lbounds_section) { |
| | 1993 | if (roinf->sh_size == 0) { |
| | 1994 | roinf->sh_offset = s->sh_offset; |
| | 1995 | roinf->sh_addr = s->sh_addr; |
| | 1996 | } |
| | 1997 | roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size; |
| | 1998 | } |
| 1961 | addr += s->sh_size; | 1999 | addr += s->sh_size; |
| 1962 | if (s->sh_type != SHT_NOBITS) | 2000 | if (s->sh_type != SHT_NOBITS) |
| 1963 | file_offset += s->sh_size; | 2001 | file_offset += s->sh_size; |
| @@ -2018,7 +2056,7 @@ static void put_dt(Section *dynamic, int dt, addr_t val) · 54 unmodified lines |
| 2018 | } | 2056 | } |
| 2019 | | 2057 | |
| 2020 | static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, | 2058 | static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, |
| 2021 | Section *dynamic, Section *note) | 2059 | Section *dynamic, Section *note, struct ro_inf *roinf) |
| 2022 | { | 2060 | { |
| 2023 | ElfW(Phdr) *ph; | 2061 | ElfW(Phdr) *ph; |
| 2024 | | 2062 | |
| @@ -2046,7 +2084,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 21 unmodified lines |
| 2046 | } | 2084 | } |
| 2047 | | 2085 | |
| 2048 | if (note) { | 2086 | if (note) { |
| 2049 | ph = &phdr[phnum - 2]; | 2087 | ph = &phdr[phnum - 2 - (roinf != NULL)]; |
| 2050 | | 2088 | |
| 2051 | ph->p_type = PT_NOTE; | 2089 | ph->p_type = PT_NOTE; |
| 2052 | ph->p_offset = note->sh_offset; | 2090 | ph->p_offset = note->sh_offset; |
| @@ -2060,7 +2098,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 7 unmodified lines |
| 2060 | | 2098 | |
| 2061 | /* if dynamic section, then add corresponding program header */ | 2099 | /* if dynamic section, then add corresponding program header */ |
| 2062 | if (dynamic) { | 2100 | if (dynamic) { |
| 2063 | ph = &phdr[phnum - 1]; | 2101 | ph = &phdr[phnum - 1 - (roinf != NULL)]; |
| 2064 | | 2102 | |
| 2065 | ph->p_type = PT_DYNAMIC; | 2103 | ph->p_type = PT_DYNAMIC; |
| 2066 | ph->p_offset = dynamic->sh_offset; | 2104 | ph->p_offset = dynamic->sh_offset; |
| @@ -2071,6 +2109,19 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 4 unmodified lines |
| 2071 | ph->p_flags = PF_R | PF_W; | 2109 | ph->p_flags = PF_R | PF_W; |
| 2072 | ph->p_align = dynamic->sh_addralign; | 2110 | ph->p_align = dynamic->sh_addralign; |
| 2073 | } | 2111 | } |
| | 2112 | |
| | 2113 | if (roinf) { |
| | 2114 | ph = &phdr[phnum - 1]; |
| | 2115 | |
| | 2116 | ph->p_type = PT_GNU_RELRO; |
| | 2117 | ph->p_offset = roinf->sh_offset; |
| | 2118 | ph->p_vaddr = roinf->sh_addr; |
| | 2119 | ph->p_paddr = ph->p_vaddr; |
| | 2120 | ph->p_filesz = roinf->sh_size; |
| | 2121 | ph->p_memsz = roinf->sh_size; |
| | 2122 | ph->p_flags = PF_R; |
| | 2123 | ph->p_align = 1; |
| | 2124 | } |
| 2074 | } | 2125 | } |
| 2075 | | 2126 | |
| 2076 | /* Fill the dynamic section with tags describing the address and size of | 2127 | /* Fill the dynamic section with tags describing the address and size of |
| @@ -2440,8 +2491,9 @@ static Section *create_bsd_note_section(TCCState *s1, · 363 unmodified lines |
| 2440 | /* XXX: suppress unneeded sections */ | 2491 | /* XXX: suppress unneeded sections */ |
| 2441 | static int elf_output_file(TCCState *s1, const char *filename) | 2492 | static int elf_output_file(TCCState *s1, const char *filename) |
| 2442 | { | 2493 | { |
| 2443 | int ret, phnum, shnum, file_type, file_offset, *sec_order; | 2494 | int i, ret, phnum, phfill, shnum, file_type, file_offset, *sec_order; |
| 2444 | struct dyn_inf dyninf = {0}; | 2495 | struct dyn_inf dyninf = {0}; |
| | 2496 | struct ro_inf roinf, *roinf_use = NULL; |
| 2445 | ElfW(Phdr) *phdr; | 2497 | ElfW(Phdr) *phdr; |
| 2446 | Section *strsec, *interp, *dynamic, *dynstr, *note = NULL; | 2498 | Section *strsec, *interp, *dynamic, *dynstr, *note = NULL; |
| 2447 | | 2499 | |
| @@ -2489,6 +2541,8 @@ static int elf_output_file(TCCState *s1, const char *filename) · 41 unmodified lines |
| 2489 | s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC, | 2541 | s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC, |
| 2490 | ".dynstr", | 2542 | ".dynstr", |
| 2491 | ".hash", SHF_ALLOC); | 2543 | ".hash", SHF_ALLOC); |
| | 2544 | /* Number of local symbols (readelf complains if not set) */ |
| | 2545 | s1->dynsym->sh_info = 1; |
| 2492 | dynstr = s1->dynsym->link; | 2546 | dynstr = s1->dynsym->link; |
| 2493 | /* add dynamic section */ | 2547 | /* add dynamic section */ |
| 2494 | dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, | 2548 | dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, |
| @@ -2556,22 +2610,31 @@ static int elf_output_file(TCCState *s1, const char *filename) · 61 unmodified lines |
| 2556 | } | 2610 | } |
| 2557 | #endif | 2611 | #endif |
| 2558 | | 2612 | |
| | 2613 | for (i = 1; i < s1->nb_sections && |
| | 2614 | !(s1->sections[i]->sh_flags & SHF_TLS); i++); |
| | 2615 | phfill = 2 + (i < s1->nb_sections); |
| | 2616 | |
| 2559 | /* compute number of program headers */ | 2617 | /* compute number of program headers */ |
| 2560 | if (file_type == TCC_OUTPUT_OBJ) | 2618 | if (file_type == TCC_OUTPUT_OBJ) |
| 2561 | phnum = 0; | 2619 | phnum = phfill = 0; |
| 2562 | else if (file_type == TCC_OUTPUT_DLL) | 2620 | else if (file_type == TCC_OUTPUT_DLL) |
| 2563 | phnum = 3; | 2621 | phnum = 3; |
| 2564 | else if (s1->static_link) | 2622 | else if (s1->static_link) |
| 2565 | phnum = 2; | 2623 | phnum = 2; |
| 2566 | else { | 2624 | else { |
| 2567 | int i; | 2625 | phnum = 5 + (i < s1->nb_sections); |
| 2568 | for (i = 1; i < s1->nb_sections && | | |
| 2569 | !(s1->sections[i]->sh_flags & SHF_TLS); i++); | | |
| 2570 | phnum = i < s1->nb_sections ? 6 : 5; | | |
| 2571 | } | 2626 | } |
| 2572 | | 2627 | |
| 2573 | phnum += note != NULL; | 2628 | phnum += note != NULL; |
| 2574 | | 2629 | |
| | 2630 | #if !TARGETOS_FreeBSD && !TARGETOS_NetBSD && !defined(__APPLE__) && !defined(_WIN32) |
| | 2631 | /* GNU_RELRO */ |
| | 2632 | if (file_type != TCC_OUTPUT_OBJ) { |
| | 2633 | phnum++; |
| | 2634 | roinf_use = &roinf; |
| | 2635 | } |
| | 2636 | #endif |
| | 2637 | |
| 2575 | /* allocate program segment headers */ | 2638 | /* allocate program segment headers */ |
| 2576 | phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); | 2639 | phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); |
| 2577 | | 2640 | |
| @@ -2583,14 +2646,14 @@ static int elf_output_file(TCCState *s1, const char *filename) · 5 unmodified lines |
| 2583 | sec_order[0] = 0; | 2646 | sec_order[0] = 0; |
| 2584 | | 2647 | |
| 2585 | /* compute section to program header mapping */ | 2648 | /* compute section to program header mapping */ |
| 2586 | file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf, | 2649 | file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec, |
| 2587 | sec_order); | 2650 | &dyninf, &roinf, sec_order); |
| 2588 | | 2651 | |
| 2589 | #ifndef ELF_OBJ_ONLY | 2652 | #ifndef ELF_OBJ_ONLY |
| 2590 | /* Fill remaining program header and finalize relocation related to dynamic | 2653 | /* Fill remaining program header and finalize relocation related to dynamic |
| 2591 | linking. */ | 2654 | linking. */ |
| 2592 | if (file_type != TCC_OUTPUT_OBJ) { | 2655 | if (file_type != TCC_OUTPUT_OBJ) { |
| 2593 | fill_unloadable_phdr(phdr, phnum, interp, dynamic, note); | 2656 | fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use); |
| 2594 | if (dynamic) { | 2657 | if (dynamic) { |
| 2595 | ElfW(Sym) *sym; | 2658 | ElfW(Sym) *sym; |
| 2596 | dynamic->data_offset = dyninf.data_offset; | 2659 | dynamic->data_offset = dyninf.data_offset; |