This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ARM]ÂWrong BLX destination


Hi,

I noticed a behavior I can't explain while playing with gas and ld on ARM, I thought this list would be the best place to ask for help. There is nothing mission-critical, I would just like an explanation to satisfy my curiosity.

My initial question was if it was possible to have a BLX instruction (the version that takes a an immediate value) that jumps from ARM code to Thumb code, to an address that is not a multiple of 4. The ARM instruction set seems to support it (because of the H bit in the instruction's encoding), so I wanted to try to make gas generate it.

It seems like C functions (even in Thumb mode) are always placed on PCs multiples of four, so I decided to generate symbols by hand in assembly. I just want to see the generated instruction, I don't intend to run it, so the data at these location is garbage.

So I made this little test.S:

  .arm

  hello1:
  .hword 0x1111

  hello2:
  .hword 0x2222

  hello3:
  .hword 0x3333

  # Space things out a bit
  .fill 20, 4, 0

  .align 4

  blx hello1
  blx hello2
  blx hello3

I compile it like this (main.c is just an empty main function):

  gcc -g3 -O0  main.c test.S

This is the relevant disassembly:

  000083d0 <hello1>:
      83d0:       1111            asrs    r1, r2, #4

  000083d2 <hello2>:
      83d2:       2222            movs    r2, #34 ; 0x22

  000083d4 <hello3>:
      83d4:       3333            adds    r3, #51 ; 0x33
          ...
      8426:       0000            .short  0x0000
      8428:       e320f000        nop     {0}
      842c:       e320f000        nop     {0}
      8430:       faffffe6        blx     83d0 <hello1>
      8434:       fbffffe5        blx     83d2 <hello2>
      8438:       faffffe5        blx     83d4 <hello3>
      843c:       e320f000        nop     {0}

Everything looks good, we can see that the call to hello2 points indeed to an address that isn't a multiple of 4.

I then tried to do the same thing, except I placed the target symbols in another compilation unit (IOW, ld is now involved in linking/patching the instructions). So I now have test.S with only the calls:

  .arm

  .align 4

  blx hello1
  blx hello2
  blx hello3

  # Space things out a bit
  .fill 20, 4, 0

and test2.S with the labels:

  .arm

  .global hello1
  .global hello2
  .global hello3

  hello1:
  .hword 0x1111

  hello2:
  .hword 0x2222

  hello3:
  .hword 0x3333

  # Space things out a bit
  .fill 20, 4, 0

This is the resulting disassembly:

      83d0:       fa000016        blx     8430 <hello1>
83d4: fa000015 blx 8430 <hello1> <---- WRONG TARGET
      83d8:       fa000015        blx     8434 <hello3>
          ...
      842c:       e320f000        nop     {0}

  00008430 <hello1>:
8430: 22221111 eorcs r1, r2, #1073741828 ; 0x40000004

  00008432 <hello2>:
      8432:       33332222        teqcc   r3, #536870914  ; 0x20000002

  00008434 <hello3>:
      8434:       00003333        andeq   r3, r0, r3, lsr r3

As you can see, the second blx instruction points to hello1, whereas it should point to hello2.

Do you know if this is the intended behavior, and if so, what explains it? Is there some alignment requirements that differs in both cases?

Thanks!

Simon


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]