When will ml64 complain about symbol redefinitions and when not?

Started by markallyn, November 22, 2017, 09:04:11 AM

Previous topic - Next topic

markallyn

Hello everyone,

I am puzzled as to why ml will complain about redefining some symbols and not others.  Consider the following code snippet
Quote[
include \masm32\include64\masm64rt.inc

printf PROTO :QWORD , :VARARG
GetSystemInfo PROTO :QWORD


ml complains with this error "symbol redefinition : __imp_GetSystemInfo

But,  it's quite happy with the printf PROTO.

What's the difference?  I know the two are in two different iimplibs and dlls, but why does ml handle them differently?

Thanks for any clarity you can provide.

Mark Allyn

qWord

masm64rt.inc includes kernel32.inc, which declares GetSystemInfo as __imp_GetSystemInfo and is thus ready to use. printf is not declared, but the include file msvcrt.inc is also included by masm64rt.inc, which does declare vc_printf. The idea was to avoid name conflicts and thus give all functions from the CRT the prefix "cv_" (for masm32 it is "crt_" BTW). Your declaration of printf will be accepted by MASM, but the linker cannot resolve that symbol later, because there is no library associated with it  ==> use vc_printf instead.
MREAL macros - when you need floating point arithmetic while assembling!

markallyn

Good morning, qWord,

I tested your proposal to use vc_printf and NOT declare it with a PROTO statement.  And, indeed, it worked the way you said it would.  Two additional questions.

First, (and this will expose my ignorance about how import libraries work), why does the __imp_ prefix mean that the function is "thus ready to use"? (whereas vc_ disqualifies the associated function from being "ready to use"?).

Second, could you clarify your last sentence a bit more.  (And this probably will further reveal my lack of understanding of how import libraries work...):  The printf PROTO statement is indeed accepted by ml64, but the linker DOES resolve it insofar as printf functions properly.

Thanks for taking the trouble to respond.

Mark


qWord

Sorry, printf is of course supplied by the msvcrt.lib. It's just that the function in the MASM64 SDK is mapped to the prefixed name - so all OK with your own prototype.

Looking in the include files, you will find:
PPROC TYPEDEF PTR PROC
...
externdef __imp_printf:PPROC
vc_printf equ <__imp_printf>

__imp_printf is an external defined symbol, a pointer to a function (printf in this example). vc_printf is a textmacro to give it a more readable name. This symbol (the pointer) is defined by the import library and in the final executable it (the pointer) is placed in (resp. is part of) the import table for the corresponding DLL, which is fixed up with the addresses from the DLL when the program is loaded to run. The import library also exports a symbol without the __imp_ prefix that is  of type "function". For this symbol a small peach of code is supplied (the function) that do nothing more than jumping to the location pointed by __imp_printf, which in turn is fixed up as described before. The none-prefixed symbol is used when declaring a prototype with PROTO (so as external function).

For details on the import table and symbols (in this context) see the PE/COFF specifications.
MREAL macros - when you need floating point arithmetic while assembling!

markallyn

Hello again, qWord,

Thanks for your explanation.  I think I see what happened.  I have been reading the coff/pe specs for a few days now and had previously looked at the .idata section, so I was able to follow your tutorial.

A question out of curiosity:  what happened to the crt prefix for msvcrt functions?  I didn't find it when I inspected the Include64 msvcrt.inc file?  Perhaps it was deprecated when 64 bit came along?

Regards,
Mark

qWord

There are two set of includes: one for 32 bit code (\masm32\include\) and one for 64 bit code (\masm32\include64\). I cannot tell you why hutch changed the prefix from crt_ to vc_ for 64 bit, but as said, the purpose of these prefixes is just to avoid name conflicts.

regards
MREAL macros - when you need floating point arithmetic while assembling!

Vortex

I think vc_ looks more descriptive as there are two main versions of C run-time DLLs :

msvcrt.dll
crtdll.dll


Naturally, one can find more DLLs with each release of Visual Studio.

markallyn

hello qWord and Vortex,

I see what Vortex means and I agree with him that vc_ is visibly more accurate. 

It remains unclear to me why not just leave the original textequ macro so it matches others found in import libraries like kernel32.lib  I understand the point about name conflicts in the abstract, but are they any more prevalent or likely to occur than conflicts over printf and other msvcrt functions simply because printf gets prepended with vc_ ?  I guess you think so.

Anyway, thanks both of you for helping me with this.  It's bothered me for quite some time and I was too lazy to investigate.  And perhaps a bit too shy.

Mark

hutch--

Mark,

While the 64 bit version of MASM looks much like the 32 bit version of MASM32, they are structurally very different and the 64 bit version had to be written from scratch and that meant includes, libraries and macros. When a dedicated system provided runtime library like MSVCRT is used, it has many hundreds of function names in it, some of which cannot be used due to being the same as MASM reserve words and then you have a multitude of later variations on MSVCRT which have overlaps in function names so the cleanest solution was to prefix the function names so that you could use any of the versions of MSVC****.LIB without linker errors from trying to use the same name for different runtime DLLs.

The 64 bit project does NOT attempt to be backwards compatible with the 32 bit version as it will not be compromised with the assumptions of 16 and 32 bit code, at a coding level it looks similar but behind that, it is very different by necessity due to OS design differences.

markallyn

Good morning/evening Hutch,

Thank you for replying to my query.   I believe I understand your explanation.  As always, this site is beautiully kind and generous to novices like me.

I do have one further question on this subject.  Namely, is msvcrt.lib/dll the only instance where I will get an error if I attempt to do a PROTO on one of the functions.  Thus far it has only happened in connection with kernel32.lib functions, but there may be others too.

Thanks again. 

Mark

hutch--

Mark,

In most instances you don't use prototypes in ml64 as it does not support them, it frees you from having to make them but means you must get the arguments right. Once you are used to it you code a lot faster but there is no warning about argument errors. ml64 is a reasonably low level tool that was never aimed at the consumer market and it can pelt garbage at you if you get it wrong but the code quality is fine if you get it right.

markallyn

Good evening\morning Hutch,

Thanks.  I had thought as much, but wasn't sure.  Very clear.

Mark