How do I link with FreePascal a NASM program calling a DLL? - dll

Problem
I have a function "bob" written in assembler (nasm), which makes use of functions in kernel32.dll. And I have a program in FreePascal, that calls "bob".
I use nasm with:
nasm -fwin32 bob.asm
In FreePascal I declare:
{$link bob.obj}
function bob(s:pchar):longint; stdcall; external name 'bob';
But I get an error when I compile with fpc, telling it doesn't find GetStdHandle and WriteConsoleA (without #n suffix), which are declared extern in bob.asm. I would like to tell fpc to look for them in kernel32.dll, or in an adequate import library.
However, when I use the same function in pure assembly program, it works fine with nasm and golink. And when I don't call DLL functions, I can link with FreePascal with no trouble.
How can I link kernel32 functions with FreePascal, so that assembly functions "see" them ?
A Solution
Given by BeniBela. I change names so that things are easy to follow.
program dlltest;
function WindowsGetStdHandle(n: longint): longint; stdcall;
external 'kernel32.dll' name 'GetStdHandle';
{$asmmode intel}
procedure WrapperGetStdHandle; assembler; public name 'AliasGetStdHandle';
asm
jmp WindowsGetStdHandle
end;
{$link myget.obj}
function AsmGetStdHandle(n: longint): longint; stdcall;
external name 'gethandle';
const STDOUT = -11;
begin
writeln(AsmGetStdHandle(STDOUT));
writeln(WindowsGetStdHandle(STDOUT));
end.
With this in assembly, in myget.asm:
section .text
extern AliasGetStdHandle
global gethandle
gethandle:
mov eax, [esp+4]
push eax
call AliasGetStdHandle
ret 4
WindowsGetStdHandle is another name for GetStdHandle in kernel32.dll.
WrapperGetStdHandle only jump to the preceding, it's here for the alias or public name capability : we give it the name AliasGetStdHandle for external objects. This is the important part, the function get visible to the assembly program.
AsmGetStdHandle is the name in FreePascal of the assembly function gethandle. It calls WrapperStdHandle (nicknamed AliasGetStdHandle), which jumps to WindowsGetStdHandle, the DLL function.
And we are done, now the assembly program can be linked, without changing anything in it. All the renaming machinery is done in the pascal program calling it.
The only drawback: the need for a wrapper function, but it's not overpriced for a fine control of names.
Another solution
If kernel32.dll is not specified in declaration of WindowsGetStdHandle, but with {$linklib kernel32}, then the symbol gets visible in object files linked in the pascal program. However, it seems the $linklib directive alone is not enough, one still has to declare in pascal some function refering to it
program dlltest;
{$linklib kernel32}
function WindowsGetStdHandle(n: longint): longint; stdcall;
external name 'GetStdHandle';
{$link myget.obj}
function AsmGetStdHandle(n: longint): longint; stdcall;
external name 'gethandle';
const STDOUT = -11;
begin
writeln(AsmGetStdHandle(STDOUT));
writeln(WindowsGetStdHandle(STDOUT));
end.
With the following assembly program. AliasGetStdHandle is replaced with GetStdHandle, which now points directly to kernel32 function.
section .text
extern GetStdHandle
global gethandle
gethandle:
mov eax, [esp+4]
push eax
call GetStdHandle
ret 4
But this only works when using the external linker (gnu ld), with command
fpc -Xe dlltest.pas
When omitting opton '-Xe', fpc gives the following error
Free Pascal Compiler version 2.6.0 [2011/12/25] for i386
Copyright (c) 1993-2011 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling dlltest.pas
Linking dlltest.exe
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_dir_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_names_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_fixup_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_dll_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_names_end_kernel32.dll
dlltest.pas(17,1) Error: Asm: Duplicate label __imp_fixup_end_kernel32.dll
dlltest.pas(17,1) Fatal: There were 6 errors compiling module, stopping
Fatal: Compilation aborted

I do not know how to fix the linking issue directly, but you could declare public wrapper functions that export these functions from the Pascal source.
E.g.:
{$ASMMODE INTEL}
procedure WrapperGetStdHandle; assembler; public; alias: '_GetStdHandle#4';
asm jmp GetStdHandle end;
procedure WrapperWriteConsoleA; assembler; public; alias: '_WriteConsoleA#20';
asm jmp WriteConsoleA end;

I suspect there is some import library automatically linked by nasm them for use with nasm code, and probably you need to link the relevant stubs from that library too.
amended:
It might be a problem with smart linking. As said FPC generates import stubs on the fly, but only when needed. Because the Windows unit (that holds all core WINAPI calls) is so large, smart linking (only adding what you use) is activated for it. (there are other reasons too)
The NASM originated obj is outside FPC's control, so the relevant functions are not generated for it.
If that is the case, BeniBela's code might work because it forces a reference from FPC code, linking in the symbols. This is speculation though, it might be something with the decoration too, or something with the leading underscore.
Testing that is simple, use the functions from pascal code without the declarations from Benibela.
Btw, FPC's default is NOT stdcall, so BenBela's functions should probably get a stdcall modifier

Related

How do I link a custom dll in Ada?

So this is a simple project I put together just to test before doing some cool stuff with it later. The eventual goal is to make the program able to handle modularity through awesome dll kung fu.
But, baby steps. Right now I just want to make the thing link.
Here I have Adder.ads:
package Adder is
function Add(A : Integer; B : Integer) return Integer;
end Adder;
And the respective Adder.adb:
package body Adder is
function Add(A : Integer; B : Integer) return Integer is
begin
return A + B;
end Add;
end Adder;
Exciting, I know.
I've seen several different tutorials on how to do this, and none of them agree, but taking a cue from this one, I came up with these commands:
gnatmake -c Adder.adb
gcc -shared -shared-libgcc -o Adder.dll Adder.o
This at least generates a dll. I dunno if it generates one that will actually work or if the problem is with the main exe though.
Now the main exe, I have kept everything in a separate directory so gnat doesn't try to cheat and use the .ali and .o files. Then you copy the dll into the directory before trying to build. I've tried this tweaking lots of different ways and gotten several different errors, but here is what I have right now.
Main.adb:
with Adder_Spec; use Adder_Spec;
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
begin
Put_Line(Integer'Image(Add(3,4)));
end Main;
Yay most useless program ever. Now, knowing I'm supposed to have a spec for the dll, I came up with the aforewith'd Adder_Spec.ads:
package Adder_Spec is
function Add(A : Integer; B : Integer) return Integer;
private
pragma Import(Ada, Add, "Add");
end Adder_Spec;
Now, like I said I've tried this a bunch of different ways, sometimes omitting the third import parameter, other times omitting the import altogether, sometimes keeping the import but not separating it into the private part, you name it. I've also tried playing with the compile command several ways, but here's the most recent one:
gnatmake Main.adb -bargs -shared -largs -lAdder
With this particular command it spits out an "Undefined reference to 'Add'" error. If I add the -v flag, it doesn't provide much more useful information.
Checking gnatmake --help shows me that the default mode is gnat 2012, if that makes any difference. It probably shouldn't, as I've tried compiling with the flags for 2005 and 95, too.
So... can anybody savvy enough spot the problem? Thanks in advance.
If you want to say
package Adder_Spec is
function Add(A : Integer; B : Integer) return Integer;
private
pragma Import(Ada, Add, "Add");
end Adder_Spec;
when importing the DLL, then you have to say
package Adder is
function Add(A : Integer; B : Integer) return Integer;
pragma Export (Ada, Add, "Add");
end Adder;
when building it.
GNAT’s default linker name for the generated Add would be (I think) adder__add; you should be able to see what it is using nm Adder.o.
I suggest that you follow the instructions in "Ada Plug-ins and Shared Libraries" (part 1, part 2) from AdaCore.
I've used the technique described there, and it worked quite fine.

How to load a dll into VS c++, which acts like a wrapper to another CAPL code?

I am trying to reference functions in a 3rd party dll file through CAPL Script. Since, I cannot directly call them, I am trying to create a wrapper which exports the functions in the dll.
int MA_Init(char *TbName, int Option); is the function in the dll file.
The wrapper code for this is
int CAPLEXPORT far CAPLPASCAL CMA_Init(char *TbName, int Option)
{
return MA_Init(*TbName, Option);
}
I am trying to use
HINSTANCE DllHandel = loadlibrary("C:\\Turbo.dll"); to load the library and
typedef int(*TESTFnptr)(char, int);
TESTFnptr fn= (TESTFnptr)getprocaddress(DllHandle, "MA_Init"); to resolve the function address.
However the compiler says the function "MA_Init()" is not defined. I am not sure if I am using the correct procedure to load the dll into my visual C++ project. Has anyone tried doing this or knows how it's done? Thank you very much.
The standard procedure would be to include the corresponding .lib file to VS project. Go to "Project - Properties - Configuration Properties - Linker - Additional Dependencies" and add turbo.lib on a new line. Then you'll need to include the corresponding turbo.h header file which contains the definition for MA_Init function.
In this case, you'll be able to call MA_Init directly, as you do now. The compiler will happily find the definition of MA_Init in the header file, and the linker will find the reference to MA_Init in the .lib file.
If you don't have turbo.h file, you can create one yourself provided you know the prototypes of all functions you want to use. Just put definitions like
int MA_Init(char *TbName, int Option);
there and include it.
If you don't have turbo.lib file, you'll have to proceed with LoadLibrary and GetProcAddress. Obviously, you cannot call MA_Init by name in this case, since it is undefined. You'll have to call the pointer returned by GetProcAddress instead:
TESTFnptr fn = (TESTFnptr)GetProcAddress(DllHandle, "MA_Init");
int CAPLEXPORT far CAPLPASCAL CMA_Init(char *TbName, int Option)
{
return fn(TbName, Option);
}
PS. Notice I removed the start in front of TbName?
PPS. Don't forget to include your wrapper function, CMA_Init, to CAPL_DLL_INFO_LIST, otherwise it will not be accessible in CANoe/CANalyzer.

Using system symbol table from VxWorks RTP

I have an existing project, originally implemented as a Vxworks 5.5 style kernel module.
This project creates many tasks that act as a "host" to run external code. We do something like this:
void loadAndRun(char* file, char* function)
{
//load the module
int fd = open (file, O_RDONLY,0644);
loadModule(fdx, LOAD_ALL_SYMBOLS);
SYM_TYPE type;
FUNCPTR func;
symFindByName(sysSymTbl, &function , (char**) &func, &type);
while (true)
{
func();
}
}
This all works a dream, however, the functions that get called are non-reentrant, with global data all over the place etc. We have a new requirement to be able to run multiple instances of these external modules, and my obvious first thought is to use vxworks RTP to provide memory isolation.
However, no matter what I try, I cannot persuade my new RTP project to compile and link.
error: 'sysSymTbl' undeclared (first use in this function)
If I add the correct include:
#include <sysSymTbl.h>
I get:
error: sysSymTbl.h: No such file or directory
and if i just define it extern:
extern SYMTAB_ID sysSymTbl;
i get:
error: undefined reference to `sysSymTbl'
I havent even begun to start trying to stitch in the actual module load code, at the moment I just want to get the symbol lookup working.
So, is the system symbol table accessible from VxWorks RTP applications? Can moduleLoad be used?
EDIT
It appears that what I am trying to do is covered by the Application Programmers Guide in the section on Plugins (section 4.9 for V6.8) (thanks #nos), which is to use dlopen() etc. Like this:
void * hdl= dlopen("pathname",RTLD_NOW);
FUNCPTR func = dlsym(hdl,"FunctionName");
func();
However, i still end up in linker-hell, even when i specify -Xbind-lazy -non-static to the compiler.
undefined reference to `_rtld_dlopen'
undefined reference to `_rtld_dlsym'
The problem here was that the documentation says to specify -Xbind-lazy and -non-static as compiler options. However, these should actually be added to the linker options.
libc.so.1 for the appropriate build target is then required on the target to satisfy the run-time link requirements.

Get the address in ARM Inline assembly

The IAR compiler for ARM Cortex-M3 provides inline assembly. How can one store the address of a specific function to a location on the stack?
The C code would like this
void tick();
void bar()
{
int x;
// modify a value on stack
(&x)[4] = &tick;
}
While this works in general it is optimized away by the compiler in release build. I have tried to code it with inline assembly
void bar()
{
int x;
asm("ldr r0,%0" : : "i" (&tick));
asm("str r0,[sp+#0x10];
}
The ldr instruction is not accepted by the IAR compiler. The problem is that this instruction requires an addressing mode with a register and offset. The actual address of the function tick is store behind the function and the ldr instruction holds only the offset to the memory location the holds the actual address. The disassembly is similar like this:
ldr r0,??tick_address
str r0,[sp+#0x10]
bx lr ; return
??tick_address dd tick
How do I get the address of tick immediately to a register to use it for the stack manipulation?
GNU GCC inline assembly can do mere assignments via pseudo-empty asm() statements, like:
asm("" : "=r"(foo) : "0"(tick));
This tells the compiler:
The variable foo is to be taken from a register after the inline assembly block
The variable tick is to be passed in - in the same register (argument zero)
The actual choice of which register is to be used is completely left to the compiler.
The trick here are the output and input constraints - we just alias the (one and only) input to the output, and the compiler will, on its own, choose a suitable register, and generate the instructions necessary to load / store the respective variables before / after the "actual" inline assembly code. You could even do:
asm("" : "=r"(foo1), "=r"(foo2) : "0"(tick1) , "1"(tick2));
to do two "assignments" in a single inline assembly statement.
This compiler-generated "set the inputs, retrieve the outputs" code generation happens even if the actual inline assembly is empty (as here).
Another example: Say you want to read the current program counter - the PC register. You can do that on ARM via two different inline assembly statements:
asm("" : "=pc"(foo));
asm("mov %0, PC" : "=r"(foo));
This is not 100% identical; in the second case, the compiler knows that whatever register it wants to see foo in after the asm, it'll find it there. In the former, the compiler knows that were it to use foo after the statement, it needs to retrieve it from PC. The difference between the two would be if you did:
uintptr_t *val;
uintptr_t foo;
asm("" : "=pc"(foo));
*val = foo;
In this case, the compiler can possibly identify that this can be turned into a single str [R...], PC because it knows foo is in pc after the asm. Were you to write this via
asm("mov %0, PC" : "=r"(foo));
*val = foo;
the compiler would be forced to create (assuming it chooses R0 / R1 for foo/val):
MOV R0, PC
STR [R1], R0
The documentation for this behaviour is largely in the "Extended ASM" section of the GCC manuals, see the example for the contrived combine instruction.
There is no assignment the variable x in your code, therefore it's value is undefined and setting foo to an undefined value isn't required to change foo.
You need to assign the value to the variable, not to some memory location you assume the compiler use to implement it.

Can we export a function made available through a static library

I have a static library say "A.lib" which contains a function int foo(). I have another dll say "B.dll" which consumes A.lib and uses the function foo() and also exports some other functions. Is it possible to export the function int foo() (imported from A.lib) from B.dll so that it can be consumed in a third dll say "C.dll".
I want to know whether it is possible or not, I dont want workarounds like making A.lib available to the C.dll. Also, I am not concerned if this is a bad design or not.
Thanks very much for your patience to read this through.
I had the same requirement - just found a different solution:
Assuming that A.lib has an A.h (that is consumed by source files used to build B.dll e.g. assuming that A.h contains prototypes for functions contained in A.lib), just add the following in A.h:
#pragma comment(linker, "/export:_foo")
This will instruct the linker to export foo() when building B.dll. Note the leading underscore - it is there because that's the true name of the symbol for foo() contained in A.lib (use dumpbin /symbols A.lib | findstr foo to see it). In my example foo() was using the __cdecl calling convention, but if you use __stdcall() or compile as C++, you'll get different name decoration, so you'll have to adjust the #pragma statement above as a result.
It doesn't matter if A.h gets included by many source files in B.dll - the linker doesn't complain if the exact same definition is made multiple times.
One "advantage" to this approach is that you don't even have to use the __declspec(dllexport) specifier on foo() in A.lib ...
Yes, it's possible but any code example is language dependent.
(for example in C you may simply export a function with the same name and C.dll will see it)