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: shared libraries have DT_TEXTREL set #10914

Closed
mwhudson opened this issue May 20, 2015 · 18 comments
Closed

cmd/link: shared libraries have DT_TEXTREL set #10914

mwhudson opened this issue May 20, 2015 · 18 comments
Milestone

Comments

@mwhudson
Copy link
Contributor

This produces a warning from lintian, debian's package checker.

There don't actually seem to be relocations to the .text, but rather (linking with -Wl,--warn-shared-textrel):

/usr/bin/ld: /home/mwhudson/tmp/hl/runtime/go.o: warning: relocation in readonly section `.gopclntab'.
/usr/bin/ld: warning: creating a DT_TEXTREL in a shared object.

The relocations are mostly R_X86_64_RELATIVE (presumably function pointers) but there are also some references to runtime.no_pointers_stackmap.

I don't know how serious this is. There seems to be some support in the linker for a separate 'segro' vs 'segtext' but it's disabled for external linking...

@minux
Copy link
Member

minux commented May 20, 2015 via email

@mwhudson
Copy link
Contributor Author

Ah but sorting out segments is the external linker's job, the segment stuff in the linker is afaict just noise in that case. We could change .gopclntab to not require relocs but the same affects the .rodata and .typelink sections and I think those are harder.

It's easy to change the linker to make .gopclntab/.rodata/.typelink read-write, but that just makes the external linker lump everything into one RWE segment which isn't really what we want.

@minux
Copy link
Member

minux commented May 20, 2015 via email

@mwhudson
Copy link
Contributor Author

No, that's what I tried, it doesn't seem to work, you get this:

mwhudson@glamdring:src$ readelf -l libruntime,sync-atomic.so 
Elf file type is DYN (Shared object file)
Entry point 0xc5ec0
There are 6 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x00000000003c5130 0x00000000003f0880  RWE    200000
  DYNAMIC        0x000000000038a408 0x000000000038a408 0x000000000038a408
                 0x00000000000001e0 0x00000000000001e0  RW     8
  NOTE           0x0000000000000190 0x0000000000000190 0x0000000000000190
                 0x0000000000000024 0x0000000000000024  R      4
  TLS            0x000000000018a34c 0x000000000038a3f0 0x000000000038a3f0
                 0x0000000000000000 0x0000000000000008  R      8
  GNU_EH_FRAME   0x000000000018a100 0x000000000018a100 0x000000000018a100
                 0x0000000000000074 0x0000000000000074  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame .init_array .fini_array .jcr .dynamic .got .got.plt .data .typelink .gopclntab .noptrdata .bss .noptrbss 
   01     .dynamic 
   02     .note.gnu.build-id 
   03     .tbss 
   04     .eh_frame_hdr 
   05     

which aiui is worse than tip.

@mwhudson
Copy link
Contributor Author

You need to put the sections into the object file in a different order and that's a different level of mess (or so it seems to me).

@minux
Copy link
Member

minux commented May 20, 2015 via email

@mwhudson
Copy link
Contributor Author

mwhudson@glamdring:src$ readelf --wide -S /home/mwhudson/tmp/hl/runtime/go.o
There are 37 section headers, starting at offset 0x40:

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        0000000000000000 002400 068f80 00  AX  0   0 16
  [ 2] .rodata           PROGBITS        0000000000000000 06b380 05ad00 00  WA  0   0 32
  [ 3] .typelink         PROGBITS        0000000000000000 0c6080 0014f8 00  WA  0   0  8
  [ 4] .gosymtab         PROGBITS        0000000000000000 0c7578 000000 00  WA  0   0  1
  [ 5] .gopclntab        PROGBITS        0000000000000000 0c7580 037b8c 00  WA  0   0 32
  [ 6] .shstrtab         STRTAB          0000000000000000 0ff120 000207 00      0   0  1
  [ 7] .noptrdata        PROGBITS        0000000000000000 100000 0002b0 00  WA  0   0 32
  [ 8] .init_array       PROGBITS        0000000000000000 1002b0 000000 00  WA  0   0  0
  [ 9] .data             PROGBITS        0000000000000000 1002c0 000cd8 00  WA  0   0 32
  [10] .bss              NOBITS          0000000000000000 100fa0 025730 00  WA  0   0 32
  [11] .noptrbss         NOBITS          0000000000000000 1266e0 005f40 00  WA  0   0 32
  [12] .tbss             NOBITS          0000000000000000 100000 000008 00 WAT  0   0  8
  [13] .note.go.pkg-list NOTE            00000000004023d0 0023d0 000030 00      0   0  4
  [14] .symtab           SYMTAB          0000000000000000 101000 029328 18     15 2611  8
  [15] .strtab           STRTAB          0000000000000000 12a328 022bd1 00      0   0  1
  [16] .rela.text        RELA            0000000000000000 26b8e8 023040 18     14   1  8
  [17] .rela.rodata      RELA            0000000000000000 28e928 05a438 18     14   2  8
  [18] .rela.typelink    RELA            0000000000000000 2e8d60 003ee8 18     14   3  8
  [19] .rela.gosymtab    RELA            0000000000000000 2ecc48 000000 18     14   4  8
  [20] .rela.gopclntab   RELA            0000000000000000 2ecc48 020e80 18     14   5  8
  [21] .rela.noptrdata   RELA            0000000000000000 30dac8 0001f8 18     14   7  8
  [22] .rela.init_array  RELA            0000000000000000 30dcc0 000000 18     14   8  8
  [23] .rela.data        RELA            0000000000000000 30dcc0 000ea0 18     14   9  8
  [24] .note.GNU-stack   PROGBITS        0000000000000000 000000 000000 00      0   0  1
  [25] .debug_abbrev     PROGBITS        0000000000000000 14cef9 0000fd 00      0   0  1
  [26] .debug_line       PROGBITS        0000000000000000 14cff6 00c85e 00      0   0  1
  [27] .debug_frame      PROGBITS        0000000000000000 159854 00e38c 00      0   0  1
  [28] .debug_info       PROGBITS        0000000000000000 167be0 05cb00 00      0   0  1
  [29] .debug_pubnames   PROGBITS        0000000000000000 1c46e0 01c4df 00      0   0  1
  [30] .debug_pubtypes   PROGBITS        0000000000000000 1e0bbf 009a23 00      0   0  1
  [31] .debug_aranges    PROGBITS        0000000000000000 1ea5e2 000030 00      0   0  1
  [32] .debug_gdb_scripts PROGBITS        0000000000000000 1ea612 00002f 00      0   0  1
  [33] .rela.debug_info  RELA            0000000000000000 1ea648 06ff78 18     14  28  8
  [34] .rela.debug_aranges RELA            0000000000000000 25a5c0 000030 18     14  31  8
  [35] .rela.debug_line  RELA            0000000000000000 25a5f0 000018 18     14  26  8
  [36] .rela.debug_frame RELA            0000000000000000 25a608 0112e0 18     14  27  8
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

I guess we need to align the sections we want to end up in different segments at least to a page? Paging @ianlancetaylor I guess.

@ianlancetaylor
Copy link
Contributor

How did you manage to get a writable .rodata section? That does not look desirable.

@ianlancetaylor
Copy link
Contributor

I would guess that you are using GNU ld rather than gold. GNU ld sorts sections by name using a default linker script. It will put the .rodata section and the .text section in the same segment. If .rodata is writable, that forces the segment to be writable. At that point there is no need to make a separate data segment, so you wind up with a single segment. This is obviously bad.

Having a DT_TEXTREL tag is also bad. It means that the shared library text segments can not be shared--in other words, the shared libraries are not shared.

@minux
Copy link
Member

minux commented May 20, 2015 via email

@ianlancetaylor
Copy link
Contributor

I would say that the solution is to not have a writable .rodata section. That doesn't make a lot of sense.

If the value needs to be writable only to support a relocation, put it in a .data.rel.ro section and pass -z relro to the linker.

@minux
Copy link
Member

minux commented May 20, 2015 via email

@ianlancetaylor
Copy link
Contributor

No, data.rel.ro is special (and so is .gnu.linkonce.d.rel.ro and .data.rel.ro.local). A section with that name, when linked with -z relro, will be placed at the start of the data segment in such a way that the dynamic linker can mark it as readonly after applying dynamic relocations (the dynamic linker is told what to make readonly via a PT_GNU_RELRO segment).

Sections whose names are not recognized, like .pclntab, etc., will, if writable, be treated as ordinary writable sections and placed in the data segment.

The problem leading to the single segment was due to a section with a special name (.rodata) having unexpected flags.

@mwhudson
Copy link
Contributor Author

Ian appears to have answered these questions already :-) http://www.airs.com/blog/archives/189

I think the linker could (all behind a Buildmode==BuildmodeShared check of course), scan for SRODATA objects that have relocations (len(s.R) > 0) and move them to a new SRELRODATA type, plus associated stuff to create the .data.rel.ro section (I guess it could even check the relocations and if they are all to local symbols, move them to a SRELRODATALOCAL type...).

@mwhudson
Copy link
Contributor Author

Well, I've learnt a bunch about the linker: https://go-review.googlesource.com/10300.

Probably best to leave this for 1.6 though.

@gopherbot
Copy link

CL https://golang.org/cl/10300 mentions this issue.

mwhudson added a commit to mwhudson/go that referenced this issue May 22, 2015
…making a shared object

Currently Go produces shared libraries that cannot be shared between processes
because they have relocations against the text segment (not text section). This
fixes this by moving some data from .rodata to .data.rel.ro and by marking some
sections rw (so the program linker puts them into a different segment).

I think this is all way too much for 1.5 but I wanted to hammer my way to
something working. Will fix after 1.6.

Fixes golang#10914

Change-Id: I7178daadc0ae87953d5a084aa3d580f4e3b46d47
@ianlancetaylor ianlancetaylor added this to the Go1.6 milestone Jun 3, 2015
@mwhudson mwhudson changed the title cmd/internal/ld: shared libraries have DT_TEXTREL set cmd/link: shared libraries have DT_TEXTREL set Jun 17, 2015
@gopherbot
Copy link

CL https://golang.org/cl/14142 mentions this issue.

mwhudson added a commit to mwhudson/go that referenced this issue Sep 2, 2015
…making a shared object

Currently Go produces shared libraries that cannot be shared between processes
because they have relocations against the text segment (not text section). This
fixes this by moving some data to sections with magic names recognized by the
static linker.

Fixes golang#10914
Updates golang#9210

Change-Id: I7178daadc0ae87953d5a084aa3d580f4e3b46d47
mwhudson added a commit to mwhudson/go that referenced this issue Sep 2, 2015
…de=c-shared on arm

All the code was there to do this, it just wasn't hooked up.

Fixes golang#10914

Change-Id: Ide8f9bbe50fecb5d11cd579915ee98d4c7efe403
mwhudson added a commit to mwhudson/go that referenced this issue Sep 4, 2015
…making a shared object

Currently Go produces shared libraries that cannot be shared between processes
because they have relocations against the text segment (not text section). This
fixes this by moving some data to sections with magic names recognized by the
static linker.

Fixes golang#10914
Updates golang#9210

Change-Id: I7178daadc0ae87953d5a084aa3d580f4e3b46d47
mwhudson added a commit to mwhudson/go that referenced this issue Sep 4, 2015
…de=c-shared on arm

All the code was there to do this, it just wasn't hooked up.

Fixes golang#10914

Change-Id: Ide8f9bbe50fecb5d11cd579915ee98d4c7efe403
gopherbot pushed a commit that referenced this issue Sep 4, 2015
…de=c-shared on arm

All the code was there to do this, it just wasn't hooked up.

Fixes #10914

Change-Id: Ide8f9bbe50fecb5d11cd579915ee98d4c7efe403
Reviewed-on: https://go-review.googlesource.com/14142
Reviewed-by: Ian Lance Taylor <iant@golang.org>
@gopherbot
Copy link

CL https://golang.org/cl/14306 mentions this issue.

gopherbot pushed a commit that referenced this issue Sep 8, 2015
…making a shared object

Currently Go produces shared libraries that cannot be shared between processes
because they have relocations against the text segment (not text section). This
fixes this by moving some data to sections with magic names recognized by the
static linker.

The change in genasmsym to add STYPELINK to the switch should fix things on
darwin/arm64.

Fixes #10914
Updates #9210

Change-Id: Iab4a6678dd04cec6114e683caac5cf31b1063309
Reviewed-on: https://go-review.googlesource.com/14306
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
mwhudson added a commit to mwhudson/go that referenced this issue Jan 4, 2016
…making a shared object

Currently Go produces shared libraries that cannot be shared between processes
because they have relocations against the text segment (not text section). This
fixes this by moving some data to sections with magic names recognized by the
static linker.

The change in genasmsym to add STYPELINK to the switch should fix things on
darwin/arm64.

Fixes golang#10914
Updates golang#9210

Change-Id: Iab4a6678dd04cec6114e683caac5cf31b1063309
mwhudson added a commit to mwhudson/go that referenced this issue Jan 4, 2016
…de=c-shared on arm

All the code was there to do this, it just wasn't hooked up.

Fixes golang#10914

Change-Id: Ide8f9bbe50fecb5d11cd579915ee98d4c7efe403
@golang golang locked and limited conversation to collaborators Sep 5, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants