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
This commit is contained in:
Luigi Rizzo
2009-11-29 03:25:29 +01:00
committed by grischka
parent 720a32ede4
commit 55cb2170cd
2 changed files with 100 additions and 13 deletions

View File

@ -1578,10 +1578,18 @@ static int rt_get_caller_pc(unsigned long *paddr,
if (level == 0) {
/* XXX: only support linux */
#if defined(__FreeBSD__)
*paddr = uc->uc_mcontext.mc_rip;
#else
*paddr = uc->uc_mcontext.gregs[REG_RIP];
#endif
return 0;
} else {
#if defined(__FreeBSD__)
fp = uc->uc_mcontext.mc_rbp;
#else
fp = uc->uc_mcontext.gregs[REG_RBP];
#endif
for(i=1;i<level;i++) {
/* XXX: check address validity with program info */
if (fp <= 0x1000)
@ -1868,7 +1876,9 @@ TCCState *tcc_new(void)
tcc_define_symbol(s, "__STDC__", NULL);
tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
#if defined(TCC_TARGET_I386)
tcc_define_symbol(s, "__i386__", NULL);
tcc_define_symbol(s, "__i386__", "1");
tcc_define_symbol(s, "__i386", "1");
tcc_define_symbol(s, "i386", "1");
#endif
#if defined(TCC_TARGET_X86_64)
tcc_define_symbol(s, "__x86_64__", NULL);
@ -1889,8 +1899,15 @@ TCCState *tcc_new(void)
tcc_define_symbol(s, "_WIN64", NULL);
#endif
#else
tcc_define_symbol(s, "__unix__", NULL);
tcc_define_symbol(s, "__unix", NULL);
tcc_define_symbol(s, "__unix__", "1");
tcc_define_symbol(s, "__unix", "1");
tcc_define_symbol(s, "unix", "1");
#if defined(__FreeBSD__)
#define str(s) #s
tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
tcc_define_symbol(s, "__INTEL_COMPILER", "1");
#undef str
#endif
#if defined(__linux)
tcc_define_symbol(s, "__linux__", NULL);
tcc_define_symbol(s, "__linux", NULL);