cmd/interal/ld: darwin c-archive buildmode support

Uses ar to create an archive when -buildmode=c-archive.

A small example (that I hope to turn into a test in a later CL):

goarchive.go:
	package main

	import "fmt"

	import "C"

	func init() {
		fmt.Println("ran go init")
	}

	//export FuncInGo
	func FuncInGo() {
		fmt.Println("called a go function")
	}

	func main() {
		fmt.Println("in main")
	}

This can be compiled with:

	go build -ldflags=-buildmode=c-archive -o=libgo.a goarchive.go

main.c:

	#include <stdio.h>

	extern void FuncInGo();

	int main(void) {
		printf("c hello\n");
		FuncInGo();
		printf("c goodbye\n");
		return 0;
	}

Can be compiled with:

	cc main.c libgo.a

Apple provide a warning about the lack of PIE, but still produce a
binary which runs and outputs (on darwin/amd64):

	c hello
	ran go init
	called a go function
	c goodbye

Change-Id: I7611925f210a83afa6bd1e66a5601dd636a428c8
Reviewed-on: https://go-review.googlesource.com/8711
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
David Crawshaw 2015-04-09 10:44:05 -04:00
parent 6e3a6c4d38
commit ced7ffe95b
5 changed files with 110 additions and 53 deletions

View file

@ -967,8 +967,11 @@ func dosymtype() {
}
// Create a new entry in the .init_array section that points to the
// library initializer function.
if Buildmode == BuildmodeCShared && s.Name == INITENTRY {
addinitarrdata(s)
switch Buildmode {
case BuildmodeCArchive, BuildmodeCShared:
if s.Name == INITENTRY {
addinitarrdata(s)
}
}
}
}
@ -1329,7 +1332,9 @@ func dodata() {
sect.Length = uint64(datsize) - sect.Vaddr
/* shared library initializer */
if Buildmode == BuildmodeCShared || DynlinkingGo() {
switch Buildmode {
case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared:
// TODO(mwhudson): switch on Linkshared
sect := addsection(&Segdata, ".init_array", 06)
sect.Align = maxalign(s, SINITARR)
datsize = Rnd(datsize, int64(sect.Align))