Bug 23854 - 16-bit GOT access is incorrectly optimized
Summary: 16-bit GOT access is incorrectly optimized
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.32
: P2 critical
Target Milestone: 2.32
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-11-04 03:20 UTC by Stas Sergeev
Modified: 2018-11-26 12:55 UTC (History)
1 user (show)

See Also:
Host:
Target: i386,x86-64
Build:
Last reconfirmed: 2018-11-04 00:00:00


Attachments
test case (1.15 MB, application/gzip)
2018-11-04 03:20 UTC, Stas Sergeev
Details
verbose asm (487.92 KB, text/plain)
2018-11-05 09:56 UTC, Stas Sergeev
Details
preprocessed output (104.52 KB, application/gzip)
2018-11-05 10:40 UTC, Stas Sergeev
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Stas Sergeev 2018-11-04 03:20:41 UTC
Created attachment 11375 [details]
test case

Out of sudden my prog started to randomly crash on i386 target.
It appears the combination of options -no-pie -export-dynamic
causes ld to randomly corrupt the code section.
Attached is the fully automated test-case.
Just type "make" - it will link the executable and look
with gdb at the assembler in one particular place where
I spotted the corruption. It will then print "TEST FAILED!".
You can run "make good" that will do the same but without
-export-dynamic. This will end up in "TEST PASSED!".

gold has no such problem.
Comment 1 H.J. Lu 2018-11-04 20:41:22 UTC
dpmi.o has:

    8f69:       8b 83 00 00 00 00       mov    0x0(%ebx),%eax   8f6b: R_386_GOT32X      DPMI_return_from_realmode
    8f6f:       66 05 00 48             add    $0x4800,%ax
    8f73:       66 2b 83 00 00 00 00    sub    0x0(%ebx),%ax    8f76: R_386_GOT32X      DPMI_dummy_start
    8f7a:       66 89 46 30             mov    %ax,0x30(%esi)

Only the lower 16 bits of GOT slot are used. It leads to:

[hjl@gnu-cfl-1 pr23854]$ cat pr23854.s
	.data
	.type	bar, @object
bar:
	.byte	1
	.size	bar, .-bar
	.globl	foo
	.type	foo, @object
foo:
	.byte	1
	.size	foo, .-foo
	.text
	.globl	_start
	.type	_start, @function
_start:
	adcw	bar@GOT(%ecx), %ax
	addw	bar@GOT(%ecx), %bx
	andw	bar@GOT(%ecx), %cx
	cmpw	bar@GOT(%ecx), %dx
	orw	bar@GOT(%ecx), %di
	sbbw	bar@GOT(%ecx), %si
	subw	bar@GOT(%ecx), %bp
	xorw	bar@GOT(%ecx), %sp
	testw	%cx, bar@GOT(%ecx)
	adcw	foo@GOT(%ecx), %ax
	addw	foo@GOT(%ecx), %bx
	andw	foo@GOT(%ecx), %cx
	cmpw	foo@GOT(%ecx), %dx
	orw	foo@GOT(%ecx), %di
	sbbw	foo@GOT(%ecx), %si
	subw	foo@GOT(%ecx), %bp
	xorw	foo@GOT(%ecx), %sp
	testw	%cx, foo@GOT(%ecx)
	.size	_start, .-_start
[hjl@gnu-cfl-1 pr23854]$ make
as --32  -o pr23854.o pr23854.s
ld -melf_i386 -o pr23854 pr23854.o
[hjl@gnu-cfl-1 pr23854]$ objdump -dw pr23854

pr23854:     file format elf32-i386


Disassembly of section .text:

08049000 <_start>:
 8049000:	66 81 d0 00 a0       	adc    $0xa000,%ax
 8049005:	04 08                	add    $0x8,%al
 8049007:	66 81 c3 00 a0       	add    $0xa000,%bx
 804900c:	04 08                	add    $0x8,%al
 804900e:	66 81 e1 00 a0       	and    $0xa000,%cx
 8049013:	04 08                	add    $0x8,%al
 8049015:	66 81 fa 00 a0       	cmp    $0xa000,%dx
 804901a:	04 08                	add    $0x8,%al
 804901c:	66 81 cf 00 a0       	or     $0xa000,%di
 8049021:	04 08                	add    $0x8,%al
 8049023:	66 81 de 00 a0       	sbb    $0xa000,%si
 8049028:	04 08                	add    $0x8,%al
 804902a:	66 81 ed 00 a0       	sub    $0xa000,%bp
 804902f:	04 08                	add    $0x8,%al
 8049031:	66 81 f4 00 a0       	xor    $0xa000,%sp
 8049036:	04 08                	add    $0x8,%al
 8049038:	66 f7 c1 00 a0       	test   $0xa000,%cx
 804903d:	04 08                	add    $0x8,%al
 804903f:	66 81 d0 01 a0       	adc    $0xa001,%ax
 8049044:	04 08                	add    $0x8,%al
 8049046:	66 81 c3 01 a0       	add    $0xa001,%bx
 804904b:	04 08                	add    $0x8,%al
 804904d:	66 81 e1 01 a0       	and    $0xa001,%cx
 8049052:	04 08                	add    $0x8,%al
 8049054:	66 81 fa 01 a0       	cmp    $0xa001,%dx
 8049059:	04 08                	add    $0x8,%al
 804905b:	66 81 cf 01 a0       	or     $0xa001,%di
 8049060:	04 08                	add    $0x8,%al
 8049062:	66 81 de 01 a0       	sbb    $0xa001,%si
 8049067:	04 08                	add    $0x8,%al
 8049069:	66 81 ed 01 a0       	sub    $0xa001,%bp
 804906e:	04 08                	add    $0x8,%al
 8049070:	66 81 f4 01 a0       	xor    $0xa001,%sp
 8049075:	04 08                	add    $0x8,%al
 8049077:	66 f7 c1 01 a0       	test   $0xa001,%cx
 804907c:	04 08                	add    $0x8,%al
[hjl@gnu-cfl-1 pr23854]$ 

Does dpmi.o contain normal i386 code?
Comment 2 Stas Sergeev 2018-11-04 21:40:35 UTC
(In reply to H.J. Lu from comment #1)
> dpmi.o has:
> 
>     8f69:       8b 83 00 00 00 00       mov    0x0(%ebx),%eax   8f6b:
> R_386_GOT32X      DPMI_return_from_realmode
>     8f6f:       66 05 00 48             add    $0x4800,%ax
>     8f73:       66 2b 83 00 00 00 00    sub    0x0(%ebx),%ax    8f76:
> R_386_GOT32X      DPMI_dummy_start
>     8f7a:       66 89 46 30             mov    %ax,0x30(%esi)
These functions are not from dpmi.c, they
are from another translation unit. The function
of interest is "do_dpmi_int" - it gets corrupted,
as my test-case shows.

> Does dpmi.o contain normal i386 code?
Yes, but not the ones you pointed to.
These should be undefined in dpmi.c, and
are actually written in 16bit asm.
Please inspect "do_dpmi_int" instead - it
is a valid C func from dpmi.o.
You can see from my .gdbinit script where
the corruption actually happens.
Comment 3 H.J. Lu 2018-11-04 22:24:27 UTC
(In reply to Stas Sergeev from comment #2)
> (In reply to H.J. Lu from comment #1)
> > dpmi.o has:
> > 
> >     8f69:       8b 83 00 00 00 00       mov    0x0(%ebx),%eax   8f6b:
> > R_386_GOT32X      DPMI_return_from_realmode
> >     8f6f:       66 05 00 48             add    $0x4800,%ax
> >     8f73:       66 2b 83 00 00 00 00    sub    0x0(%ebx),%ax    8f76:
> > R_386_GOT32X      DPMI_dummy_start
> >     8f7a:       66 89 46 30             mov    %ax,0x30(%esi)
> These functions are not from dpmi.c, they
> are from another translation unit. The function
> of interest is "do_dpmi_int" - it gets corrupted,
> as my test-case shows.
> 
> > Does dpmi.o contain normal i386 code?
> Yes, but not the ones you pointed to.
> These should be undefined in dpmi.c, and
> are actually written in 16bit asm.
> Please inspect "do_dpmi_int" instead - it
> is a valid C func from dpmi.o.
> You can see from my .gdbinit script where
> the corruption actually happens.

do_dpmi_int has

    8f69:       8b 83 00 00 00 00       mov    0x0(%ebx),%eax   8f6b: R_386_GOT32X      DPMI_return_from_realmode
    8f6f:       66 05 00 48             add    $0x4800,%ax
    8f73:       66 2b 83 00 00 00 00    sub    0x0(%ebx),%ax    8f76: R_386_GOT32X      DPMI_dummy_start
    8f7a:       66 89 46 30             mov    %ax,0x30(%esi)
    8f7e:       0f b7 45 2c             movzwl 0x2c(%ebp),%eax

Please show me the corresponding C code.
Comment 4 Stas Sergeev 2018-11-04 23:05:57 UTC
(In reply to H.J. Lu from comment #3)
> do_dpmi_int has
Ah, I see now what you mean.

>     8f69:       8b 83 00 00 00 00       mov    0x0(%ebx),%eax   8f6b:
> R_386_GOT32X      DPMI_return_from_realmode
>     8f6f:       66 05 00 48             add    $0x4800,%ax
>     8f73:       66 2b 83 00 00 00 00    sub    0x0(%ebx),%ax    8f76:
> R_386_GOT32X      DPMI_dummy_start
>     8f7a:       66 89 46 30             mov    %ax,0x30(%esi)
>     8f7e:       0f b7 45 2c             movzwl 0x2c(%ebp),%eax
> 
> Please show me the corresponding C code.
Of course:
https://github.com/stsp/dosemu2/blob/devel/src/dosext/dpmi/dpmi.c#L2053
The function is called "do_int31", but it
gets inlined into do_dpmi_int. This is
exactly the line you look for.
The ugly macros are here:
https://github.com/stsp/dosemu2/blob/devel/src/include/cpu.h#L138
https://github.com/stsp/dosemu2/blob/devel/src/include/bios.h#L161

I will also try to attach the dpmi.s with -verbose-asm
for you tomorrow.
Comment 5 Stas Sergeev 2018-11-04 23:23:05 UTC
Basically this code calculates the distance
between "DPMI_return_from_realmode" and "DPMI_dummy_start",
and puts the result into a 16bit variable.
That explains the use of %ax. Its possible because
those funcs are in 16bit asm.
I think the gcc-generated asm code is perfectly fine here.
It optimized the 32bit calculus to 16bits.
Comment 6 H.J. Lu 2018-11-05 00:22:59 UTC
Please provide pre-processed dpmi.c from gcc -E and command-line
options to generate dpmi.s
Comment 7 Stas Sergeev 2018-11-05 09:56:17 UTC
Created attachment 11379 [details]
verbose asm

> Please provide pre-processed dpmi.c from gcc -E and command-line
> options to generate dpmi.s
Unfortunately the problem only happens
on a 32bit machine, I can't reproduce it
with multilib on my 64bit one.
So I'll provide what you ask for, later,
when I get an access to the target machine.
For now, here you have a verbose asm output.
It seems the command line is also printed there,
or at least its part.
Comment 8 Stas Sergeev 2018-11-05 10:40:43 UTC
Created attachment 11381 [details]
preprocessed output
Comment 9 Stas Sergeev 2018-11-05 10:48:39 UTC
(In reply to H.J. Lu from comment #6)
> Please provide pre-processed dpmi.c from gcc -E and command-line
> options to generate dpmi.s
gcc -xc -S -fverbose-asm -O -o dpmi.s dpmi.E

gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)

Btw, could you please explain why the problem
only happens with -export-dynamic? This doesn't
seem to be related to the generated asm, AFAICT.
Comment 10 H.J. Lu 2018-11-05 13:25:25 UTC
[hjl@gnu-cfl-1 pr23854]$ cat x.c
extern void foo (void);

short
foo_p (void)
{
  return 0x400 - (int) &foo;
}
[hjl@gnu-cfl-1 pr23854]$ cat foo.c
extern short foo_p (void);

 __attribute__ ((visibility("hidden")))
void 
foo (void)
{
}

void
_start (void)
{
  foo_p ();
}
[hjl@gnu-cfl-1 pr23854]$ make
gcc -m32 -B./ -O2 -fPIE   -c -o x.o x.c
gcc -m32 -B./ -O2 -fPIE   -c -o foo.o foo.c
ld -melf_i386 -o x x.o foo.o
[hjl@gnu-cfl-1 pr23854]$ objdump -dw x.o

x.o:     file format elf32-i386


Disassembly of section .text:

00000000 <foo_p>:
   0:	e8 fc ff ff ff       	call   1 <foo_p+0x1>
   5:	81 c2 02 00 00 00    	add    $0x2,%edx
   b:	b8 00 04 00 00       	mov    $0x400,%eax
  10:	66 2b 82 00 00 00 00 	sub    0x0(%edx),%ax
  17:	c3                   	ret    

Disassembly of section .text.__x86.get_pc_thunk.dx:

00000000 <__x86.get_pc_thunk.dx>:
   0:	8b 14 24             	mov    (%esp),%edx
   3:	c3                   	ret    
[hjl@gnu-cfl-1 pr23854]$ objdump -dw x

x:     file format elf32-i386


Disassembly of section .text:

08049000 <foo_p>:
 8049000:	e8 13 00 00 00       	call   8049018 <__x86.get_pc_thunk.dx>
 8049005:	81 c2 fb 2f 00 00    	add    $0x2ffb,%edx
 804900b:	b8 00 04 00 00       	mov    $0x400,%eax
 8049010:	66 81 e8 20 90       	sub    $0x9020,%ax
 8049015:	04 08                	add    $0x8,%al
 8049017:	c3                   	ret    

08049018 <__x86.get_pc_thunk.dx>:
 8049018:	8b 14 24             	mov    (%esp),%edx
 804901b:	c3                   	ret    
 804901c:	66 90                	xchg   %ax,%ax
 804901e:	66 90                	xchg   %ax,%ax

08049020 <foo>:
 8049020:	c3                   	ret    
 8049021:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 8049028:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 804902f:	90                   	nop

08049030 <_start>:
 8049030:	53                   	push   %ebx
 8049031:	e8 13 00 00 00       	call   8049049 <__x86.get_pc_thunk.bx>
 8049036:	81 c3 ca 2f 00 00    	add    $0x2fca,%ebx
 804903c:	83 ec 08             	sub    $0x8,%esp
 804903f:	e8 bc ff ff ff       	call   8049000 <foo_p>
 8049044:	83 c4 08             	add    $0x8,%esp
 8049047:	5b                   	pop    %ebx
 8049048:	c3                   	ret    

08049049 <__x86.get_pc_thunk.bx>:
 8049049:	8b 1c 24             	mov    (%esp),%ebx
 804904c:	c3                   	ret    
[hjl@gnu-cfl-1 pr23854]$
Comment 11 H.J. Lu 2018-11-05 13:27:00 UTC
(In reply to Stas Sergeev from comment #9)
> (In reply to H.J. Lu from comment #6)
> > Please provide pre-processed dpmi.c from gcc -E and command-line
> > options to generate dpmi.s
> gcc -xc -S -fverbose-asm -O -o dpmi.s dpmi.E

Please add -fno-pie as workaround.

> gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
> 
> Btw, could you please explain why the problem
> only happens with -export-dynamic? This doesn't
> seem to be related to the generated asm, AFAICT.

It has nothing to do with -export-dynamic.  My testcase doesn't use
-export-dynamic.
Comment 12 Stas Sergeev 2018-11-05 14:08:45 UTC
(In reply to H.J. Lu from comment #11)
> Please add -fno-pie as workaround.
Done.
This works properly.
Thank you.

> > Btw, could you please explain why the problem
> > only happens with -export-dynamic? This doesn't
> > seem to be related to the generated asm, AFAICT.
> It has nothing to do with -export-dynamic.  My testcase doesn't use
> -export-dynamic.
But my does, and in fact, when you type "make good",
the only things that changes, is no -export-dynamic.
Could you please make sure I am not hitting the second
bug here?
Comment 13 H.J. Lu 2018-11-05 14:17:39 UTC
(In reply to Stas Sergeev from comment #12)

> > > Btw, could you please explain why the problem
> > > only happens with -export-dynamic? This doesn't
> > > seem to be related to the generated asm, AFAICT.
> > It has nothing to do with -export-dynamic.  My testcase doesn't use
> > -export-dynamic.
> But my does, and in fact, when you type "make good",
> the only things that changes, is no -export-dynamic.
> Could you please make sure I am not hitting the second
> bug here?

Your check for "good" one is incomplete.  I got

Dump of assembler code from 0x814bd49 to 0x814bd86:
   0x0814bd49 <do_dpmi_int+6144>:	c7 c0 eb f5 13 08	mov    $0x813f5eb,%eax
   0x0814bd4f <do_dpmi_int+6150>:	66 05 00 48	add    $0x4800,%ax
   0x0814bd53 <do_dpmi_int+6154>:	66 81 e8 e0 f5	sub    $0xf5e0,%ax
   0x0814bd58 <do_dpmi_int+6159>:	13 08	adc    (%eax),%ecx <<<< This is wrong.
   0x0814bd5a <do_dpmi_int+6161>:	66 89 46 30	mov    %ax,0x30(%esi)
   0x0814bd5e <do_dpmi_int+6165>:	0f b7 45 2c	movzwl 0x2c(%ebp),%eax
   0x0814bd62 <do_dpmi_int+6169>:	66 3d 01 03	cmp    $0x301,%ax
   0x0814bd66 <do_dpmi_int+6173>:	0f 84 90 00 00 00	je     0x814bdfc <do_dpmi_int+6323>
   0x0814bd6c <do_dpmi_int+6179>:	66 3d 02 03	cmp    $0x302,%ax
   0x0814bd70 <do_dpmi_int+6183>:	0f 84 a4 00 00 00	je     0x814be1a <do_dpmi_int+6353>
   0x0814bd76 <do_dpmi_int+6189>:	66 3d 00 03	cmp    $0x300,%ax
   0x0814bd7a <do_dpmi_int+6193>:	0f 85 9a ec ff ff	jne    0x814aa1a <do_dpmi_int+1233>
   0x0814bd80 <do_dpmi_int+6199>:	80 7d 20 21	cmpb   $0x21,0x20(%ebp)
   0x0814bd84 <do_dpmi_int+6203>:	74 3b	je     0x814bdc1 <do_dpmi_int+6264>
End of assembler dump.
Comment 14 Stas Sergeev 2018-11-05 16:19:10 UTC
> H.J. Lu <hjl.tools at gmail dot com> changed:
>
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>           Component|ld                          |gas
Sorry for being pedantic, but there is no
such problem with gold. So while gas may be
involved too, I wonder are you sure there is
no bug in ld itself.
Comment 15 H.J. Lu 2018-11-05 16:21:42 UTC
(In reply to Stas Sergeev from comment #14)
> > H.J. Lu <hjl.tools at gmail dot com> changed:
> >
> >            What    |Removed                     |Added
> > ----------------------------------------------------------------------------
> >           Component|ld                          |gas
> Sorry for being pedantic, but there is no
> such problem with gold. So while gas may be

gold != ld

> involved too, I wonder are you sure there is
> no bug in ld itself.

Please try:

https://sourceware.org/ml/binutils/2018-11/msg00021.html

You need to compile with the new assembler.
Comment 16 Stas Sergeev 2018-11-05 18:41:09 UTC
> H.J. Lu <hjl.tools at gmail dot com> changed:
> Please try:
> 
> https://sourceware.org/ml/binutils/2018-11/msg00021.html
> 
> You need to compile with the new assembler.
Building your git now...
However. Are there really no hopes to link
these already existing objects properly?
gold have no problems with those, and if you
consider them "broken" to the point that it
isn't worth an efforts, then maybe at least
ld can detect the problem and error out?
Because its exactly ld that corrupted the
instructions, and I really am surprised you
didn't even put any small band-aid to stop
it from ever doing so.
Comment 17 H.J. Lu 2018-11-05 19:11:42 UTC
(In reply to Stas Sergeev from comment #16)
> > H.J. Lu <hjl.tools at gmail dot com> changed:
> > Please try:
> > 
> > https://sourceware.org/ml/binutils/2018-11/msg00021.html
> > 
> > You need to compile with the new assembler.
> Building your git now...
> However. Are there really no hopes to link
> these already existing objects properly?
> gold have no problems with those, and if you

Old binutils also didn't have this issue.

> consider them "broken" to the point that it
> isn't worth an efforts, then maybe at least
> ld can detect the problem and error out?
> Because its exactly ld that corrupted the
> instructions, and I really am surprised you
> didn't even put any small band-aid to stop
> it from ever doing so.

Your code doesn't conform to i386 psABI, which doesn't
support only using lower 16 bits of GOT entries.
Comment 18 Sourceware Commits 2018-11-05 19:14:29 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a4749e56cacefdc1a571231744a9b87a3f5458b9

commit a4749e56cacefdc1a571231744a9b87a3f5458b9
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Nov 5 11:12:28 2018 -0800

    Correct ChangeLog entries for PR gas/23854 commit
    
    commit e60f4d3bdac25f02875afe36b7436bc2dfbbb978
    Author: H.J. Lu <hjl.tools@gmail.com>
    Date:   Mon Nov 5 09:01:26 2018 -0800
    
        x86: Disable GOT relaxation with data prefix
    
        Since linker GOT relaxation isn't valid for 16-bit GOT access, we should
        disable GOT relaxation with data prefix.
Comment 19 Stas Sergeev 2018-11-05 19:16:19 UTC
> H.J. Lu <hjl.tools at gmail dot com> changed:
> Your code doesn't conform to i386 psABI, which doesn't
> support only using lower 16 bits of GOT entries.
I would understand if linker writes me such an error.
Silently producing corrupted binaries is the sign of
low quality software. You can add checks, error messages,
but never let the broken output...
Comment 20 Stas Sergeev 2018-11-05 19:38:12 UTC
I disasmed and diffed the object files
without and with your patch. I see a lot of:
---
597,598c597,598
<      745:     8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
<      749:     8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi
---
>      745:     8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi
>      74c:     8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
---

Is this correct, that it now applies lea to
%esi twice? As %esi is used as both arg and
result, I think it will be modified twice,
and so I can't imagine those changes lead to
an equivalent code.
Comment 21 H.J. Lu 2018-11-05 19:48:51 UTC
(In reply to Stas Sergeev from comment #19)
> > H.J. Lu <hjl.tools at gmail dot com> changed:
> > Your code doesn't conform to i386 psABI, which doesn't
> > support only using lower 16 bits of GOT entries.
> I would understand if linker writes me such an error.
> Silently producing corrupted binaries is the sign of
> low quality software. You can add checks, error messages,
> but never let the broken output...

What your code did is outside of scope of i386 psABI.
Comment 22 H.J. Lu 2018-11-05 19:50:52 UTC
(In reply to Stas Sergeev from comment #20)
> I disasmed and diffed the object files
> without and with your patch. I see a lot of:
> ---
> 597,598c597,598
> <      745:     8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
> <      749:     8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi
> ---
> >      745:     8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi
> >      74c:     8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
> ---
> 
> Is this correct, that it now applies lea to
> %esi twice? As %esi is used as both arg and
> result, I think it will be modified twice,
> and so I can't imagine those changes lead to
> an equivalent code.

These are NOPs.
Comment 23 Stas Sergeev 2018-11-05 19:54:38 UTC
> What your code did is outside of scope of i386 psABI.

Why not linker tells me so with an error msg?
Comment 24 H.J. Lu 2018-11-05 21:54:17 UTC
(In reply to Stas Sergeev from comment #23)
> > What your code did is outside of scope of i386 psABI.
> 
> Why not linker tells me so with an error msg?

There are many corner cases linker doesn't check.  You have things like

extern void foo (void);

short
foo_p (void)
{
  return 0x400 - (int) &foo;
}

In normal i386 case, &foo is 32 bits, especially with PIE.  BTW,
does your code work without -no-pie using ANY linkers?
Comment 25 Stas Sergeev 2018-11-05 22:13:16 UTC
> What your code did is outside of scope of i386 psABI.

Why not linker tells me so with an error msg?(In reply to H.J. Lu from comment #24)
> (In reply to Stas Sergeev from comment #23)
> > > What your code did is outside of scope of i386 psABI.
> > 
> > Why not linker tells me so with an error msg?
> 
> There are many corner cases linker doesn't check.
But in this particular case, when it overwrites the
instructions with something else, it _could_ have checked. :(
I don't think other unchecked corner cases give that
level of breakage and difficulty to debug.

>  You have things like
> 
> extern void foo (void);
> 
> short
> foo_p (void)
> {
>   return 0x400 - (int) &foo;
> }
> 
> In normal i386 case, &foo is 32 bits, especially with PIE.  BTW,
> does your code work without -no-pie using ANY linkers?
You mean, any other than ld, or including ld?
In fact, I added -no-pie just very recently:
https://github.com/stsp/dosemu2/commit/d5eb51320477f32df7deb9161fa728e12bcd06dd
to get the high load address.
Before that, it definitely worked with ld, and
most likely also with gold (but I haven't checked
gold for quite some time).
Note that older ubuntu distros (and likely others)
used no-pie by default. ubuntu defaulted to pie
only in 18.04 or so, which started to give me the
low load address again.
Comment 26 Stas Sergeev 2018-11-05 22:16:47 UTC
By the way, is it a feature of this
bugzilla to open the entirely different
bug ticket after I post any comment?
This always makes me worry that I posted
to wrong thread.
For example, when I post to _this_ ticket,
bugzilla opens ticket 14187.
Comment 27 Andreas Schwab 2018-11-06 08:14:24 UTC
Customize "After changing a bug" in userprefs.
Comment 28 Sourceware Commits 2018-11-06 18:46:47 UTC
The binutils-2_31-branch branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1929a39655d77686385913ef63c6c4340bb2d729

commit 1929a39655d77686385913ef63c6c4340bb2d729
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Nov 5 09:01:26 2018 -0800

    x86: Disable GOT relaxation with data prefix
    
    Since linker GOT relaxation isn't valid for 16-bit GOT access, we should
    disable GOT relaxation with data prefix.
    
    gas/
    
    	PR gas/23854
    	* config/tc-i386.c (output_disp): Disable GOT relaxation with
    	data prefix.
    	* testsuite/gas/i386/mixed-mode-reloc32.d: Updated.
    
    ld/
    
    	PR gas/23854
    	* testsuite/ld-i386/i386.exp: Run pr23854.
    	* testsuite/ld-x86-64/x86-64.exp: Likewwise.
    	* testsuite/ld-i386/pr23854.d: New file.
    	* testsuite/ld-i386/pr23854.s: Likewwise.
    	* testsuite/ld-i386/pr23854.d: Likewwise.
    	* testsuite/ld-x86-64/pr23854.d: Likewwise.
    	* testsuite/ld-x86-64/pr23854.s: Likewwise.
    
    (cherry picked from commit e60f4d3bdac25f02875afe36b7436bc2dfbbb978)
Comment 29 H.J. Lu 2018-11-06 18:54:35 UTC
Fixed for 2.32 and 2.31 branch.
Comment 30 Sourceware Commits 2018-11-26 12:55:34 UTC
The binutils-2_30-branch branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3050b43068674882b01a51351c5c39e950f0ee41

commit 3050b43068674882b01a51351c5c39e950f0ee41
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Nov 5 09:01:26 2018 -0800

    x86: Disable GOT relaxation with data prefix
    
    Since linker GOT relaxation isn't valid for 16-bit GOT access, we should
    disable GOT relaxation with data prefix.
    
    gas/
    
    	PR gas/23854
    	* config/tc-i386.c (output_disp): Disable GOT relaxation with
    	data prefix.
    	* testsuite/gas/i386/mixed-mode-reloc32.d: Updated.
    
    ld/
    
    	PR gas/23854
    	* testsuite/ld-i386/i386.exp: Run pr23854.
    	* testsuite/ld-x86-64/x86-64.exp: Likewwise.
    	* testsuite/ld-i386/pr23854.d: New file.
    	* testsuite/ld-i386/pr23854.s: Likewwise.
    	* testsuite/ld-i386/pr23854.d: Likewwise.
    	* testsuite/ld-x86-64/pr23854.d: Likewwise.
    	* testsuite/ld-x86-64/pr23854.s: Likewwise.
    
    (cherry picked from commit e60f4d3bdac25f02875afe36b7436bc2dfbbb978)