Hook CALL GATE with C function

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
pepito
Posts: 23
Joined: Thu Oct 21, 2004 11:00 pm
Location: México D.F.

Hook CALL GATE with C function

Post by pepito »

Hello:

It is posible to hook a CALL GATE with a C function using DJGPP?
It is posible to hook a INTERRUPT GATE with a C function using DJGPP?

Thank you
Pepito :)
Legend
Member
Member
Posts: 195
Joined: Tue Nov 02, 2004 12:00 am
Contact:

Re: Hook CALL GATE with C function

Post by Legend »

Although someone claimed that it is possible to, it was only in some cases, so in general it would be a good idea to build asm stubs that call your C function!
*post*
bregma
Member
Member
Posts: 25
Joined: Tue Oct 26, 2004 11:00 pm
Location: the back woods
Contact:

Re: Hook CALL GATE with C function

Post by bregma »

pepito wrote:It is posible to hook a CALL GATE with a C function using DJGPP?
It is posible to hook a INTERRUPT GATE with a C function using DJGPP?
You can certainly hook the gate using a C function, but you will probably want an asm routine to bounce an interrupt through the gate, since you'll want an iret instruction at the end.

I use C++ in my kernel and my interrupt gates look something like this.

Code: Select all

class InterruptGate
{
public:
    /** Constructs an InterruptGate. */
    InterruptGate(u16 segment = 0,
                  u32 offset = 0,
                  u08 privilegeLevel = 0,
                  bool isTrap = false);

    /** Dumps the InterruptGate to an output stream. */
    std::ostream& printStream(std::ostream& ostr) const;

private:
    u16	m_offset00_15;			
    u16 m_segment;
    u08 m_unused2;
    u08 m_type:3;	        /* 6 (INT) or 7 (TRAP) */
    u08 m_size:1;	        /* 0 */
    u08 m_isSystemDescriptor:1;	/* 0 (16-bit) or 1 (32-bit) */
    u08 m_privilegeLevel:2;
    u08 m_segmentIsPresent:1;	/* 0 (not present) or 1 (present) */
    u16	m_offset16_31;
} __attribute__((__packed__);
That's the actual structure the CPU sees when it receives an interrupt.

Here's the implementation of the constructor.

Code: Select all

InterruptGate::
InterruptGate(u16 segment,
              u32 offset,
              u08 privilegeLevel,
              bool isTrap)
: m_offset00_15(offset & 0xffff)
, m_segment(segment)
, m_type(isTrap ? 7 : 6)
, m_size(1)
, m_isSystemDescriptor(0)
, m_privilegeLevel(privilegeLevel)
, m_segmentIsPresent(1)
, m_offset16_31((offset >> 16) & 0xffff)
{ }
The actual hook is something like this, given an instance of the Interrupt Dispatch Table class with an insert() member function.

Code: Select all

extern "C" void _divideErrorException();

extern "C" void _nmiInterrupt();
extern "C" void _breakpointException();
extern "C" void _overflowException();
extern "C" void _boundRangeExceededException();
extern "C" void _invalidOpcodeException();
extern "C" void _deviceNotAvailableException();
extern "C" void _doubleFaultException();
extern "C" void _segmentOverrun();
extern "C" void _invalidTSSException();
extern "C" void _segmentNotPresent();
extern "C" void _stackFaultException();
extern "C" void _generalProtectionFault();
extern "C" void _pageFaultException();

/* ... */

idt.insert(kFAULT_GENERAL_PROTECTION,
  InterruptGate(0x08,
                (u32)_generalProtectionFault,
                0,
                false));
Where _generalProtectionFault is the pointer to an asm trampoline hook.

The trampoline hooks are in GAS format. All they do is push the interrupt/trap number and maybe an error code o the stack and invoke the inetrrupt trampoline. There is one of these hooks for each and every interrupt or trap in the system.

Code: Select all

	.macro INTERRUPT LABEL,INT_NUM,HAS_ERROR=no
	.text
	.globl \LABEL
	.type  \LABEL,@function
\LABEL:
	.ifc \HAS_ERROR,no
	pushl 0
	.endif
	pushl $\INT_NUM
	call idtTrampoline
	.ifc \HAS_ERROR,no
	addl $8,%esp
	.else
	addl $4,%esp
	.endif
	iret
	.endm

	/**
	 * Reserved CPU interrupt vectors 0 .. 32
	 */
	INTERRUPT _divideErrorException         0

	INTERRUPT _nmiInterrupt                 2
	INTERRUPT _breakpointException          3
	INTERRUPT _overflowException            4
	INTERRUPT _boundRangeExceededException  5
	INTERRUPT _invalidOpcodeException       6
	INTERRUPT _deviceNotAvailableException  7
	INTERRUPT _doubleFaultException         8
	INTERRUPT _segmentOverrun               9
	INTERRUPT _invalidTSSException         10 yes
	INTERRUPT _segmentNotPresent           11 yes
	INTERRUPT _stackFaultException         12 yes
	INTERRUPT _generalProtectionFault      13 yes
	INTERRUPT _pageFaultException          14 yes
Finally, the trampoline itself is a namespace-level function. There's only one, and it just calls the interrupt dispatcher object, which then does clever things like call all the chained registered interrupt handlers. All in C++.

Code: Select all

extern "C" void idtTrampoline(long interruptNumber,
                              int error);

/**
 * Bounces a fired interrupt request to the interrupt dispatcher.
 *
 * @param interruptNumber [IN]  The interrupt vector being raised.
 * @param error           [IN]  The error value associated with the trap (if
 *                              any).
 */
void idtTrampoline(long interruptNumber, int error)
{
    klog() << "idtTrampoline(" << interruptNumber << ", " << error << ")\n";
    gIDT->dispatchInterrupt(interruptNumber);
}
Simple, no? You mileage may vary.

--
smw
Da_Maestro
Member
Member
Posts: 144
Joined: Tue Oct 26, 2004 11:00 pm
Location: Australia

Re: Hook CALL GATE with C function

Post by Da_Maestro »

It is very possible to hook a C function into a CALL GATE, as call gates return using the normal "ret" instruction.

INTERRUPT GATES are different though. I do know that some old Pascal compilers (Turbo Pascal yay!!) had an "interrupt" calling convention that you could use to hook pascal procedures directly to interrupts, but this was in real mode and I don't think DJGPP has that functionality. Read over the DJGPP docs.
Ytinasni
Posts: 5
Joined: Wed Oct 20, 2004 11:00 pm
Location: New Zealand

Re: Hook CALL GATE with C function

Post by Ytinasni »

A call gate will return with a 'retf' instruction. That will definately not work correctly with a normal ret.
pepito
Posts: 23
Joined: Thu Oct 21, 2004 11:00 pm
Location: México D.F.

Re: Hook CALL GATE with C function

Post by pepito »

Thank you to everyone!

I like to focus in the CALL GATES first:

I have been reveiw the INTEL documents and seems that the CALL GATES are designed to work with a C compiler that support segmentation. I am right?

Then, maybe I am trying to do the job with the wrong tool.

Someone know about the Open Watcom compiler?
Can it be used to write an operating system kernel?
Pepito :)
Da_Maestro
Member
Member
Posts: 144
Joined: Tue Oct 26, 2004 11:00 pm
Location: Australia

Re: Hook CALL GATE with C function

Post by Da_Maestro »

oh yeah.....
Two things are infinite: The universe and human stupidity. But I'm not quite sure about the universe.
--- Albert Einstein
Post Reply