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
15781578
15791579 if (level == 0) {
15801580 /* XXX: only support linux */
1581+#if defined(__FreeBSD__)
1582+ *paddr = uc->uc_mcontext.mc_rip;
1583+#else
15811584 *paddr = uc->uc_mcontext.gregs[REG_RIP];
1585+#endif
15821586 return 0;
15831587 } else {
1588+#if defined(__FreeBSD__)
1589+ fp = uc->uc_mcontext.mc_rbp;
1590+#else
15841591 fp = uc->uc_mcontext.gregs[REG_RBP];
1592+#endif
15851593 for(i=1;i<level;i++) {
15861594 /* XXX: check address validity with program info */
15871595 if (fp <= 0x1000)
@@ -1868,7 +1876,9 @@ TCCState *tcc_new(void) · 280 unmodified lines
18681876 tcc_define_symbol(s, "__STDC__", NULL);
18691877 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
18701878 #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");
18721882 #endif
18731883 #if defined(TCC_TARGET_X86_64)
18741884 tcc_define_symbol(s, "__x86_64__", NULL);
@@ -1889,8 +1899,15 @@ TCCState *tcc_new(void) · 14 unmodified lines
18891899 tcc_define_symbol(s, "_WIN64", NULL);
18901900 #endif
18911901 #else
1892− tcc_define_symbol(s, "__unix__", NULL);
1893− tcc_define_symbol(s, "__unix", NULL);
1902+ tcc_define_symbol(s, "__unix__", "1");
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
18941911 #if defined(__linux)
18951912 tcc_define_symbol(s, "__linux__", NULL);
18961913 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
13021302
13031303 /* name of ELF interpreter */
13041304 #if defined __FreeBSD__
1305−static const char elf_interp[] = "/usr/libexec/ld-elf.so.1";
1305+static const char elf_interp[] = "/libexec/ld-elf.so.1";
13061306 #elif defined TCC_ARM_EABI
13071307 static const char elf_interp[] = "/lib/ld-linux.so.3";
13081308 #elif defined(TCC_TARGET_X86_64)
@@ -1335,6 +1335,31 @@ static void tcc_output_binary(TCCState *s1, FILE *f, · 26 unmodified lines
13351335 }
13361336 }
13371337
1338+#if defined(__FreeBSD__)
1339+#define HAVE_PHDR 1
1340+#define EXTRA_RELITEMS 14
1341+
1342+/* move the relocation value from .dynsym to .got */
1343+void 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+
13381363 /* output an ELF file */
13391364 /* XXX: suppress unneeded sections */
13401365 int elf_output_file(TCCState *s1, const char *filename)
@@ -1353,7 +1378,8 @@ int elf_output_file(TCCState *s1, const char *filename) · 12 unmodified lines
13531378 ElfW(Sym) *sym;
13541379 int type, file_type;
13551380 unsigned long rel_addr, rel_size;
1356−
1381+ unsigned long bss_addr, bss_size;
1382+
13571383 file_type = s1->output_type;
13581384 s1->nb_errors = 0;
13591385
@@ -1377,16 +1403,20 @@ int elf_output_file(TCCState *s1, const char *filename) · 17 unmodified lines
13771403 const char *name;
13781404 int sym_index, index;
13791405 ElfW(Sym) *esym, *sym_end;
1380−
1406+
13811407 if (file_type == TCC_OUTPUT_EXE) {
13821408 char *ptr;
1409+ /* allow override the dynamic loader */
1410+ const char *elfint = getenv("LD_SO");
1411+ if (elfint == NULL)
1412+ elfint = elf_interp;
13831413 /* add interpreter section only if executable */
13841414 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
13851415 interp->sh_addralign = 1;
1386− ptr = section_ptr_add(interp, sizeof(elf_interp));
1387− strcpy(ptr, elf_interp);
1416+ ptr = section_ptr_add(interp, 1+strlen(elfint));
1417+ strcpy(ptr, elfint);
13881418 }
1389−
1419+
13901420 /* add dynamic symbol table */
13911421 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
13921422 ".dynstr",
@@ -1543,7 +1573,7 @@ int elf_output_file(TCCState *s1, const char *filename) · 150 unmodified lines
15431573
15441574 /* add necessary space for other entries */
15451575 saved_dynamic_data_offset = dynamic->data_offset;
1546− dynamic->data_offset += sizeof(ElfW(Dyn)) * 9;
1576+ dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
15471577 } else {
15481578 /* still need to build got entries in case of static link */
15491579 build_got_entries(s1);
@@ -1572,7 +1602,7 @@ int elf_output_file(TCCState *s1, const char *filename) · 22 unmodified lines
15721602 break;
15731603 case TCC_OUTPUT_EXE:
15741604 if (!s1->static_link)
1575− phnum = 4;
1605+ phnum = 4 + HAVE_PHDR;
15761606 else
15771607 phnum = 2;
15781608 break;
@@ -1649,10 +1679,11 @@ int elf_output_file(TCCState *s1, const char *filename) · 70 unmodified lines
16491679 rel_size = 0;
16501680 rel_addr = 0;
16511681
1682+ bss_addr = bss_size = 0;
16521683 /* leave one program header for the program interpreter */
16531684 ph = &phdr[0];
16541685 if (interp)
1655− ph++;
1686+ ph += 1 + HAVE_PHDR;
16561687
16571688 for(j = 0; j < 2; j++) {
16581689 ph->p_type = PT_LOAD;
@@ -1714,9 +1745,20 @@ int elf_output_file(TCCState *s1, const char *filename) · 55 unmodified lines
17141745 }
17151746 /* update dynamic relocation infos */
17161747 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
17171758 if (rel_size == 0)
17181759 rel_addr = addr;
17191760 rel_size += s->sh_size;
1761+#endif
17201762 }
17211763 addr += s->sh_size;
17221764 if (s->sh_type != SHT_NOBITS)
@@ -1743,7 +1785,22 @@ int elf_output_file(TCCState *s1, const char *filename) · 20 unmodified lines
17431785 /* if interpreter, then add corresponing program header */
17441786 if (interp) {
17451787 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+
17471804 ph->p_type = PT_INTERP;
17481805 ph->p_offset = interp->sh_offset;
17491806 ph->p_vaddr = interp->sh_addr;
@@ -1843,10 +1900,19 @@ int elf_output_file(TCCState *s1, const char *filename) · 93 unmodified lines
18431900 put_dt(dynamic, DT_RELA, rel_addr);
18441901 put_dt(dynamic, DT_RELASZ, rel_size);
18451902 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);
18461911 #else
18471912 put_dt(dynamic, DT_REL, rel_addr);
18481913 put_dt(dynamic, DT_RELSZ, rel_size);
18491914 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1915+#endif
18501916 #endif
18511917 if (s1->do_debug)
18521918 put_dt(dynamic, DT_DEBUG, 0);
@@ -1979,6 +2045,10 @@ int elf_output_file(TCCState *s1, const char *filename) · 126 unmodified lines
19792045 for(i=1;i<s1->nb_sections;i++) {
19802046 s = s1->sections[section_order[i]];
19812047 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
19822052 while (offset < s->sh_offset) {
19832053 fputc(0, f);
19842054 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