1

I can jmp to an address using Visual Studio 2012.. When it comes to gcc/mingw, I cannot tell if my jump is correct.

How can I jump to an address in gcc?

I tried:

__declspec(naked) void DXHook_D3DPERF_BeginEvent()
{
    #ifdef _MSC_VER  //If using visual studio..
    __asm{jmp[Addr]} //Jump to: Address stored in Addr.
    #else            //else using gcc..
    __asm("jmp *%0"
          : /*No Outputs*/
          : "r" (Addr)
          : "%eax");
    #endif
}

Is this correct? Also, is there a way to get gcc to stop bothering me about:

warning: 'naked' attribute directive ignored.

Why does it ignore my naked attribute?

Brandon
  • 22,723
  • 11
  • 93
  • 186
  • 1
    May be helpful [naked (C++)](http://msdn.microsoft.com/en-us/library/h5w10wxs.aspx) and [Could someone explain __declspec(naked) please?](http://stackoverflow.com/questions/3021513/could-someone-explain-declspecnaked-please) – Shafik Yaghmour Oct 24 '13 at 22:27
  • 1
    The naked attribute is ignored as it is not implemented for x86. What are trying to do? What should happen to the value of the registers? Should variables be written back to memory before the jump? – Timothy Baldwin Oct 25 '13 at 18:25
  • Have you tried clang? It should support the same syntax as GCC and I think they are working on MVC support as well... – nonsensickle Feb 10 '15 at 00:34

2 Answers2

2

TL;DR In GCC, this is only available on: ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU ports

It is NOT available on x86.

Workaround (proposed by Brendon in the comments).

Full answer

(The rest of this answer assumes you are using a supported target)

That is because you are using the Windows attribute syntax, __declspec with GCC.

Quote from the MSDN reference on __declspec:

The extended attribute syntax simplifies and standardizes Microsoft-specific extensions to the C and C++ languages.

You should use the GCC function attribute syntax instead or in parallel.

Please also note the following quote from this GCC article:

Note: The semantics are not the same between Windows and this GCC feature - for example, __declspec(dllexport) void (*foo)(void) and void (__declspec(dllexport) *foo)(void) mean quite different things whereas this generates a warning about not being able to apply attributes to non-types on GCC.

So there could also be an issue with the way you are using the __declspec syntax in GCC (if it even supports it).

You should also note that the only __declspec attribute that GCC states it supports is the __declspec(dllexport) (as stated in the already mentioned GCC attribute syntax link).

So let's look for a generic solution to your problem but first we will need to read about the actual GCC attribute syntax and find the following:

An attribute specifier list may appear immediately before a declarator (other than the first) in a comma-separated list of declarators in a declaration of more than one identifier using a single list of specifiers and qualifiers. Such attribute specifiers apply only to the identifier before whose declarator they appear. For example, in

 __attribute__((noreturn)) void d0 (void),
     __attribute__((format(printf, 1, 2))) d1 (const char *, ...),
      d2 (void)

the noreturn attribute applies to all the functions declared; the format attribute only applies to d1.

So the solution to your problem would be something like the following:

#ifdef __GNUC__
#define ATTRIBUTE_NAKED __attribute__((naked))
#else
#define ATTRIBUTE_NAKED __declspec(naked)
#endif

ATTRIBUTE_NAKED void DXHook_D3DPERF_BeginEvent()
{
    #ifdef _MSC_VER  //If using visual studio..
    __asm{jmp[Addr]} //Jump to: Address stored in Addr.
    #else            //else using gcc..
    __asm("jmp *%0"
          : /*No Outputs*/
          : "r" (Addr)
          : "%eax");
    #endif
}

Edit:

It is important to note that this attribute is platform specific. And I quote:

naked

This attribute is available on the ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU ports. It allows the compiler to construct the requisite function declaration, while allowing the body of the function to be assembly code. The specified function will not have prologue/epilogue sequences generated by the compiler. Only basic asm statements can safely be included in naked functions (see Basic Asm). While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be depended upon to work reliably and are not supported.

Quoted from the GCC documentation on function attributes.

Side note

Possible further reading on clang attributes could help (mostly compatible with GCC) but these comments seem to suggest a desire to match GCC behavior.

Community
  • 1
  • 1
nonsensickle
  • 4,438
  • 2
  • 34
  • 61
  • http://i.imgur.com/IfZsecR.png and http://i.imgur.com/hIzpIsW.png Did you test your code because I sure did.. GCC 4.9.2 – Brandon Feb 09 '15 at 23:34
  • Sigh, it seems that you are using an unsupported target. I assumed that you were working with ARM and it seems I assumed incorrectly. It clearly states in the [documentation](https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html) that x86 is not supported next to the naked attribute. There is also a [bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50242) about this. I have updated my answer to explain this. – nonsensickle Feb 10 '15 at 00:20
  • @Brandon Looking at your inline asm it is clear that this is x86... Whoops, not sure how I missed it before. – nonsensickle Feb 10 '15 at 00:32
  • 1
    The work around for x86 is to add a function declaration and implement the body using asm: http://stackoverflow.com/a/8375416/1462718 – Brandon Feb 10 '15 at 00:41
1

To do the equivalent of the Visual C++ code, implement it entirely in assembly either in a separate file or in a top level (not in a function) asm statement.

Timothy Baldwin
  • 3,551
  • 1
  • 14
  • 23