0

I'm trying to compile a toy example as a homework problem. I've been given a small snippet of code, but it won't compile on my home machine (Ubuntu 17, gcc 7.2.0). The exact same code compiles on school machines (Ubuntu 16, gcc 5.4.1).

When I run make, I get the following error:

/usr/bin/ld: age.o: relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC

/usr/bin/ld: final link failed: Nonrepresentable section on output

collect2: error: ld returned 1 exit status

Compiling with the -fPIC flag does not fix the problem.

Here is the sample assembly code:

.string1:
    .string "Please enter your name: "
.string2:
    .string "Thank you %s!\n"
.string3:
    .string "Please enter your year of birth: "

    .globl get_age
get_age:
    push %rbx              
    push %rbp              # callee saved registers

                           # local variables:
    leaq -8(%rsp), %rsp    #   - endptr
    leaq -24(%rsp), %rsp   #   - name_str[24]
    leaq -24(%rsp), %rsp   #   - year_of_birth[24]
    mov %rsp, %rbp

    movq $.string1, %rdi
    xorl %eax, %eax
    call printf            # printf("Please enter your name: ");

    leaq 24(%rbp), %rdi
    call gets              # gets(name_str);

    ret

This code is called from a simple main function:

#include <stdio.h>

long get_age(void);

void main () {
    long age;

    age = get_age();
    printf("You are at least %ld years old.\n", age);
    return;
    printf("You are at least %ld years old and you look like it too.\n", age);
}

Here is the makefile I'm using. Note, the failure occurs when gcc -o x age.o main.o is called:

all:    x

x:  main.o age.o
    gcc -o x age.o main.o

main.o: main.s
    gcc -c main.s

age.o:  age.s
    gcc -g -c age.s

main.s: main.c
    gcc -O2 -S main.c

clean:  
    rm -f x *.o main.s

As previously mentioned, the -fPIC flag does not seem to make any difference (I've tried adding it to every stage of the makefile). Any ideas?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
b1skit
  • 327
  • 4
  • 16
  • Unrelated to your problem, but don't use `gets`. Never ever use it! It's a dangerous function and have therefore been removed from the C specification. Use [`fgets`](http://en.cppreference.com/w/c/io/fgets) instead, or (since you're on a POSIX system) [`getline`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html). – Some programmer dude Feb 05 '18 at 06:46
  • The linker error message's suggestion to use `-fPIC` is assuming the offending code was generated by `gcc`, not hand-written. Your gcc is configured to use `-fPIE -pie` by default (see the linked duplicate). `movq` uses a 32-bit immediate, unlike `movabs` which would work but be sub-optimal. You should use RIP-relative LEA (see MichaelPetch's link) if you aren't going to optimize for position-dependent code with the default code model by using a 5-byte `movl $.string1, %edi`. (zero-extended instead of sign-extended immediate). – Peter Cordes Feb 05 '18 at 07:01
  • Another unrelated thing: Why do you generate an assembly file for `main.c`? Why not directly to object file (which is the usual)? Furthermore, if you get the code you show to build, you will have a weird "age" since what you effectively return is the string you store the name in. Lastly, remember that `return` returns immediately. – Some programmer dude Feb 05 '18 at 07:01
  • If you want a position independent version you can see this answer on how to access labels using [RIP relative addressing](https://stackoverflow.com/a/3260178/3857942). You can modify it to be `leaq .string1(%rip), %rdi` and then use `call printf@plt` and `call puts@plt` . See programmer dudes comment about the dangerous use of `puts` – Michael Petch Feb 05 '18 at 07:02
  • 1
    Thank you all - Feeding gcc the flags "-fno-pie -no-pie" fixed the issue. To the other questions regarding the style of the code: Like I said, this was a toy homework problem. I didn't write it, just trying to compile it :) – b1skit Feb 05 '18 at 16:25

0 Answers0