Page 1 of 1

Hook CALL GATE with C function

Posted: Tue Nov 09, 2004 12:00 am
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

Re: Hook CALL GATE with C function

Posted: Tue Nov 09, 2004 12:00 am
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!

Re: Hook CALL GATE with C function

Posted: Tue Nov 09, 2004 12:00 am
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

Re: Hook CALL GATE with C function

Posted: Tue Nov 09, 2004 12:00 am
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.

Re: Hook CALL GATE with C function

Posted: Wed Nov 10, 2004 12:00 am
by Ytinasni
A call gate will return with a 'retf' instruction. That will definately not work correctly with a normal ret.

Re: Hook CALL GATE with C function

Posted: Sat Nov 13, 2004 12:00 am
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?

Re: Hook CALL GATE with C function

Posted: Sat Nov 20, 2004 12:00 am
by Da_Maestro
oh yeah.....