0

I'll explain the problem briefly. I have a Leon3 board (gr-ut-g99). Using GRMON2 I can load executables at the desired address in the board.

I have two programs. Let's call them A and B. I tried to load both in memory and individually they work.

What I would like to do now is to make the A program call the B program.

Both programs are written in C using a variant of the gcc compiler (the Gaisler Sparc GCC).

To do the jump I wrote a tiny inline assembler function in program A that jumps to a memory address where I loaded the program B.

below a snippet of the program A

 unsigned int return_address;
 unsigned int * const RAM_pointer = (unsigned int *) RAM_ADDRESS;
 printf("RAM pointer set to: 0x%08x \n",(unsigned int)RAM_pointer);
 printf("jumping...\n");

 __asm__(" nop;" //clean the pipeline
         "jmp %1;" // jmp to programB
       :"=r" (return_address)
       :"r" (RAM_pointer)
     );

RAM_ADDRESS is a #define

#define RAM_ADDRESS 0x60000000

The program B is a simple hello world. The program B is loaded at the 0x60000000 address. If I try to run it, it works!

int main()
{
  printf ("HELLO! I'M BOOTED! \n");
  fflush(stdout);

  return 0;
}

What I expect when I run the ProgramA, is to see the "jumping..." message on the console and then see the "HELLO! I'M BOOTED!" from the programB

What happens instead an IU exception. Below I posted the messages show by grmon2 monitor. I also reported the "inst" report which should show the last operations performed before the exception.

  grmon2> run

  IU exception (tt = 0x07, mem address not aligned)

  0x60004824: 9fc04000  call  %g1


grmon2> inst
  TIME     ADDRESS   INSTRUCTION                   RESULT      SYMBOL

   407085  600047FC  mov  %i3, %o2                 [600063B8]  -

   407086  60004800  cmp  %i4                      [00000013]  -

   407089  60004804  be  0x60004970                [00000000]  -

   407090  60004808  mov  %i0, %o0                 [6000646C]  -

   407091  6000480C  mov  %i4, %o3                 [00000013]  -

   407092  60004810  cmp  %i4, %l0                 [80000413]  -

   407108  60004814  bleu  0x60004820              [00000000]  -

   407144  60004818  ld  [%i1 + 0x20], %o1         [FFFFFFFF]  -

   407179  60004820  ld  [%i1 + 0x28], %g1         [FFFFFFFF]  -

   407186  60004824  call  %g1                     [  TRAP  ]  -

I also tried to substitute the "jmp" with a "jmpl" or a "call" but it does not worked. I'm quite confused. I do not know how to cope well with the problem and therefore I do not know what other information it is necessary to provide.

I can say that, the programB is loaded at 0x60000000 and the entry_point is, of course, 0x60000000. Running directly program B from that entry point it works good!

Thanks in advance for your help!

Andak
  • 124
  • 12
  • `ld [%i1 + 0x28], %g1 [FFFFFFFF]`: looks like the result is `FFFFFFFF`, seems that you're trying to jump to FFFFFFFF (which is somehow confirmed by "address is not aligned" error (PC needs to be at an even address) – Jean-François Fabre Mar 28 '18 at 13:11
  • 1
    By the way, if you don't require jump, you can use plain C with a function pointer. – Jester Mar 28 '18 at 13:12
  • Jester is right. Using inline asm with parameters is not the simplest thing. If you can do it in pure C, do it. – Jean-François Fabre Mar 28 '18 at 13:14
  • 1
    The disassembly shown is not the disassembly of program A. Also, GCC officially does not support `asm` transferring control to an arbitrary address. I would recommend writing the first-stage bootstrap entirely in assembly. – zwol Mar 28 '18 at 14:32
  • I've discovered a bug at an "higher" level and I'm trying to solve that. In particular the new bug (I don't know if it is better to open another question) is: If I load the program A first and sequentially the program B, then i run the program A that calls program B and works. If I load the program B first and sequentially the program A, then i run the program A that calls program B... it does not work. I'm confused . . @zwol, I'm not sure that what I showed is the disassembly. It is simply the instruction trace buffer. – Andak Mar 28 '18 at 14:41
  • @Andak What I'm trying to tell you is that the instruction trace says the crash happened in some other code entirely, not the part of program A that you showed us. It does not end with a nop and then a jmp. – zwol Mar 28 '18 at 15:04
  • 1
    @zwol The addresses hint that it is a trace of program B. Now the question is how program B is linked. In particular, what is called at address 60004824. The map file should help. – user58697 Mar 28 '18 at 20:18

1 Answers1

1

Looks to me like you did execute the jump, and it got to program B, as evidenced by the addresses of the instructions in the trace buffer. But where you crashed was in stdio trying to print stuff. Stdio makes extensive use of function pointers, and the sequence clearly shows a call instruction with the target address in a register, which indicates use of a function pointer.

I suggest putting fflush(stdout) in program A just before the jump, and this will allow you to see the messages before doing the jump. Then, in program B, instead of using printf, just put some known value in memory that you can examine later via the monitor to verify that it got there.

My guess is that the stdio library has some data or parameter that needs to be set up at the start of the program, and that's not being done or not done properly. Not sure about the platform you are running on, but do you have some sort of debugging or single stepping ability, like in a debugger? If so, just single step through the jump and follow where the program goes.

Rob Gardner
  • 201
  • 1
  • 4