3

I'm trying to produce a executable without dependency on libc (or any other). First I have done this:

// test.c
void _start()
{
    // write(1, "hello!\n", 7);
    asm ("int $0x80"::"a"(4), "b"(1), "c"("hello!\n"), "d"(7));

    // exit(0);
    asm ("int $0x80"::"a"(1), "b"(0));
}

Compiling with gcc -m32 -nostdlib test.c -o test:

hello

So far so good. Later I attempted to use some more "advanced" C like long long. On 32-bit platforms (my case) this requires libgcc:

// test.c
void _start()
{
    volatile long long int a = 10;
    volatile long long int b = 5;
    volatile int c = a/b; // Implemented as a call to '__divdi3'
}

This fails compilation with undefined reference to '__divdi3'. Seems correct as I didn't actually told it to link. But adding the flag -static-libgcc does not fix the issue! Why?

Note that I cannot link dynamically to libgcc. The following must hold true:

$ ldd test
    not a dynamic executable

I'm compiling from 64-bit Ubuntu 14.04 with gcc 4.8.2 (nothing fancy).

Guilherme Bernal
  • 8,183
  • 25
  • 43
  • Using `gcc -v ...` to make sure that you indeed linked to `libgcc` statically. – Lee Duhem May 01 '14 at 15:09
  • Doesn't that interrupt return a result code? If your asm modifies registers, you must list them as outputs (or clobbers). – David Wohlferd May 01 '14 at 20:46
  • @DavidWohlferd [GCC Inline Assembly](http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3): *We shoudn’t list the input and output registers in this list. Because, gcc knows that "asm" uses them (because they are specified explicitly as constraints).* – Guilherme Bernal May 01 '14 at 20:52
  • 1
    While gcc knows the asm uses them, it only knows that they are inputs, not that the asm is going to modify them. As a result, gcc assumes that eax still contains the value 4 on exit, and may re-use that register for another purpose that also requires eax to contain 4. For example: `int main() { asm("# %0": : "a" (4)); return 4; }` Compile with -Os -S. Looking at the .s file, 4 gets loaded into eax before calling the asm (as expected), but NOT after. AAR, if the asm changes eax, the return from main will NOT be 4. Weirdness ensues.You CANNOT (safely) modify input-only params. – David Wohlferd May 02 '14 at 02:35

1 Answers1

3

Ended up finding the solution myself. Seems like gcc wasn't able to find the library and didn't bother complaining about it. I ran the following:

$ locate libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.8/32/libgcc.a
/usr/lib/gcc/x86_64-linux-gnu/4.8/x32/libgcc.a

Then instead of giving -static-libgcc to the compiler, I changed the flags to this:

gcc -m32 -nostdlib test.c -o test -L/usr/lib/gcc/x86_64-linux-gnu/4.8/32 -lgcc

And it compiles and runs just fine!


The -L is redundant. The following also works:

gcc -m32 -nostdlib test.c -o test -lgcc
Guilherme Bernal
  • 8,183
  • 25
  • 43