Author Topic: DLL to LIB unresolved external symbol  (Read 2663 times)

2B||!2B

  • Member
  • **
  • Posts: 75
DLL to LIB unresolved external symbol
« on: November 05, 2018, 04:39:40 PM »
Hi,

I have tried the tool Dll2lib from http://www.binary-soft.com/ to convert my Delphi 7 DLL to a static library.

However, no matter what i try, i always get linker error

Code: [Select]
error LNK2001: unresolved external symbol _AddNumbers@8
My delphi dll looks like this

Code: [Select]
library MyDLL;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
 //ShareMem,
  SysUtils,
  Classes,
  Windows,
  Controls,
  Forms,
  ImgList,
  Unit1 in 'Unit1.pas' {Form1};

  function AddNumbers(a:Integer;b:Integer):Integer;stdcall;forward;





exports  AddNumbers;



{$R *.res}



 function AddNumbers(a:Integer;b:Integer):Integer  ;  stdcall;




begin
  Result  := a + b;

end;
end.

MASM calling

Code: [Select]
includelib MyDLL.lib ;The one generated by dll2lib.
AddNumbers   PROTO :DWORD,:DWORD
invoke AddNumbers,1,2

I have also tried this one here http://www.ionicwind.com/forums/index.php?topic=1361.0
I got the same result about linking error.

Does anyone know if this is possible at all?

jj2007

  • Member
  • *****
  • Posts: 10339
  • Assembler is fun ;-)
    • MasmBasic
Re: DLL to LIB unresolved external symbol
« Reply #1 on: November 05, 2018, 06:53:49 PM »
Write a little module that contains AddNumbers, and link the obj file together with the obj file obtained from the DLL.

2B||!2B

  • Member
  • **
  • Posts: 75
Re: DLL to LIB unresolved external symbol
« Reply #2 on: November 05, 2018, 08:59:37 PM »
The problem is that Delphi does not generate COFF obj file format but rather OMF obj format.
I have already converted it to COFF obj file with objconv tool. When i link this converted obj file, it still unable to resolve the external symbols.

jj2007

  • Member
  • *****
  • Posts: 10339
  • Assembler is fun ;-)
    • MasmBasic
Re: DLL to LIB unresolved external symbol
« Reply #3 on: November 05, 2018, 09:09:16 PM »
When i link this converted obj file, it still unable to resolve the external symbols.

Well... do you link it with a module that does contain the correctly prototyped AddNumbers? Try something like this:
Code: [Select]
.486                                      ; create 32 bit code
.model flat, stdcall                      ; 32 bit memory model

.code
AddNumbers proc int1, int2
  mov eax, int1
  add eax, int2
  ret
AddNumbers endp
end

sinsi

  • Guest
Re: DLL to LIB unresolved external symbol
« Reply #4 on: November 05, 2018, 09:24:54 PM »
Try dumping the .lib to see how AddNumbers is declared. Maybe this will work?
Code: [Select]
_imp__AddNumbers@8 PROTO :dword,:dword
AddNumbers TEXTEQU <_imp__AddNumbers@8>

Mikl__

  • Member
  • ****
  • Posts: 927
Re: DLL to LIB unresolved external symbol
« Reply #5 on: November 05, 2018, 09:40:17 PM »
Hi, to be or not to be!
look here I think that much will be clear without translation, but in the extreme case, you can use the online service Google Translator

2B||!2B

  • Member
  • **
  • Posts: 75
Re: DLL to LIB unresolved external symbol
« Reply #6 on: November 05, 2018, 10:38:18 PM »
When i link this converted obj file, it still unable to resolve the external symbols.

Well... do you link it with a module that does contain the correctly prototyped AddNumbers? Try something like this:
Code: [Select]
.486                                      ; create 32 bit code
.model flat, stdcall                      ; 32 bit memory model

.code
AddNumbers proc int1, int2
  mov eax, int1
  add eax, int2
  ret
AddNumbers endp
end

Yes, i did. Both .lib and obj gives the same linking error.


Try dumping the .lib to see how AddNumbers is declared. Maybe this will work?
Code: [Select]
_imp__AddNumbers@8 PROTO :dword,:dword
AddNumbers TEXTEQU <_imp__AddNumbers@8>

It does not work. It also shows the linking error with this function name but rather with double @8


Hi, to be or not to be!
look here I think that much will be clear without translation, but in the extreme case, you can use the online service Google Translator

Hey Mikl__,

Thanks for your link. I will have to read this carefully after translating it. See if i can get anywhere.


I have attached the example if someone might want to take a look at it.
It contains the dll and the static library.

MyDLL.lib - generated by dll2lib
« Last Edit: November 06, 2018, 07:26:22 AM by 2B||!2B »

TimoVJL

  • Member
  • ****
  • Posts: 526
Re: DLL to LIB unresolved external symbol
« Reply #7 on: November 05, 2018, 11:05:42 PM »
Delphi dll exports undecorated function names, so converter can't know that decorated name.

EDIT:
Code: [Select]
library MyDLL;

function AddNumbers(a:Integer;b:Integer):Integer;stdcall;forward;

exports
  AddNumbers, AddNumbers name '_AddNumbers@8';

function AddNumbers(a:Integer;b:Integer):Integer  ;  stdcall;
begin
  Result  := a + b;
end;
end.
EDIT: Dll to Dll can use dll's import library.
« Last Edit: November 06, 2018, 09:07:47 AM by TimoVJL »
May the source be with you

sinsi

  • Guest
Re: DLL to LIB unresolved external symbol
« Reply #8 on: November 05, 2018, 11:14:51 PM »
You may have more than one problem.

Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

MyDLL.lib(MyDLL.obj) : warning LNK4078: multiple ".edata" sections found with different attributes (50100040)
MyDLL.lib(MyDLL.obj) : warning LNK4078: multiple ".rsrc" sections found with different attributes (50100040)
LINK : fatal error LNK1104: cannot open file "LIBC.lib"


Added this code
Code: [Select]
prAddNumbers TYPEDEF PROTO STDCALL  :DWORD,:DWORD
PAddNumbers TYPEDEF PTR prAddNumbers
EXTERNDEF AddNumbers:PAddNumbers
No complaints about AddNumbers

edit: using "includelib libc.lib" then complains about a missing oldnames.lib (libc is in the masm32\lib folder but oldnames isn't)

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 7326
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: DLL to LIB unresolved external symbol
« Reply #9 on: November 06, 2018, 01:19:02 AM »
I guess it depends on the type of lib you want to get from the DLL. I would imagine that am import library would be no big deal if you can match the calling convention but a static library derived from a DLL is far more problematic in what you have to do to get it to work. The conversion tool has to be able to identify the start and end of each procedure, correctly identify any function it imports from system DLLs and get all of the OFFSETs right.

An old friend of mine years ago (Jeremy Collake) was writing tools like this but they were always problematic as the form of DLLs is very diverse, particularly if you are using Borland compilers which differ from Microsoft compilers.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

AW

  • Member
  • *****
  • Posts: 2583
  • Let's Make ASM Great Again!
Re: DLL to LIB unresolved external symbol
« Reply #10 on: November 06, 2018, 03:30:56 AM »
I use Delphi since immemorial times, last version I purchased was XE2 which supports the COFF format. Previous versions use the OMF as you know. If this helps in any way, I have never been able to make a proper OMF to COFF conversion using any utility including objconv. There is an article in CodeProject that may help you somehow.

Vortex

  • Member
  • *****
  • Posts: 2245
Re: DLL to LIB unresolved external symbol
« Reply #11 on: November 06, 2018, 05:08:50 AM »
Hi  2B||!2B,

The OMF format is an antique specification dating from the late 70s. It's possible to employ DLLs like "static libraries" The trick is to write your own custom PE loader.

2B||!2B

  • Member
  • **
  • Posts: 75
Re: DLL to LIB unresolved external symbol
« Reply #12 on: November 06, 2018, 07:24:39 AM »
Delphi dll exports undecorated function names, so converter can't know that decorated name.

EDIT:
Code: [Select]
library MyDLL;

function AddNumbers(a:Integer;b:Integer):Integer;stdcall;forward;

exports
  AddNumbers, AddNumbers name 'AddNumbers@8';

function AddNumbers(a:Integer;b:Integer):Integer  ;  stdcall;
begin
  Result  := a + b;
end;
end.

I don't think this is the problem. I have tried to use the name AddNumbers@8 but it still has the same linking error.

You may have more than one problem.

Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

MyDLL.lib(MyDLL.obj) : warning LNK4078: multiple ".edata" sections found with different attributes (50100040)
MyDLL.lib(MyDLL.obj) : warning LNK4078: multiple ".rsrc" sections found with different attributes (50100040)
LINK : fatal error LNK1104: cannot open file "LIBC.lib"


Added this code
Code: [Select]
prAddNumbers TYPEDEF PROTO STDCALL  :DWORD,:DWORD
PAddNumbers TYPEDEF PTR prAddNumbers
EXTERNDEF AddNumbers:PAddNumbers
No complaints about AddNumbers

edit: using "includelib libc.lib" then complains about a missing oldnames.lib (libc is in the masm32\lib folder but oldnames isn't)

Hi sinsi,

Very good way of fixing this  :greenclp:
oldnames.lib is found in C:\Program Files\Microsoft Visual Studio\VC98\Lib if you have the VC6.0
It worked fine with me without the need of linking libc and oldnames.lib. However, there is one issue
the compiled exe turned out to use a call to a pointer rather than a direct call to the function using the Invoke keyword.

Code: [Select]
00401000 >  6A 0A           PUSH 0A
00401002    6A 0A           PUSH 0A
00401004    FF15 B2104000   CALL DWORD PTR DS:[4010B2]


But at 4010B2 is the function itself not a pointer to function

4010B2 - AddNumbers successfully compiled
Code: [Select]
004010B2    55              PUSH EBP
004010B3    8BEC            MOV EBP,ESP
004010B5    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]
004010B8    0345 0C         ADD EAX,DWORD PTR SS:[EBP+C]
004010BB    5D              POP EBP                                  ; kernel32.7742EE6C
004010BC    C2 0800         RETN 8




I guess it depends on the type of lib you want to get from the DLL. I would imagine that am import library would be no big deal if you can match the calling convention but a static library derived from a DLL is far more problematic in what you have to do to get it to work. The conversion tool has to be able to identify the start and end of each procedure, correctly identify any function it imports from system DLLs and get all of the OFFSETs right.

An old friend of mine years ago (Jeremy Collake) was writing tools like this but they were always problematic as the form of DLLs is very diverse, particularly if you are using Borland compilers which differ from Microsoft compilers.

Hi hutch,

I think you are right. Delphi is very diverse in it's way of laying out the resources, the classes, and the forms.
Take a look here https://stackoverflow.com/questions/16892601/omf-format-to-coff-format


I use Delphi since immemorial times, last version I purchased was XE2 which supports the COFF format. Previous versions use the OMF as you know. If this helps in any way, I have never been able to make a proper OMF to COFF conversion using any utility including objconv. There is an article in CodeProject that may help you somehow.

Hi AW,

Thanks for the link.
Yes, you are right. I found Delphi 7 To be different in many ways. Haven't used Delphi X2
See the stackoverflow link i posted above to hatch.

Hi  2B||!2B,

The OMF format is an antique specification dating from the late 70s. It's possible to employ DLLs like "static libraries" The trick is to write your own custom PE loader.

Hi Vortex,

Do you mean loading the DLL directly to memory and then resolve imports/exports/relocs etc and then call the functions directly in memory?

Vortex

  • Member
  • *****
  • Posts: 2245
Re: DLL to LIB unresolved external symbol
« Reply #13 on: November 06, 2018, 07:33:59 AM »
Quote
Do you mean loading the DLL directly to memory and then resolve imports/exports/relocs etc and then call the functions directly in memory?

Exactly. You can check the DLLmem example in the attachment.


TimoVJL

  • Member
  • ****
  • Posts: 526
Re: DLL to LIB unresolved external symbol
« Reply #14 on: November 06, 2018, 09:25:11 AM »
Delphi dll exports undecorated function names, so converter can't know that decorated name.

EDIT:
Code: [Select]
library MyDLL;

function AddNumbers(a:Integer;b:Integer):Integer;stdcall;forward;

exports
  AddNumbers, AddNumbers name 'AddNumbers@8';

function AddNumbers(a:Integer;b:Integer):Integer  ;  stdcall;
begin
  Result  := a + b;
end;
end.

I don't think this is the problem. I have tried to use the name AddNumbers@8 but it still has the same linking error.
My bad,
Code: [Select]
exports
  AddNumbers, AddNumbers name '_AddNumbers@8';
I made a test ;)
EDIT: Dll2Lib support import lib for decorated names.
EDIT: A test program in C:
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "msvcrt.lib")
//#pragma comment(lib, "MyDll.lib")
#pragma comment(lib, "MyDllS.lib")
int __stdcall AddNumbers(int, int);
void mainCRTStartup(void) {exit(main());}
int __cdecl main(void)
{
int n = AddNumbers(1,2);
printf("n=%d\n", n);
return 0;
}
« Last Edit: November 07, 2018, 05:26:17 AM by TimoVJL »
May the source be with you