1

I'm trying to use a label as the offset in base-offset addressing mode, for accessing a global variable in a shellcode-like environment. The base address of the code and data is stored in $s7, and I'm trying to do this:

# global variable @ offset 20 in code, 
foobar: .word <non-constant value>

# ...

lw $s0, foobar($s7)

And then getting the assembler to translate this to lw $t0, 20($s7). Instead, when compiling without special options it takes a detour via $gp. Similarily, when using -mno-abicalls or -mno-shared, the lw is translated to:

lui     $s0, 0x0
addu    $s0, $s0, $s7
lw      $s0, 20($s0)

Is there any way to get it to interpret foobar as an immediate value, just like when doing addiu $t0, $t1, foobar, which is translated to addiu $t0, $t1, 20 as expected?

Digging through the docs hasn't yielded anything useful so far.

Thanks in advance!

jclehner
  • 1,440
  • 10
  • 18
  • Why are you trying to address a compile-time/link-time constant through a runtime value (a register)? That makes no sense whatsoever. – EOF Jun 28 '18 at 16:41
  • The value is not actually a constant, I just used that as an example! – jclehner Jun 28 '18 at 16:47
  • Think of it as a global variable - I've updated the question to clarify this! – jclehner Jun 28 '18 at 16:54
  • But *the address* of the value *is* a constant. – EOF Jun 28 '18 at 18:42
  • 1
    @EOF: This is position-independent code, but MIPS doesn't have a PC-relative addressing mode. (Only reg + disp16, which I think is a *signed* displacement, so actually the OP's answer works for labels <= `0x7fff`). – Peter Cordes Jun 28 '18 at 19:25
  • MIPS is unfortunately quite bad at PIC: even its call instruction (`jal`) is basically an absolute target (except for keeping the high few bits of the old PC value). https://www.linux-mips.org/wiki/PIC_code shows that `jal` in PIC mode is assembled as a pseudo-instruction which loads the branch target from the GOT and uses an indirect `jalr $t9` or whatever. But you can find your own address with a fully relative `bgezal $0, offset` (because `$0>0` is always true), to get an absolute return address in the link register. http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html – Peter Cordes Jun 28 '18 at 19:41
  • 2
    @PeterCordes Modern MIPS releases have `[d]addiupc` for PIC. – EOF Jun 28 '18 at 19:53
  • @EOF the target in question doesn't have PC-relative addressing. @PeterCordes Yes, that's exactly the technique I'm using - determining my address using a `bal` (or `bgezal $0`) and then reading `$ra`. – jclehner Jun 29 '18 at 08:49

1 Answers1

2

I've found a solution. For now I'll be using lw $s0, %lo(foobar)($s7) which works, as long as the labels are <= 0xffff - plus you couldn't do this in a single instruction with a larger offset anyways.

jclehner
  • 1,440
  • 10
  • 18