Bug 17592 - x86-64 linker generates wrong PLT for large model
Summary: x86-64 linker generates wrong PLT for large model
Status: NEW
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.26
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-11-12 22:34 UTC by H.J. Lu
Modified: 2023-07-29 14:09 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2014-11-12 22:34:11 UTC
When PLT is more 2GB from GOT, we must use large model PLT layout.
Otherwise, PLT entry can't load GOT entry:

[hjl@gnu-6 large-2]$ cat main.c 
extern void foo (void);
extern void bar (void);

int
main ()
{
  foo ();
  bar ();
  return 0;
}
[hjl@gnu-6 large-2]$ cat foo.c 
#include <stdio.h>

void
foo (void)
{
  printf ("hello\n");
}
[hjl@gnu-6 large-2]$ cat gap.S 
	.text
	.p2align 4,,15
	.globl	bar
	.type	bar, @function
bar:
	jmp .L0
	.space 0x40000000, 0x90
.L0:
	jmp .L2
	.space 0x3fdffe14, 0x90
.L2:
	leaq	.L2(%rip), %rcx
	movabsq	$_GLOBAL_OFFSET_TABLE_-.L2, %r11
	movabsq	$foo@PLTOFF, %rax
	addq	%r11, %rcx
	addq	%rcx, %rax
	jmp	*%rax
	.size	bar, .-bar
	.section	.note.GNU-stack,"",@progbits
[hjl@gnu-6 large-2]$ make
gcc -O2   -c -o main.o main.c
gcc -O2 -c -o gap.o gap.S
gcc -O2 -mcmodel=large -fpic   -c -o foo.o foo.c
./ld -shared -o libfoo.so gap.o foo.o
gcc -O2 -o foo main.o libfoo.so -Wl,-R,.
./foo
make: *** [all] Segmentation fault
[hjl@gnu-6 large-2]$
Comment 1 Michael Matz 2014-11-17 13:22:31 UTC
Back in http://www.sourceware.org/ml/binutils/2006-03/msg00276.html
I suggested to place .plt after .text so that PLT and GOT are nearer
to each other.  In that case the large PLT layout would only need to
be used if there were more that 100 million PLT slots (and GOT entry).

Nevertheless, for full large model support you're right, the large PLT
layout needs to be implemented.
Comment 2 H.J. Lu 2014-11-17 20:26:36 UTC
(In reply to Michael Matz from comment #1)
> Back in http://www.sourceware.org/ml/binutils/2006-03/msg00276.html
> I suggested to place .plt after .text so that PLT and GOT are nearer
> to each other.  In that case the large PLT layout would only need to
> be used if there were more that 100 million PLT slots (and GOT entry).
> 

It is an interesting idea.  If we place .plt just after .text, there
may be readonly sections before .got, the distance between .plt and
.got.plt can still be big.  If we place .plt just before .got, the
text segment will have text, readonly data and followed by text. Do
we want to do that?
Comment 3 Michael Matz 2014-11-18 13:07:00 UTC
(In reply to H.J. Lu from comment #2)
> It is an interesting idea.

Yeah, that's how I tested the large model back in the days when I implemented
some of it.  Never got around to actually change the PLT layout.

> If we place .plt just after .text, there
> may be readonly sections before .got, the distance between .plt and
> .got.plt can still be big.

Yes, unfortunately.

> If we place .plt just before .got, the
> text segment will have text, readonly data and followed by text. Do
> we want to do that?

At least it wouldn't change the executable view of the ELF files, those
sections would still be contained in the read-only-exec segment.  Also the
GNU_RELRO (writable, but only during loading) part could be moved after .got.
Thereby .got would be first in the RW segment and .plt last in the RE segment,
right next to each other.
Comment 4 H.J. Lu 2014-11-18 14:38:20 UTC
(In reply to Michael Matz from comment #3)
> (In reply to H.J. Lu from comment #2)
> > It is an interesting idea.
> 
> Yeah, that's how I tested the large model back in the days when I implemented
> some of it.  Never got around to actually change the PLT layout.
> 
> > If we place .plt just after .text, there
> > may be readonly sections before .got, the distance between .plt and
> > .got.plt can still be big.
> 
> Yes, unfortunately.
> 
> > If we place .plt just before .got, the
> > text segment will have text, readonly data and followed by text. Do
> > we want to do that?
> 
> At least it wouldn't change the executable view of the ELF files, those
> sections would still be contained in the read-only-exec segment.  Also the
> GNU_RELRO (writable, but only during loading) part could be moved after .got.
> Thereby .got would be first in the RW segment and .plt last in the RE
> segment,
> right next to each other.

When there is a large readonly section,  it makes no differences between

text
plt
readonly
got

and

text
readonly
plt
got

since text needs to reach plt and plt needs to reach got.  We should go
with

text
plt
readonly
got

I will prepare a patch.
Comment 5 Michael Matz 2014-11-18 14:45:47 UTC
(In reply to H.J. Lu from comment #4)
> When there is a large readonly section,  it makes no differences between
> 
> text, plt, readonly, got
> 
> and
> 
> text, readonly, plt, got
> 
> since text needs to reach plt and plt needs to reach got.

Yes, but text reaching PLT is trivial with the large code model.  But PLT
reaching GOT requires changing the PLT layout.  The reason for my idea
of moving the PLT was to avoid doing that.  And with a large readonly only
the latter layout achieves that.  So I think that should be the default layout.
Comment 6 H.J. Lu 2014-11-18 14:57:21 UTC
(In reply to Michael Matz from comment #5)
> (In reply to H.J. Lu from comment #4)
> > When there is a large readonly section,  it makes no differences between
> > 
> > text, plt, readonly, got
> > 
> > and
> > 
> > text, readonly, plt, got
> > 
> > since text needs to reach plt and plt needs to reach got.
> 
> Yes, but text reaching PLT is trivial with the large code model.  But PLT
> reaching GOT requires changing the PLT layout.  The reason for my idea
> of moving the PLT was to avoid doing that.  And with a large readonly only
> the latter layout achieves that.  So I think that should be the default
> layout.

Putting readonly data between text makes this even worse:

https://sourceware.org/bugzilla/show_bug.cgi?id=16685
Comment 7 H.J. Lu 2014-11-18 14:59:23 UTC
(In reply to Michael Matz from comment #5)
> (In reply to H.J. Lu from comment #4)
> > When there is a large readonly section,  it makes no differences between
> > 
> > text, plt, readonly, got
> > 
> > and
> > 
> > text, readonly, plt, got
> > 
> > since text needs to reach plt and plt needs to reach got.
> 
> Yes, but text reaching PLT is trivial with the large code model.  But PLT
> reaching GOT requires changing the PLT layout.  The reason for my idea
> of moving the PLT was to avoid doing that.  And with a large readonly only
> the latter layout achieves that.  So I think that should be the default
> layout.

I also want to support larger code size in small model.  Put .plt after .text
will help small model.  I will implement large PLT for large model.
Comment 8 Evandro 2014-11-18 20:11:30 UTC
(In reply to H.J. Lu from comment #7)
> I also want to support larger code size in small model.  Put .plt after .text
> will help small model.  I will implement large PLT for large model.

Methinks that it's more appealing to maintain a single PLT template, regardless of the model, and have sparse segments to support text-ro-plt-got.  The overhead in the memory space should be insignificant if done only in the large code model.