Search code examples
cgccassemblygnu-assemblerpowerpc

Referencing symbols in other files using PPC assembly


How can you reference a symbol external to the current file in ppc assembly? I've tried looking at the .extern keyword as well as adding a new symbol in the linker file but with no success.

I have two ppc assembly files that are part of a larger project. I wish to reference a symbol (__head) in file1 from file2 in this way:

file1.S:

    .section ".head","ax"

    . = 0
.global __head
__head:

file2.S:

    .section ".head","ax"
...
    LOAD_32(%r3, file2_symbol_name - __head)

where LOAD_32 is

#define LOAD_32(r, e)           \
    lis     r,(e)@h;            \
    ori     r,r,(e)@l;      

...but am getting the following error:

file2.S: Assembler messages:
file2.S:113: Error: can't resolve `file2_symbol_name' {.head section} - `__head' {*UND* section}
file2.S:113: Error: expression too complex

When used in file1 LOAD_32(%r3, file1_symbol_name - __head) works just fine so I know I'm not importing the symbol name correctly. How can I do this?

EDIT:

I have reduced my problem to the bare minimum parts so that I am clear about the problem. Below is all of the code, linker file, Makefile, and the terminal output for "make quick".

NB: When I comment out line 9 of other.S the project compiles without error.

head.S:

#include "asm-defines.h"

    .section ".head","ax"
    .align 0x10

    . = 0x0

.global __head
__head:
    LOAD_32(%r3, file1_symbol_name - __head)
    b   .

file1_symbol_name:
    b   .

other.S

#include "asm-defines.h"

    .section ".head","ax"
    .align 0x10

.global other
other:
    LOAD_32(%r3, file2_symbol_name)
    LOAD_32(%r3, file2_symbol_name - __head)
    b   .

file2_symbol_name:
    b   .

asm-defines.h:

#ifndef ASM_DEFINES_H
#define ASM_DEFINES_H

/* Load an immediate 32-bit value into a register */
#define LOAD_32(r, e)           \
    lis     r,(e)@h;            \
    ori     r,r,(e)@l;      

#endif //ASM_DEFINES_H

quick.lds

ENTRY(__head);

Makefile

CC=$(CROSS)gcc
QFLAGS := -Wl,--oformat,elf64-powerpc -pie -m64 -mbig-endian -nostdlib

quick:
    $(CC) $(QFLAGS) -T quick.lds head.S other.S -o quick.o

$(CROSS) is a path to the cross compiler which I have omitted. The CC is powerpc64le-buildroot-linux-gnu-gcc

Terminal

$ make quick
powerpc64le-buildroot-linux-gnu-gcc -Wl,--oformat,elf64-powerpc -pie -m64 -mbig-endian -nostdlib -T quick.lds head.S other.S -o quick.o
other.S: Assembler messages:
other.S:9: Error: can't resolve `.head' {.head section} - `__head' {*UND* section}
other.S:9: Error: expression too complex
other.S:9: Error: can't resolve `.head' {.head section} - `__head' {*UND* section}
other.S:9: Error: expression too complex
make: *** [quick] Error 1

Solution

  • The assembler cannot know the placement / relative position of head.S and other.S at assembly time to be able to compute the relative displacement of the file2_symbol_name and __head labels. This is a general assembly language question, not PPC specific.