summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/5l/l.h1
-rw-r--r--src/cmd/6l/l.h1
-rw-r--r--src/cmd/8l/l.h1
-rw-r--r--src/cmd/8l/obj.c4
-rw-r--r--src/cmd/ld/data.c139
-rw-r--r--src/cmd/ld/elf.c2
-rw-r--r--src/cmd/ld/lib.c13
-rw-r--r--src/cmd/ld/lib.h1
8 files changed, 95 insertions, 67 deletions
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index 059e269a9..0b31b07ab 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -38,6 +38,7 @@ enum
thechar = '5',
PtrSize = 4,
IntSize = 4,
+ MaxAlign = 8, // max data alignment
FuncAlign = 4 // single-instruction alignment
};
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 1790f718a..a06dff8c0 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -42,6 +42,7 @@ enum
thechar = '6',
PtrSize = 8,
IntSize = 8,
+ MaxAlign = 32, // max data alignment
// Loop alignment constants:
// want to align loop entry to LoopAlign-byte boundary,
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index 062dc0566..f6de74646 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -42,6 +42,7 @@ enum
thechar = '8',
PtrSize = 4,
IntSize = 4,
+ MaxAlign = 32, // max data alignment
FuncAlign = 16
};
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index f06bc5d9d..8144dfadd 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -130,6 +130,10 @@ main(int argc, char *argv[])
flagparse(&argc, &argv, usage);
+ // TODO: link mode flag instead of isobj
+ if(isobj)
+ linkmode = LinkExternal;
+
if(argc != 1)
usage();
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index b344abd9b..3cdef2877 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -875,36 +875,38 @@ dosymtype(void)
}
static int32
-alignsymsize(int32 s)
+symalign(Sym *s)
{
- if(s >= 8)
- s = rnd(s, 8);
- else if(s >= PtrSize)
- s = rnd(s, PtrSize);
- else if(s > 2)
- s = rnd(s, 4);
- return s;
+ int32 align;
+
+ align = MaxAlign;
+ while(align > s->size && align > 1)
+ align >>= 1;
+ if(align < s->align)
+ align = s->align;
+ return align;
}
-
+
static int32
aligndatsize(int32 datsize, Sym *s)
{
- int32 t;
+ return rnd(datsize, symalign(s));
+}
- if(s->align != 0) {
- datsize = rnd(datsize, s->align);
- } else {
- t = alignsymsize(s->size);
- if(t & 1) {
- ;
- } else if(t & 2)
- datsize = rnd(datsize, 2);
- else if(t & 4)
- datsize = rnd(datsize, 4);
- else
- datsize = rnd(datsize, 8);
+// maxalign returns the maximum required alignment for
+// the list of symbols s; the list stops when s->type exceeds type.
+static int32
+maxalign(Sym *s, int type)
+{
+ int32 align, max;
+
+ max = 0;
+ for(; s != S && s->type <= type; s = s->next) {
+ align = symalign(s);
+ if(max < align)
+ max = align;
}
- return datsize;
+ return max;
}
static void
@@ -938,7 +940,7 @@ gcaddsym(Sym *gc, Sym *s, int32 off)
void
dodata(void)
{
- int32 t, datsize;
+ int32 datsize;
Section *sect;
Sym *s, *last, **l;
Sym *gcdata1, *gcbss1;
@@ -1026,52 +1028,54 @@ dodata(void)
datsize = 0;
for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
sect = addsection(&segdata, s->name, 06);
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ sect->align = symalign(s);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
s->sect = sect;
s->type = SDATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
sect->len = datsize - sect->vaddr;
}
/* pointer-free data */
sect = addsection(&segdata, ".noptrdata", 06);
+ sect->align = maxalign(s, SDATARELRO-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("noptrdata", 0)->sect = sect;
lookup("enoptrdata", 0)->sect = sect;
for(; s != nil && s->type < SDATARELRO; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SDATA;
- t = alignsymsize(s->size);
- datsize = aligndatsize(datsize, s);
s->value = datsize;
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* dynamic relocated rodata */
if(flag_shared) {
sect = addsection(&segdata, ".data.rel.ro", 06);
+ sect->align = maxalign(s, SDATARELRO);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("datarelro", 0)->sect = sect;
lookup("edatarelro", 0)->sect = sect;
for(; s != nil && s->type == SDATARELRO; s = s->next) {
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SDATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
}
/* data */
sect = addsection(&segdata, ".data", 06);
+ sect->align = maxalign(s, SBSS-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("data", 0)->sect = sect;
lookup("edata", 0)->sect = sect;
@@ -1082,39 +1086,39 @@ dodata(void)
}
s->sect = sect;
s->type = SDATA;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
s->value = datsize;
gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
adduintxx(gcdata1, GC_END, PtrSize);
setuintxx(gcdata1, 0, sect->len, PtrSize);
/* bss */
sect = addsection(&segdata, ".bss", 06);
+ sect->align = maxalign(s, SNOPTRBSS-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("bss", 0)->sect = sect;
lookup("ebss", 0)->sect = sect;
for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
s->sect = sect;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
s->value = datsize;
gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
adduintxx(gcbss1, GC_END, PtrSize);
setuintxx(gcbss1, 0, sect->len, PtrSize);
/* pointer-free bss */
sect = addsection(&segdata, ".noptrbss", 06);
+ sect->align = maxalign(s, SNOPTRBSS);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("noptrbss", 0)->sect = sect;
lookup("enoptrbss", 0)->sect = sect;
@@ -1123,11 +1127,10 @@ dodata(void)
cursym = s;
diag("unexpected symbol type %d", s->type);
}
- s->sect = sect;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
+ s->sect = sect;
s->value = datsize;
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
lookup("end", 0)->sect = sect;
@@ -1135,103 +1138,112 @@ dodata(void)
/* we finished segdata, begin segtext */
/* read-only data */
+ s = datap;
sect = addsection(&segtext, ".rodata", 04);
+ sect->align = maxalign(s, STYPELINK-1);
sect->vaddr = 0;
lookup("rodata", 0)->sect = sect;
lookup("erodata", 0)->sect = sect;
datsize = 0;
- s = datap;
for(; s != nil && s->type < STYPELINK; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
s->type = SRODATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* type */
sect = addsection(&segtext, ".typelink", 04);
+ sect->align = maxalign(s, STYPELINK);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("typelink", 0)->sect = sect;
lookup("etypelink", 0)->sect = sect;
for(; s != nil && s->type == STYPELINK; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* gcdata */
sect = addsection(&segtext, ".gcdata", 04);
+ sect->align = maxalign(s, SGCDATA);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("gcdata", 0)->sect = sect;
lookup("egcdata", 0)->sect = sect;
for(; s != nil && s->type == SGCDATA; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* gcbss */
sect = addsection(&segtext, ".gcbss", 04);
+ sect->align = maxalign(s, SGCBSS);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("gcbss", 0)->sect = sect;
lookup("egcbss", 0)->sect = sect;
for(; s != nil && s->type == SGCBSS; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* gosymtab */
sect = addsection(&segtext, ".gosymtab", 04);
+ sect->align = maxalign(s, SPCLNTAB-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("symtab", 0)->sect = sect;
lookup("esymtab", 0)->sect = sect;
for(; s != nil && s->type < SPCLNTAB; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* gopclntab */
sect = addsection(&segtext, ".gopclntab", 04);
+ sect->align = maxalign(s, SELFROSECT-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("pclntab", 0)->sect = sect;
lookup("epclntab", 0)->sect = sect;
for(; s != nil && s->type < SELFROSECT; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* read-only ELF sections */
for(; s != nil && s->type < SELFSECT; s = s->next) {
sect = addsection(&segtext, s->name, 04);
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ sect->align = symalign(s);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
sect->len = datsize - sect->vaddr;
}
}
@@ -1251,6 +1263,7 @@ textaddress(void)
// Could parallelize, by assigning to text
// and then letting threads copy down, but probably not worth it.
sect = segtext.sect;
+ sect->align = FuncAlign;
lookup("text", 0)->sect = sect;
lookup("etext", 0)->sect = sect;
va = INITTEXT;
@@ -1274,11 +1287,6 @@ textaddress(void)
}
va += sym->size;
}
-
- // Align end of code so that rodata starts aligned.
- // 128 bytes is likely overkill but definitely cheap.
- va = rnd(va, 128);
-
sect->len = va - sect->vaddr;
}
@@ -1296,8 +1304,9 @@ address(void)
segtext.vaddr = va;
segtext.fileoff = HEADR;
for(s=segtext.sect; s != nil; s=s->next) {
+ va = rnd(va, s->align);
s->vaddr = va;
- va += rnd(s->len, PtrSize);
+ va += s->len;
}
segtext.len = va - INITTEXT;
segtext.filelen = segtext.len;
@@ -1318,6 +1327,8 @@ address(void)
noptrbss = nil;
datarelro = nil;
for(s=segdata.sect; s != nil; s=s->next) {
+ if(s->next)
+ s->len = s->next->vaddr - s->vaddr;
s->vaddr = va;
va += s->len;
segdata.filelen += s->len;
@@ -1333,7 +1344,7 @@ address(void)
if(strcmp(s->name, ".data.rel.ro") == 0)
datarelro = s;
}
- segdata.filelen -= bss->len + noptrbss->len; // deduct .bss
+ segdata.filelen = bss->vaddr - segdata.vaddr;
text = segtext.sect;
rodata = text->next;
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 630906653..0eb2fa531 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -762,7 +762,7 @@ elfshbits(Section *sect)
sh->flags |= SHF_WRITE;
if(!isobj)
sh->addr = sect->vaddr;
- sh->addralign = PtrSize;
+ sh->addralign = sect->align;
sh->size = sect->len;
sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index db6b7761b..99ff86aab 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -598,7 +598,7 @@ hostlink(void)
Biobuf *f;
static char buf[64<<10];
- if(linkmode != LinkExternal)
+ if(linkmode != LinkExternal || nerrors > 0)
return;
argv = malloc((10+nhostobj+nldflag)*sizeof argv[0]);
@@ -606,6 +606,14 @@ hostlink(void)
// TODO: Add command-line flag to override gcc path and specify additional leading options.
// TODO: Add command-line flag to specify additional trailing options.
argv[argc++] = "gcc";
+ switch(thechar){
+ case '8':
+ argv[argc++] = "-m32";
+ break;
+ case '6':
+ argv[argc++] = "-m64";
+ break;
+ }
if(!debug['s'])
argv[argc++] = "-ggdb";
argv[argc++] = "-o";
@@ -1249,6 +1257,7 @@ addsection(Segment *seg, char *name, int rwx)
sect->rwx = rwx;
sect->name = name;
sect->seg = seg;
+ sect->align = PtrSize; // everything is at least pointer-aligned
*l = sect;
return sect;
}
@@ -1781,7 +1790,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
put(s, s->name, 'T', s->value, s->size, s->version, 0);
for(s=allsym; s!=S; s=s->allsym) {
- if(s->hide || (s->name[0] == '.' && s->version == 0))
+ if(s->hide || (s->name[0] == '.' && s->version == 0 && strcmp(s->name, ".rathole") != 0))
continue;
switch(s->type&SMASK) {
case SCONST:
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 0b7e48c8a..8b6793231 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -104,6 +104,7 @@ struct Segment
struct Section
{
uchar rwx;
+ int32 align;
char *name;
uvlong vaddr;
uvlong len;