Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/link: possible linker bug when using the -T flag to set the text address #28257

Open
iansmith opened this issue Oct 17, 2018 · 3 comments
Open
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@iansmith
Copy link

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)?

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

@josharian
Copy link
Contributor

I think @navytux might also have encountered this.

@navytux
Copy link
Contributor

navytux commented Oct 18, 2018

I only saw crashes with -T xxx but then I suspected that the crashes were due to xxx being not page aligned in my case:

#18977 (comment)

And concluded that something in Go runtime may be assuming text/data has to be page-aligned. But I had not checked.

@bradfitz bradfitz changed the title possible linker bug when using the -T flag to set the text address cmd/link: possible linker bug when using the -T flag to set the text address Oct 18, 2018
@bradfitz bradfitz added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Oct 18, 2018
@FiloSottile FiloSottile added this to the Go1.12 milestone Oct 19, 2018
@ianlancetaylor ianlancetaylor modified the milestones: Go1.12, Unplanned Dec 7, 2018
@andrejro
Copy link

This issues arises when the address passed via -T flag is not aligned with the address rounding quantum, that can be tuned via -R flag.

You can check the default rounding quantum for the target architecture value via -v flag:

$ GOARCH=arm go build -ldflags "-T 0x10000 -v" hello.go
HEADER = -H5 -T0x10000 -R0x10000
...

@iansmith In your case you should use the following linker flags:
-ldflags='-T 0x88000 -R 0x1000'

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Jul 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

8 participants