Weak Externals: Description, Usage, and Errors

ID Number: Q72651

5.05 5.10 5.11 5.13 | 5.05 5.10 5.11 5.13

MS-DOS | OS/2

Summary:

Weak externals are a special type of extern reference that allow the

linker to use an alternate symbol to fix up an address. Through the

use of a weak external record, a library developer can have an

alternate symbol used if no other references are made to the module

where the primary symbol resides.

The Microsoft Incremental Linker (ILINK) does not provide support for

this type of record and will return the following error message if it

encounters a weak extern record:

fatal error L1246: weak externals not supported

To work around the problem, perform a full link.

More Information:

You can create weak externals with the Microsoft Macro Assembler

(MASM) version 6.0, which will allow you to specify an alternate

symbol when defining an EXTRN. MASM takes this alternate ID and

creates both a standard EXTDEF record for the primary symbol and a

COMENT record with the alternate symbol in the object file.

The COMENT record tells LINK and LIB to treat the alternate symbol as

a "weak" external reference. If there are no other references to the

module in which the standard symbol resides, LINK will use the weak

extern address to fix up the reference.

For example, assume you write some functions in assembler to perform

some housekeeping chores and you put these functions in your library.

In addition, you might write one function that calls these various

housekeeping functions. For example:

EXTRN _InitHeap:near

EXTRN _InitFile:near

EXTRN _InitKbd:near

InitLib PROC NEAR

call _InitHeap

call _InitFile

call _InitKbd

InitLib ENDP

Each of these functions (_InitHeap, _InitFile, and _InitKbd) may

reside in a module that defines the functions and symbols each

subsystem uses. For instance, here is a sample LIB listing showing the

possible contents of the module in which _InitKbd resides:

KbdStuff Offset: 00000010H Code and data size: 915H

_InitKbd _ReadKey _SendKey _KeyBuffer

_FlushKey _ScanCode _CharCode _BiosState

_Int16Handler _CtrlBrkStat _EchoState

Regardless of whether the program uses anything else from the KbdStuff

module, the entire module is linked into the .EXE. If none of the

other modules are required for the program, the _InitKbd function

might not be required either. Thus, using regular EXTRNs, you have

added dead code (that is, the rest of the KbdStuff module) to the

.EXE, and you have also executed code (_InitKbd) that is not necessary.

Now, reconsider this example with the use of weak externals. Just

change the EXTRN statement to specify an alternate symbol. For

instance:

EXTRN _InitKbd(_EmptyInit):near

Here is the _EmptyInit code:

_EmptyInit PROC NEAR

ret

_EmptyInit ENDP

The linker can now use the weak external _EmptyInit to resolve the

reference to _InitKbd if none of the other symbols in the KbdStuff

module are needed. If other symbols in KbdStuff really are referenced,

the original _InitKbd symbol will be used.

The same situation applies to data symbols. For instance, you may want

to set a flag to indicate if a branch in your code should be taken

based on other modules that may be linked in. Once again, you just add

the default and alternate resolution to the EXTRN statement and

assemble the code. The linker will use the one that is needed.

Note: Assume you define the same alternate reference with two

different primary references in two separate modules as follows:

MOD1.ASM

--------

EXTRN Primary1(Alternate):near

MOD2.ASM

--------

EXTRN Primary2(Alternate):near

In this case, LINK will generate the following warning:

warning L4067: changing default resolution for weak external

'symbol' from 'oldresolution' to 'newresolution'

When this happens, LINK uses the default reference from the second

module in both cases (Primary2 in this example).

For more information on the EXTRN directive, the see the online help

and section 8.4.2 of the "Microsoft Macro Assembler Programmer's

Guide" for version 6.0.

For more information on the weak extern (WKEXT) .OBJ record format,

see section 2.11 of the "Microsoft C Developer's Toolkit Reference."