[Top][All Lists]
[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
---------------------------------------------------------------------------
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Tinycc-devel] TCC for NetBSD/i386 ELF [PATCH],
Lubomir Kundrak <=