History

solve tccelf problem on FreeBSD

On Sun, Nov 22, 2009 at 05:43:14PM +0100, Luigi Rizzo wrote: > Hi, > there is a well known problem with tcc and FreeBSD in the generation > of elf objects -- see > http://lists.gnu.org/archive/html/tinycc-devel/2005-07/msg00070.html > > Apparently Sergey Lyubka has tried a partial fix to the problem. > I was wondering if Sergey or someone can post some more detail on > what needs to be done so we can try to help fixing this issue I think i have managed to solve the problem and produce almost valid elf files on FreeBSD. The two patches attached address a few problems (trying to explain to the best of my knowledge; i am not very familiar with ELF and the FreeBSD ELF conventions): 1. ELF file format tcc produces an ELF executable which is good for linux but not for FreeBSD. It misses the PHDR section which is almost mandatory for shared executables, puts in the .dynsym section some relocation info that FreeBSD expects to be in .got, and expect the relocation sections to be contiguous. patch-tccelf.c tries to address the above problem using conditional sections (so hopefully can be imported upstream) and also adds the ability to override the name of the dynamic loader through an environment variable (this is important to debug tcc). 2. predefined macros patch-libtcc.c adds/fixes some predefined macros when compiling on FreeBSD: these are __FreeBSD__ and the usual set of __i386__ and __unix__ variants. It also sets __INTEL_COMPILER so we can grab the __aligned macro from cdefs.h , otherwise many programs would fail The resulting elf file is still not 100% correct -- if you strip it, the program will not run (presumably there is some dangling reference). Other than that, program do seem to run correctly. It would be nice to integrate these patches in the main repository. The FreeBSD specific code is in #ifdef so it should not harm linux users cheers luigi

Luigi Rizzo committed 16 years ago

Commit 55cb2171 parent 720a32e2 files · +100 −13Browse files

Unified · Split

2 files
  1. libtcc.c +20 −3
  2. tccelf.c +80 −10
libtcc.c+20−3
@@ -1578,10 +1578,18 @@ static int rt_get_caller_pc(unsigned long *paddr, · 1577 unmodified lines
1578 1578
1579 if (level == 0) {1579 if (level == 0) {
1580 /* XXX: only support linux */1580 /* XXX: only support linux */
1581#if defined(__FreeBSD__)
1582 *paddr = uc->uc_mcontext.mc_rip;
1583#else
1581 *paddr = uc->uc_mcontext.gregs[REG_RIP];1584 *paddr = uc->uc_mcontext.gregs[REG_RIP];
1585#endif
1582 return 0;1586 return 0;
1583 } else {1587 } else {
1588#if defined(__FreeBSD__)
1589 fp = uc->uc_mcontext.mc_rbp;
1590#else
1584 fp = uc->uc_mcontext.gregs[REG_RBP];1591 fp = uc->uc_mcontext.gregs[REG_RBP];
1592#endif
1585 for(i=1;i<level;i++) {1593 for(i=1;i<level;i++) {
1586 /* XXX: check address validity with program info */1594 /* XXX: check address validity with program info */
1587 if (fp <= 0x1000)1595 if (fp <= 0x1000)
@@ -1868,7 +1876,9 @@ TCCState *tcc_new(void) · 280 unmodified lines
1868 tcc_define_symbol(s, "__STDC__", NULL);1876 tcc_define_symbol(s, "__STDC__", NULL);
1869 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");1877 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
1870#if defined(TCC_TARGET_I386)1878#if defined(TCC_TARGET_I386)
1871 tcc_define_symbol(s, "__i386__", NULL);1879 tcc_define_symbol(s, "__i386__", "1");
1880 tcc_define_symbol(s, "__i386", "1");
1881 tcc_define_symbol(s, "i386", "1");
1872#endif1882#endif
1873#if defined(TCC_TARGET_X86_64)1883#if defined(TCC_TARGET_X86_64)
1874 tcc_define_symbol(s, "__x86_64__", NULL);1884 tcc_define_symbol(s, "__x86_64__", NULL);
@@ -1889,8 +1899,15 @@ TCCState *tcc_new(void) · 14 unmodified lines
1889 tcc_define_symbol(s, "_WIN64", NULL);1899 tcc_define_symbol(s, "_WIN64", NULL);
1890#endif1900#endif
1891#else1901#else
1892 tcc_define_symbol(s, "__unix__", NULL);1902 tcc_define_symbol(s, "__unix__", "1");
1893 tcc_define_symbol(s, "__unix", NULL);1903 tcc_define_symbol(s, "__unix", "1");
1904 tcc_define_symbol(s, "unix", "1");
1905#if defined(__FreeBSD__)
1906#define str(s) #s
1907 tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
1908 tcc_define_symbol(s, "__INTEL_COMPILER", "1");
1909#undef str
1910#endif
1894#if defined(__linux)1911#if defined(__linux)
1895 tcc_define_symbol(s, "__linux__", NULL);1912 tcc_define_symbol(s, "__linux__", NULL);
1896 tcc_define_symbol(s, "__linux", NULL);1913 tcc_define_symbol(s, "__linux", NULL);
tccelf.c+80−10
@@ -1302,7 +1302,7 @@ static void tcc_add_linker_symbols(TCCState *s1) · 1301 unmodified lines
1302 1302
1303/* name of ELF interpreter */1303/* name of ELF interpreter */
1304#if defined __FreeBSD__1304#if defined __FreeBSD__
1305static const char elf_interp[] = "/usr/libexec/ld-elf.so.1";1305static const char elf_interp[] = "/libexec/ld-elf.so.1";
1306#elif defined TCC_ARM_EABI1306#elif defined TCC_ARM_EABI
1307static const char elf_interp[] = "/lib/ld-linux.so.3";1307static const char elf_interp[] = "/lib/ld-linux.so.3";
1308#elif defined(TCC_TARGET_X86_64)1308#elif defined(TCC_TARGET_X86_64)
@@ -1335,6 +1335,31 @@ static void tcc_output_binary(TCCState *s1, FILE *f, · 26 unmodified lines
1335 }1335 }
1336}1336}
1337 1337
1338#if defined(__FreeBSD__)
1339#define HAVE_PHDR 1
1340#define EXTRA_RELITEMS 14
1341
1342/* move the relocation value from .dynsym to .got */
1343void patch_dynsym_undef(TCCState *s1, Section *s)
1344{
1345 uint32_t *gotd = (void *)s1->got->data;
1346 ElfW(Sym) *sym, *sym_end;
1347
1348 gotd += 3; // dummy entries in .got
1349 /* relocate symbols in .dynsym */
1350 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1351 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1352 if (sym->st_shndx == SHN_UNDEF) {
1353 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1354 sym->st_value = 0;
1355 }
1356 }
1357}
1358#else
1359#define HAVE_PHDR 0
1360#define EXTRA_RELITEMS 9
1361#endif
1362
1338/* output an ELF file */1363/* output an ELF file */
1339/* XXX: suppress unneeded sections */1364/* XXX: suppress unneeded sections */
1340int elf_output_file(TCCState *s1, const char *filename)1365int elf_output_file(TCCState *s1, const char *filename)
@@ -1353,7 +1378,8 @@ int elf_output_file(TCCState *s1, const char *filename) · 12 unmodified lines
1353 ElfW(Sym) *sym;1378 ElfW(Sym) *sym;
1354 int type, file_type;1379 int type, file_type;
1355 unsigned long rel_addr, rel_size;1380 unsigned long rel_addr, rel_size;
1356 1381 unsigned long bss_addr, bss_size;
1382
1357 file_type = s1->output_type;1383 file_type = s1->output_type;
1358 s1->nb_errors = 0;1384 s1->nb_errors = 0;
1359 1385
@@ -1377,16 +1403,20 @@ int elf_output_file(TCCState *s1, const char *filename) · 17 unmodified lines
1377 const char *name;1403 const char *name;
1378 int sym_index, index;1404 int sym_index, index;
1379 ElfW(Sym) *esym, *sym_end;1405 ElfW(Sym) *esym, *sym_end;
1380 1406
1381 if (file_type == TCC_OUTPUT_EXE) {1407 if (file_type == TCC_OUTPUT_EXE) {
1382 char *ptr;1408 char *ptr;
1409 /* allow override the dynamic loader */
1410 const char *elfint = getenv("LD_SO");
1411 if (elfint == NULL)
1412 elfint = elf_interp;
1383 /* add interpreter section only if executable */1413 /* add interpreter section only if executable */
1384 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);1414 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1385 interp->sh_addralign = 1;1415 interp->sh_addralign = 1;
1386 ptr = section_ptr_add(interp, sizeof(elf_interp));1416 ptr = section_ptr_add(interp, 1+strlen(elfint));
1387 strcpy(ptr, elf_interp);1417 strcpy(ptr, elfint);
1388 }1418 }
1389 1419
1390 /* add dynamic symbol table */1420 /* add dynamic symbol table */
1391 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,1421 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1392 ".dynstr", 1422 ".dynstr",
@@ -1543,7 +1573,7 @@ int elf_output_file(TCCState *s1, const char *filename) · 150 unmodified lines
1543 1573
1544 /* add necessary space for other entries */1574 /* add necessary space for other entries */
1545 saved_dynamic_data_offset = dynamic->data_offset;1575 saved_dynamic_data_offset = dynamic->data_offset;
1546 dynamic->data_offset += sizeof(ElfW(Dyn)) * 9;1576 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1547 } else {1577 } else {
1548 /* still need to build got entries in case of static link */1578 /* still need to build got entries in case of static link */
1549 build_got_entries(s1);1579 build_got_entries(s1);
@@ -1572,7 +1602,7 @@ int elf_output_file(TCCState *s1, const char *filename) · 22 unmodified lines
1572 break;1602 break;
1573 case TCC_OUTPUT_EXE:1603 case TCC_OUTPUT_EXE:
1574 if (!s1->static_link)1604 if (!s1->static_link)
1575 phnum = 4;1605 phnum = 4 + HAVE_PHDR;
1576 else1606 else
1577 phnum = 2;1607 phnum = 2;
1578 break;1608 break;
@@ -1649,10 +1679,11 @@ int elf_output_file(TCCState *s1, const char *filename) · 70 unmodified lines
1649 rel_size = 0;1679 rel_size = 0;
1650 rel_addr = 0;1680 rel_addr = 0;
1651 1681
1682 bss_addr = bss_size = 0;
1652 /* leave one program header for the program interpreter */1683 /* leave one program header for the program interpreter */
1653 ph = &phdr[0];1684 ph = &phdr[0];
1654 if (interp)1685 if (interp)
1655 ph++;1686 ph += 1 + HAVE_PHDR;
1656 1687
1657 for(j = 0; j < 2; j++) {1688 for(j = 0; j < 2; j++) {
1658 ph->p_type = PT_LOAD;1689 ph->p_type = PT_LOAD;
@@ -1714,9 +1745,20 @@ int elf_output_file(TCCState *s1, const char *filename) · 55 unmodified lines
1714 }1745 }
1715 /* update dynamic relocation infos */1746 /* update dynamic relocation infos */
1716 if (s->sh_type == SHT_RELX) {1747 if (s->sh_type == SHT_RELX) {
1748#if defined(__FreeBSD__)
1749 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1750 rel_addr = addr;
1751 rel_size += s->sh_size; // XXX only first rel.
1752 }
1753 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1754 bss_addr = addr;
1755 bss_size = s->sh_size; // XXX only first rel.
1756 }
1757#else
1717 if (rel_size == 0)1758 if (rel_size == 0)
1718 rel_addr = addr;1759 rel_addr = addr;
1719 rel_size += s->sh_size;1760 rel_size += s->sh_size;
1761#endif
1720 }1762 }
1721 addr += s->sh_size;1763 addr += s->sh_size;
1722 if (s->sh_type != SHT_NOBITS)1764 if (s->sh_type != SHT_NOBITS)
@@ -1743,7 +1785,22 @@ int elf_output_file(TCCState *s1, const char *filename) · 20 unmodified lines
1743 /* if interpreter, then add corresponing program header */1785 /* if interpreter, then add corresponing program header */
1744 if (interp) {1786 if (interp) {
1745 ph = &phdr[0];1787 ph = &phdr[0];
1746 1788
1789#if defined(__FreeBSD__)
1790 {
1791 int len = phnum * sizeof(ElfW(Phdr));
1792
1793 ph->p_type = PT_PHDR;
1794 ph->p_offset = sizeof(ElfW(Ehdr));
1795 ph->p_vaddr = interp->sh_addr - len;
1796 ph->p_paddr = ph->p_vaddr;
1797 ph->p_filesz = ph->p_memsz = len;
1798 ph->p_flags = PF_R | PF_X;
1799 ph->p_align = 4; // interp->sh_addralign;
1800 ph++;
1801 }
1802#endif
1803
1747 ph->p_type = PT_INTERP;1804 ph->p_type = PT_INTERP;
1748 ph->p_offset = interp->sh_offset;1805 ph->p_offset = interp->sh_offset;
1749 ph->p_vaddr = interp->sh_addr;1806 ph->p_vaddr = interp->sh_addr;
@@ -1843,10 +1900,19 @@ int elf_output_file(TCCState *s1, const char *filename) · 93 unmodified lines
1843 put_dt(dynamic, DT_RELA, rel_addr);1900 put_dt(dynamic, DT_RELA, rel_addr);
1844 put_dt(dynamic, DT_RELASZ, rel_size);1901 put_dt(dynamic, DT_RELASZ, rel_size);
1845 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));1902 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1903#else
1904#if defined(__FreeBSD__)
1905 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1906 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1907 put_dt(dynamic, DT_JMPREL, rel_addr);
1908 put_dt(dynamic, DT_PLTREL, DT_REL);
1909 put_dt(dynamic, DT_REL, bss_addr);
1910 put_dt(dynamic, DT_RELSZ, bss_size);
1846#else1911#else
1847 put_dt(dynamic, DT_REL, rel_addr);1912 put_dt(dynamic, DT_REL, rel_addr);
1848 put_dt(dynamic, DT_RELSZ, rel_size);1913 put_dt(dynamic, DT_RELSZ, rel_size);
1849 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));1914 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1915#endif
1850#endif1916#endif
1851 if (s1->do_debug)1917 if (s1->do_debug)
1852 put_dt(dynamic, DT_DEBUG, 0);1918 put_dt(dynamic, DT_DEBUG, 0);
@@ -1979,6 +2045,10 @@ int elf_output_file(TCCState *s1, const char *filename) · 126 unmodified lines
1979 for(i=1;i<s1->nb_sections;i++) {2045 for(i=1;i<s1->nb_sections;i++) {
1980 s = s1->sections[section_order[i]];2046 s = s1->sections[section_order[i]];
1981 if (s->sh_type != SHT_NOBITS) {2047 if (s->sh_type != SHT_NOBITS) {
2048#if defined(__FreeBSD__)
2049 if (s->sh_type == SHT_DYNSYM)
2050 patch_dynsym_undef(s1, s);
2051#endif
1982 while (offset < s->sh_offset) {2052 while (offset < s->sh_offset) {
1983 fputc(0, f);2053 fputc(0, f);
1984 offset++;2054 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