]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld: make mach-o sections match internal sections
authorRuss Cox <rsc@golang.org>
Sun, 10 Mar 2013 18:17:04 +0000 (14:17 -0400)
committerRuss Cox <rsc@golang.org>
Sun, 10 Mar 2013 18:17:04 +0000 (14:17 -0400)
This brings Mach-O generation more in line with ELF generation.

Having separate sections for the symtab and pclntab mean that we
can find them that way, instead of using the deprecated debug segments.
(And the host linker will keep separate sections for us, but probably
not the debug segments.)

R=ken2
CC=golang-dev
https://golang.org/cl/7688043

src/cmd/ld/data.c
src/cmd/ld/dwarf.c
src/cmd/ld/lib.h
src/cmd/ld/macho.c
src/cmd/ld/macho.h
src/libmach/executable.c

index 22cb4f3e6058d322294fdb48f9298ff05785753f..10dba90305b91ce19f5dd27f8133b3d7e3823deb 100644 (file)
@@ -879,6 +879,9 @@ symalign(Sym *s)
 {
        int32 align;
 
+       if(s->align != 0)
+               return s->align;
+
        align = MaxAlign;
        while(align > s->size && align > 1)
                align >>= 1;
@@ -1136,9 +1139,10 @@ dodata(void)
        lookup("end", 0)->sect = sect;
 
        /* we finished segdata, begin segtext */
+       s = datap;
+       datsize = 0;
 
        /* read-only data */
-       s = datap;
        sect = addsection(&segtext, ".rodata", 04);
        sect->align = maxalign(s, STYPELINK-1);
        sect->vaddr = 0;
@@ -1202,7 +1206,7 @@ dodata(void)
        }
        sect->len = datsize - sect->vaddr;
 
-       /* read-only ELF sections */
+       /* read-only ELF, Mach-O sections */
        for(; s != nil && s->type < SELFSECT; s = s->next) {
                sect = addsection(&segtext, s->name, 04);
                sect->align = symalign(s);
@@ -1266,6 +1270,7 @@ address(void)
        Section *typelink;
        Sym *sym, *sub;
        uvlong va;
+       vlong vlen;
 
        va = INITTEXT;
        segtext.rwx = 05;
@@ -1295,11 +1300,11 @@ address(void)
        noptrbss = nil;
        datarelro = nil;
        for(s=segdata.sect; s != nil; s=s->next) {
+               vlen = s->len;
                if(s->next)
-                       s->len = s->next->vaddr - s->vaddr;
+                       vlen = s->next->vaddr - s->vaddr;
                s->vaddr = va;
-               va += s->len;
-               segdata.filelen += s->len;
+               va += vlen;
                segdata.len = va - segdata.vaddr;
                if(strcmp(s->name, ".data") == 0)
                        data = s;
index 949752994b185cbe8a2a2dc007f3c7f8d91e4206..99569be851c8f0972116f15d100db121ee3f9e18 100644 (file)
@@ -2298,42 +2298,42 @@ dwarfaddmachoheaders(void)
        ms->fileoffset = fakestart;
        ms->filesize = abbrevo-fakestart;
 
-       msect = newMachoSect(ms, "__debug_abbrev");
+       msect = newMachoSect(ms, "__debug_abbrev", "__DWARF");
        msect->off = abbrevo;
        msect->size = abbrevsize;
        ms->filesize += msect->size;
 
-       msect = newMachoSect(ms, "__debug_line");
+       msect = newMachoSect(ms, "__debug_line", "__DWARF");
        msect->off = lineo;
        msect->size = linesize;
        ms->filesize += msect->size;
 
-       msect = newMachoSect(ms, "__debug_frame");
+       msect = newMachoSect(ms, "__debug_frame", "__DWARF");
        msect->off = frameo;
        msect->size = framesize;
        ms->filesize += msect->size;
 
-       msect = newMachoSect(ms, "__debug_info");
+       msect = newMachoSect(ms, "__debug_info", "__DWARF");
        msect->off = infoo;
        msect->size = infosize;
        ms->filesize += msect->size;
 
        if (pubnamessize > 0) {
-               msect = newMachoSect(ms, "__debug_pubnames");
+               msect = newMachoSect(ms, "__debug_pubnames", "__DWARF");
                msect->off = pubnameso;
                msect->size = pubnamessize;
                ms->filesize += msect->size;
        }
 
        if (pubtypessize > 0) {
-               msect = newMachoSect(ms, "__debug_pubtypes");
+               msect = newMachoSect(ms, "__debug_pubtypes", "__DWARF");
                msect->off = pubtypeso;
                msect->size = pubtypessize;
                ms->filesize += msect->size;
        }
 
        if (arangessize > 0) {
-               msect = newMachoSect(ms, "__debug_aranges");
+               msect = newMachoSect(ms, "__debug_aranges", "__DWARF");
                msect->off = arangeso;
                msect->size = arangessize;
                ms->filesize += msect->size;
@@ -2341,7 +2341,7 @@ dwarfaddmachoheaders(void)
 
        // TODO(lvd) fix gdb/python to load MachO (16 char section name limit)
        if (gdbscriptsize > 0) {
-               msect = newMachoSect(ms, "__debug_gdb_scripts");
+               msect = newMachoSect(ms, "__debug_gdb_scripts", "__DWARF");
                msect->off = gdbscripto;
                msect->size = gdbscriptsize;
                ms->filesize += msect->size;
index 6b4f4d704472dc0eeff8b49021c266000556b42c..4e18bf267790acff03c81c72ea95d196e9f00cae 100644 (file)
@@ -34,7 +34,6 @@ enum
 
        /* order here is order in output file */
        STEXT,
-       SMACHOPLT,
        STYPE,
        SSTRING,
        SGOSTRING,
@@ -43,12 +42,13 @@ enum
        SSYMTAB,
        SPCLNTAB,
        SELFROSECT,
+       SMACHOPLT,
        SELFSECT,
+       SMACHO, /* Mach-O __nl_symbol_ptr */
+       SMACHOGOT,
        SNOPTRDATA,
        SDATARELRO,
        SDATA,
-       SMACHO, /* Mach-O __nl_symbol_ptr */
-       SMACHOGOT,
        SWINDOWS,
        SBSS,
        SNOPTRBSS,
index 75be9d940233c5806bd8676162d0118435cc0240..a282987de2c5bc3293bc539b3d6369e7713e1cd1 100644 (file)
@@ -14,7 +14,6 @@ static        int     macho64;
 static MachoHdr        hdr;
 static MachoLoad       *load;
 static MachoSeg        seg[16];
-static MachoDebug      xdebug[16];
 static int     nload, mload, nseg, ndebug, nsect;
 
 // Amount of space left for adding load commands
@@ -86,7 +85,7 @@ newMachoSeg(char *name, int msect)
 }
 
 MachoSect*
-newMachoSect(MachoSeg *seg, char *name)
+newMachoSect(MachoSeg *seg, char *name, char *segname)
 {
        MachoSect *s;
 
@@ -96,21 +95,11 @@ newMachoSect(MachoSeg *seg, char *name)
        }
        s = &seg->sect[seg->nsect++];
        s->name = name;
+       s->segname = segname;
        nsect++;
        return s;
 }
 
-MachoDebug*
-newMachoDebug(void)
-{
-       if(ndebug >= nelem(xdebug)) {
-               diag("too many debugs");
-               errorexit();
-       }
-       return &xdebug[ndebug++];
-}
-
-
 // Generic linking code.
 
 static char **dylib;
@@ -126,7 +115,6 @@ machowrite(void)
        int i, j;
        MachoSeg *s;
        MachoSect *t;
-       MachoDebug *d;
        MachoLoad *l;
 
        o1 = cpos();
@@ -186,7 +174,7 @@ machowrite(void)
                        t = &s->sect[j];
                        if(macho64) {
                                strnput(t->name, 16);
-                               strnput(s->name, 16);
+                               strnput(t->segname, 16);
                                VPUT(t->addr);
                                VPUT(t->size);
                                LPUT(t->off);
@@ -199,7 +187,7 @@ machowrite(void)
                                LPUT(0);        /* reserved */
                        } else {
                                strnput(t->name, 16);
-                               strnput(s->name, 16);
+                               strnput(t->segname, 16);
                                LPUT(t->addr);
                                LPUT(t->size);
                                LPUT(t->off);
@@ -221,14 +209,6 @@ machowrite(void)
                        LPUT(l->data[j]);
        }
 
-       for(i=0; i<ndebug; i++) {
-               d = &xdebug[i];
-               LPUT(3);        /* obsolete gdb debug info */
-               LPUT(16);       /* size of symseg command */
-               LPUT(d->fileoffset);
-               LPUT(d->filesize);
-       }
-
        return cpos() - o1;
 }
 
@@ -258,6 +238,7 @@ domacho(void)
        s = lookup(".got", 0);  // will be __nl_symbol_ptr
        s->type = SMACHOGOT;
        s->reachable = 1;
+       s->align = 4;
        
        s = lookup(".linkedit.plt", 0); // indirect table for .plt
        s->type = SMACHOINDIRECTPLT;
@@ -287,6 +268,52 @@ machoadddynlib(char *lib)
        dylib[ndylib++] = lib;
 }
 
+static void
+machoshbits(MachoSeg *mseg, Section *sect, char *segname)
+{
+       MachoSect *msect;
+       char buf[40];
+       char *p;
+       
+       snprint(buf, sizeof buf, "__%s", sect->name+1);
+       for(p=buf; *p; p++)
+               if(*p == '.')
+                       *p = '_';
+
+       msect = newMachoSect(mseg, estrdup(buf), segname);
+       
+       while(1<<msect->align < sect->align)
+               msect->align++;
+       msect->addr = sect->vaddr;
+       msect->size = sect->len;
+       msect->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
+       
+       if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen) {
+               // data in file
+               if(sect->len > sect->seg->vaddr + sect->seg->filelen - sect->vaddr)
+                       diag("macho cannot represent section %s crossing data and bss", sect->name);
+       } else {
+               // zero fill
+               msect->flag |= 1;
+       }
+
+       if(sect->rwx & 1)
+               msect->flag |= 0x400; /* has instructions */
+       
+       if(strcmp(sect->name, ".plt") == 0) {
+               msect->name = "__symbol_stub1";
+               msect->flag = 0x80000408; /* only instructions, code, symbol stubs */
+               msect->res1 = 0;
+               msect->res2 = 6;
+       }
+
+       if(strcmp(sect->name, ".got") == 0) {
+               msect->name = "__nl_symbol_ptr";
+               msect->flag = 6;        /* section with nonlazy symbol pointers */
+               msect->res1 = lookup(".linkedit.plt", 0)->size / 4;     /* offset into indirect symbol table */
+       }
+}
+
 void
 asmbmacho(void)
 {
@@ -294,11 +321,9 @@ asmbmacho(void)
        vlong va;
        int a, i;
        MachoHdr *mh;
-       MachoSect *msect;
        MachoSeg *ms;
-       MachoDebug *md;
        MachoLoad *ml;
-       Sym *s;
+       Section *sect;
 
        /* apple MACH */
        va = INITTEXT - HEADR;
@@ -323,62 +348,29 @@ asmbmacho(void)
 
        /* text */
        v = rnd(HEADR+segtext.len, INITRND);
-       ms = newMachoSeg("__TEXT", 2);
+       ms = newMachoSeg("__TEXT", 20);
        ms->vaddr = va;
        ms->vsize = v;
+       ms->fileoffset = 0;
        ms->filesize = v;
        ms->prot1 = 7;
        ms->prot2 = 5;
-
-       msect = newMachoSect(ms, "__text");
-       msect->addr = INITTEXT;
-       msect->size = segtext.sect->len;
-       msect->off = INITTEXT - va;
-       msect->flag = 0x400;    /* flag - some instructions */
        
-       s = lookup(".plt", 0);
-       if(s->size > 0) {
-               msect = newMachoSect(ms, "__symbol_stub1");
-               msect->addr = symaddr(s);
-               msect->size = s->size;
-               msect->off = ms->fileoffset + msect->addr - ms->vaddr;
-               msect->flag = 0x80000408;       /* flag */
-               msect->res1 = 0;        /* index into indirect symbol table */
-               msect->res2 = 6;        /* size of stubs */
-       }
+       for(sect=segtext.sect; sect!=nil; sect=sect->next)
+               machoshbits(ms, sect, "__TEXT");
 
        /* data */
        w = segdata.len;
-       ms = newMachoSeg("__DATA", 3);
+       ms = newMachoSeg("__DATA", 20);
        ms->vaddr = va+v;
        ms->vsize = w;
        ms->fileoffset = v;
        ms->filesize = segdata.filelen;
-       ms->prot1 = 7;
+       ms->prot1 = 3;
        ms->prot2 = 3;
-
-       msect = newMachoSect(ms, "__data");
-       msect->addr = va+v;
-       msect->off = v;
-       msect->size = segdata.filelen;
-
-       s = lookup(".got", 0);
-       if(s->size > 0) {
-               msect->size = symaddr(s) - msect->addr;
-
-               msect = newMachoSect(ms, "__nl_symbol_ptr");
-               msect->addr = symaddr(s);
-               msect->size = s->size;
-               msect->off = datoff(msect->addr);
-               msect->align = 2;
-               msect->flag = 6;        /* section with nonlazy symbol pointers */
-               msect->res1 = lookup(".linkedit.plt", 0)->size / 4;     /* offset into indirect symbol table */
-       }
-
-       msect = newMachoSect(ms, "__bss");
-       msect->addr = va+v+segdata.filelen;
-       msect->size = segdata.len - segdata.filelen;
-       msect->flag = 1;        /* flag - zero fill */
+       
+       for(sect=segdata.sect; sect!=nil; sect=sect->next)
+               machoshbits(ms, sect, "__DATA");
 
        switch(thechar) {
        default:
@@ -456,21 +448,8 @@ asmbmacho(void)
                }
        }
 
-       if(!debug['s']) {
-               Sym *s;
-
-               md = newMachoDebug();
-               s = lookup("symtab", 0);
-               md->fileoffset = datoff(s->value);
-               md->filesize = s->size;
-
-               md = newMachoDebug();
-               s = lookup("pclntab", 0);
-               md->fileoffset = datoff(s->value);
-               md->filesize = s->size;
-
+       if(!debug['s'])
                dwarfaddmachoheaders();
-       }
 
        a = machowrite();
        if(a > HEADR)
index baea6ff03d9580bcd0056e95fdd2be62d3906e3e..4499bb06fe23313d4f9a31a562c83b041034459a 100644 (file)
@@ -11,6 +11,7 @@ struct MachoHdr {
 typedef struct MachoSect MachoSect;
 struct MachoSect {
        char*   name;
+       char*   segname;
        uint64  addr;
        uint64  size;
        uint32  off;
@@ -44,17 +45,10 @@ struct MachoLoad {
        uint32  *data;
 };
 
-typedef struct MachoDebug MachoDebug;
-struct MachoDebug {
-       uint32  fileoffset;
-       uint32  filesize;
-};
-
 MachoHdr*      getMachoHdr(void);
 MachoSeg*      newMachoSeg(char*, int);
-MachoSect*     newMachoSect(MachoSeg*, char*);
+MachoSect*     newMachoSect(MachoSeg*, char*, char*);
 MachoLoad*     newMachoLoad(uint32, uint32);
-MachoDebug*    newMachoDebug(void);
 int    machowrite(void);
 void   machoinit(void);
 
index 221e56cdef2e1343945262904539448c18d03425..6d0bc2088813cad14864ce42c797cfc91ebdf6c9 100644 (file)
@@ -1030,8 +1030,8 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
        uvlong textsize, datasize, bsssize;
        uchar *cmdbuf;
        uchar *cmdp;
-       int i, hdrsize;
-       uint32 textva, textoff, datava, dataoff;
+       int i, j, hdrsize;
+       uint32 textva, textoff, datava, dataoff, symoff, symsize, pclnoff, pclnsize;
 
        mp = &hp->e.machhdr;
        if (leswal(mp->filetype) != MACH_EXECUTABLE_TYPE) {
@@ -1141,33 +1141,24 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
                        if (strcmp(seg32->segname, "__TEXT") == 0) {
                                textva = seg32->vmaddr;
                                textoff = seg32->fileoff;
+                               textsize = seg32->vmsize;
                                sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
-                               if (strcmp(sect32->sectname, "__text") == 0) {
-                                       textsize = swal(sect32->size);
-                               } else {
-                                       werrstr("no text section");
-                                       goto bad;
+                               for(j = 0; j < seg32->nsects; j++, sect32++) {
+                                       if (strcmp(sect32->sectname, "__gosymtab") == 0) {
+                                               symoff = swal(sect32->offset);
+                                               symsize = swal(sect32->size);
+                                       }
+                                       if (strcmp(sect32->sectname, "__gopclntab") == 0) {
+                                               pclnoff = swal(sect32->offset);
+                                               pclnsize = swal(sect32->size);
+                                       }
                                }
                        }
                        if (strcmp(seg32->segname, "__DATA") == 0) {
                                datava = seg32->vmaddr;
                                dataoff = seg32->fileoff;
-                               sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
-                               if (strcmp(sect32->sectname, "__data") == 0) {
-                                       datasize = swal(sect32->size);
-                               } else {
-                                       werrstr("no data section");
-                                       goto bad;
-                               }
-                               sect32++;
-                               if (strcmp(sect32->sectname, "__nl_symbol_ptr") == 0)
-                                       sect32++;
-                               if (strcmp(sect32->sectname, "__bss") == 0) {
-                                       bsssize = swal(sect32->size);
-                               } else {
-                                       werrstr("no bss section");
-                                       goto bad;
-                               }
+                               datasize = seg32->filesize;
+                               bsssize = seg32->vmsize - seg32->filesize;
                        }
                        break;
 
@@ -1188,42 +1179,39 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
                        if (strcmp(seg->segname, "__TEXT") == 0) {
                                textva = seg->vmaddr;
                                textoff = seg->fileoff;
+                               textsize = seg->vmsize;
                                sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
-                               if (strcmp(sect->sectname, "__text") == 0) {
-                                       textsize = swav(sect->size);
-                               } else {
-                                       werrstr("no text section");
-                                       goto bad;
+                               for(j = 0; j < seg->nsects; j++, sect++) {
+print("%s %#x %#x\n", sect->sectname, swal(sect->offset), swal(sect->size));
+                                       if (strcmp(sect->sectname, "__gosymtab") == 0) {
+                                               symoff = swal(sect->offset);
+                                               symsize = swal(sect->size);
+                                       }
+                                       if (strcmp(sect->sectname, "__gopclntab") == 0) {
+                                               pclnoff = swal(sect->offset);
+                                               pclnsize = swal(sect->size);
+                                       }
                                }
                        }
                        if (strcmp(seg->segname, "__DATA") == 0) {
                                datava = seg->vmaddr;
                                dataoff = seg->fileoff;
-                               sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
-                               if (strcmp(sect->sectname, "__data") == 0) {
-                                       datasize = swav(sect->size);
-                               } else {
-                                       werrstr("no data section");
-                                       goto bad;
-                               }
-                               sect++;
-                               if (strcmp(sect->sectname, "__nl_symbol_ptr") == 0)
-                                       sect++;
-                               if (strcmp(sect->sectname, "__bss") == 0) {
-                                       bsssize = swav(sect->size);
-                               } else {
-                                       werrstr("no bss section");
-                                       goto bad;
-                               }
+                               datasize = seg->filesize;
+                               bsssize = seg->vmsize - seg->filesize;
                        }
                        break;
                case MACH_UNIXTHREAD:
                        break;
                case MACH_SYMSEG:
-                       if (symtab == 0)
+                       if (symtab == 0) {
                                symtab = (MachSymSeg*)c;
-                       else if (pclntab == 0)
+                               symoff = swal(symtab->fileoff);
+                               symsize = swal(symtab->filesize);
+                       } else if (pclntab == 0) {
                                pclntab = (MachSymSeg*)c;
+                               pclnoff = swal(pclntab->fileoff);
+                               pclnsize = swal(pclntab->filesize);
+                       }
                        break;
                }
                cmdp += c->size;
@@ -1236,8 +1224,8 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
        /* compute entry by taking address after header - weird - BUG? */
        settext(fp, textva+sizeof(Machhdr) + mp->sizeofcmds, textva, textsize, textoff);
        setdata(fp, datava, datasize, dataoff, bsssize);
-       if(symtab != 0)
-               setsym(fp, symtab->fileoff, symtab->filesize, 0, 0, 0, pclntab? pclntab->filesize : 0);
+       if(symoff > 0)
+               setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsize);
        free(cmd);
        free(cmdbuf);
        return 1;