Skip to contentSkip to conversation

Newbie questions

Linux-ia64 Matthew Wilcox 5 participants 6 messages Nov 8, 2002 – Nov 11, 2002

lore
Share & tools
lore
#0 lore raw
Quoted 14 lines · CH Gowri Kumar

I wrote the above program and compiled it and found the appropriate codes for the instructions using objdump -d and wrote the following program

char sc[] ="\x0a"

           "\x10"
           "\x00"
           "\x18\x00\x21\x00\x92\x00\x00\x42\xe0\x11\x00\x20\x84\x0a";
       main()
       {
         void (*fp)(void);
         fp = (void*)sc;
         fp();
      }
Quoted 3 lines

But this program on execution gives me the error:
"Illegal instruction (core dumped)"
(A similar program for IA-32 worked well.)

function pointers on ia64 are "fat" -- that is, they are not the address of the function, they are the address of a function descriptor which contains (iirc) the GP and the address of the function. i believe glibc pokes around with this kind of thing, so you may wish to look at the ia64 assembly code in there to see how it does it.

Signature · 1 line
Revolutions do not require corporate support.
#1 lore raw

hello all,
I am a post-graduate student trying to write a JIT compiler for .NET CLR on Linux,IA-64.

I have some queries related to IA-64 assembly programming

I plan to write the JIT this way:
I generate the native code directly (instead of assembly language and then using assembler)for a particular method and jump to the address of the starting memory location where I have generated the native code. I have written a small program to check whether such a thing is feasible, which is as follows:

#include<unistd.h>
int main()
{
__asm__("

      mov r32
      mov r1525
      break 0x100000"

);
}

I wrote the above program and compiled it and found the appropriate codes for the instructions using objdump -d and wrote the following program

char sc[] ="\x0a"

           "\x10"
           "\x00"
           "\x18\x00\x21\x00\x92\x00\x00\x42\xe0\x11\x00\x20\x84\x0a";
       main()
       {
         void (*fp)(void);
         fp = (void*)sc;
         fp();
      }

But this program on execution gives me the error:
"Illegal instruction (core dumped)"
(A similar program for IA-32 worked well.)

I couldn't figure out what could be the problem.
I also tried using "br instruction" approach instead of the function pointer approach, but couldn't succeed.

Can anyone explain why it is failing or atleast give me pointers where to look for?

Thanks in advance.
Gowri Kumar

#2 lore raw
In reply to Matthew Wilcox
Quoted 19 lines · Matthew Wilcox
Quoted 14 lines · CH Gowri Kumar

I wrote the above program and compiled it and found the appropriate codes for the instructions using objdump -d and wrote the following program

char sc[] ="\x0a"

           "\x10"
           "\x00"
           "\x18\x00\x21\x00\x92\x00\x00\x42\xe0\x11\x00\x20\x84\x0a";
       main()
       {
         void (*fp)(void);
         fp = (void*)sc;
         fp();
      }
Quoted 3 lines

But this program on execution gives me the error:
"Illegal instruction (core dumped)"
(A similar program for IA-32 worked well.)

Quoted 6 lines

function pointers on ia64 are "fat" -- that is, they are not the address of the function, they are the address of a function descriptor which contains (iirc) the GP and the address of the function. i believe glibc pokes around with this kind of thing, so you may wish to look at the ia64 assembly code in there to see how it does it.

to be more precise a function descriptors is:

	struct {
		unsigned long func_addr;
		unsigned long gp;
	};

You should also take a look at the calling convention documentation at:
http://developer.intel.com/design/itanium

Signature · 1 line
-Stephane
#3 lore raw
In reply to Matthew Wilcox
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · CH Gowri Kumar

Gowri> char sc[] ="\x0a" "\x10" "\x00"
Gowri> "\x18\x00\x21\x00\x92\x00\x00\x42\xe0\x11\x00\x20\x84\x0a"; Gowri> main() { void (*fp)(void); fp = (void*)sc; fp(); }

Gowri> But this program on execution gives me the error: "Illegal Gowri> instruction (core dumped)" (A similar program for IA-32 Gowri> worked well.)

Gowri> I couldn't figure out what could be the problem. I also Gowri> tried using "br instruction" approach instead of the function Gowri> pointer approach, but couldn't succeed.

Gowri> Can anyone explain why it is failing or atleast give me Gowri> pointers where to look for?

You'll want to read the software convention manual, especially that portion talking about function descriptors. The manual is normally available at:

http://www.intel.com/design/Itanium/arch_spec.htm

Unfortunately, the URL it points to
(http://www.intel.com/design/itanium/downloads/24535803s.htm) is currently broken. [Could someone from Intel look into getting this fixed?]

But briefly, a function descriptor consists of (at least) two words:
the first one being the entry point (instruction address) and the second one being the global pointer. I attached a small test program that demos "dynamic" code generation (note: instruction bundles must be aligned to 16-byte boundary, which wasn't guaranteed in your test program).

	--david

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>

#include <sys/mman.h>

#ifdef __ia64__
typedef struct _fp
{
long addr;
long gp;
} IA64_FUNCTION;

static void flush_cache (void *addr, unsigned long len) {
void *end = (char *) addr + len;

while (addr < end)

    {
      asm volatile ("fc %0" :: "r"(addr));
      addr = (char *) addr + 32;
    }

asm volatile (";;sync.i;;srlz.i;;");
}
#endif

void TestApp(void)
{
#ifdef __ia64__
__asm__ __volatile__ ("nop.i 0");
__asm__ __volatile__ ("nop.i 0");
__asm__ __volatile__ ("nop.i 0");
__asm__ __volatile__ ("nop.i 0");
#else
__asm__ __volatile__ ("nop");
#endif
return;
}

int main(int argc, char *argv[])
{
void (*pSubroutine)(void);
unsigned char *pBuffer1;
long alignment;
#ifdef __ia64__
IA64_FUNCTION *fp;
IA64_FUNCTION newfp;
#endif

  printf("Test ***\n");

  malloc(0x10000);

  // Allocate and align buffer on 16 byte boundary
  pBuffer1 = (unsigned char *)malloc(0x1000);
  alignment = ((unsigned long)pBuffer1 % 16);
  pBuffer1 = pBuffer1 + 16 - alignment;

#ifdef __ia64__
fp = (IA64_FUNCTION *)TestApp;
printf("pSub Addr = 0x%lX GP = 0x%lX\n", fp->addr, fp->gp); memcpy(pBuffer1, (unsigned char *)fp->addr, 256); flush_cache(pBuffer1, 0x1000);

  newfp.gp = fp->gp;
  newfp.addr = (long)pBuffer1;
  printf("pSub Addr = 0x%lX GP = 0x%lX\n", newfp.addr, newfp.gp);
  pSubroutine = (void (*)(void))&newfp;

mprotect((void *) ((long) pBuffer1 & ~(getpagesize () - 1)),

	   getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC);

#else
printf("pSub Addr = 0x%lX\n", pBuffer1);
memcpy(pBuffer1, &TestApp, 32);
pSubroutine = (void (*)(void)) pBuffer1;
#endif

  (*pSubroutine)();

printf ("done!\n");
return(0);
}

#4 lore raw
In reply to Matthew Wilcox

The Software conventions document is at
http://developer.intel.com/design/itanium/downloads/245358.htm

All documents can now be found at
http://developer.intel.com/design/itanium/arch_spec.htm

Thanks
Sunil
-----Original Message-----
From: David Mosberger [mailto:[email protected]]
Sent: Friday, November 08, 2002 11:09 AM
To: CH Gowri Kumar
Cc: '[email protected] '
Subject: Re: [Linux-ia64] Newbie questions

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

On Sat, 9 Nov 2002 00:21:40 +0530 (IST), CH Gowri Kumar

<[email protected]> said:

Gowri> char sc[] ="\x0a" "\x10" "\x00"
Gowri> "\x18\x00\x21\x00\x92\x00\x00\x42\xe0\x11\x00\x20\x84\x0a"; Gowri> main() { void (*fp)(void); fp = (void*)sc; fp(); }

Gowri> But this program on execution gives me the error: "Illegal Gowri> instruction (core dumped)" (A similar program for IA-32 Gowri> worked well.)

Gowri> I couldn't figure out what could be the problem. I also Gowri> tried using "br instruction" approach instead of the function Gowri> pointer approach, but couldn't succeed.

Gowri> Can anyone explain why it is failing or atleast give me Gowri> pointers where to look for?

You'll want to read the software convention manual, especially that portion talking about function descriptors. The manual is normally available at:

http://www.intel.com/design/Itanium/arch_spec.htm

Unfortunately, the URL it points to
(http://www.intel.com/design/itanium/downloads/24535803s.htm) is currently broken. [Could someone from Intel look into getting this fixed?]

But briefly, a function descriptor consists of (at least) two words:
the first one being the entry point (instruction address) and the second one being the global pointer. I attached a small test program that demos "dynamic" code generation (note: instruction bundles must be aligned to 16-byte boundary, which wasn't guaranteed in your test program).

	--david

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>

#include <sys/mman.h>

#ifdef __ia64__
typedef struct _fp
{
long addr;
long gp;
} IA64_FUNCTION;

static void flush_cache (void *addr, unsigned long len) {
void *end = (char *) addr + len;

while (addr < end)

    {
      asm volatile ("fc %0" :: "r"(addr));
      addr = (char *) addr + 32;
    }

asm volatile (";;sync.i;;srlz.i;;");
}
#endif

void TestApp(void)
{
#ifdef __ia64__
__asm__ __volatile__ ("nop.i 0");
__asm__ __volatile__ ("nop.i 0");
__asm__ __volatile__ ("nop.i 0");
__asm__ __volatile__ ("nop.i 0");
#else
__asm__ __volatile__ ("nop");
#endif
return;
}

int main(int argc, char *argv[])
{
void (*pSubroutine)(void);
unsigned char *pBuffer1;
long alignment;
#ifdef __ia64__
IA64_FUNCTION *fp;
IA64_FUNCTION newfp;
#endif

  printf("Test ***\n");

  malloc(0x10000);

  // Allocate and align buffer on 16 byte boundary
  pBuffer1 = (unsigned char *)malloc(0x1000);
  alignment = ((unsigned long)pBuffer1 % 16);
  pBuffer1 = pBuffer1 + 16 - alignment;

#ifdef __ia64__
fp = (IA64_FUNCTION *)TestApp;
printf("pSub Addr = 0x%lX GP = 0x%lX\n", fp->addr, fp->gp); memcpy(pBuffer1, (unsigned char *)fp->addr, 256); flush_cache(pBuffer1, 0x1000);

  newfp.gp = fp->gp;
  newfp.addr = (long)pBuffer1;
  printf("pSub Addr = 0x%lX GP = 0x%lX\n", newfp.addr, newfp.gp);
  pSubroutine = (void (*)(void))&newfp;

mprotect((void *) ((long) pBuffer1 & ~(getpagesize () - 1)),

	   getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC);

#else
printf("pSub Addr = 0x%lX\n", pBuffer1);
memcpy(pBuffer1, &TestApp, 32);
pSubroutine = (void (*)(void)) pBuffer1;
#endif

  (*pSubroutine)();

printf ("done!\n");
return(0);
}

_______________________________________________
Linux-IA64 mailing list
[email protected]
http://lists.linuxia64.org/lists/listinfo/linux-ia64

#5 lore raw
In reply to Matthew Wilcox
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Sunil

Sunil> The Software conventions document is at
Sunil> http://developer.intel.com/design/itanium/downloads/245358.htm

Ah, yes, this works!

Sunil> All documents can now be found at
Sunil> http://developer.intel.com/design/itanium/arch_spec.htm

Should this be: http://developer.intel.com/design/itanium/family/ ? The former results in a "this page has moved page" (it does redirect eventually, but it's slower).

In any case, thanks for providing the URL for the conventions manual.

	--david