]> Cypherpunks repositories - gostls13.git/commitdiff
First steps towards cleaner support for ELF64 in 6l.
authorRob Pike <r@golang.org>
Fri, 17 Jul 2009 21:32:37 +0000 (14:32 -0700)
committerRob Pike <r@golang.org>
Fri, 17 Jul 2009 21:32:37 +0000 (14:32 -0700)
R=rsc
DELTA=337  (165 added, 119 deleted, 53 changed)
OCL=31786
CL=31794

src/cmd/6l/Makefile
src/cmd/6l/asm.c
src/cmd/6l/elf64.c [new file with mode: 0644]
src/cmd/6l/l.h
src/cmd/6l/obj.c
src/cmd/ld/elf64.c [new file with mode: 0644]
src/cmd/ld/elf64.h [new file with mode: 0644]

index eba976c638566687a7f75b41e0bc24bde7a4ccd7..bcbdb3de7d47507e32f28ae4a8f0fe1dff0a1b07 100644 (file)
@@ -10,6 +10,7 @@ TARG=\
 OFILES=\
        asm.$O\
        compat.$O\
+       elf64.$O\
        enam.$O\
        go.$O\
        list.$O\
@@ -21,6 +22,7 @@ OFILES=\
 HFILES=\
        l.h\
        ../6l/6.out.h\
+       ../ld/elf64.h\
 
 
 $(TARG): $(OFILES)
@@ -38,3 +40,5 @@ install: $(TARG)
        cp $(TARG) $(BIN)/$(TARG)
 
 go.o: ../ld/go.c
+
+elf64.o: ../ld/elf64.c
index b981570c0d82e635371d59240c1780649764b2d5..fcfbc6ad2dcbfb0e1203a2d070a74f2ec8ab7284 100644 (file)
@@ -29,6 +29,7 @@
 // THE SOFTWARE.
 
 #include       "l.h"
+#include       "../ld/elf64.h"
 
 #define        Dbufslop        100
 
@@ -126,6 +127,7 @@ asmb(void)
        vlong vl, va, fo, w, symo;
        int strtabsize;
        vlong symdatva = 0x99LL<<32;
+       Elf64SHdr *sh;
 
        strtabsize = 0;
 
@@ -194,7 +196,7 @@ asmb(void)
        case 7:
                debug['8'] = 1; /* 64-bit addresses */
                seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
-               strtabsize = linuxstrtable();
+               strtabsize = elf64strtable();
                cflush();
                v = rnd(HEADR+textsize, INITRND);
                seek(cout, v, 0);
@@ -448,7 +450,7 @@ asmb(void)
                va = INITTEXT & ~((vlong)INITRND - 1);
                w = HEADR+textsize;
 
-               linuxphdr(1,                    /* text - type = PT_LOAD */
+               elf64phdr(1,                    /* text - type = PT_LOAD */
                        1L+4L,                  /* text - flags = PF_X+PF_R */
                        0,                      /* file offset */
                        va,                     /* vaddr */
@@ -461,7 +463,7 @@ asmb(void)
                va = rnd(va+w, INITRND);
                w = datsize;
 
-               linuxphdr(1,                    /* data - type = PT_LOAD */
+               elf64phdr(1,                    /* data - type = PT_LOAD */
                        2L+4L,                  /* data - flags = PF_W+PF_R */
                        fo,                     /* file offset */
                        va,                     /* vaddr */
@@ -471,7 +473,7 @@ asmb(void)
                        INITRND);               /* alignment */
 
                if(!debug['s']) {
-                       linuxphdr(1,                    /* data - type = PT_LOAD */
+                       elf64phdr(1,                    /* data - type = PT_LOAD */
                                2L+4L,                  /* data - flags = PF_W+PF_R */
                                symo,           /* file offset */
                                symdatva,                       /* vaddr */
@@ -481,7 +483,7 @@ asmb(void)
                                INITRND);               /* alignment */
                }
 
-               linuxphdr(0x6474e551,           /* gok - type = gok */
+               elf64phdr(0x6474e551,           /* gok - type = gok */
                        1L+2L+4L,               /* gok - flags = PF_X+PF_W+PF_R */
                        0,                      /* file offset */
                        0,                      /* vaddr */
@@ -490,75 +492,57 @@ asmb(void)
                        0,                      /* memory size */
                        8);                     /* alignment */
 
-               linuxshdr(nil,                  /* name */
-                       0,                      /* type */
-                       0,                      /* flags */
-                       0,                      /* addr */
-                       0,                      /* off */
-                       0,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       0,                      /* align */
-                       0);                     /* entsize */
+               sh = newElf64SHdr();
+               elf64shdr(nil, sh);
 
                stroffset = 1;  /* 0 means no name, so start at 1 */
                fo = HEADR;
                va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR;
                w = textsize;
 
-               linuxshdr(".text",              /* name */
-                       1,                      /* type */
-                       6,                      /* flags */
-                       va,                     /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       8,                      /* align */
-                       0);                     /* entsize */
+               sh = newElf64SHdr();
+               sh->type = 1;
+               sh->flags = 6;
+               sh->addr = va;
+               sh->off = fo;
+               sh->size = w;
+               sh->addralign = 8;
+               elf64shdr(".text", sh);
 
                fo = rnd(fo+w, INITRND);
                va = rnd(va+w, INITRND);
                w = datsize;
 
-               linuxshdr(".data",              /* name */
-                       1,                      /* type */
-                       3,                      /* flags */
-                       va,                     /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       8,                      /* align */
-                       0);                     /* entsize */
+               sh = newElf64SHdr();
+               sh->type = 1;
+               sh->flags = 3;
+               sh->addr = va;
+               sh->off = fo;
+               sh->size = w;
+               sh->addralign = 8;
+               elf64shdr(".data", sh);
 
                fo += w;
                va += w;
                w = bsssize;
 
-               linuxshdr(".bss",               /* name */
-                       8,                      /* type */
-                       3,                      /* flags */
-                       va,                     /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       8,                      /* align */
-                       0);                     /* entsize */
+               sh = newElf64SHdr();
+               sh->type = 8;
+               sh->flags = 3;
+               sh->addr = va;
+               sh->off = fo;
+               sh->size = w;
+               sh->addralign = 8;
+               elf64shdr(".bss", sh);
 
                w = strtabsize;
 
-               linuxshdr(".shstrtab",          /* name */
-                       3,                      /* type */
-                       0,                      /* flags */
-                       0,                      /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       1,                      /* align */
-                       0);                     /* entsize */
+               sh = newElf64SHdr();
+               sh->type = 3;
+               sh->off = fo;
+               sh->size = w;
+               sh->addralign = 1;
+               elf64shdr(".shstrtab", sh);
 
                if (debug['s'])
                        break;
@@ -566,30 +550,25 @@ asmb(void)
                fo = symo+8;
                w = symsize;
 
-               linuxshdr(".gosymtab",          /* name */
-                       1,                      /* type 1 = SHT_PROGBITS */
-                       0,                      /* flags */
-                       0,                      /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       1,                      /* align */
-                       24);                    /* entsize */
+               sh = newElf64SHdr();
+               sh->type = 1;   /* type 1 = SHT_PROGBITS */
+               sh->off = fo;
+               sh->size = w;
+               sh->addralign = 1;
+               sh->entsize = 24;
+               elf64shdr(".gosymtab", sh);
 
                fo += w;
                w = lcsize;
 
-               linuxshdr(".gopclntab",         /* name */
-                       1,                      /* type 1 = SHT_PROGBITS*/
-                       0,                      /* flags */
-                       0,                      /* addr */
-                       fo,                     /* off */
-                       w,                      /* size */
-                       0,                      /* link */
-                       0,                      /* info */
-                       1,                      /* align */
-                       24);                    /* entsize */
+               sh = newElf64SHdr();
+               sh->type = 1;   /* type 1 = SHT_PROGBITS */
+               sh->off = fo;
+               sh->size = w;
+               sh->addralign = 1;
+               sh->entsize = 24;
+               elf64shdr(".gopclntab", sh);
+
                break;
        }
        cflush();
@@ -899,91 +878,3 @@ machheadr(void)
 
        return a*4;
 }
-
-uint32
-linuxheadr(void)
-{
-       uint32 a;
-
-       a = 64;         /* a.out header */
-
-       a += 56;        /* page zero seg */
-       a += 56;        /* text seg */
-       a += 56;        /* stack seg */
-
-       a += 64;        /* nil sect */
-       a += 64;        /* .text sect */
-       a += 64;        /* .data seg */
-       a += 64;        /* .bss sect */
-       a += 64;        /* .shstrtab sect - strings for headers */
-       if (!debug['s']) {
-               a += 56;        /* symdat seg */
-               a += 64;        /* .gosymtab sect */
-               a += 64;        /* .gopclntab sect */
-       }
-
-       return a;
-}
-
-
-void
-linuxphdr(int type, int flags, vlong foff,
-       vlong vaddr, vlong paddr,
-       vlong filesize, vlong memsize, vlong align)
-{
-
-       lputl(type);                    /* text - type = PT_LOAD */
-       lputl(flags);                   /* text - flags = PF_X+PF_R */
-       vputl(foff);                    /* file offset */
-       vputl(vaddr);                   /* vaddr */
-       vputl(paddr);                   /* paddr */
-       vputl(filesize);                /* file size */
-       vputl(memsize);         /* memory size */
-       vputl(align);                   /* alignment */
-}
-
-void
-linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off,
-       vlong size, uint32 link, uint32 info, vlong align, vlong entsize)
-{
-       lputl(stroffset);
-       lputl(type);
-       vputl(flags);
-       vputl(addr);
-       vputl(off);
-       vputl(size);
-       lputl(link);
-       lputl(info);
-       vputl(align);
-       vputl(entsize);
-
-       if(name != nil)
-               stroffset += strlen(name)+1;
-}
-
-int
-putstrtab(char* name) {
-       int w;
-
-       w = strlen(name)+1;
-       strnput(name, w);
-       return w;
-}
-
-int
-linuxstrtable(void)
-{
-       int size;
-
-       size = 0;
-       size += putstrtab("");
-       size += putstrtab(".text");
-       size += putstrtab(".data");
-       size += putstrtab(".bss");
-       size += putstrtab(".shstrtab");
-       if (!debug['s']) {
-               size += putstrtab(".gosymtab");
-               size += putstrtab(".gopclntab");
-       }
-       return size;
-}
diff --git a/src/cmd/6l/elf64.c b/src/cmd/6l/elf64.c
new file mode 100644 (file)
index 0000000..20e502f
--- /dev/null
@@ -0,0 +1,6 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "l.h"
+#include "../ld/elf64.c"
index 41e233f62a108e2c4803c39a19203fe69f376a9c..e09579a6e7f3716b61e2b2cbfe511e645a94cc09 100644 (file)
@@ -432,9 +432,11 @@ int        relinv(int);
 int32  reuse(Prog*, Sym*);
 vlong  rnd(vlong, vlong);
 void   span(void);
+void   strnput(char*, int);
 void   undef(void);
 void   undefsym(Sym*);
 vlong  vaddr(Adr*);
+void   vputl(vlong);
 void   wput(ushort);
 void   xdefine(char*, int, vlong);
 void   xfol(Prog*);
@@ -448,14 +450,6 @@ void       machstack(vlong);
 void   machdylink(void);
 uint32 machheadr(void);
 
-uint32 linuxheadr(void);
-void   linuxphdr(int type, int flags, vlong foff,
-       vlong vaddr, vlong paddr,
-       vlong filesize, vlong memsize, vlong align);
-void   linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off,
-       vlong size, uint32 link, uint32 info, vlong align, vlong entsize);
-int    linuxstrtable(void);
-
 
 #pragma        varargck        type    "D"     Adr*
 #pragma        varargck        type    "P"     Prog*
index bcaa9da3b1bfc5d7a9316b5e9effa04b3ec67499..a2a520396f634eae0e242c9efd3dbbac679e41ba 100644 (file)
@@ -30,6 +30,7 @@
 
 #define        EXTERN
 #include       "l.h"
+#include       "../ld/elf64.h"
 #include       <ar.h>
 
 char   *noname         = "<none>";
@@ -196,7 +197,7 @@ main(int argc, char *argv[])
                        INITRND = 4096;
                break;
        case 7: /* elf64 executable */
-               HEADR = linuxheadr();
+               HEADR = elf64headr();
                if(INITTEXT == -1)
                        INITTEXT = (1<<22)+HEADR;
                if(INITDAT == -1)
diff --git a/src/cmd/ld/elf64.c b/src/cmd/ld/elf64.c
new file mode 100644 (file)
index 0000000..483b51c
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for 64-bit Elf binaries
+
+#include "../ld/elf64.h"
+
+void
+elf64phdr(int type, int flags, vlong foff,
+       vlong vaddr, vlong paddr,
+       vlong filesize, vlong memsize, vlong align)
+{
+
+       lputl(type);                    /*  type */
+       lputl(flags);                   /* flags */
+       vputl(foff);                    /* file offset */
+       vputl(vaddr);                   /* vaddr */
+       vputl(paddr);                   /* paddr */
+       vputl(filesize);                /* file size */
+       vputl(memsize);         /* memory size */
+       vputl(align);                   /* alignment */
+}
+
+void
+elf64shdr(char *name, Elf64SHdr *e)
+{
+       lputl(e->name);
+       lputl(e->type);
+       vputl(e->flags);
+       vputl(e->addr);
+       vputl(e->off);
+       vputl(e->size);
+       lputl(e->link);
+       lputl(e->info);
+       vputl(e->addralign);
+       vputl(e->entsize);
+
+       if(name != nil)
+               stroffset += strlen(name)+1;
+}
+
+int
+putelf64strtab(char* name)
+{
+       int w;
+
+       w = strlen(name)+1;
+       strnput(name, w);
+       return w;
+}
+
+
+int
+elf64strtable(void)
+{
+       int size;
+
+       size = 0;
+       size += putelf64strtab("");
+       size += putelf64strtab(".text");
+       size += putelf64strtab(".data");
+       size += putelf64strtab(".bss");
+       size += putelf64strtab(".shstrtab");
+       if (!debug['s']) {
+               size += putelf64strtab(".gosymtab");
+               size += putelf64strtab(".gopclntab");
+       }
+       return size;
+}
+
+
+uint32
+elf64headr(void)
+{
+       uint32 a;
+
+       a = 64;         /* a.out header */
+
+       a += 56;        /* page zero seg */
+       a += 56;        /* text seg */
+       a += 56;        /* stack seg */
+
+       a += 64;        /* nil sect */
+       a += 64;        /* .text sect */
+       a += 64;        /* .data seg */
+       a += 64;        /* .bss sect */
+       a += 64;        /* .shstrtab sect - strings for headers */
+       if (!debug['s']) {
+               a += 56;        /* symdat seg */
+               a += 64;        /* .gosymtab sect */
+               a += 64;        /* .gopclntab sect */
+       }
+
+       return a;
+}
+
+Elf64SHdr*
+newElf64SHdr()
+{
+       Elf64SHdr *e;
+
+       e = malloc(sizeof *e);
+       memset(e, 0, sizeof *e);
+       e->name = stroffset;
+       return e;
+}
+
diff --git a/src/cmd/ld/elf64.h b/src/cmd/ld/elf64.h
new file mode 100644 (file)
index 0000000..cd4964b
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Derived from:
+ * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
+ * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
+ * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
+ * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $
+ * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
+ * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $
+ * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
+ * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
+ * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
+ *
+ * Copyright (c) 1996-1998 John D. Polstra.  All rights reserved.
+ * Copyright (c) 2001 David E. O'Brien
+ * Portions Copyright 2009 The Go Authors.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+typedef uint64 Elf64_Addr;     /* Unsigned program address */
+typedef uint64 Elf64_Off;      /* Unsigned file offset */
+typedef uint16 Elf64_Half;     /* Unsigned medium integer */
+typedef uint32 Elf64_Word;     /* Unsigned integer */
+typedef int32  Elf64_Sword;    /* Signed integer */
+typedef uint64 Elf64_Xword;    /* Unsigned long integer */
+typedef int64  Elf64_Sxword;   /* Signed long integer */
+
+typedef struct Elf64Hdr Elf64Hdr;
+typedef struct Elf64SHdr Elf64SHdr;
+
+struct Elf64Hdr
+{
+       uchar ident[16];        /* ELF identification */
+       Elf64_Half      type;   /* Object file type */
+       Elf64_Half      machine;        /* Machine type */
+       Elf64_Word      version;        /* Object file version */
+       Elf64_Addr      entry;  /* Entry point address */
+       Elf64_Off       phoff;  /* Program header offset */
+       Elf64_Off       shoff;  /* Section header offset */
+       Elf64_Word      flags;  /* Processor-specific flags */
+       Elf64_Half      ehsize; /* ELF header size */
+       Elf64_Half      phentsize;      /* Size of program header entry */
+       Elf64_Half      phnum;  /* Number of program header entries */
+       Elf64_Half      shentsize;      /* Size of section header entry */
+       Elf64_Half      shnum;  /* Number of section header entries */
+       Elf64_Half      shstrndx;       /* Section name string table index */
+};
+
+struct Elf64SHdr
+{
+       Elf64_Word      name;   /* Section name */
+       Elf64_Word      type;   /* Section type */
+       Elf64_Xword     flags;  /* Section attributes */
+       Elf64_Addr      addr;   /* Virtual address in memory */
+       Elf64_Off       off; /* Offset in file */
+       Elf64_Xword     size;   /* Size of section */
+       Elf64_Word      link;   /* Link to other section */
+       Elf64_Word      info;   /* Miscellaneous information */
+       Elf64_Xword     addralign;      /* Address alignment boundary */
+       Elf64_Xword     entsize;        /* Size of entries, if section has table */
+};
+
+Elf64SHdr *newElf64SHdr();
+uint32 elf64headr(void);
+void   elf64phdr(int type, int flags, vlong foff,
+       vlong vaddr, vlong paddr,
+       vlong filesize, vlong memsize, vlong align);
+void   elf64shdr(char*, Elf64SHdr*);
+int    elf64strtable(void);