Author Topic: problems with riip relative addressing  (Read 11007 times)

Offline markallyn

  • Jr. Member
  • *
  • Posts: 10
problems with riip relative addressing
« on: March 24, 2017, 05:39:16 PM »
Hello everyone,

I am struggling to understand how nasm does rip addressing.  Here's the problem code:

Quote
extern       printf

SEGMENT      .text
      GLOBAL   _start
      _start:
      nop
      lea     rsi, [rel msg wrt ..gotpc]
      lea   rdi, [rel fmt wrt ..gotpc]
      mov   rax, 0
      call   printf
      
      mov   rax, 60
      syscall

SEGMENT      .data
      GLOBAL fmt
      fmt   db "%s",0
      GLOBAL msg
      msg   db "Don't you dare twerk!",0


As you can see it's a Miley Cyrus parent's version of hello world.  The problem is that the two lea instructions to load addresses into rdi and rsi load the wrong addresses.  Clearly, this attempt at PIC is a fiasco.  Could someone who knows what ails it tell me how to fix.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: problems with riip relative addressing
« Reply #1 on: March 24, 2017, 07:08:34 PM »
I'm way over my head with this! I have no experience with 64-bit code and very little with PIC even in 32-bit. I'm confused with what you're trying to do. You have PIC(?) but the _start entrypoint is in your code. Huh? In any case, I think someone who knows what you're doing will want to see what your command line to ld looks like. My understanding would be that if you want to use "..gotpc" that you're going to have to do "GET_GOT" first. Further, I thought "rel" would be an alternative to the whole "..got" rigamarole. I can only refer you to the Friendly Manual:

http://www.nasm.us/doc/nasmdoc9.html#section-9.2

Best,
Frank


Offline markallyn

  • Jr. Member
  • *
  • Posts: 10
Re: problems with riip relative addressing
« Reply #2 on: March 24, 2017, 08:28:53 PM »
Hi Frank,

Can't blame you for being confused. My bad.  The thing should have been structured as a function with a an entry point other than _start and the usual prologue and epilogue.

But, the problem remains the same even when coded as a function--namely, the two lea instructions load addresses that are not the locations of the data items.

I'll reply with a fresh piece of code that actually illustrates the problem more clearly.

Meanwhile, I have looked everywhere on the inet for a decent, readable piece on pic relative addressing, and the nasm manual is really written for 32-bit code which is largely silent on this particular issue.  Searching this forum turned up very little, only about 10 postings by my count.  Somebody on the forum who is knowledgeable on this issue would make a great contribution if they put together and publicized a tutorial.

Back shortly with a revision of the code.

Thanks again.

Mark

Offline markallyn

  • Jr. Member
  • *
  • Posts: 10
Re: problems with riip relative addressing
« Reply #3 on: March 26, 2017, 05:35:49 PM »
Hello Frank and everyone else,

OK, I promised more readable code and herein it follows.  I have structured the problem by writing a simple calling program (callrel) that is linked dynamically to  a called program (twerk).

The caller looks just like this:
Quote
extern       twerk
extern      dataquad
extern      printf

SEGMENT      .data
      fmt    db "The value in dataquad is %x",13,10,0
GLOBAL      _start
SEGMENT      .text
      _start:
      nop
      call   twerk wrt ..plt
      lea   rdi, [rel dataquad wrt ..gotpc]
      mov   rdi, [rdi]  ; I would have thought a single dereference would do the job, but
      mov   rsi, [rdi]  ; I was wrong!  It takes yet another dereference to get to the value.  Namely, 0x69
      mov   rdi, fmt
      call   printf

      mov   rax, 60
      mov   rdi, 0
      syscal

And the shared library function (librel.so.1.0) looks like this:

Quote
extern       printf
DEFAULT   rel    ;Following guidance from a swarm of different inet locations I use the default rel.  But is it necessary to do this here?  Why not just the caller?

SEGMENT      .data
      GLOBAL fmt
      fmt   db "%s",0
      GLOBAL msg
      msg   db "Don't you dare twerk!",13,10,0
      msglen  equ $-msg
      GLOBAL   dataquad:data
      dataquad  dd  0x69

SEGMENT      .text
      GLOBAL   twerk
      twerk:
      push   rbp
      mov   rbp, rsp
      lea     rsi, [msg ]
      
      ; do the twerk-out with syscall
      mov   rdi, 1
      mov   rdx, msglen
      mov   rax, 1
      syscall
      
      ; do twerk-out again with printf   
      mov     rdi, msg
      call   printf wrt ..plt
      

      mov   rsp, rbp
      pop     rbp
      ret

I have skipped including the assembly and link code for brevity.
Yes, the thing runs as intended, unlike my initial flawed posting.  But, I'm still struggling to understand how this RIP thing works.  As noted in the calling program, it appears that a double dereferencing of the global data item (dataquad--admittedly ill-chosen name) from the shared library is required, and I don't see why.  Second question is:  Do I need to use RIP addressing in the SHARED library--isn't it sufficient to do this just in the caller.

Can someone clariy what is going on here?

Ciao,
Mark Allyn 

Offline markallyn

  • Jr. Member
  • *
  • Posts: 10
Re: problems with riip relative addressing
« Reply #4 on: March 31, 2017, 09:36:18 PM »
Hello everyone,

Well, the answer to my own question about twice dereferencing is because the location loaded by the lea instruction is actually a pointer to a pointer.  The moral here is:  always read the fine print in any discussion of relocations.

Mark Allyn