I have a question to the list, if anyone here knows details of how windows dlls work.
I cross compile for windows with
./configure --host=x86_64-w64-mingw32 --enable-mini-gmp CXX=/bin/false make
and run tests with
make check EMULATOR=wine64
It fails the ecc-dup and ecc-add tests, in this and similar asserts:
ASSERT (ecc->dup == ecc_dup_jj);
Here, the right hand side is a symbol from libhogweed-x.dll, and on the left hand side, ecc refers to a constant struct in the same dll.
My guess us that dynamic linking on windows doesn't provide function pointer comparisons as specified by the C standard. Maybe left-hand side is the real function entry point, and the right hand side is the address of some glue code related to dynamic linking. Is that right? If so, I can just disable this assert for windows, but I'd like to understand what'g going on.
I think the reason it works with ELF, is that ELF dynamic linking tries harder to make all references point to the same PLT glue code, but I don't fully understand the details there either.
Somewhat related to this: The ecc pointer is taken from this array in testutils.c:
const struct ecc_curve * const ecc_curves[] = { &_nettle_secp_192r1, &_nettle_secp_224r1, &_nettle_secp_256r1, &_nettle_secp_384r1, &_nettle_secp_521r1, &_nettle_curve25519, &_nettle_curve448, &_nettle_gost_gc256b, &_nettle_gost_gc512a, NULL };
The entries are references to data objects in the dll. I'm a bit surprised that works at all, is it expected to work? I had the impression that dlls only exported functions. Should the test code be changed to use the advertised getter functions, nettle_get_secp_256r1 and friends?
Regards, /Niels
From: nisse@lysator.liu.se (Niels Möller) Date: Wed, 22 Apr 2020 21:48:31 +0200
I have a question to the list, if anyone here knows details of how windows dlls work.
I cross compile for windows with
./configure --host=x86_64-w64-mingw32 --enable-mini-gmp CXX=/bin/false make
and run tests with
make check EMULATOR=wine64
It fails the ecc-dup and ecc-add tests, in this and similar asserts:
ASSERT (ecc->dup == ecc_dup_jj);
Here, the right hand side is a symbol from libhogweed-x.dll, and on the left hand side, ecc refers to a constant struct in the same dll.
Please tell more details, perhaps showing the code which obtains the values of these variables. In particular, I don't understand what do you mean by "symbol": this is C, and C doesn't have symbols as one of its data types. And what is the purpose of this assertion?
My guess us that dynamic linking on windows doesn't provide function pointer comparisons as specified by the C standard. Maybe left-hand side is the real function entry point, and the right hand side is the address of some glue code related to dynamic linking. Is that right? If so, I can just disable this assert for windows, but I'd like to understand what'g going on.
Yes, a DLL call is an indirect call through a function address in a table, but to give you a detailed enough answer, I'd like to understand the situation better.
Somewhat related to this: The ecc pointer is taken from this array in testutils.c:
const struct ecc_curve * const ecc_curves[] = { &_nettle_secp_192r1, &_nettle_secp_224r1, &_nettle_secp_256r1, &_nettle_secp_384r1, &_nettle_secp_521r1, &_nettle_curve25519, &_nettle_curve448, &_nettle_gost_gc256b, &_nettle_gost_gc512a, NULL };
The entries are references to data objects in the dll. I'm a bit surprised that works at all, is it expected to work? I had the impression that dlls only exported functions.
No, DLLs can export variables as well, and programs linked against it can import them.
Eli Zaretskii eliz@gnu.org writes:
It fails the ecc-dup and ecc-add tests, in this and similar asserts:
ASSERT (ecc->dup == ecc_dup_jj);
Here, the right hand side is a symbol from libhogweed-x.dll, and on the left hand side, ecc refers to a constant struct in the same dll.
Please tell more details, perhaps showing the code which obtains the values of these variables. In particular, I don't understand what do you mean by "symbol": this is C, and C doesn't have symbols as one of its data types.
The "ecc" variable is a local defined like
const struct ecc_curve *ecc = ecc_curves[i];
(where ecc_curves is the array quoted below). And ecc_dup_jj is a top-level function, declared as
void ecc_dup_jj (const struct ecc_curve *ecc, mp_limb_t *r, const mp_limb_t *p, mp_limb_t *scratch);
The implementation is in the dll, so it is resolved by the dynamic linker. I've found this stackoverflow question which also asks about pointer equality with dlls: https://stackoverflow.com/questions/20517589/function-pointer-values-inside-...
And by "symbol", I mean a name that is handled in the linking process.
And what is the purpose of this assertion?
To check that the ecc_curve points to an appropriate implementation of the point duplication function (different curves uses different functions). To get a clearer error than just unexpected output numbers if the wrong function is used.
But maybe value is quite small, I'll consider deleting the assert.
Somewhat related to this: The ecc pointer is taken from this array in testutils.c:
const struct ecc_curve * const ecc_curves[] = { &_nettle_secp_192r1, &_nettle_secp_224r1, &_nettle_secp_256r1, &_nettle_secp_384r1, &_nettle_secp_521r1, &_nettle_curve25519, &_nettle_curve448, &_nettle_gost_gc256b, &_nettle_gost_gc512a, NULL };
The entries are references to data objects in the dll. I'm a bit surprised that works at all, is it expected to work? I had the impression that dlls only exported functions.
No, DLLs can export variables as well, and programs linked against it can import them.
Thanks, that's good to know.
Regards, /Niels
From: nisse@lysator.liu.se (Niels Möller) Cc: nettle-bugs@lists.lysator.liu.se Date: Thu, 23 Apr 2020 17:10:54 +0200
The "ecc" variable is a local defined like
const struct ecc_curve *ecc = ecc_curves[i];
(where ecc_curves is the array quoted below). And ecc_dup_jj is a top-level function, declared as
void ecc_dup_jj (const struct ecc_curve *ecc, mp_limb_t *r, const mp_limb_t *p, mp_limb_t *scratch);
The implementation is in the dll, so it is resolved by the dynamic linker. I've found this stackoverflow question which also asks about pointer equality with dlls: https://stackoverflow.com/questions/20517589/function-pointer-values-inside-...
And by "symbol", I mean a name that is handled in the linking process.
Then yes, you need to use GetProcAddress to obtain the real address of a function in a DLL. Then you can compare that with your table of function pointers. When you write code that directly calls a function whose implementation is in a DLL, you actually call through a jump table. You can clearly see that if you disassemble the code around such call.
nettle-bugs@lists.lysator.liu.se