Clang is using the wrong memory model

Agner Fog agner@agner.org
Sat Aug 17 06:59:00 GMT 2019


> 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



More information about the Cygwin mailing list