Bug 20979 - DLL relocation totally broken
Summary: DLL relocation totally broken
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.25
: P2 critical
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-12-17 20:51 UTC by Linda Zhang
Modified: 2020-11-20 11:08 UTC (History)
2 users (show)

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


Attachments
minimal case for the DLL relocation bug (564 bytes, application/x-7z-compressed)
2016-12-17 20:51 UTC, Linda Zhang
Details
Duplicate .reloc info (116.01 KB, image/png)
2017-01-07 06:30 UTC, Linda Zhang
Details
Patch for dllwrap (516 bytes, patch)
2017-01-08 10:25 UTC, Linda Zhang
Details | Diff
Everything necessary for your test should be in the appendix. Thank you. (74 bytes, text/plain)
2020-11-19 19:10 UTC, Veit Devil
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Linda Zhang 2016-12-17 20:51:45 UTC
Created attachment 9707 [details]
minimal case for the DLL relocation bug

OS: Win7 SP1
Toolchain: Mingw-w64 i686-6.2.0-release-win32-dwarf-rt_v5-rev1
Binutils: 2.25.1

I don't know whether it's a GCC bug or a binutils bug, but I think it's not a mingw bug. I can't submit bug to GCC bugzilla because it is rejecting new account creation.

Consider a dll whose base address is overlapped with an existing module, so that the operating system must relocate it, or for another word, rebase it, to work.

Relocation is the fundamental part of the security feature ASLR and is enabled by default since Windows Vista. When ASLR is enabled, all executables are relocated.

BUT, After relocation, the compiled DLL fails to load at all. That's to say, the compiled DLL is broken.

Not only x86-dw2 builds produces the broken DLL, but x86-sjlj, x64-sjlj, x64-seh, all gcc 6.2 builds with binutils 2.25.1 have the same problem. OH MY GOD. I believe previous builds also have the same problem.

Minical case:

=====================
testexe.c
=====================
#include <stdio.h>

__declspec(dllimport) int a();

int main() {
	a();
	printf("hello world\n");
	return 0;
}

=====================
testdll.c
=====================
__declspec(dllexport) int a() {return 0;}

=====================
test.def
=====================
EXPORTS
a

=====================
makefile
=====================
all: test.dll test.exe
clean:
	rm test.exe test.dll libtest.a
test.exe: testexe.c
	gcc -o $@ $^ libtest.a -Wl,--image-base,0x400000
test.dll: testdll.c
	dllwrap -o $@ $^ --def test.def --implib libtest.a -Wl,--image-base,0x400000

=====================
Case end. Also see the attachment. In this case, test.exe refuses to work with error 0xC0000005 because test.dll fails to load.


I don't know what's going wrong, GCC or binutils? Nothing is wrong when using Microsoft Visual C++. It's really annoying to see GCC compiled programs showing 0xC0000005 frequently and randomly.
Comment 1 Nick Clifton 2017-01-04 12:45:16 UTC
Hi Linda,

> Binutils: 2.25.1

Have you tried using a more recent version of the binutils ?  We are currently on release 2.27 and release 2.28 is about to happen.

Cheers
  Nick
Comment 2 Linda Zhang 2017-01-07 02:39:52 UTC
(In reply to Nick Clifton from comment #1)
> Hi Linda,
> 
> > Binutils: 2.25.1
> 
> Have you tried using a more recent version of the binutils ?  We are
> currently on release 2.27 and release 2.28 is about to happen.
> 
> Cheers
>   Nick

Hi Nick,

Thank you for your reply, but I don't know how to build binutils for mingw so I can only wait for their builds. :(
I even don't know whom to ask so I'm asking mingw now because it's their bundle.

I found at least in lib/gcc/i686-w64-mingw32/6.2.0/crtbegin.o, some NULL pointers were accidently relocated thus lead to SEGFAULT. There may be more errors. Buggy builds from at least 4.8.x to 6.2.
Comment 3 Linda Zhang 2017-01-07 06:30:42 UTC
Created attachment 9742 [details]
Duplicate .reloc info
Comment 4 Linda Zhang 2017-01-07 06:37:04 UTC
(In reply to Linda Zhang from comment #2)
> (In reply to Nick Clifton from comment #1)
> > Hi Linda,
> > 
> > > Binutils: 2.25.1
> > 
> > Have you tried using a more recent version of the binutils ?  We are
> > currently on release 2.27 and release 2.28 is about to happen.
> > 
> > Cheers
> >   Nick
> 
> Hi Nick,
> 
> Thank you for your reply, but I don't know how to build binutils for mingw
> so I can only wait for their builds. :(
> I even don't know whom to ask so I'm asking mingw now because it's their
> bundle.
> 
> I found at least in lib/gcc/i686-w64-mingw32/6.2.0/crtbegin.o, some NULL
> pointers were accidently relocated thus lead to SEGFAULT. There may be more
> errors. Buggy builds from at least 4.8.x to 6.2.

Hi Nick,

I think I found the reason.

Binutils (it should be) produced duplicate .reloc info into the binary. The wrong one comes first, and the correct one comes after, resulting in double relocation.

The new attached picture "bug.png" says all.
Comment 5 Linda Zhang 2017-01-07 07:12:36 UTC
(In reply to Linda Zhang from comment #4)
> (In reply to Linda Zhang from comment #2)
> > (In reply to Nick Clifton from comment #1)
> > > Hi Linda,
> > > 
> > > > Binutils: 2.25.1
> > > 
> > > Have you tried using a more recent version of the binutils ?  We are
> > > currently on release 2.27 and release 2.28 is about to happen.
> > > 
> > > Cheers
> > >   Nick
> > 
> > Hi Nick,
> > 
> > Thank you for your reply, but I don't know how to build binutils for mingw
> > so I can only wait for their builds. :(
> > I even don't know whom to ask so I'm asking mingw now because it's their
> > bundle.
> > 
> > I found at least in lib/gcc/i686-w64-mingw32/6.2.0/crtbegin.o, some NULL
> > pointers were accidently relocated thus lead to SEGFAULT. There may be more
> > errors. Buggy builds from at least 4.8.x to 6.2.
> 
> Hi Nick,
> 
> I think I found the reason.
> 
> Binutils (it should be) produced duplicate .reloc info into the binary. The
> wrong one comes first, and the correct one comes after, resulting in double
> relocation.
> 
> The new attached picture "bug.png" says all.

OK, update, both gcc -shared and ld -shared are OK. The bug is confirmed to be DLLWRAP issues, which I see was deprecated in 2002......
Comment 6 Linda Zhang 2017-01-08 10:25:02 UTC
Created attachment 9744 [details]
Patch for dllwrap

OK I saw dllwrap is not maintained for 15 years..... OMG! So I'd like to submit a patch to warn use of dllwrap to prevent further problems.....
Comment 7 Veit Devil 2020-11-19 19:10:48 UTC
Created attachment 12979 [details]
Everything necessary for your test should be in the appendix. Thank you.

Everything necessary for your test should be in the appendix. Thank you.
Comment 8 Sourceware Commits 2020-11-20 11:07:49 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

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

commit 8881640c8071b04fa2566f21eb2a47e691caf11c
Author: Linda Zhang <lindasc@qq.com>
Date:   Fri Nov 20 11:07:26 2020 +0000

    Add a warning to dllwrap that it is deprecated.
    
            PR 20979
            * dllwrap.c (main): Deprecate and warn the use of dllwrap.
Comment 9 Nick Clifton 2020-11-20 11:08:55 UTC
Wow - sorry for letting this patch slip through, and thanks for the reminder.

Patch applied.