| TIP: Click on subject to list as thread! | ANSI |
| echo: | |
|---|---|
| to: | |
| from: | |
| date: | |
| subject: | How do DLLs load and unl |
Original from Jonathan de Boyne Pollard to Denis Tonn on 10-06-1998
Original Subject: How do DLLs load and unlo
---------------------------------------
JP>> The problem with this is with recursion, and pathological
JP>> InitTerm functions. As I said:
JP>>> [...] the pathological, but permissible, case that the InitTerm
JP>>> function of a module may itself call DosLoadModule or
JP>>> DosFreeModule ? Or the equally pathological case that the InitTerm
JP>>> function, either accidentally or deliberately, never returns at all
JP>>> (leaving the kernel internals in an intermediate state) [...]
JP>> I wasn't asking whether this sort of code was *valid*, by
JP>> the way. It's obviously valid, and in any case a decent
JP>> operating system has to protect itself against mischeivous
JP>> application code. The question is how does the kernel deal
JP>> with the kernel stack overflow or deadlock issues that
JP>> result ? You didn't see that this was the main thrust of
JP>> my question, and only referred to this obliquely:
DT> It doesn't operate with a kernel stack during the callback. It
DT> operates with the Ring 3 stack. If the process/thread stack
DT> overflows, normal exception processing applies.
JP> You haven't thought about the kernel stack. When the first call to
JP> DosLoadModule or DosFreeModule calls the InitTerm function
JP> in ring 3, it is several stack frames deep on the kernel
JP> stack. Even though the stack switches to the user stack
JP> for the ring 3 callback, these stack frames on the kernel
JP> stack *do not go away*. They are there for the kernel to
JP> continue. When a nested DosLoadModule or DosFreeModule
JP> happens in the InitTerm function, *further* stack frames
JP> are pushed onto the kernel stack. It is obvious that
JP> eventually the kernel stack is going to overflow if this is
JP> nested enough times.
Each thread has it's OWN Ring 0 stack (stored in the TSD). The
default size is 8K (4K commited and 4K guard page). I have not checked
if additional stack would be allocated, or what the limits are beyond
this.
This stack is ONLY used when operating in a thread context. It is NOT
used in kernel mode.
When in Kmode, the system is non-preemptable, and will have returned
out of Kmode (stack cleaned up) before any appication context code is
given control again (R3 or R0 in application context).
JP> So to add the emphasis to the question I asked above: How
JP> does the kernel deal with the *kernel stack* overflow issue
JP> that results ?
If a thread overflows it's unique ring 0 stack, it is treated in much
the same way that an invalid buffer passed to the kernel would be
treated. IE: an exception pointing to the ring 3 IP *after* the API
call that caused the "application context" ring 0 code to trap.
DT> For deadlock issues, it is again a process related situation. The
DT> kernel is not affected.
JP> Of course it is. If the kernel needs to lock the system module table, or the
JP> "per-process module table" (which there must be some form
JP> of, in order to store the reference counts described above)
JP> at the start of DosLoadModule or DosFreeModule, and unlock
JP> it at the end, the kernel will deadlock itself if a thread
It does not update the reference count until the module has loaded.
There are no calls to application code between obtaining the reference
count semaphore in the MTE and updating it. In fact, this happens in
non-preemtable code, so the only place it needs a semaphore is on an
SMP system (spinlock).
JP> makes a recursive call into DosFreeModule or DosLoadModule
JP> from an InitTerm function. The only way around this is to
JP> use a recursive mutex (as I hypothesised before) that
JP> allows the *same thread* to recursively enter DosLoadModule
JP> or DosFreeModule. But if one chooses that route, one then
JP> encounters the problem of the fact that the mutex is there
JP> in the first place in order to prevent threads from seeing
JP> the system or process module tables in an inconsistent
JP> state. If an InitTerm function makes a recursive call into
JP> DosLoadModule or DosFreeModule, and that sort of recursion
JP> is allowed, then the *nested* DosLoadModule or
JP> DosFreeModule function will see the module tables in an
JP> inconsistent state, because the outermost call, which
JP> called the InitTerm function in the first place, will be
JP> only partway through traversing the module graph, and thus
JP> only partway through updating the reference counts.
The updating of the reference counts are done on a module by module
basis. *After* the module has been loaded and fixups applied. The
loader will have traversed the tree of "load time DLLs" and updated
the reference counts as it "walks back up the tree" and before Init is
called in any of the modules. Init/Term is optional on a DLL by DLL
basis (and that information is stored in the MTE).
For "run time loading", the same kind of thing will happen (the DLL
may have other DLL's referenced in *it's* exe header).
Likewise, Term will only be called before a DLL is "unloaded" from
the process address space. If a DLL "loads itself" in Term, it's Init
will NOT be called (and therefore can't recurse itself). Term is ONLY
called just before the DLL is unloaded/unmapped from the process.
It will not hold a semaphore against the MTE during any Ring 3
callbacks.
Denis
All opinions are my very own, IBM has no claim upon them
.
.
.
--- Maximus/2 3.01
* Origin: T-Board - (604) 277-4574 (1:153/908)SEEN-BY: 396/1 632/0 371 633/210 260 267 270 371 635/506 728 639/252 670/218 @PATH: 153/908 8086 800 140/1 396/1 633/260 635/506 728 633/267 |
|
| SOURCE: echomail via fidonet.ozzmosis.com | |
Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.