tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] TCC for NetBSD/i386 ELF [PATCH]


From: Lubomir Kundrak
Subject: [Tinycc-devel] TCC for NetBSD/i386 ELF [PATCH]
Date: Wed, 8 Mar 2006 15:06:39 +0100
User-agent: Mutt/1.4.2.1i

Hello everyone!

I've made some effort to make TinyCC generate ELF executables for
NetBSD/i386 target. Even though some earlier reports (see links below)
claimed, that TinyCC works for NetBSD, it is definitely not true for
current versions of NetBSD and TinyCC. My work is incomplete since I
don't have enough clue about both ELF and TinyCC internals, but it might
be usable for someone else, or myself when I will read through the code
and specs.

[Tinycc-devel] TinyCC ported on NetBSD-i386, Marc Vertes
        tinycc-devel/2002-12/msg00025.html
[Tinycc-devel] TCC for NetBSD
        tinycc-devel/2005-05/msg00016.html

First of all, TinyCC itself cannot be built on NetBSD host without
patching. So my modification is based on CVS snapshot patched with patches
from pkgsrc-wip project (http://pkgsrc-wip.sf.net). Patches here seem to
be similar/same as ones second maillist message above.

After executing binaries generated with this compiler, NetBSD identified
them as System V UNIX executables and used "svr4" emulation to run them.
This was due to missing NOTE program header which is needed to identify
NetBSD binaries. I added '.note.netbsd.ident' section and NOTE program
header covering it.

The code used to construct this section uses some constants from
<machdep/exec_elf.h> header, that depends on some constants in <sys/elf.h>
that conflicts with "elf.h" bundled with TinyCC. When building a native
compiler this is no problem, but NetBSD's elf.h doesn't contain definitions
for other platforms preventing cross-compiler to be built.

Furthermore, the NetBSD dynamic linker was segfalting (NULL ptr) before
passing control to the main program. This was because NetBSD kernel didn't
construct correct auxiliary vector due to missing PHDR program header.
I corrected this.

Binaries still don't run correctly. When I execute it I get output like
this (My ld.elf_so is built with DEBUG, RTLD_DEBUG and i have LD_DEBUG
set):

$ ./a.out
...
relocating objects
 relocating ./a.out (17/0 rel/rela, 0/0 plt rel/rela)
doing non-PLT relocations
sym = 1, type = 7, offset = 0x8049a2c, contents = 0x0, symbol = __syscall
doing lazy PLT binding
./a.out: Unsupported relocation type 7 in non-PLT relocations

Here my knowledge of ELF ends. This probably refers to:

Relocation section '.rel.got' at offset 0x448 contains 16 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
 08049a2c  00000107 R_386_JUMP_SLOT   08048910   __syscall
...

That is, dynamic linker is likely unhappy about R_386_JMP_SLOT relocation
being in .rel.got section. In gcc-generated files all R_386_JMP_SLOT are in
.rel.plt section. I have a little very clue about what PLT and GOT so
someone else has to investigate this.

The actual patch to relevant files follows:

Index: tcc.c
===================================================================
RCS file: /usr/home/lkundrak/cvs/tinycc/tinycc/tcc.c,v
retrieving revision 1.179
diff -u -r1.179 tcc.c
--- tcc.c       3 Sep 2005 22:51:34 -0000       1.179
+++ tcc.c       7 Mar 2006 19:48:25 -0000
@@ -43,6 +43,7 @@
 #include <windows.h>
 #endif
 #ifndef WIN32
+#include <sys/param.h>
 #include <sys/time.h>
 #include <sys/ucontext.h>
 #include <sys/mman.h>
@@ -54,7 +55,14 @@
 #define PAGESIZE 4096
 #endif
 
+#ifdef __NetBSD__
+#include <sys/cdefs.h>
+#include <sys/exec_elf.h>
+#include <elf.h>
+#else
 #include "elf.h"
+#endif
+
 #include "stab.h"
 
 #ifndef O_BINARY
@@ -730,7 +738,7 @@
   #define strtof (float)strtod
   #define strtoll (long long)strtol
 #endif
-#elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
+#elif defined(TCC_UCLIBC) || defined(BSD)
 /* currently incorrect */
 long double strtold(const char *nptr, char **endptr)
 {
@@ -9508,9 +9516,14 @@
 
 /* fix for glibc 2.1 */
 #ifndef REG_EIP
+#ifdef BSD
+#define REG_EIP _REG_EIP
+#define REG_EBP _REG_EBP
+#else
 #define REG_EIP EIP
 #define REG_EBP EBP
 #endif
+#endif
 
 /* return the PC at frame level 'level'. Return non zero if not found */
 static int rt_get_caller_pc(unsigned long *paddr, 
@@ -9522,6 +9535,8 @@
     if (level == 0) {
 #if defined(__FreeBSD__)
         *paddr = uc->uc_mcontext.mc_eip;
+#elif defined(__NetBSD__)
+       *paddr = uc->uc_mcontext.__gregs[REG_EIP];
 #elif defined(__dietlibc__)
         *paddr = uc->uc_mcontext.eip;
 #else
@@ -9531,6 +9546,8 @@
     } else {
 #if defined(__FreeBSD__) 
         fp = uc->uc_mcontext.mc_ebp;
+#elif defined(__NetBSD__)
+       fp = uc->uc_mcontext.__gregs[REG_EBP];
 #elif defined(__dietlibc__)
         fp = uc->uc_mcontext.ebp;
 #else
@@ -9705,7 +9722,11 @@
         struct sigaction sigact;
         /* install TCC signal handlers to print debug info on fatal
            runtime errors */
+#ifdef BSD
+        sigact.sa_flags = SA_RESETHAND;
+#else
         sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
+#endif
         sigact.sa_sigaction = sig_error;
         sigemptyset(&sigact.sa_mask);
         sigaction(SIGFPE, &sigact, NULL);
@@ -10149,9 +10170,20 @@
 #ifndef TCC_TARGET_PE
     if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
         !s->nostdlib) {
+#ifdef __NetBSD__
+        tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt0.o");
+       tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
+       if (s->static_link)
+           tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crtbegin.o");
+       else 
+           tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crtbeginT.o");
+       tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crtend.o");
+       tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crtn.o");
+#else
         if (output_type != TCC_OUTPUT_DLL)
             tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
         tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
+#endif /* !__NetBSD__ */
     }
 #endif
     return 0;
Index: tccelf.c
===================================================================
RCS file: /usr/home/lkundrak/cvs/tinycc/tinycc/tccelf.c,v
retrieving revision 1.32
diff -u -r1.32 tccelf.c
--- tccelf.c    30 Oct 2005 21:53:14 -0000      1.32
+++ tccelf.c    7 Mar 2006 19:40:45 -0000
@@ -18,6 +18,23 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#ifdef __NetBSD__
+/* See src/libexec/ld.elf_so/sysident.h */
+struct {
+    long name_sz;
+    long desc_sz;
+    long type;
+    char os_name[ELF_NOTE_NETBSD_NAMESZ+1];
+    long os_version;
+} __attribute__((packed)) NetBSD_ELF_ident = {
+    ELF_NOTE_NETBSD_NAMESZ,
+    ELF_NOTE_NETBSD_DESCSZ,
+    ELF_NOTE_TYPE_NETBSD_TAG,
+    ELF_NOTE_NETBSD_NAME,
+    __NetBSD_Version__
+};
+#endif
+
 static int put_elf_str(Section *s, const char *sym)
 {
     int offset, len;
@@ -1063,6 +1080,8 @@
 /* name of ELF interpreter */
 #ifdef __FreeBSD__
 static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
+#elif defined(__NetBSD__)
+static char elf_interp[] = "/libexec/ld.elf_so";
 #else
 static char elf_interp[] = "/lib/ld-linux.so.2";
 #endif
@@ -1107,10 +1126,26 @@
     Elf32_Sym *sym;
     int type, file_type;
     unsigned long rel_addr, rel_size;
+#ifdef __NetBSD__
+    Section *abinote;
+#endif
     
     file_type = s1->output_type;
     s1->nb_errors = 0;
 
+#ifdef __NetBSD__
+    abinote = NULL;
+
+    /* NetBSD ABI identification section */
+    if (file_type == TCC_OUTPUT_EXE) {
+       char *ptr;
+
+       abinote = new_section(s1, ".note.netbsd.ident", SHT_NOTE, SHF_ALLOC);
+       ptr = section_ptr_add(abinote, sizeof(NetBSD_ELF_ident));
+       memcpy(ptr, &NetBSD_ELF_ident, sizeof(NetBSD_ELF_ident));
+    }
+#endif
+
     if (file_type != TCC_OUTPUT_OBJ) {
         tcc_add_runtime(s1);
     }
@@ -1310,6 +1345,9 @@
             phnum = 4;
         else
             phnum = 2;
+#ifdef __NetBSD__
+       phnum += 2;     /* NOTE & PHDR headers */
+#endif
         break;
     case TCC_OUTPUT_DLL:
         phnum = 3;
@@ -1475,6 +1513,35 @@
             ph->p_flags = PF_R;
             ph->p_align = interp->sh_addralign;
         }
+
+#ifdef __NetBSD__
+        if (abinote) {
+            ph = &phdr[phnum - 2];
+            
+            ph->p_type = PT_NOTE;
+            ph->p_offset = abinote->sh_offset;
+            ph->p_vaddr = abinote->sh_addr;
+            ph->p_paddr = ph->p_vaddr;
+            ph->p_filesz = abinote->sh_size;
+            ph->p_memsz = abinote->sh_size;
+            ph->p_flags = PF_R;
+            ph->p_align = abinote->sh_addralign;
+        }
+
+        if (s1->output_type == TCC_OUTPUT_EXE) {
+            ph = &phdr[phnum - 3];
+            
+            ph->p_type = PT_PHDR;
+            ph->p_offset = sizeof(Elf32_Ehdr);
+            ph->p_vaddr = ELF_START_ADDR + sizeof(Elf32_Ehdr);
+            ph->p_paddr = ELF_START_ADDR + sizeof(Elf32_Ehdr);
+            ph->p_filesz = sizeof(Elf32_Phdr);
+            ph->p_memsz = sizeof(Elf32_Phdr);
+            ph->p_flags = PF_R | PF_X;
+            ph->p_align = 4;
+        }
+#endif
         
         /* if dynamic section, then add corresponing program header */
         if (dynamic) {
@@ -1643,6 +1710,10 @@
 #ifdef __FreeBSD__
         ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
 #endif
+#ifdef __NetBSD__
+       ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
+       /* See elf(5) for a reason why don't we use ELFOSABI_NETBSD */
+#endif
 #ifdef TCC_TARGET_ARM
         ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
 #endif

regards,
Lubo.

---------------------------------------------------------------------------
  o     Lubomir Kundrak
 *O*    <address@hidden>, http://skosi.org/~lkundrak/
 (_)    SKOSI -- Slovak OpenSource Initiative
---------------------------------------------------------------------------




reply via email to

[Prev in Thread] Current Thread [Next in Thread]