Showing posts with label DLL. Show all posts
Showing posts with label DLL. Show all posts

Sunday, 6 September 2009

Dependency Walker for Windows binaries

I find Dependency Walker a very useful utility. This helps us to scan any of windows binaries (exe, dll ...).

It can dissect almost any type of windows binary file, to show up all possible details hidden within.

Listing few of the details this utility can provide,

  • Basic binary properties Ex: physical path, version info, etc.
  • Exported functions with their signatures and ordinal numbers.
  • Recursive list of dependent libraries and their details.

It didn’t took much time for me to discover the power of this tiny tool which is distributed as apart of MS Visual Studio Tools. This can also be downloaded for free at http://www.dependencywalker.com/.

Below is one of such situation, where this tool helped me to rapidly identify and debug the problem.

I was building Qt for Win with ‘-openssl-linked’ option and this required me to download the openSSL libraries separately. I had downloaded and copied ‘libeay32.dll’ under Qt’s bin folder.

Even though Qt compiled without any problems, I had issues with launching few of the processes which had dependency over libeay32.dll. For some reasons, loader started complaining about missing ordinal in libeay32.dll.

Dependency walker came into rescue. I simply loaded the failing process into DependencyWalker and it listed all dependent DLLs with respective details. I could just walk to the libeay32.dll and examine its version.

There you go! It was loading an older version of DLL which had been installed as part of Wireless monitor app. Since PATH variable had the wireless app’s path occurring before Qt’s bin path, it was always picking the older DLL from wrong location which caused the issue.

It hardly took me few minutes to identify and fix the issue.

Hope this is useful :)

Wednesday, 22 July 2009

Resolving the exported symbols from a Symbian DLL

Symbian OS optimizes DLL program code to save ROM and RAM space, by offering only "lookup by ordinal" and not "lookup by name".

Symbian OS does not offer “lookup by name” because this adds an overhead to the size of the DLL (storing the names of all the functions exported from the library is wasteful of space). Instead, Symbian OS only uses link by ordinal, which has significant implications for binary compatibility.

If we are loading a DLL dynamically and need to resolve a exported function address, we need to use the following RLibrary API, which takes an integer parameter representing the ordinal number of the exported function.

TLibraryFunction RLibrary::Lookup(TInt anOrdinal)

Luckily, as part of POSIX for Symbian (P.I.P.S), widely known as Open-C library, we can achieve “lookup by name” with a Symbian DLL.

This is possible only if the library is built as STDDLL.

This allows us to have the POSIX like behavior for resolving the exported DLL symbols even on Symbian. Following POSIX like APIs can be used on Symbian provided the DLL is built as STDDLL.

void *dlopen(const char *filename, int flag);
void *dlsym(void *handle, const char *symbol);
void dlclose(void *handle);

An example with source using the PIPS libraries is here.

Sunday, 11 January 2009

Backward Compatibility with DLLs – Part 2 (Private Implementation)

A very Happy New Year to all of the readers!

This article is in continuation with the previous one, about preserving DLL exported APIs’ backward compatibility.

The last article described a technique of achieving this by privatizing the API’s constructor. This has many disadvantages of its own, as the c’tor is private, ex: Object can not be instantiated on stack.

An alternative technique is to have a “Private Implementation”.

If you have a class, which you intend to export, separate out all the internal implementation including the data members and the functions which you think can be hidden. The exported class will only have the functions exported along with a private member pointer to the new internal class.

As an example, consider the following class,

#define DLL_EXPORT __declspec(dllexport)
class DLL_EXPORT ExampleExport
{
public: // c'tors and d'tors
    ExampleExport();
    ~ExampleExport();

public: // functions
    void function1();
    int function2();

private: // private data members
    int m_member1;
    int m_member2;
};

We have 2 integer member variables. Adding or removing the member variables later, will always cause a binary compatibility break as described in the previous article.

Let’s try to separate out the internal implementation. We will move all the private data members to a different class – ExampleExportPrivate.

class ExampleExportPrivate
{
public: // c'tors and d'tors
    ExampleExportPrivate();
    ~ExampleExportPrivate();

public: // data members
    int m_member1;
    int m_member2;
};

We will redefine ExampleExport to use ExampleExportPrivate.

#define DLL_EXPORT __declspec(dllexport)

class ExampleExportPrivate; // <<-- forward declaration of the private implementation which is defined in cpp file


class DLL_EXPORT ExampleExport
{
public: // c'tors and d'tors
    ExampleExport();
    ~ExampleExport();

public: // functions
    void function1();
    int function2();

private:
    ExampleExportPrivate *m_private; // <—Pointer to private implementation. };

As a first step, forward declare the private implementation class – ExampleExportPrivate. The actual definition of this private implementation class can be placed as part of the cpp file. So, we are not exposing this class outside, even in the header files exported. Next step is to have a private pointer member variable which points to ExampleExportPrivate. Any references to the data will be redirected to the internal private implementation.

This technique will help us to not change the size of the exported class. If we need to add or delete a new member variable, ExampleExportPrivate will be the class which will have those changes, but not ExampleExport.

This technique is usually called as “PImpl” (Private Implementation). Here is an interesting article http://www.gotw.ca/publications/mill04.htm

Monday, 1 December 2008

Backward Compatibility with DLLs

This and the following articles, I personally feel very interesting.

It’s related to the “backward compatibility” of the DLLs.

If you are distributing your DLLs to people or 3rd party, whom you expect to use them, you should be very careful about the interface you expose out of the DLLs.

Consider you are distributing a DLL, which has an exported class of some size and few public functions. If you update the same DLL in future and redistribute it, you cannot always expect the users to re-link their application with your new DLL. In such cases, users of the DLL expect the same interface what you had provided in the earlier release. If by any way there is a change in the interface, it results in failure of backward compatibility.

Let’s take an example to explain this situation. The following is a class which you are exporting as part of your DLL,

#define DLL_EXPORT __declspec(dllexport)

class DLL_EXPORT ExampleExport
{
    public:
        ExampleExport();
        ~ExampleExport();

        void function1();
        int function2();

    private:

        int m_member1;
        int m_member2;
};

In a future release you updated this class to have an additional member variable,

class DLL_EXPORT ExampleExport
{
    public:
        ExampleExport();
        ~ExampleExport();

        void function1();
        int function2();

    private:

        int m_member1;
        int m_member2;
        int m_member3; // <<---- a new member variable added
};

You can observer that the class size has been changed. Earlier it was 8 bytes (assuming int as 4 bytes) and it’s changed to 12 by adding an additional integer member variable.

Consequence: For an end user application, which is not re-linked with the updated DLL, the size of the class is still 8 bytes. Since the application was compiled and linked with the first version of DLL, the size is still the same even after they started using the new DLL. The application may have unpredicted behavior.

Resolution: This problem needs to be addressed before we release the first version of the DLL. Of course we cannot restrict the size of the class to not to change in future. We may need to update it by adding or removing new member variables. One solution is to force the end user application to not to construct the object by itself.

  • Make constructor private.
  • Export a new static member function which creates an object by calling private constructor

class DLL_EXPORT ExampleExport
{
public:
    ~ExampleExport();

public:
    static ExampleExport* Instance();

public:
    void function1();
    int function2();

private:
    ExampleExport(); // <<---- private constructor

private:
    int m_member1;
    int m_member2;
    int m_member3; // <<---- a new member variable added
};

This forces the client application to use ExampleExport::Instance() function always to construct an object and since the definition of Instance() is part of the DLL, 12 bytes will be allocated with the new DLL.

Let’s have a look at another solution for the same problem, in the next article.

Saturday, 30 June 2007

Library - Reusable binary component

In our daily development activities, we will come across various types of libraries. Like Static Library, Dynamic Linked Library, Plugins etc,


In this article, I have tried to explain each of these.


You consider any type of library, final objective will remain the same - Binary Reusability.


Developer should identify a set of re-usable components or routines in his module and create a library. So that, this can be distributed and used by anyone instead of rewriting the components again.


Lets start from Static Library(.lib) (called as Archive in unix world). Usually libraries will be create with .lib extension (.a in unix). The idea behind static library is to create a reusable binary module that can be linked with any executable or another dynamic library, so that it can reuse the static library components. Linking/Binding module will have the responsibility of linking your executable with the static library. Hence the final size of the executable will be original executable code size + the static library code size. The executable will embed the static library within.




All the routines and components which were present in the static library can be directly used as if they were implemented in the same module.


After compilation, at link time the linker module will look for all the symbols which were referenced in the executable and tries to link the static library. The developer has to specify the static library so that the linker can link it with the executable.



Dynamically Linked Library (DLL): Generally we export functions or routines from DLLs. When we say export that means those are all the entry points for the executables that are linked with it. Only the exported functions can be accessed by the executables.


We can use the DLLs in two ways. One way is to link the static interface of a DLL with an executable and another is to load the DLL at run-time. Both have its own advantages.


Statically linking the DLL interface : For any DLL, there will always be a static library(.lib) generated. This static library is just an interface to the DLLs exported functions, they wont have any definitions for the exported functions. They are just like routers to the actual definition which is present in the DLL.


Executables can link to this static library and use the exported functions in the DLL. The executable will just have DLLs interface embedded in it. DLL will be a separate module which will be loaded by the loader when we start the executable.






In this method, the DLL will be loaded when we start the executable. The life span of the exe along with the DLL can be depicted as below,



Loading a DLL at Run-time : This is the second way of using a DLL. Where we can use certain System API's to load the DLL at run-time. The static interface for the DLL is not used in this case. A typical example is shown below.



// Load the library
MyDll = LoadLibrary("C:\\MyWork\\aDll.dll");

// Get address of exported function
FuncPointer = GetProcAddress(MyDll, "SomeExportedFunc");

// Make call
FuncPointer();

// Release the library
FreeLibrary(MyDll)


Note here that, the DLL can be loaded and released at any point of time with in the life span of the exe. Which is different from the previous method where it would load it at the start of the execution itself.


A Plugin is an extension to this method. Lets talk about this in further articles.

Cheers!