4

I have this "assembly" file (containing only directives)

// declare protected region as somewhere within the stack
.equiv prot_start, $stack_top & 0xFFFFFF00 - 0x1400
.equiv prot_end,   $stack_top & 0xFFFFFF00 - 0x0C00

Combined with this linker script:

SECTIONS {
   "$stack_top"   = 0x10000;
}

Assembling produces this output

file.s: Assembler messages:
file.s: Error: invalid operands (*UND* and *ABS* sections) for `&' when setting `prot_start'
file.s: Error: invalid operands (*UND* and *ABS* sections) for `&' when setting `prot_end'

How can I make this work?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Eric
  • 95,302
  • 53
  • 242
  • 374

2 Answers2

3

Why it is not possible?

You have linked to the GAS docs, but what is the rationale for that inability?

Answer: GAS must communicate operations to the linker through the ELF object file, and the only things that can be conveyed like this are + and - (- is just + a negative value). So this is a fundamental limition of the ELF format, and not just lazyness from GAS devs.

When GAS compiles to the object file, a link step will follow, and it is the relocation which will determine the final value of the symbol.

Question: why can + be conveyed, but not &?

Answer: because + is transitive: (a + b) + c == a + (b + c) but + and & are not "transitive together": (a & b) + c!= a & (b + c).

Let us see how + is conveyed through the ELF format to convince ourselves that & is not possible.

First learn what relocation is if you are not familiar with it: https://stackoverflow.com/a/30507725/895245

Let's minimize your example with another that would generate the same error:

a: .long s
b: .long s + 0x12345678
/* c: .long s & 1 */
s:

Compile and decompile:

as --32 -o main.o main.S
objdump -dzr main.o

The output contains:

00000000 <a>:
   0:   08 00                   or     %al,(%eax)
            0: R_386_32 .text
   2:   00 00                   add    %al,(%eax)

00000004 <b>:
   4:   80 56 34 12             adcb   $0x12,0x34(%esi)
            4: R_386_32 .text

Ignore the disassembly since this is not code, and look just at the symbols, bytes and relocations.

We have two R_386_32 relocations. From the System V ABI for IA-32 (which defines the ELF format), that type of relocation is calculated as:

S + A

where:

  • S: the value before relocation in the object file.

    Value of a before relocation == 08 00 00 00 == 8 in little endian

    Value of b before relocation == 80 56 34 12 == 0x12345680 in little endian

  • A: addend, a field of the rellocation entry, here 0 (not shown by objdump), so lets just forget about it.

When relocation happens:

  • a will be replaced with:

    address of text section + 8
    

    There is a + 8 because s: is the 8th byte of the text section, preceded by 2 longs.

  • b will be replaced with:

     address of text section + (0x12345678 + 8)
     ==
     address of text section + 0x12345680
    

    Aha, so that is why 0x12345680 appeared on the object file!

So as we've just seen, it is possible to express + on the ELF file by just adding to the actual offset.

But it would not possible to express & with this mechanism (or any other that I know of), because we don't what the address of the text section will be after relocation, so we can't apply & to it.

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
1

Darn:

Infix Operators

Infix operators take two arguments, one on either side. Operators have precedence, but operations with equal precedence are performed left to right. Apart from + or -, both arguments must be absolute, and the result is absolute.

Eric
  • 95,302
  • 53
  • 242
  • 374