Date: Wed, 1 Dec 1999 09:13:04 +1100 From: Peter Jeremy <jeremyp@gsmx07.alcatel.com.au> To: David Gilbert <dgilbert@velocet.ca> Cc: stable@FreeBSD.ORG Subject: Re: Stack/i386-type ugh question. Message-ID: <99Dec1.090547est.40328@border.alcanet.com.au> In-Reply-To: <14404.9723.200774.823194@trooper.velocet.net> References: <14404.9723.200774.823194@trooper.velocet.net>
next in thread | previous in thread | raw e-mail | index | archive | help
On 1999-Dec-01 06:31:07 +1100, David Gilbert wrote: >Ok... chasing down some memory corruption in FreeBSD's new vinum >code. I have the following: ... > So. Which of those registers is the program counter? As a full address, the PC is %cs:%eip (tf_cs and tf_eif in the trap frame). > I need to find the stack frame #6, >basically... but I suppose I need to know a few things... > >Is frame #6 > or < the address of frame #5? An i386 function call looks like: pushl argN ... pushl arg2 pushl arg1 call func addl #...,%esp Note that the `addl' can be deferred to improve speed (see -fno-defer-pop), but the effect remains the same. And a normal function looks like: func: pushl %ebp movl %esp,%ebp subl #locals_size,%esp ... movl %ebp,%esp popl %ebp ret There are also enter and leave instructions which handle the prologue and epilogue, but the above code shows the linkage more clearly. It is also possible to disable the linked frame generation, but this isn't done by default (see -fomit-frame-pointer). Assuming a function in frame M calls frame (M-1), this gives a stack frame as follows: | | high memory |----------------| | argN | | ... | | arg2 | | arg1 | |----------------| Frame M | return address | |----------------| | previous frame |<+ |----------------| | | local vars | | |----------------| | ------------------------- | argN | | | ... | | | arg2 | | | arg1 | | Frame M-1 |----------------| | | return address | | |----------------| | | previous frame |-+ <-- %ebp |----------------| | local vars | |----------------| <-- %esp | | | | low memory gdb and ddb normally rely on the frame pointer (%ebp) to work out the stack frames during a backtrace. The problem here is that it looks like there has been a buffer overflow within a local variable which has trashed the saved frame pointer and return address. It should be possible to locate a stack by rummaging through kernel memory looking for the {previous frame},{return address} pairs, where {previous frame} can be recognised by being an int aligned memory address slightly higher (between 8 and ~200 bytes) than the current address, which points to another {previous frame}. {return address} can be recognised as being within the kernel text segment. (Finding the correct stack will be more difficult). If you are in a process context, then you should be able to find the kernel stack associated with the active process (though I can't remember how). Peter To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-stable" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?99Dec1.090547est.40328>