Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Feb 2002 14:36:40 -0800
From:      Terry Lambert <tlambert2@mindspring.com>
To:        dak <aurelien.nephtali@wanadoo.fr>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Kernel Module
Message-ID:  <3C781978.4E43221A@mindspring.com>
References:  <20020223220605.GA1863@mars>

next in thread | previous in thread | raw e-mail | index | archive | help
dak wrote:
> I want to make a module that re-writes a kernel function.
> Anybody can point me to a doc/skeleton code please ?
> I've already taken a look at examples provided with FreeBSD
> but I've only seen code to make new syscalls (or devices).
> 
> Thanks in advance (and sorry for the bad english :>)

This is called thunking.

If you need to do this, you should reconsider your application
or define an interface boundary for what you want to replace.
The easiest way is to define a global function pointer you can
overwrite (or a local one, if the overwrite is in the same file),
e.g.:


	static int
	default_foo(int i, char c)
	{
		return( i * c);
	}

	int (*foo)(int i, char c) = default_foo;


	static int
	new_foo(int i, char c)
	{
		return( i + c);
	}

	int
	replace_foo()
	{
		foo = new_foo;	
	}

Alternately, you can replace the function at the address with
a "thunk".

A thunk is a "call new_func; ret;".  You take the address of the
function and write your replacement there (you will need to come
up with the instruction value yourself):

	replace_default_foo()
	{
		char *instr = "\x71\x77\x78\x78xxxxxxxx"; /* abs call*/
		void *old;

		old = (char *)default_foo;

		memcpy( (void *)instr+4 (void *)new_foo, sizeof(void *));
		memcpy( old, (void&)instr, 4 + sizeof(void *));
	}

Basically, you eat an additional call/ret overhead.  It's better
to replace a function pointer.

Alternately, you could do a fixup.  With a fixup, you have a
fake function, and when it's called, it patches the caller to
point to the new function.  Since relative calls are shorter
than absolute, you can't fixup everything (not enough space for
the absolute call instruction operand), but you can thunk to
everything by stomping the caller.

For the fixup, you stomp the address of the function with a
replacement fixup function, instead of the real replacement
function.  When it gets called, it walks back the stack to
find the caller, stops the caller code, then finishes calling
through the replacement function.  Thus the expense of the
extra work occurs the first time you call it, but subseqnet
calls use the fixed-up code instead, and call the replacement
function directly.  For relative calls, you fixup to a thunk,
so that you don't have fixup failure overhead each time, but
you still have cal overhead.

If what your doing needs this, then you probably should be
fixing the interface so that you don't need to do this, as
other people are likely to want to do what you are doing, too.


-- Terry

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3C781978.4E43221A>