1

In an attempt to get the Interrupt Descriptor Table's data using the following code:

/* SIDT returns IDT in following format */
#pragma pack(1)
typedef struct
{
    unsigned short IDTLimit;
    unsigned short LowIDTBase;
    unsigned short HighIDTBase

} s_idt_info;
#pragma pack()

.
.
.

    s_idt_info idt_info;        // returned by sidt
    s_idt_entry *idt_entries;   // obtained from idt_info
    unsigned long count;

    // load idt_info
    __asm ("sidt idt_info");

I get the following error:

||=== Build: Release in driver2 (compiler: gnu_64) ===|
obj\Release\driver.o:driver.c|| undefined reference to `idt_info'|
||error: ld returned 1 exit status|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

Using MinGW-64bit's g++ compiler

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
W2a
  • 736
  • 2
  • 9
  • 23
  • gcc is not an "inline assembler" and that's not related to mingw! – too honest for this site Nov 25 '16 at 20:37
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – too honest for this site Nov 25 '16 at 20:38
  • 2
    Olaf : I don't think this is a duplicate of that question, since this is really the issue of GCC basic inline assembly only having visibility of global variables. In this case `idt_info` is likely local to the function the code was in (that is a bit of a guess since the function isn't shown in the code) – Michael Petch Nov 25 '16 at 20:52

1 Answers1

2

GCC doesn't support local variables (inside a function) within inline assembly unlike MSVC. If the variable idt_info were made global then it should be visible to the inline assembly, however the GCC documentation discourages this:

Accessing data from C programs without using input/output operands (such as by using global symbols directly from the assembler template) may not work as expected. Similarly, calling functions directly from an assembler template requires a detailed understanding of the target assembler and ABI.

Since GCC does not parse the assembler template, it has no visibility of any symbols it references. This may result in GCC discarding those symbols as unreferenced unless they are also listed as input, output, or goto operands.

What you want to do is use a GCC extended assembler template and use an output constraint to allow GCC to pass in the address of idt_info that will be updated by SIDT. Something like this should work:

__asm__ __volatile__ ("sidt %[idtptr]" : [idtptr]"=m"(idt_info));

The = denotes the constraint will be used for output, m forces GCC to pass a memory operand. SIDT requires a memory operand and not a register. %[idtptr] is the name given to the parameter, and GCC will replace it with the actual memory reference.

Community
  • 1
  • 1
Michael Petch
  • 46,082
  • 8
  • 107
  • 198