Repository: go
Issue: cmd/link: possible linker bug when using the -T flag to set the text address
Labels: help wanted,NeedsInvestigation,compiler/runtime

Please answer these questions before submitting your issue. Thanks!


### What version of Go are you using (`go version`)?
1.11.1 darwin/amd64

### Does this issue reproduce with the latest release?
Yes.

### What operating system and processor architecture are you using (`go env`)?

```$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="on"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/iansmith/qemu/xxx"
GOPROXY=""
GORACE=""
GOROOT="/Users/iansmith/qemu/go-1.11/go"
GOTMPDIR=""
GOTOOLDIR="/Users/iansmith/qemu/go-1.11/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="0"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/w0/fw3qzvvx54b39b790yxq6v100000gn/T/go-build145968613=/tmp/go-build -gno-record-gcc-switches -fno-common"
```

### What did you do?
`aarch64-elf-readelf -W -l -S  bin/xxx_xxx/surprise`

If possible, provide a recipe for reproducing the error.

I have found this error to be caused by any link that supplies an start address *other* than one ending in 0x1000.  I was doing some experiments on arm (thus the aarch64 above) but I think this is actually in the offset calculations for the elf headers (section and program).

Commands like this seem to cause the problem (using the -T flag with something that doesn't end in 1000):

`GOOS=xxx GOARCH=xxx go install -v -ldflags='-T 0x88000'  github.com/iansmith/xxx/surprise/cmd/surprise`

A complete runnable program is good.
A link on play.golang.org is best.

https://play.golang.org/p/b32fVLNTGxP

That link shows the diff to my "fix".  My fix is clearly not the real one, but whoever wrote the code in elf.go (`go/src/cmd/link/internal/ld/elf.go`) will probably see the problem immediately when they see what I have done.

### What did you expect to see?
I expected to see normal elf section headers and program headers.  After my (ahem) "fix", you get the normal output:

```
$ aarch64-elf-readelf -W -l -S  bin/xxx_xxx/surprise
There are 24 section headers, starting at offset 0x158:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        0000000000088000 001000 03f8c0 00  AX  0   0  8
  [ 2] .rodata           PROGBITS        00000000000d0000 050000 024e79 00   A  0   0 32
  [ 3] .shstrtab         STRTAB          0000000000000000 074e80 000193 00      0   0  1
  [ 4] .typelink         PROGBITS        00000000000f5020 075020 000624 00   A  0   0 32
  [ 5] .itablink         PROGBITS        00000000000f5648 075648 000008 00   A  0   0  8
  [ 6] .gosymtab         PROGBITS        00000000000f5650 075650 000000 00   A  0   0  1
  [ 7] .gopclntab        PROGBITS        00000000000f5660 075660 0337c3 00   A  0   0 32
  [ 8] .noptrdata        PROGBITS        0000000000130000 0b0000 000ba8 00  WA  0   0 32
  [ 9] .data             PROGBITS        0000000000130bc0 0b0bc0 0015b0 00  WA  0   0 32
  [10] .bss              NOBITS          0000000000132180 0b2180 01a330 00  WA  0   0 32
  [11] .noptrbss         NOBITS          000000000014c4c0 0cc4c0 002258 00  WA  0   0 32
  [12] .zdebug_abbrev    PROGBITS        0000000000150000 0c0000 000112 00      0   0  8
  [13] .zdebug_line      PROGBITS        0000000000150112 0c0112 008fb1 00      0   0  8
  [14] .zdebug_frame     PROGBITS        00000000001590c3 0c90c3 0031ac 00      0   0  8
  [15] .zdebug_pubnames  PROGBITS        000000000015c26f 0cc26f 000973 00      0   0  8
  [16] .zdebug_pubtypes  PROGBITS        000000000015cbe2 0ccbe2 001cf1 00      0   0  8
  [17] .debug_gdb_scripts PROGBITS        000000000015e8d3 0ce8d3 00003c 00      0   0  1
  [18] .zdebug_info      PROGBITS        000000000015e90f 0ce90f 015a44 00      0   0  8
  [19] .zdebug_loc       PROGBITS        0000000000174353 0e4353 009793 00      0   0  8
  [20] .zdebug_ranges    PROGBITS        000000000017dae6 0edae6 00309b 00      0   0  8
  [21] .note.go.buildid  NOTE            0000000000087f9c 000f9c 000064 00   A  0   0  4
  [22] .symtab           SYMTAB          0000000000000000 100000 006630 18     23  91  8
  [23] .strtab           STRTAB          0000000000000000 106630 006bf7 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0xc4520
There are 5 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000087040 0x0000000000087040 0x000118 0x000118 R   0x10000
  NOTE           0x000f9c 0x0000000000087f9c 0x0000000000087f9c 0x000064 0x000064 R   0x4
  LOAD           0x000000 0x0000000000087000 0x0000000000087000 0x0408c0 0x0408c0 R E 0x10000
  LOAD           0x057000 0x00000000000d7000 0x00000000000d7000 0x051e23 0x051e23 R   0x10000
  LOAD           0x0b7000 0x0000000000137000 0x0000000000137000 0xffffffffffffb180 0x017718 RW  0x10000
readelf: Error: the segment's file size is larger than its memory size

 Section to Segment mapping:
  Segment Sections...
   00
   01     .note.go.buildid
   02     .text .note.go.buildid
   03     .typelink .itablink .gosymtab .gopclntab
   04     .noptrbss
```


### What did you see instead?
Note the negative value in the 3rd program header (the program text segment)!  .shstrtab (section header string table) section has been overwritten so the names are garbage.

```
$ aarch64-elf-readelf -W -l -S  bin/xxx_xxx/surprise
There are 24 section headers, starting at offset 0x158:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0] ^B                NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1]                   PROGBITS        0000000000088000 001000 03f8c0 00  AX  0   0  8
  [ 2]                   PROGBITS        00000000000d0000 050000 024e79 00   A  0   0 32
  [ 3]                   STRTAB          0000000000000000 06de80 000193 00      0   0  1
  [ 4]                   PROGBITS        00000000000f5020 075020 000624 00   A  0   0 32
  [ 5]                   PROGBITS        00000000000f5648 075648 000008 00   A  0   0  8
  [ 6] ^V                PROGBITS        00000000000f5650 075650 000000 00   A  0   0  1
  [ 7]                   PROGBITS        00000000000f5660 075660 0337c3 00   A  0   0 32
  [ 8]                   PROGBITS        0000000000130000 0b0000 000ba8 00  WA  0   0 32
  [ 9]                   PROGBITS        0000000000130bc0 0b0bc0 0015b0 00  WA  0   0 32
  [10] ^B                NOBITS          0000000000132180 0b2180 01a330 00  WA  0   0 32
  [11]                   NOBITS          000000000014c4c0 0cc4c0 002258 00  WA  0   0 32
  [12] ^B                PROGBITS        0000000000150000 0c0000 000112 00      0   0  8
  [13]                   PROGBITS        0000000000150112 0c0112 008fb1 00      0   0  8
  [14] ^D                PROGBITS        00000000001590c3 0c90c3 0031ac 00      0   0  8
  [15]                   PROGBITS        000000000015c26f 0cc26f 000973 00      0   0  8
  [16] ^E^A              PROGBITS        000000000015cbe2 0ccbe2 001cf1 00      0   0  8
  [17]                   PROGBITS        000000000015e8d3 0ce8d3 00003c 00      0   0  1
  [18]                   PROGBITS        000000000015e90f 0ce90f 015a44 00      0   0  8
  [19]                   PROGBITS        0000000000174353 0e4353 009793 00      0   0  8
  [20]                   PROGBITS        000000000017dae6 0edae6 00309b 00      0   0  8
  [21]                   NOTE            0000000000087f9c 000f9c 000064 00   A  0   0  4
  [22]                   SYMTAB          0000000000000000 100000 006630 18     23  91  8
  [23]                   STRTAB          0000000000000000 106630 006bf7 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0xc4520
There are 5 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000087040 0x0000000000087040 0x000118 0x000118 R   0x10000
  NOTE           0x000f9c 0x0000000000087f9c 0x0000000000087f9c 0x000064 0x000064 R   0x4
  LOAD           0xffffffffffff9000 0x0000000000080000 0x0000000000080000 0x0478c0 0x0478c0 R E 0x10000
  LOAD           0x050000 0x00000000000d0000 0x00000000000d0000 0x058e23 0x058e23 R   0x10000
  LOAD           0x0b0000 0x0000000000130000 0x0000000000130000 0x002180 0x01e718 RW  0x10000

 Section to Segment mapping:
  Segment Sections...
   00
   01
   02
   03        ^V
   04       ^B

```