summaryrefslogtreecommitdiff
path: root/src/cmd/5l
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-04-06 15:14:11 +0200
committerOndřej Surý <ondrej@sury.org>2012-04-06 15:14:11 +0200
commit505c19580e0f43fe5224431459cacb7c21edd93d (patch)
tree79e2634c253d60afc0cc0b2f510dc7dcbb48497b /src/cmd/5l
parent1336a7c91e596c423a49d1194ea42d98bca0d958 (diff)
downloadgolang-505c19580e0f43fe5224431459cacb7c21edd93d.tar.gz
Imported Upstream version 1upstream/1
Diffstat (limited to 'src/cmd/5l')
-rw-r--r--src/cmd/5l/5.out.h3
-rw-r--r--src/cmd/5l/Makefile42
-rw-r--r--src/cmd/5l/asm.c54
-rw-r--r--src/cmd/5l/doc.go32
-rw-r--r--src/cmd/5l/l.h1
-rw-r--r--src/cmd/5l/list.c2
-rw-r--r--src/cmd/5l/noop.c3
-rw-r--r--src/cmd/5l/obj.c30
-rw-r--r--src/cmd/5l/pass.c5
-rw-r--r--src/cmd/5l/softfloat.c1
-rw-r--r--src/cmd/5l/span.c2
11 files changed, 76 insertions, 99 deletions
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h
index cf86ae48b..569536ebd 100644
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -35,7 +35,8 @@
#define NOPROF (1<<0)
#define DUPOK (1<<1)
#define NOSPLIT (1<<2)
-#define ALLTHUMBS (1<<3)
+#define RODATA (1<<3)
+#define NOPTR (1<<4)
#define REGRET 0
/* -1 disables use of REGARG */
diff --git a/src/cmd/5l/Makefile b/src/cmd/5l/Makefile
index 8489abc64..3f528d751 100644
--- a/src/cmd/5l/Makefile
+++ b/src/cmd/5l/Makefile
@@ -1,43 +1,5 @@
-# Copyright 2009 The Go Authors. All rights reserved.
+# Copyright 2012 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 ../../Make.inc
-O:=$(HOST_O)
-
-TARG=5l
-
-OFILES=\
- asm.$O\
- data.$O\
- elf.$O\
- enam.$O\
- ldelf.$O\
- ldmacho.$O\
- ldpe.$O\
- lib.$O\
- list.$O\
- noop.$O\
- obj.$O\
- optab.$O\
- pass.$O\
- prof.$O\
- softfloat.$O\
- span.$O\
- symtab.$O\
- go.$O\
-
-HFILES=\
- l.h\
- 5.out.h\
- ../ld/elf.h\
-
-include ../../Make.ccmd
-
-enam.c: 5.out.h
- sh mkenam
-
-CLEANFILES+=enam.c
-
-%.$O: ../ld/%.c
- $(HOST_CC) $(HOST_CFLAGS) -c -I. ../ld/$*.c
+include ../../Make.dist
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 5b7f6f111..b36a982d1 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -73,6 +73,9 @@ enum {
ElfStrShstrtab,
ElfStrRelPlt,
ElfStrPlt,
+ ElfStrNoteNetbsdIdent,
+ ElfStrNoPtrData,
+ ElfStrNoPtrBss,
NElfStr
};
@@ -90,6 +93,7 @@ needlib(char *name)
/* reuse hash code in symbol table */
p = smprint(".dynlib.%s", name);
s = lookup(p, 0);
+ free(p);
if(s->type == 0) {
s->type = 100; // avoid SDATA, etc.
return 1;
@@ -162,8 +166,12 @@ doelf(void)
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrText] = addstring(shstrtab, ".text");
+ elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
+ elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
+ if(HEADTYPE == Hnetbsd)
+ elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
addstring(shstrtab, ".rodata");
addstring(shstrtab, ".gosymtab");
addstring(shstrtab, ".gopclntab");
@@ -232,7 +240,7 @@ doelf(void)
/* define dynamic elf table */
s = lookup(".dynamic", 0);
s->reachable = 1;
- s->type = SELFROSECT;
+ s->type = SELFSECT; // writable
/*
* .dynamic table
@@ -251,6 +259,7 @@ doelf(void)
elfwritedynent(s, DT_PLTREL, DT_REL);
elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
+ elfwritedynent(s, DT_DEBUG, 0);
elfwritedynent(s, DT_NULL, 0);
}
}
@@ -293,7 +302,7 @@ asmb(void)
{
int32 t;
int a, dynsym;
- uint32 fo, symo, startva;
+ uint32 fo, symo, startva, resoff;
ElfEhdr *eh;
ElfPhdr *ph, *pph;
ElfShdr *sh;
@@ -321,11 +330,6 @@ asmb(void)
cseek(segdata.fileoff);
datblk(segdata.vaddr, segdata.filelen);
- /* output read-only data in text segment */
- sect = segtext.sect->next;
- cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
- datblk(sect->vaddr, sect->len);
-
if(iself) {
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
@@ -335,6 +339,8 @@ asmb(void)
if(elfverneed)
elftextsh += 2;
}
+ if(HEADTYPE == Hnetbsd)
+ elftextsh += 1;
}
/* output symbol table */
@@ -370,7 +376,7 @@ asmb(void)
cseek(symo);
if(iself) {
if(debug['v'])
- Bprint(&bso, "%5.2f elfsym\n", cputime());
+ Bprint(&bso, "%5.2f elfsym\n", cputime());
asmelfsym();
cflush();
cwrite(elfstrdat, elfstrsize);
@@ -454,6 +460,7 @@ asmb(void)
eh = getElfEhdr();
fo = HEADR;
startva = INITTEXT - fo; /* va of byte 0 of file */
+ resoff = ELFRESERVE;
/* This null SHdr must appear before all others */
newElfShdr(elfstr[ElfStrEmpty]);
@@ -486,7 +493,7 @@ asmb(void)
sh->addralign = 1;
if(interpreter == nil)
interpreter = linuxdynld;
- elfinterp(sh, startva, interpreter);
+ resoff -= elfinterp(sh, startva, resoff, interpreter);
ph = newElfPhdr();
ph->type = PT_INTERP;
@@ -494,11 +501,24 @@ asmb(void)
phsh(ph, sh);
}
+ if(HEADTYPE == Hnetbsd) {
+ sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
+ sh->type = SHT_NOTE;
+ sh->flags = SHF_ALLOC;
+ sh->addralign = 4;
+ resoff -= elfnetbsdsig(sh, startva, resoff);
+
+ ph = newElfPhdr();
+ ph->type = PT_NOTE;
+ ph->flags = PF_R;
+ phsh(ph, sh);
+ }
+
elfphload(&segtext);
elfphload(&segdata);
/* Dynamic linking sections */
- if (!debug['d']) { /* -d suppresses dynamic loader format */
+ if(!debug['d']) { /* -d suppresses dynamic loader format */
/* S headers for dynamic linking */
sh = newElfShdr(elfstr[ElfStrGot]);
sh->type = SHT_PROGBITS;
@@ -589,7 +609,7 @@ asmb(void)
for(sect=segdata.sect; sect!=nil; sect=sect->next)
elfshbits(sect);
- if (!debug['s']) {
+ if(!debug['s']) {
sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB;
sh->off = symo;
@@ -631,8 +651,10 @@ asmb(void)
a += elfwritehdr();
a += elfwritephdrs();
a += elfwriteshdrs();
- cflush();
- if(a+elfwriteinterp() > ELFRESERVE)
+ a += elfwriteinterp(elfstr[ElfStrInterp]);
+ if(HEADTYPE == Hnetbsd)
+ a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
+ if(a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
}
@@ -1827,14 +1849,20 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
case STYPE:
case SSTRING:
case SGOSTRING:
+ case SNOPTRDATA:
+ case SSYMTAB:
+ case SPCLNTAB:
if(!s->reachable)
continue;
put(s, s->name, 'D', s->value, s->size, s->version, s->gotype);
continue;
case SBSS:
+ case SNOPTRBSS:
if(!s->reachable)
continue;
+ if(s->np > 0)
+ diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
put(s, s->name, 'B', s->value, s->size, s->version, s->gotype);
continue;
diff --git a/src/cmd/5l/doc.go b/src/cmd/5l/doc.go
index aa7ccebfc..969f502a7 100644
--- a/src/cmd/5l/doc.go
+++ b/src/cmd/5l/doc.go
@@ -4,36 +4,10 @@
/*
-5l is a modified version of the Plan 9 linker. The original is documented at
+5l is the linker for the ARM.
+The $GOARCH for these tools is arm.
- http://plan9.bell-labs.com/magic/man2html/1/2l
-
-Its target architecture is the ARM, referred to by these tools as arm.
-It reads files in .5 format generated by 5g, 5c, and 5a and emits
-a binary called 5.out by default.
-
-Major changes include:
- - support for segmented stacks (this feature is implemented here, not in the compilers).
-
-
-Original options are listed in the link above.
-
-Options new in this version:
-
--F
- Force use of software floating point.
- Also implied by setting GOARM=5 in the environment.
--Hlinux
- Write Linux ELF binaries (default when $GOOS is linux)
--I interpreter
- Set the ELF dynamic linker to use.
--L dir1 -L dir2
- Search for libraries (package files) in dir1, dir2, etc.
- The default is the single location $GOROOT/pkg/$GOOS_arm.
--r dir1:dir2:...
- Set the dynamic linker search path when using ELF.
--V
- Print the linker version.
+The flags are documented in ../ld/doc.go.
*/
package documentation
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index dabe93d37..b1a48ded8 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -143,6 +143,7 @@ struct Sym
int32 value;
int32 sig;
int32 size;
+ int32 align; // if non-zero, required alignment in bytes
uchar special;
uchar fnptr; // used as fn ptr
Sym* hash; // in hash table
diff --git a/src/cmd/5l/list.c b/src/cmd/5l/list.c
index fa838215b..7b623d78a 100644
--- a/src/cmd/5l/list.c
+++ b/src/cmd/5l/list.c
@@ -65,7 +65,7 @@ Pconv(Fmt *fp)
switch(a) {
default:
fmtprint(fp, "(%d)", p->line);
- if(p->reg == NREG)
+ if(p->reg == NREG && p->as != AGLOBL)
fmtprint(fp, " %A%C %D,%D",
a, p->scond, &p->from, &p->to);
else
diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c
index eb44344f4..004f9f2fa 100644
--- a/src/cmd/5l/noop.c
+++ b/src/cmd/5l/noop.c
@@ -226,8 +226,7 @@ noops(void)
p->as = AMOVW;
p->scond = C_SCOND_LO;
p->from.type = D_CONST;
- /* 160 comes from 3 calls (3*8) 4 safes (4*8) and 104 guard */
- p->from.offset = autosize+160;
+ p->from.offset = autosize;
p->to.type = D_REG;
p->to.reg = 1;
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index fc5806aac..a3f816160 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -81,7 +81,7 @@ void
main(int argc, char *argv[])
{
int c, i;
- char *p;
+ char *p, *name, *val;
Binit(&bso, 1, OWRITE);
listinit();
@@ -92,6 +92,7 @@ main(int argc, char *argv[])
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
+ nuxiinit();
p = getenv("GOARM");
if(p != nil && strcmp(p, "5") == 0)
@@ -136,6 +137,11 @@ main(int argc, char *argv[])
case 'V':
print("%cl version %s\n", thechar, getgoversion());
errorexit();
+ case 'X':
+ name = EARGF(usage());
+ val = EARGF(usage());
+ addstrdata(name, val);
+ break;
} ARGEND
USED(argc);
@@ -235,7 +241,6 @@ main(int argc, char *argv[])
histgen = 0;
pc = 0;
dtype = 4;
- nuxiinit();
version = 0;
cbp = buf.cbuf;
@@ -535,7 +540,7 @@ loop:
s->type = SBSS;
s->value = 0;
}
- if(s->type != SBSS) {
+ if(s->type != SBSS && s->type != SNOPTRBSS && !s->dupok) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
@@ -544,6 +549,10 @@ loop:
s->size = p->to.offset;
if(p->reg & DUPOK)
s->dupok = 1;
+ if(p->reg & RODATA)
+ s->type = SRODATA;
+ else if(p->reg & NOPTR)
+ s->type = SNOPTRBSS;
break;
case ADATA:
@@ -553,8 +562,8 @@ loop:
// redefinitions.
s = p->from.sym;
if(s->dupok) {
- if(debug['v'])
- Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
+// if(debug['v'])
+// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
goto loop;
}
if(s->file == nil)
@@ -585,6 +594,10 @@ loop:
errorexit();
}
cursym = s;
+ if(s->type != 0 && s->type != SXREF && (p->reg & DUPOK)) {
+ skip = 1;
+ goto casedef;
+ }
if(ntext++ == 0 && s->type != 0 && s->type != SXREF) {
/* redefinition, so file has probably been seen before */
if(debug['v'])
@@ -592,13 +605,8 @@ loop:
return;
}
skip = 0;
- if(s->type != 0 && s->type != SXREF) {
- if(p->reg & DUPOK) {
- skip = 1;
- goto casedef;
- }
+ if(s->type != 0 && s->type != SXREF)
diag("redefinition: %s\n%P", s->name, p);
- }
if(etextp)
etextp->next = s;
else
diff --git a/src/cmd/5l/pass.c b/src/cmd/5l/pass.c
index c43049459..0f2afbd85 100644
--- a/src/cmd/5l/pass.c
+++ b/src/cmd/5l/pass.c
@@ -213,6 +213,8 @@ patch(void)
if((a == ABL || a == ABX || a == AB || a == ARET) &&
p->to.type != D_BRANCH && p->to.sym != S) {
s = p->to.sym;
+ if(s->text == nil)
+ continue;
switch(s->type) {
default:
diag("undefined: %s", s->name);
@@ -222,7 +224,8 @@ patch(void)
case STEXT:
p->to.offset = s->value;
p->to.type = D_BRANCH;
- break;
+ p->cond = s->text;
+ continue;
}
}
if(p->to.type != D_BRANCH)
diff --git a/src/cmd/5l/softfloat.c b/src/cmd/5l/softfloat.c
index 4f799d17e..401107178 100644
--- a/src/cmd/5l/softfloat.c
+++ b/src/cmd/5l/softfloat.c
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define EXTERN
#include "l.h"
#include "../ld/lib.h"
diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c
index 2e1232a1a..13e1848e1 100644
--- a/src/cmd/5l/span.c
+++ b/src/cmd/5l/span.c
@@ -421,6 +421,8 @@ symaddr(Sym *s)
case SDATA:
case SBSS:
case SCONST:
+ case SNOPTRDATA:
+ case SNOPTRBSS:
break;
}
return v;