Any trick to get RIP-rel addressing without COFF relocation?

Started by mazegen, January 03, 2020, 07:29:51 AM

Previous topic - Next topic

mazegen

UASM supports generated RIP-rel addressing but it also generates unnecessary COFF relocation in some cases. Consider rip-rel.asm:


.code
lea rax, [lbl]
nop
lbl:
nop
end


Assemble with: uasm64.exe -win64 -Fl rip_rel.asm

You get:


UASM v2.49, Jun 21 2019, Masm-compatible assembler.

rip_rel.asm
                                .code
00000000  488D0500000000         lea rax, [lbl]
00000007  90                     nop
00000008                        lbl:
00000008  90                     nop
                                end


The code 488D0500000000 means LEA RAX, [RIP+0]. Why zero? This is because it is relocated by COFF relocation REL32. You can use dumpbin to see it:


RELOCATIONS #1
                                                Symbol    Symbol
Offset    Type              Applied To         Index     Name
--------  ----------------  -----------------  --------  ------
00000003  REL32                      00000000         6  lbl


In this case, the COFF relocation is unnecessary because the distance of the instruction from the label is known to UASM. Do you know any trick how to get rid of the COFF relocation?

The only solution seems to be manual RIP-rel addressing but I can't use it unfortunately:


.code
lea rax, [rip+(lbl-next)]
next:
nop
lbl:
nop
end


Listing file:


                                .code
00000000  488D0501000000         lea rax, [rip+(lbl-next)]
00000007                        next:
00000007  90                     nop
00000008                        lbl:
00000008  90                     nop
                                end


The code 488D0501000000 means LEA RAX, [RIP+1] and no COFF relocation is involved.

I could use a macro similar to the following:


RIPREL MACRO lbl:REQ
EXITM <(type lbl) ptr [rip + (lbl-end_of_current_instruction)]
ENDM

mov bl, [RIPREL(a_label)]


The problem here is the "end_of_current_instruction". As far as I know, there's no UASM symbol that would represent that.

johnsa

I think the problem with creating a symbol for the end of current instruction is that the macro expansion happens before code-gen, which is the only place that would know how big the instruction actually is.

I always wondered why they decided to make RIP based on the end of the current instr. rather than a known value (being the start)...  :rolleyes:

RIP relative modes really shouldn't be generating relocations, except if the RIP-rel is to an item in a different section/segment in which case it may be unwise to assume any fixed location of that segment relative to the RIP to establish the distance. but for stuff in code this should be fine.

mazegen

Yep, the COFF relocation is completely unnecessary in code segment.

Quote from: johnsa on January 03, 2020, 09:38:43 PM
I always wondered why they decided to make RIP based on the end of the current instr. rather than a known value (being the start)...  :rolleyes:
This is because when the instruction runs, it is already decoded and RIP points to next instruction already.

johnsa

Yes, but the cpu knows that.. we don't.. it's really semantics at the end of the day, they could've had it such that RIP = the currently executing instruction and it would simplify a lot of relative calculations from the users/code perspective.. I will see what we can do to remove the code-seg relative ones at least.