Discussion:
DLL
(too old to reply)
muta...@gmail.com
2021-08-28 19:23:00 UTC
Permalink
I am having trouble building a DLL via what appears
to be the documented process, and I thought I would
use this opportunity to find out what a DLL actually is.

If I have two independent source files, foo.c and bar.c,
each with one function in it, ie foo() and bar()
respectively, is this something that is suitable to put
into a DLL, or is there an expectation that it all be
linked in to a single executable?

I ask because I have this code in dllcrt.c:

BOOL WINAPI DllMainCRTStartup(HINSTANCE hinstDll,
DWORD fdwReason,
LPVOID lpvReserved)
{
BOOL bRet;

/* DllMain() is optional, so it would be good to handle that case too. */
bRet = DllMain(hinstDll, fdwReason, lpvReserved);

return (bRet);
}

(apparently written by Alica).

Although the code works fine with gccwin, when I
tried to build my own kernel32.dll using the old
version of Visual Studio I have installed, I got a
link error which was resolved by adding an
underscore to the above name.

But the DLL being produced is very small and doesn't
contain the functions I want, and that is confirmed
by the link map.

Any idea what a DLL actually is?

Thanks. Paul.




cl -c -O2 -Oi- -Zl -GS- -nologo -D__WIN32__ -D__EXPORT__ -I ../pdpclib -I . ../pdpclib/dllcrt.c

cl -c -O2 -Oi- -Zl -GS- -nologo -D__WIN32__ -D__EXPORT__ -I ../pdpclib -I . kernel32.c
cl -c -O2 -Oi- -Zl -GS- -nologo -D__WIN32__ -D__32BIT__ -I ../pdpclib -I . pos.c

rem ml -c -coff support.s
aswin -o support.obj support.s

rem ldwin -s -o kernel32.dll --shared --kill-at dllcrt.o kernel32.o pos.o support.o
rem dlltwin -S aswin -k --export-all-symbols -D kernel32.dll kernel32.o -l kernel32.a

cl -LD -Fm -Fekernel32.dll dllcrt.obj kernel32.obj pos.obj support.obj



kernel32

Timestamp is 612a6f08 (Sun Aug 29 03:14:48 2021)

Preferred load address is 10000000

Start Length Name Class
0001:00000000 00000200H .text CODE
0002:00000000 00000000H .data DATA
0002:00000000 00000010H .bss DATA

Address Publics by Value Rva+Base Lib:Object

0000:00000000 ___safe_se_handler_table 00000000 <absolute>
0000:00000000 ___safe_se_handler_count 00000000 <absolute>
0001:00000000 ***@12 10001000 f dllcrt.obj
0001:00000010 _int86 10001010 support.obj
0001:00000010 _int86x 10001010 support.obj
0001:00000135 _enable 10001135 support.obj
0001:00000137 _disable 10001137 support.obj
0001:00000139 _inp 10001139 support.obj
0001:00000149 _inpw 10001149 support.obj
0001:0000015a _inpd 1000115a support.obj
0001:0000016a _outp 1000116a support.obj
0001:00000178 _outpw 10001178 support.obj
0001:00000187 _outpd 10001187 support.obj
0001:00000195 ___setj 10001195 support.obj
0001:000001c6 ___longj 100011c6 support.obj
0002:00000000 ___needdum 10002000 dllcrt.obj

entry point at 0001:00000000

Static symbols
Tavis Ormandy
2021-08-28 23:26:48 UTC
Permalink
Post by ***@gmail.com
But the DLL being produced is very small and doesn't
contain the functions I want, and that is confirmed
by the link map.
You need to mark the symbols you want exported, or the compiler will
assume it's dead code and remove them - they're not visible outside of
the current compilation unit, and you never called them...so why keep
them!

The easy solution is to just add __declspec(dllexport) to the functions
you want exported. Alternatively, you can make a def file to tell the
linker precisely what you wanted.

Tavis.
--
_o) $ lynx lock.cmpxchg8b.com
/\\ _o) _o) $ finger ***@sdf.org
_\_V _( ) _( ) @taviso
muta...@gmail.com
2021-08-29 05:20:20 UTC
Permalink
Post by Tavis Ormandy
Post by ***@gmail.com
But the DLL being produced is very small and doesn't
contain the functions I want, and that is confirmed
by the link map.
You need to mark the symbols you want exported, or the compiler will
assume it's dead code and remove them - they're not visible outside of
the current compilation unit, and you never called them...so why keep
them!
The easy solution is to just add __declspec(dllexport) to the functions
you want exported. Alternatively, you can make a def file to tell the
linker precisely what you wanted.
Hi Tavis. Thanks for your reply.

That solved the problem!

My next problem is that my functions appear to have an
underscore in front of them (from kernel32.map):

0001:00000040 ***@20 10001040 f kernel32.obj

What will Microsoft be doing to suppress that?

Here is how each function I define looks like:

#define WINAPI __declspec(dllexport) __stdcall

I'm guessing that Microsoft has done something special
to avoid namespace pollution. Any idea what?

Thanks. Paul.
Scott Lurndal
2021-08-29 13:33:02 UTC
Permalink
Post by ***@gmail.com
My next problem is that my functions appear to have an
https://www.google.com/search?q=why+do+DLL+symbols+start+with+an+underscore%3F
muta...@gmail.com
2021-08-29 18:20:36 UTC
Permalink
Post by Scott Lurndal
Post by ***@gmail.com
My next problem is that my functions appear to have an
https://www.google.com/search?q=why+do+DLL+symbols+start+with+an+underscore%3F
That doesn't answer my question.

I think Microsoft either have a secret compiler
option, or they are using small assembler functions
with a jmp, ie

***@20:
jmp ***@20

Because it's not enough to just have a .def file to
remap names - you need to get the DLL right.

BFN. Paul.
Alexei A. Frounze
2021-08-29 21:58:10 UTC
Permalink
Post by ***@gmail.com
My next problem is that my functions appear to have an
What will Microsoft be doing to suppress that?
#define WINAPI __declspec(dllexport) __stdcall
I'm guessing that Microsoft has done something special
to avoid namespace pollution. Any idea what?
I think this is the normal name decoration per the __stdcall calling convention:
https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160

There's nothing wrong with it.

The default C/C++ convention is __cdecl:
https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-160

Which prepends an underscore, except when exporting, if I'm reading it right.

The @size suffix is what makes __stdcall and __cdecl coexist without clashing.

Seems like either you should use __cdecl or you're missing proper function
declarations (with the calling convention/dllimport modifiers) on the importing side.

Alex
muta...@gmail.com
2023-05-03 12:56:45 UTC
Permalink
Post by ***@gmail.com
Post by Tavis Ormandy
Post by ***@gmail.com
But the DLL being produced is very small and doesn't
contain the functions I want, and that is confirmed
by the link map.
You need to mark the symbols you want exported, or the compiler will
assume it's dead code and remove them - they're not visible outside of
the current compilation unit, and you never called them...so why keep
them!
The easy solution is to just add __declspec(dllexport) to the functions
you want exported. Alternatively, you can make a def file to tell the
linker precisely what you wanted.
Hi Tavis. Thanks for your reply.
That solved the problem!
My next problem is that my functions appear to have an
What will Microsoft be doing to suppress that?
#define WINAPI __declspec(dllexport) __stdcall
I'm guessing that Microsoft has done something special
to avoid namespace pollution. Any idea what?
I had another crack at this.

I spent a lot of effort, writing programs to generate assembler
code and generate aliases.

In the end it was near the end of this that nailed it:

https://stackoverflow.com/questions/2804893/c-dll-export-decorated-mangled-names/2805560#2805560

Use a simple:

EXPORTS
SetCallback

and it removes the decoration automatically.

So I can now use Visual Studio 2005 to create kernel32.dll,
kernel32.lib, msvcrt.dll and msvcrt.lib (my own versions of
all of those) and both the DLLs and programs linked with
them work on both PDOS/386 and Windows. (Although I
didn't specifically attempt to replace the Windows DLLs
on Windows).

I think it is good to have the option of professionally
supported tools like Visual Studio.

I also have the option of the gnu toolchain.

And I almost have the option of public domain replacements
for everything.

Oh - I have a little bit (400 lines) of assembler that is AT&T syntax
so I am using binutils to assemble that. I'm not yet in a position
to switch to using masm syntax.

BFN. Paul.

Loading...