code review 6643050: cmd/5l: generate FreeBSD compatible ELF (issue 6643050)

24 views
Skip to first unread message

minu...@gmail.com

unread,
Oct 9, 2012, 12:02:58 PM10/9/12
to r...@golang.org, golan...@googlegroups.com, re...@codereview-hr.appspotmail.com
Reviewers: rsc,

Message:
Hello r...@golang.org (cc: golan...@googlegroups.com),

I'd like you to review this change to
https://code.google.com/p/go/


Description:
cmd/5l: generate FreeBSD compatible ELF
1. correctly initialize .plt.got entries (point to the 1st entry)
2. add section .rel.plt (FreeBSD insists PLT relocs to be there)
3. put relocs of .got.plt to .rel.plt
4. set ELFOSABI_FREEBSD in ELF header

Please review this at http://codereview.appspot.com/6643050/

Affected files:
M src/cmd/5l/asm.c
M src/cmd/5l/obj.c


Index: src/cmd/5l/asm.c
===================================================================
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -38,6 +38,7 @@
static Prog *PP;

char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
+char freebsddynld[] = "/usr/libexec/ld-elf.so.1";

int32
entryvalue(void)
@@ -344,13 +345,16 @@
if(iself) {
plt = lookup(".plt", 0);
got = lookup(".got.plt", 0);
- rel = lookup(".rel", 0);
+ rel = lookup(".rel.plt", 0);
if(plt->size == 0)
elfsetupplt();

// .got entry
s->got = got->size;
- adduint32(got, 0);
+ // In theory, all GOT should point to the first PLT entry,
+ // Linux/ARM's dynamic linker will do that for us, but FreeBSD/ARM's
+ // dynamic linker won't, so we'd better do it ourselves.
+ addaddrplus(got, plt, 0);

// .plt entry, this depends on the .got entry
s->plt = plt->size;
@@ -696,7 +700,7 @@
/* !debug['d'] causes extra sections before the .text section */
elftextsh = 2;
if(!debug['d']) {
- elftextsh += 9;
+ elftextsh += 10;
if(elfverneed)
elftextsh += 2;
}
@@ -755,6 +759,9 @@
Bflush(&bso);
cseek(0L);
switch(HEADTYPE) {
+ default:
+ if(iself)
+ goto Elfput;
case Hnoheader: /* no header */
break;
case Hrisc: /* aif for risc os */
@@ -815,7 +822,7 @@
lputl(0xe3300000); /* nop */
lputl(0xe3300000); /* nop */
break;
- case Hlinux:
+ Elfput:
/* elf arm */
eh = getElfEhdr();
fo = HEADR;
@@ -851,8 +858,16 @@
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC;
sh->addralign = 1;
- if(interpreter == nil)
- interpreter = linuxdynld;
+ if(interpreter == nil) {
+ switch(HEADTYPE) {
+ case Hlinux:
+ interpreter = linuxdynld;
+ break;
+ case Hfreebsd:
+ interpreter = freebsddynld;
+ break;
+ }
+ }
resoff -= elfinterp(sh, startva, resoff, interpreter);

ph = newElfPhdr();
@@ -886,6 +901,31 @@
/* Dynamic linking sections */
if(!debug['d']) { /* -d suppresses dynamic loader format */
/* S headers for dynamic linking */
+ dynsym = eh->shnum;
+ sh = newElfShdr(elfstr[ElfStrDynsym]);
+ sh->type = SHT_DYNSYM;
+ sh->flags = SHF_ALLOC;
+ sh->entsize = ELF32SYMSIZE;
+ sh->addralign = 4;
+ sh->link = dynsym+1; // dynstr
+ // sh->info = index of first non-local symbol (number of local symbols)
+ shsym(sh, lookup(".dynsym", 0));
+
+ sh = newElfShdr(elfstr[ElfStrDynstr]);
+ sh->type = SHT_STRTAB;
+ sh->flags = SHF_ALLOC;
+ sh->addralign = 1;
+ shsym(sh, lookup(".dynstr", 0));
+
+ sh = newElfShdr(elfstr[ElfStrRelPlt]);
+ sh->type = SHT_REL;
+ sh->flags = SHF_ALLOC;
+ sh->entsize = ELF32RELSIZE;
+ sh->addralign = 4;
+ sh->link = dynsym;
+ sh->info = eh->shnum; // .plt
+ shsym(sh, lookup(".rel.plt", 0));
+
// ARM ELF needs .plt to be placed before .got
sh = newElfShdr(elfstr[ElfStrPlt]);
sh->type = SHT_PROGBITS;
@@ -908,22 +948,6 @@
sh->addralign = 4;
shsym(sh, lookup(".got", 0));

- dynsym = eh->shnum;
- sh = newElfShdr(elfstr[ElfStrDynsym]);
- sh->type = SHT_DYNSYM;
- sh->flags = SHF_ALLOC;
- sh->entsize = ELF32SYMSIZE;
- sh->addralign = 4;
- sh->link = dynsym+1; // dynstr
- // sh->info = index of first non-local symbol (number of local symbols)
- shsym(sh, lookup(".dynsym", 0));
-
- sh = newElfShdr(elfstr[ElfStrDynstr]);
- sh->type = SHT_STRTAB;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- shsym(sh, lookup(".dynstr", 0));
-
if(elfverneed) {
sh = newElfShdr(elfstr[ElfStrGnuVersion]);
sh->type = SHT_GNU_VERSYM;
@@ -1029,6 +1053,11 @@
eh->ident[EI_CLASS] = ELFCLASS32;
eh->ident[EI_DATA] = ELFDATA2LSB;
eh->ident[EI_VERSION] = EV_CURRENT;
+ switch(HEADTYPE) {
+ case Hfreebsd:
+ eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
+ break;
+ }

eh->type = ET_EXEC;
eh->machine = EM_ARM;
Index: src/cmd/5l/obj.c
===================================================================
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -52,6 +52,7 @@
"ixp1200", Hixp1200,
"ipaq", Hipaq,
"linux", Hlinux,
+ "freebsd", Hfreebsd,
0, 0
};

@@ -152,7 +153,7 @@
libinit();

if(HEADTYPE == -1)
- HEADTYPE = Hlinux;
+ HEADTYPE = headtype(goos);
switch(HEADTYPE) {
default:
diag("unknown -H option");
@@ -212,6 +213,7 @@
INITRND = 1024;
break;
case Hlinux: /* arm elf */
+ case Hfreebsd:
debug['d'] = 0; // with dynamic linking
tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then
4-byte word for m
// this number is known
to ../../pkg/runtime/cgo/gcc_linux_arm.c


minux

unread,
Oct 9, 2012, 12:17:33 PM10/9/12
to r...@golang.org, golan...@googlegroups.com, re...@codereview-hr.appspotmail.com
I guess I always choose a bad time to propose CLs. ;-)

I know we are approaching feature freeze (or already frozen?)
for Go 1.1, but i really don't want to maintain another fork for
FreeBSD/ARM.

AFAIK, the only remaining thing is missing ARMv5 support,
but that won't affect many, as FreeBSD-supported ARMv5
boards are mostly not capable of building Go (my test setup
has 512MiB memory so as to pass all.bash).
Adding missing sync/atomic and runtime pieces to support
ARMv5 won't be tough though.

The only problem I anticipate now is that we need a capable
FreeBSD/ARM builder (ARMv6+, preferably ARMv7, with at
least 512MiB of memory, with ~1GiB memory the builder could
run the build in tmpfs)

Russ Cox

unread,
Oct 9, 2012, 12:41:05 PM10/9/12
to minux, golan...@googlegroups.com, re...@codereview-hr.appspotmail.com
LGTM

minu...@gmail.com

unread,
Oct 9, 2012, 1:03:03 PM10/9/12
to minu...@gmail.com, r...@golang.org, golan...@googlegroups.com, re...@codereview-hr.appspotmail.com
*** Submitted as
http://code.google.com/p/go/source/detail?r=c58647359c01 ***

cmd/5l: generate FreeBSD compatible ELF
1. correctly initialize .plt.got entries (point to the 1st entry)
2. add section .rel.plt (FreeBSD insists PLT relocs to be there)
3. put relocs of .got.plt into .rel.plt
4. set ELFOSABI_FREEBSD in ELF header

R=rsc
CC=golang-dev
http://codereview.appspot.com/6643050


http://codereview.appspot.com/6643050/
Reply all
Reply to author
Forward
0 new messages