]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld: avoid redundant external relocation calculations
authorRuss Cox <rsc@golang.org>
Mon, 11 Mar 2013 02:07:16 +0000 (19:07 -0700)
committerRuss Cox <rsc@golang.org>
Mon, 11 Mar 2013 02:07:16 +0000 (19:07 -0700)
R=ken2, ken
CC=golang-dev
https://golang.org/cl/7483045

src/cmd/5l/asm.c
src/cmd/5l/l.h
src/cmd/6l/asm.c
src/cmd/6l/l.h
src/cmd/8l/asm.c
src/cmd/8l/l.h
src/cmd/ld/data.c
src/cmd/ld/elf.c
src/cmd/ld/elf.h

index 4afbedfc43c123eb74dceb858e8f7fef7b638895..9ff25f1e127a8f229ba39175b33b5827dc9d21d5 100644 (file)
@@ -240,12 +240,13 @@ adddynrel(Sym *s, Reloc *r)
 }
 
 int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
 {
-       USED(add);      // written to obj file by ../ld/data.c's reloc
-
-       LPUT(off);
+       int32 elfsym;
+       
+       LPUT(sectoff);
 
+       elfsym = r->xsym->elfsym;
        switch(r->type) {
        default:
                return -1;
index 78f99d873d847934dbbe7a161817337630a6d620..83c8b755c6e76e40cf34918f9f0f7eb203178ae7 100644 (file)
@@ -96,9 +96,12 @@ struct       Reloc
 {
        int32   off;
        uchar   siz;
+       uchar   done;
        int16   type;
        int32   add;
+       int32   xadd;
        Sym*    sym;
+       Sym*    xsym;
 };
 
 struct Prog
index d2c6f86d35bbeb58aa31b35ccf41e1e90f93d5dc..e1d114642a62a510cd82b623b0ff495828afbf12 100644 (file)
@@ -284,10 +284,13 @@ adddynrel(Sym *s, Reloc *r)
 }
 
 int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
 {
-       VPUT(off);
+       int32 elfsym;
 
+       VPUT(sectoff);
+
+       elfsym = r->xsym->elfsym;
        switch(r->type) {
        default:
                return -1;
@@ -306,11 +309,10 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
                        VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
                else
                        return -1;
-               add -= r->siz;
                break;
        }
 
-       VPUT(add);
+       VPUT(r->xadd);
        return 0;
 }
 
index a48639d7ae5917cf9afdd0f3f6369c6f6c6b439a..1d6e55c97b385d879404ecd98ea6c7e0e9360eca 100644 (file)
@@ -101,9 +101,12 @@ struct     Reloc
 {
        int32   off;
        uchar   siz;
+       uchar   done;
        int32   type;
        int64   add;
+       int64   xadd;
        Sym*    sym;
+       Sym*    xsym;
 };
 
 struct Prog
index 9250aeeae32296f4d7f2322f82e8320112dbf6bb..9bd04ff1aa861980541e815df9af673aced7c6c7 100644 (file)
@@ -270,12 +270,13 @@ adddynrel(Sym *s, Reloc *r)
 }
 
 int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
 {
-       USED(add);      // written to obj file by ../ld/data.c's reloc
+       int32 elfsym;
 
-       LPUT(off);
+       LPUT(sectoff);
 
+       elfsym = r->xsym->elfsym;
        switch(r->type) {
        default:
                return -1;
index 18a3de218de19c313343122c49bc9d5260333b91..980a7f830c72de7e7531614f7af3a08d83236176 100644 (file)
@@ -84,9 +84,12 @@ struct       Reloc
 {
        int32   off;
        uchar   siz;
+       uchar   done;
        int32   type;
        int32   add;
+       int32   xadd;
        Sym*    sym;
+       Sym*    xsym;
 };
 
 struct Prog
index e035942be7319c19dbb5a9c9dc22fd19ba797e7e..ca6c5300bd4d172b53aa5f6d860e7b7d14b76a6a 100644 (file)
@@ -155,6 +155,7 @@ relocsym(Sym *s)
        cursym = s;
        memset(&p, 0, sizeof p);
        for(r=s->r; r<s->r+s->nr; r++) {
+               r->done = 1;
                off = r->off;
                siz = r->siz;
                if(off < 0 || off+siz > s->np) {
@@ -181,31 +182,51 @@ relocsym(Sym *s)
                                diag("unknown reloc %d", r->type);
                        break;
                case D_ADDR:
-                       o = symaddr(r->sym) + r->add;
                        if(isobj && r->sym->type != SCONST) {
+                               r->done = 0;
+
+                               // set up addend for eventual relocation via outer symbol.
+                               rs = r->sym;
+                               r->xadd = r->add;
+                               while(rs->outer != nil) {
+                                       r->xadd += symaddr(rs) - symaddr(rs->outer);
+                                       rs = rs->outer;
+                               }
+                               r->xsym = rs;
+
                                if(thechar == '6')
                                        o = 0;
-                               else {
-                                       // set up addend for eventual relocation via outer symbol
-                                       rs = r->sym;
-                                       while(rs->outer != nil)
-                                               rs = rs->outer;
-                                       o -= symaddr(rs);
-                               }
+                               else
+                                       o = r->xadd;
+                               break;
                        }
+                       o = symaddr(r->sym) + r->add;
                        break;
                case D_PCREL:
                        // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
-                       o = 0;
-                       if(r->sym)
-                               o += symaddr(r->sym);
-                       o += r->add - (s->value + r->off + r->siz);
-                       if(isobj && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
+                       if(isobj && r->sym && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
+                               r->done = 0;
+
+                               // set up addend for eventual relocation via outer symbol.
+                               rs = r->sym;
+                               r->xadd = r->add;
+                               while(rs->outer != nil) {
+                                       r->xadd += symaddr(rs) - symaddr(rs->outer);
+                                       rs = rs->outer;
+                               }
+                               r->xsym = rs;
+                               r->xadd -= r->siz;
+
                                if(thechar == '6')
                                        o = 0;
                                else
-                                       o = r->add - r->siz;
+                                       o = r->xadd;
+                               break;
                        }
+                       o = 0;
+                       if(r->sym)
+                               o += symaddr(r->sym);
+                       o += r->add - (s->value + r->off + r->siz);
                        break;
                case D_SIZE:
                        o = r->sym->size + r->add;
index 9f7cb75fa9b26971fd7357bdd48072aea22fb5eb..50711a0ec10d108c714d614fe56bd7ab84cd603a 100644 (file)
@@ -805,10 +805,9 @@ elfshreloc(Section *sect)
 void
 elfrelocsect(Section *sect, Sym *first)
 {
-       Sym *sym, *rs;
+       Sym *sym;
        int32 eaddr;
        Reloc *r;
-       int64 add;
 
        // If main section is SHT_NOBITS, nothing to relocate.
        // Also nothing to relocate in .shstrtab.
@@ -834,30 +833,15 @@ elfrelocsect(Section *sect, Sym *first)
                cursym = sym;
                
                for(r = sym->r; r < sym->r+sym->nr; r++) {
-                       // Ignore relocations handled by reloc already.
-                       switch(r->type) {
-                       case D_SIZE:
+                       if(r->done)
+                               continue;
+                       if(r->xsym == nil) {
+                               diag("missing xsym in relocation");
                                continue;
-                       case D_ADDR:
-                       case D_PCREL:
-                               if(r->sym->type == SCONST)
-                                       continue;       // handled in data.c:/^relocsym
-                               if(r->type == D_PCREL && r->sym->sect == sym->sect)
-                                       continue;       // handled in data.c:/^relocsym
-                               break;
-                       }
-
-                       add = r->add;
-                       rs = r->sym;
-                       while(rs->outer != nil) {
-                               add += rs->value - rs->outer->value;
-                               rs = rs->outer;
                        }
-                               
-                       if(rs->elfsym == 0)
-                               diag("reloc %d to non-elf symbol %s (rs=%s) %d", r->type, r->sym->name, rs->name, rs->type);
-
-                       if(elfreloc1(r, sym->value - sect->vaddr + r->off, rs->elfsym, add) < 0)
+                       if(r->xsym->elfsym == 0)
+                               diag("reloc %d to non-elf symbol %s (outer=%s) %d", r->type, r->sym->name, r->xsym->name, r->sym->type);
+                       if(elfreloc1(r, sym->value+r->off - sect->vaddr) < 0)
                                diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
                }
        }
index 3e22125b2114291e6b6e8f88a64ab09a3af87708..336fab4b4bbdacb75c301093d7db7f1cc7a17e80 100644 (file)
@@ -1005,7 +1005,7 @@ extern char linuxdynld[];
 extern char freebsddynld[];
 extern char netbsddynld[];
 extern char openbsddynld[];
-int    elfreloc1(Reloc*, vlong off, int32 elfsym, vlong add);
+int    elfreloc1(Reloc*, vlong sectoff);
 
 EXTERN int     elfstrsize;
 EXTERN char*   elfstrdat;