Windows: DLL loading

Hey,

I've been reading on the subject of linkers and executable loaders. However, I have been unable to get a clear answer to the following question:
Any windows process links to atleast a couple dynamic link libraries. These libraries are loaded into the process' mememory space by the executable loader when loads the executable.
So does that mean, that EACH process on my computer (with perhaps one or two exceptions) has it's own instance of kernel32.dll in memory? Meaning that at this moment I have around 12 mB's of Kernel32 in my memory?

It seems like such a waist, and not to mention slow way of loading executables. Because, sure, when it's just kernel32 it'd be ok, but this goes for every DLL. And a basic windows process links to atleast 5 (?) standard DLL's which all have to be loaded into memory seperately for each single process that starts.

Also, that leaves me a bit puzzled with how some of the underlying magic of Windows works. For instance, at some point there will be need to call a driver to do low-level IO stuff (like painting something to the screen). Where is this 'priveledge-switch' made? I would then suspect it to be a SYSCALL (?) in the DLL's.

Anyway, if someone could answer any one of these questions it would be much appreciated. Or if you know any literature/links on the subject that do a good job of explaining further I'd love to know about them.

Best Regards,
Richard

The way I see it... Well, it's all pretty blurry

Comments

  • : Hey,
    :
    : I've been reading on the subject of linkers and executable loaders.
    : However, I have been unable to get a clear answer to the following
    : question:
    : Any windows process links to atleast a couple dynamic link
    : libraries. These libraries are loaded into the process' mememory
    : space by the executable loader when loads the executable.
    : So does that mean, that EACH process on my computer (with perhaps
    : one or two exceptions) has it's own instance of kernel32.dll in
    : memory? Meaning that at this moment I have around 12 mB's of
    : Kernel32 in my memory?
    :
    : It seems like such a waist, and not to mention slow way of loading
    : executables. Because, sure, when it's just kernel32 it'd be ok, but
    : this goes for every DLL. And a basic windows process links to
    : atleast 5 (?) standard DLL's which all have to be loaded into memory
    : seperately for each single process that starts.
    :
    : Also, that leaves me a bit puzzled with how some of the underlying
    : magic of Windows works. For instance, at some point there will be
    : need to call a driver to do low-level IO stuff (like painting
    : something to the screen). Where is this 'priveledge-switch' made? I
    : would then suspect it to be a SYSCALL (?) in the DLL's.
    :
    : Anyway, if someone could answer any one of these questions it would
    : be much appreciated. Or if you know any literature/links on the
    : subject that do a good job of explaining further I'd love to know
    : about them.
    :
    : Best Regards,
    : Richard
    :
    : The way I see it... Well, it's all pretty blurry

    The code itself is loaded only once in all the processes, but the declared variables in the DLLs are duplicated for each process. For example: Take the following "helloworld.dll":
    [code]
    SomeString = 'hello world'

    void PrintHelloWorld() {
    Display a messagebox with hello world.
    }
    [/code]
    In this example every process has its own SomeString variable, but share the PrintHelloWorld() code.
    When a new process is started it first checks if the DLL has been loaded already. If it has, then a table of all the entry-point addresses is created within the process memory space and all the variables are initialized within the process memory space. I don't know the order in which this happens. Should two DLLs share the same base address, then a translation is done on the entry-point addresses.
    I don't know about the low-level IO stuff.
  • :
    : The code itself is loaded only once in all the processes, but the
    : declared variables in the DLLs are duplicated for each process. For
    : example: Take the following "helloworld.dll":
    : [code]:
    : SomeString = 'hello world'
    :
    : void PrintHelloWorld() {
    : Display a messagebox with hello world.
    : }
    : [/code]:
    : In this example every process has its own SomeString variable, but
    : share the PrintHelloWorld() code.
    : When a new process is started it first checks if the DLL has been
    : loaded already. If it has, then a table of all the entry-point
    : addresses is created within the process memory space and all the
    : variables are initialized within the process memory space. I don't
    : know the order in which this happens. Should two DLLs share the same
    : base address, then a translation is done on the entry-point
    : addresses.
    : I don't know about the low-level IO stuff.

    Thanks for the quick response.

    That raises another question though: how does the DLL know which instance to use?

    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
  • : :
    : : The code itself is loaded only once in all the processes, but the
    : : declared variables in the DLLs are duplicated for each process. For
    : : example: Take the following "helloworld.dll":
    : : [code]: :
    : : SomeString = 'hello world'
    : :
    : : void PrintHelloWorld() {
    : : Display a messagebox with hello world.
    : : }
    : : [/code]: :
    : : In this example every process has its own SomeString variable, but
    : : share the PrintHelloWorld() code.
    : : When a new process is started it first checks if the DLL has been
    : : loaded already. If it has, then a table of all the entry-point
    : : addresses is created within the process memory space and all the
    : : variables are initialized within the process memory space. I don't
    : : know the order in which this happens. Should two DLLs share the same
    : : base address, then a translation is done on the entry-point
    : : addresses.
    : : I don't know about the low-level IO stuff.
    :
    : Thanks for the quick response.
    :
    : That raises another question though: how does the DLL know which
    : instance to use?
    :
    : Best Regards,
    : Richard
    :
    : The way I see it... Well, it's all pretty blurry

    If you mean, which version of the DLL then it uses the DLL search path, thus current directory, then windows/system directories.
    If you mean which instance of the code, then the answer is pretty simple: there's only one. For example: if a DLL exports a quicksort algorithm, then the parameter given when calling the algorithm tells it what to sort, but the sorting code itself doesn't change.
    If you are referring to object instances, then the answer depends on how the memory manager handles objects. I know that in Delphi object methods have an additional implicit parameter, which references the object which is used when calling the method.
  • : If you mean, which version of the DLL then it uses the DLL search
    : path, thus current directory, then windows/system directories.
    : If you mean which instance of the code, then the answer is pretty
    : simple: there's only one. For example: if a DLL exports a quicksort
    : algorithm, then the parameter given when calling the algorithm tells
    : it what to sort, but the sorting code itself doesn't change.
    : If you are referring to object instances, then the answer depends on
    : how the memory manager handles objects. I know that in Delphi object
    : methods have an additional implicit parameter, which references the
    : object which is used when calling the method.

    I was talking about code like this:
    [code]
    /* In DLL */
    char szMessage[20] = "Base message";

    void SetMessage()
    {
    strcpy(szMessage, "Hello world");
    }

    void PrintMessage()
    {
    //Prints szMessage
    ...
    }
    [/code]

    How would the function PrintMessage know what szMessage is?
    Because ProcessA could have called SetMessage already, whereas ProcessB didn't yet.
    If they then both call PrintMessage() you'd want it to print A: "Base message" and B: "Hello world". How does the function PrintMessage know which instance of the variables to use?

    For such a thing to work, I can imagine something being needed as a hidden parameter (like the this-pointer) that points to a data section that was created for the specific instance (so process A would have a special data section for the DLL,
  • : : If you mean, which version of the DLL then it uses the DLL search
    : : path, thus current directory, then windows/system directories.
    : : If you mean which instance of the code, then the answer is pretty
    : : simple: there's only one. For example: if a DLL exports a quicksort
    : : algorithm, then the parameter given when calling the algorithm tells
    : : it what to sort, but the sorting code itself doesn't change.
    : : If you are referring to object instances, then the answer depends on
    : : how the memory manager handles objects. I know that in Delphi object
    : : methods have an additional implicit parameter, which references the
    : : object which is used when calling the method.
    :
    : I was talking about code like this:
    : [code]:
    : /* In DLL */
    : char szMessage[20] = "Base message";
    :
    : void SetMessage()
    : {
    : strcpy(szMessage, "Hello world");
    : }
    :
    : void PrintMessage()
    : {
    : //Prints szMessage
    : ...
    : }
    : [/code]:
    :
    : How would the function PrintMessage know what szMessage is?
    : Because ProcessA could have called SetMessage already, whereas
    : ProcessB didn't yet.
    : If they then both call PrintMessage() you'd want it to print A:
    : "Base message" and B: "Hello world". How does the function
    : PrintMessage know which instance of the variables to use?
    :
    : For such a thing to work, I can imagine something being needed as a
    : hidden parameter (like the this-pointer) that points to a data
    : section that was created for the specific instance (so process A
    : would have a special data section for the DLL,
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories