So errno was a bad example but you can try accessing e.g. __ctype_ptr__,
__progname, optarg, h_errno, or use FE_DFL_ENV from another DLL, just
for kicks.
__ctype_ptr__ is a function

h_errno works like errno with an imported function

FE_DFL_ENV is a macro

__progname and optarg are local variables to each exe or dll


Note that the 2GB limit applies to_static linking_, not to_dynamic linking_.

Allow me to explain the difference. Static linking is the linking of object 
files together into an EXE or DLL file. Dynamic linking is the linking between 
different EXE or DLL files.

Static linking is done by the linker. If function A() in a.cpp is calling 
function B() in b.cpp, then you can compile and link a.cpp and b.cpp together 
into ab.exe, using the linker. The linker will insert the relative address of B 
by directly modifying the call B instruction in a.o. The linker will give an 
error message if the address overflows beyond the 2GB limit. The same process 
applies when linking to a global variable in b.cpp. The call instruction always 
uses a 32-bit relative address. The link to a variable can use different 
addressing modes: 32-bit absolute address, 32-bit relative address, and 64-bit 
absolute address. The 32-bit absolute address can be used in Linux, but not in 
Win64 and MacOS. This is why the small memory model is different in Linux and 
Windows (64 bit).

Dynamic linking is done by the loader, not the linker. If a function in ab.exe 
calls function C() in C.DLL, then the process is different. D.DLL is loaded by 
the loader, and the address of C() is inserted into an import table. The import 
table contains 64-bit absolute addresses.

It is not possible to insert the address of a function or variable from a 
different EXE or DLL directly into a code instruction. The loader simply cannot 
do this, only the linker can.

This is the reason why the link to errno and other seemingly global variables 
are replaced by functions. errno was not a bad example, it shows how a variable 
in a different DLL is accessed.

gcc is using the small memory model by default in Cygwin64, and it works.

clang is using the small memory by default when cross-compiling for a Cygwin64 
target from Linux, and it works.

Kai Tietz wrote:
  Another thing, which
cygwin depends heavily on is the pseudo-relocation stuff.  It is not
guaranteed that code distance between DSOs are in valid range here to
fit in a single instruction to be relocated.  So the distance allowed
for a "small model instruction" might be in some cases even less 4 GB.
For pseudo-relocation the large memory model is absolutely mandatory
for bigger application.
Kai, can you please point me to a description of the DSO and pseudo-relocation. 
I cannot find it. But I suppose it inserts 64-bit addresses into some sort of 
GOT or PLT without using the traditional linker.

Agner


On 16/08/2019 13.11, Corinna Vinschen wrote:
On Aug 16 12:38, Agner Fog wrote:
On 16/08/2019 11.52, Corinna Vinschen wrote:
2 GB. Think errno accessed from another DLL. Your application works only
by chance.
Good example.

errno appears to be a global variable for historical reasons, but errno is
implemented as a macro that translates to a call to the imported function
__errno.

This function call goes through a 64-bit import table from cygwin1.dll

Works fine with -mcmodel=small

Static sharing of a global variable between exe and dll, or between
different dll's is not possible.
So errno was a bad example but you can try accessing e.g. __ctype_ptr__,
__progname, optarg, h_errno, or use FE_DFL_ENV from another DLL, just
for kicks.

Just because lots of stuff works with the small mode doesn't mean it's
the right thing to do.  Mcmodels medium and large have been introduced
into GCC during the Cygwin 64 bit port for a reason.


Corinna


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to