linklookup uses hash(name, v) as the hash table index but then
only compares name to find a symbol to return.
If hash(name, v1) == hash(name, v2) for v1 != v2, the lookup
for v2 will return the symbol with v1.
The input routines assume that each symbol is found only once,
and then each symbol is added to a linked list, with the list header
in the symbol. Adding a symbol to such a list multiple times
short-circuits the list the second time it is added, causing symbols
to be dropped.
The liblink rewrite introduced an elegant, if inefficient, handling
of duplicated symbols by creating a dummy symbol to read the
duplicate into. The dummy symbols are named .dup with
sequential version numbers. With many .dup symbols, eventually
there will be a conflict, causing a duplicate list add, causing elided
symbols, causing a crash when calling one of the elided symbols.
The bug is old (2011) but could not have manifested until the
liblink rewrite introduced this heavily duplicated symbol .dup.
(See History section below.)
1. Correct the lookup function.
2. Since we want all the .dup symbols to be different, there's no
point in inserting them into the table. Call linknewsym directly,
avoiding the lookup function entirely.
3. Since nothing can refer to the .dup symbols, do not bother
adding them to the list of functions (textp) at all.
4. In lieu of a unit test, introduce additional consistency checks to
detect adding a symbol to a list multiple times. This would have
caught the short-circuit more directly, and it will detect a variety
of double-use bugs, including the one arising from the bad lookup.
Fixes#7749.
History
On April 9, 2011, I submitted CL 4383047, making ld 25% faster.
Much of the focus was on the hash table lookup function, and
one of the changes was to remove the s->version == v comparison [1].
I don't know if this was a simple editing error or if I reasoned that
same name but different v would yield a different hash slot and
so the name test alone sufficed. It is tempting to claim the former,
but it was probably the latter.
Because the hash is an iterated multiply+add, the version ends up
adding v*3ⁿ to the hash, where n is the length of the name.
A collision would need x*3ⁿ ≡ y*3ⁿ (mod 2²⁴ mod 100003),
or equivalently x*3ⁿ ≡ x*3ⁿ + (y-x)*3ⁿ (mod 2²⁴ mod 100003),
so collisions will actually be periodic: versions x and y collide
when d = y-x satisfies d*3ⁿ ≡ 0 (mod 2²⁴ mod 100003).
Since we allocate version numbers sequentially, this is actually
about the best case one could imagine: the collision rate is
much lower than if the hash were more random.
http://play.golang.org/p/TScD41c_hA computes the collision
period for various name lengths.
The most common symbol in the new linker is .dup, and for n=4
the period is maximized: the 100004th symbol is the first collision.
Unfortunately, there are programs with more duplicated symbols
than that.
In Go 1.2 and before, duplicate symbols were handled without
creating a dummy symbol, so this particular case for generating
many duplicate symbols could not happen. Go does not use
versioned symbols. Only C does; each input file gives a different
version to its static declarations. There just aren't enough C files
for this to come up in that context.
So the bug is old but the realization of the bug is new.
[1] https://golang.org/cl/4383047/diff/5001/src/cmd/ld/lib.c
LGTM=minux.ma, iant, dave
R=golang-codereviews, minux.ma, bradfitz, iant, dave
CC=golang-codereviews, r
https://golang.org/cl/87910047
If we compile a generated file stored in a temporary
directory - let's say /tmp/12345/work/x.c - then by default
6c stores the full path and then the pcln table in the
final binary includes the full path. This makes repeated builds
(using different temporary directories) produce different
binaries, even if the inputs are the same.
In the old 'go tool pack', the P flag specified a prefix to remove
from all stored paths (if present), and cmd/go invoked
'go tool pack grcP $WORK' to remove references to the
temporary work directory.
We've changed the build to avoid pack as much as possible,
under the theory that instead of making pack convert from
.6 to .a, the tools should just write the .a directly and save a
round of I/O.
Instead of going back to invoking pack always, define a common
flag -trimpath in the assemblers, C compilers, and Go compilers,
implemented in liblink, and arrange for cmd/go to use the flag.
Then the object files being written out have the shortened paths
from the start.
While we are here, reimplement pcln support for GOROOT_FINAL.
A build in /tmp/go uses GOROOT=/tmp/go, but if GOROOT_FINAL=/usr/local/go
is set, then a source file named /tmp/go/x.go is recorded instead as
/usr/local/go/x.go. We use this so that we can prepare distributions
to be installed in /usr/local/go without actually working in that
directory. The conversion to liblink deleted all the old file name
handling code, including the GOROOT_FINAL translation.
Bring the GOROOT_FINAL translation back.
Before this CL, using GOROOT_FINAL=/goroot make.bash:
g% strings $(which go) | grep -c $TMPDIR
6
g% strings $(which go) | grep -c $GOROOT
793
g%
After this CL:
g% strings $(which go) | grep -c $TMPDIR
0
g% strings $(which go) | grep -c $GOROOT
0
g%
(The references to $TMPDIR tend to be cgo-generated source files.)
Adding the -trimpath flag to the assemblers required converting
them to the new Go-semantics flag parser. The text in go1.3.html
is copied and adjusted from go1.1.html, which is when we applied
that conversion to the compilers and linkers.
Fixes#6989.
LGTM=iant
R=r, iant
CC=golang-codereviews
https://golang.org/cl/88300045
When I did the original 386 ports on Linux and OS X, I chose to
define GS-relative expressions like 4(GS) as relative to the actual
thread-local storage base, which was usually GS but might not be
(it might be FS, or it might be a different constant offset from GS or FS).
The original scope was limited but since then the rewrites have
gotten out of control. Sometimes GS is rewritten, sometimes FS.
Some ports do other rewrites to enable shared libraries and
other linking. At no point in the code is it clear whether you are
looking at the real GS/FS or some synthesized thing that will be
rewritten. The code manipulating all these is duplicated in many
places.
The first step to fixing issue 7719 is to make the code intelligible
again.
This CL adds an explicit TLS pseudo-register to the 386 and amd64.
As a register, TLS refers to the thread-local storage base, and it
can only be loaded into another register:
MOVQ TLS, AX
An offset from the thread-local storage base is written off(reg)(TLS*1).
Semantically it is off(reg), but the (TLS*1) annotation marks this as
indexing from the loaded TLS base. This emits a relocation so that
if the linker needs to adjust the offset, it can. For example:
MOVQ TLS, AX
MOVQ 8(AX)(TLS*1), CX // load m into CX
On systems that support direct access to the TLS memory, this
pair of instructions can be reduced to a direct TLS memory reference:
MOVQ 8(TLS), CX // load m into CX
The 2-instruction and 1-instruction forms correspond roughly to
ELF TLS initial exec mode and ELF TLS local exec mode, respectively.
Liblink applies this rewrite on systems that support the 1-instruction form.
The decision is made using only the operating system (and probably
the -shared flag, eventually), not the link mode. If some link modes
on a particular operating system require the 2-instruction form,
then all builds for that operating system will use the 2-instruction
form, so that the link mode decision can be delayed to link time.
Obviously it is late to be making changes like this, but I despair
of correcting issue 7719 and issue 7164 without it. To make sure
I am not changing existing behavior, I built a "hello world" program
for every GOOS/GOARCH combination we have and then worked
to make sure that the rewrite generates exactly the same binaries,
byte for byte. There are a handful of TODOs in the code marking
kludges to get the byte-for-byte property, but at least now I can
explain exactly how each binary is handled.
The targets I tested this way are:
darwin-386
darwin-amd64
dragonfly-386
dragonfly-amd64
freebsd-386
freebsd-amd64
freebsd-arm
linux-386
linux-amd64
linux-arm
nacl-386
nacl-amd64p32
netbsd-386
netbsd-amd64
openbsd-386
openbsd-amd64
plan9-386
plan9-amd64
solaris-amd64
windows-386
windows-amd64
There were four exceptions to the byte-for-byte goal:
windows-386 and windows-amd64 have a time stamp
at bytes 137 and 138 of the header.
darwin-386 and plan9-386 have five or six modified
bytes in the middle of the Go symbol table, caused by
editing comments in runtime/sys_{darwin,plan9}_386.s.
Fixes#7164.
LGTM=iant
R=iant, aram, minux.ma, dave
CC=golang-codereviews
https://golang.org/cl/87920043
The relocation and automatic variable types were using
arch-specific numbers. Introduce portable enumerations
instead.
To the best of my knowledge, these are the only arch-specific
bits left in the new object file format.
Remove now, before Go 1.3, because file formats are forever.
LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/87670044
We have never released cmd/prof and don't plan to.
Now that nm, addr2line, and objdump have been rewritten in Go,
cmd/prof is the only thing keeping us from deleting libmach.
Delete cmd/prof, and then since nothing is using libmach, delete libmach.
13,000 lines of C deleted.
LGTM=minux.ma
R=golang-codereviews, minux.ma
CC=golang-codereviews, iant, r
https://golang.org/cl/87020044
Superficial inconsistencies that trigger warnings in
Plan 9. Small enough to be considered trivial and
seemingly benign outside of the Plan 9 environment.
LGTM=iant
R=golang-codereviews, 0intro, iant
CC=golang-codereviews
https://golang.org/cl/73460043
For non-closure functions, the context register is uninitialized
on entry and will not be used, but morestack saves it and then the
garbage collector treats it as live. This can be a source of memory
leaks if the context register points at otherwise dead memory.
Avoid this by introducing a parallel set of morestack functions
that clear the context register, and use those for the non-closure functions.
I hope this will help with some of the finalizer flakiness, but it probably won't.
Fixes#7244.
LGTM=dvyukov
R=khr, dvyukov
CC=golang-codereviews
https://golang.org/cl/71030044
This CL replays the following one CL from the rsc-go13nacl repo.
This is the last replay CL: after this CL the main repo will have
everything the rsc-go13nacl repo did. Changes made to the main
repo after the rsc-go13nacl repo branched off probably mean that
NaCl doesn't actually work after this CL, but all the code is now moved
over and just needs to be redebugged.
---
cmd/6l, cmd/8l, cmd/ld: support for Native Client
See golang.org/s/go13nacl for design overview.
This CL is publicly visible but not CC'ed to golang-dev,
to avoid distracting from the preparation of the Go 1.2
release.
This CL and the others will be checked into my rsc-go13nacl
clone repo for now, and I will send CLs against the main
repo early in the Go 1.3 development.
R≡khr
https://golang.org/cl/15750044
---
LGTM=bradfitz, dave, iant
R=dave, bradfitz, iant
CC=golang-codereviews
https://golang.org/cl/69040044
The VARDEF placement must be before the initialization
but after any final use. If you have something like s = ... using s ...
the rhs must be evaluated, then the VARDEF, then the lhs
assigned.
There is a large comment in pgen.c on gvardef explaining
this in more detail.
This CL also includes Ian's suggestions from earlier CLs,
namely commenting the use of mode in link.h and fixing
the precedence of the ~r check in dcl.c.
This CL enables the check that if liveness analysis decides
a variable is live on entry to the function, that variable must
be a function parameter (not a result, and not a local variable).
If this check fails, it indicates a bug in the liveness analysis or
in the generated code being analyzed.
The race detector generates invalid code for append(x, y...).
The code declares a temporary t and then uses cap(t) before
initializing t. The new liveness check catches this bug and
stops the compiler from writing out the buggy code.
Consequently, this CL disables the race detector tests in
run.bash until the race detector bug can be fixed
(golang.org/issue/7334).
Except for the race detector bug, the liveness analysis check
does not detect any problems (this CL and the previous CLs
fixed all the detected problems).
The net test still fails with GOGC=0 but the rest of the tests
now pass or time out (because GOGC=0 is so slow).
TBR=iant
CC=golang-codereviews
https://golang.org/cl/64170043
We now use the %A, %D, %P, and %R routines from liblink
across the board.
Fixes#7178.
Fixes#7055.
LGTM=iant
R=golang-codereviews, gobot, rsc, dave, iant, remyoudompheng
CC=golang-codereviews
https://golang.org/cl/49170043
rsc suggested that we split the whole linker changes into three parts.
This is the first one, mostly dealing with adding Hsolaris.
LGTM=iant
R=golang-codereviews, iant, dave
CC=golang-codereviews
https://golang.org/cl/54210050
Many calls to symgrow pass a vlong value. Change the function
to not implicitly truncate, and to instead give an error if
the value is too large.
R=golang-codereviews, gobot, rsc
CC=golang-codereviews
https://golang.org/cl/54010043
Everything was doing this already with #defines.
Do it right.
R=golang-codereviews, jsing, 0intro, iant
CC=golang-codereviews
https://golang.org/cl/49090043
The CL 49090043 renamed Ureg structures to Ureg386,
UregArm and UregAmd64. This broke build on Plan 9,
since ureg_x86.h includes /386/include/ureg.h, which
declares a structure named Ureg instead of Ureg386.
R=golang-codereviews, bradfitz
CC=golang-codereviews, rsc
https://golang.org/cl/49260043
- new object file reader/writer (liblink/objfile.c)
- remove old object file writing routines
- add pcdata iterator
- remove all trace of "line number stack" and "path fragments" from
object files, linker (!!!)
- dwarf now writes a single "compilation unit" instead of one per package
This CL disables the check for chains of no-split functions that
could overflow the stack red zone. A future CL will attack the problem
of reenabling that check (issue 6931).
This CL is just the liblink and cmd/ld changes.
There are minor associated adjustments in CL 37030045.
Each depends on the other.
R=golang-dev, dave, iant
CC=golang-dev
https://golang.org/cl/39680043
There is an enormous amount of code moving around in this CL,
but the code is the same, and it is invoked in the same ways.
This CL is preparation for the new linker structure, not the new
structure itself.
The new library's definition is in include/link.h.
The main change is the use of a Link structure to hold all the
linker-relevant state, replacing the smattering of global variables.
The Link structure should both make it clearer which state must
be carried around and make it possible to parallelize more easily
later.
The main body of the linker has moved into the architecture-independent
cmd/ld directory. That includes the list of known header types, so the
distinction between Hplan9x32 and Hplan9x64 is removed (no other
header type distinguished 32- and 64-bit formats), and code for unused
formats such as ipaq kernels has been deleted.
The code being deleted from 5l, 6l, and 8l reappears in liblink or in ld.
Because multiple files are being merged in the liblink directory,
it is not possible to show the diffs nicely in hg.
The Prog and Addr structures have been unified into an
architecture-independent form and moved to link.h, where they will
be shared by all tools: the assemblers, the compilers, and the linkers.
The unification makes it possible to write architecture-independent
traversal of Prog lists, among other benefits.
The Sym structures cannot be unified: they are too fundamentally
different between the linker and the compilers. Instead, liblink defines
an LSym - a linker Sym - to be used in the Prog and Addr structures,
and the linker now refers exclusively to LSyms. The compilers will
keep using their own syms but will fill out the corresponding LSyms in
the Prog and Addr structures.
Although code from 5l, 6l, and 8l is now in a single library, the
code has been arranged so that only one architecture needs to
be linked into a particular program: 5l will not contain the code
needed for x86 instruction layout, for example.
The object file writing code in liblink/obj.c is from cmd/gc/obj.c.
Preparation for golang.org/s/go13linker work.
This CL does not build by itself. It depends on 35740044
and will be submitted at the same time.
R=iant
CC=golang-dev
https://golang.org/cl/35790044
If you thought gcc -ansi -pedantic was pedantic, just wait
until you meet clang -fsanitize=undefined.
I think this addresses all the reported "errors", but we'll
need another run to be sure.
all.bash still passes.
Update #5764
Dave, can you please try again?
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/13334049
Also introduce BGET2/4, BPUT2/4 as they are widely used.
Slightly improve BGETC/BPUTC implementation.
This gives ~5% CPU time improvement on go install -a -p1 std.
Before:
real user sys
0m23.561s 0m16.625s 0m5.848s
0m23.766s 0m16.624s 0m5.846s
0m23.742s 0m16.621s 0m5.868s
after:
0m22.999s 0m15.841s 0m5.889s
0m22.845s 0m15.808s 0m5.850s
0m22.889s 0m15.832s 0m5.848s
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/12745047
Revision 01810e5c68e9 added the following to src/pkg/runtime/stack.h:
StackPreempt = (uintptr)(intptr)0xffffade,
The typedef for intptr is defined in two places:
1. src/pkg/runtime/runtime.h for use by the runtime
2. include/u.h for use by the compilers and linkers
On Plan 9, we don't use include/u.h but instead augment the host's
u.h with extra typedefs. These are in include/plan9/GOARCH/u.h.
We forgot to add intptr. It didn't cause a problem until now since
that typedef was never used outside the runtime.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/10023043
Add missing getgoextlinkenabled(void) declaration
in Plan 9 libc.h. This function was added as part
of CL #8183043.
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/8191043
Change build system to set GO_EXTLINK_ENABLED=0 by default for
OS X 10.6, since the system linker has a bug and can not
handle the object files generated by 6l.
Fixes#5130.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/8183043
This works with at least one version of clang
that existed at one moment in time.
No guarantees about clangs past or future.
To try:
CC=clang all.bash
It does not work with the Xcode clang,
because that clang fails at printing a useful answer
to:
clang -print-libgcc-file-name
The clang that works prints a full path name for
that command, not just "libgcc.a".
Fixes#4713.
R=iant, minux.ma
CC=golang-dev
https://golang.org/cl/7323068
Runemax is already defined in libc on 64-bit version of
Plan 9, but is not defined on other versions.
To accommodate, we make sure to rename any previous
instance of Runemax and re-define it subsequently.
R=rsc, ality, rminnich
CC=golang-dev
https://golang.org/cl/7232059
This CL adds a flag parser that matches the semantics of Go's
package flag. It also changes the linkers and compilers to use
the new flag parser.
Command lines that used to work, like
8c -FVw
6c -Dfoo
5g -I/foo/bar
now need to be split into separate arguments:
8c -F -V -w
6c -D foo
5g -I /foo/bar
The new spacing will work with both old and new tools.
The new parser also allows = for arguments, as in
6c -D=foo
5g -I=/foo/bar
but that syntax will not work with the old tools.
In addition to matching standard Go binary flag parsing,
the new flag parser generates more detailed usage messages
and opens the door to long flag names.
The recently added gc flag -= has been renamed -complete.
R=remyoudompheng, daniel.morsing, minux.ma, iant
CC=golang-dev
https://golang.org/cl/7035043
A new environment variable GO386 is introduced to choose between
code generation targeting 387 or SSE2. No auto-detection is
performed and the setting defaults to 387 to preserve previous
behaviour.
The patch is a reorganization of CL6549052 by rsc.
Fixes#3912.
R=minux.ma, rsc
CC=golang-dev
https://golang.org/cl/6962043
This set of changes extends the Plan 9 support
to include the AMD64 architecture and should
work on all versions of Plan 9.
R=golang-dev, rminnich, noah.evans, rsc, minux.ma, npe
CC=akskuma, golang-dev, jfflore, noah.evans
https://golang.org/cl/6479052
Previously, I had made available a tarball of
the modified system headers that were necessary
to build on Plan 9 but that was only a stopgap.
I think this method is much better since no
files outside of $GOROOT will have to be added
or modified during the build process.
Also, this is just the first step. I'll change
the build to reference these files in another CL
(that also contains a few more Makefile changes).
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5552056
This CL grew the archive file name length from 16 to 64:
changeset: 909:58574851d792
user: Russ Cox <rsc@golang.org>
date: Mon Oct 20 13:53:56 2008 -0700
Back then, every x.go file in a package became an x.6 file
in the archive. It was important to be able to allow the
use of long Go source file names, hence the increase in size.
Today, all Go source files compile into a single _go_.6 file
regardless of their names, so the archive file name length
no longer needs to be long. The longer name causes some
problems on Plan 9, where the native archive format is the
same but with 16-byte names, so revert back to 16.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5333050
. By defining getcallerpc(x) as __builtin_return_address(0)
here, it becomes possible to use the Plan 9 compatible form
when compiling using GCC. The alternative is to add conditional
compilation based on the compiler identity in "cmd/8g/gsubr.c"
to distinguish between the two cases.
R=golang-dev
CC=golang-dev, rsc
https://golang.org/cl/4800048
The "elf.h" header changes involve only comments, the released
Plan 9 C preprocessing function does not cope with multiline
comments following the #define keyword. All multiline comments
have been moved to the line above the associated definition.
Sigh! Fixing the Plan 9 compiler is not an option.
<time.h> does not exist in the Plan 9 Native library. I have
moved it from src/cmd/ld/pe.h to include/u.h. RSC correctly points
out that this copy of <u.h> is not the one used to compile the
Go release on Plan 9 platforms.
R=golang-dev
CC=golang-dev, rsc
https://golang.org/cl/4574042
* heuristic to go farther during stack traces.
* significantly improved Linux thread handing.
acid:
* update to new libmach interface.
prof:
* use new libmach interface.
* multiple thread support (derived from Rob's copy).
* first steps toward pprof-like graphs:
keep counters indexed by pc,callerpc pairs.
R=r
DELTA=909 (576 added, 123 deleted, 210 changed)
OCL=24240
CL=24259
* add gotype string to symbol table
* fill in gotype in 6l for known funcs/vars
* print gotype with nm -t
* load symbol and pc/ln tables into memory at magic address 0x99<<32.
* add sys.symdat() to retrieve raw bytes of symbol table
and pc/ln table.
most of this should be considered experimental
and subject to change.
R=r
DELTA=157 (128 added, 0 deleted, 29 changed)
OCL=19746
CL=19750
use libbio instead of maintaining own buffer
libbio:
always use vlong offsets; die if off_t is too small
R=r
DELTA=163 (23 added, 63 deleted, 77 changed)
OCL=17508
CL=17512
make sure methods end up immediately following
the struct they are methods on.
ar:
eliminate duplicate definitions from __.PKGDEF.
check that multiple .6 do not give different defs for same
exported type/var/func/const.
increase ar header name size from 16 to 64 bytes
R=r
DELTA=379 (333 added, 18 deleted, 28 changed)
OCL=17477
CL=17481
these guys really really want long to be 32-bits,
so ,s/long/int32/ (and then manual fixup).
still passes all tests.
(i started out looking for just those longs that
needed to be int32 instead, and it was just too hard
to track them down one by one.)
the longs were rare enough that i don't think
it will cause integration problems.
R=ken
OCL=13787
CL=13789