Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINUX: Is it possible to write a working program that does not rely on the libc library?

I wonder if I could write a program in the C-programming language that is executable, albeit not using a single library call, e.g. not even exit()?

If so, it obviously wouldn't depend on libraries (libc, ld-linux) at all.

like image 451
prinzdezibel Avatar asked Feb 08 '09 00:02

prinzdezibel


People also ask

Does Linux use libc?

Because of some history (see below), use of the term "libc" to refer to the standard C library is somewhat ambiguous on Linux. By far the most widely used C library on Linux is the GNU C Library often referred to as glibc. This is the C library that is nowadays used in all major Linux distributions.

What is the purpose of the C library libc so?

DESCRIPTION top. The term "libc" is commonly used as a shorthand for the "standard C library", a library of standard functions that can be used by all C programs (and sometimes by programs in other languages).

Does Rust depend on libc?

Rust, the language, doesn't depend on libc. There are no-std targets. There are also targets like WASM/WASI which don't use libc in any way. If you were porting Rust's libstd to a new platform you could use direct kernel syscalls, or link with whatever not-C standard library the OS has.

Is libc a shared library?

The one instance of libc is shared among all the processes.


3 Answers

I suspect you could write such a thing, but it would need to have an endless loop at the end, because you can't ask the operation system to exit your process. And you couldn't do anything useful.

Well start with compiling an ELF program, look into the ELF spec and craft together the header, the program segments and the other parts you need for a program. The kernel would load your code and jump to some initial address. You could place an endless loop there. But without knowing some assembler, that's hopeless from the start on anyway.

The start.S file as used by glibc may be useful as a start point. Try to change it so that you can assemble a stand-alone executable out of it. That start.S file is the entry point of all ELF applications, and is the one that calls __libc_start_main which in turn calls main. You just change it so it fits your needs.

Ok, that was theoretical. But now, what practical use does that have?

Answer to the Updated Question

Well. There is a library called libgloss that provides a minimal interface for programs that are meant to run on embedded systems. The newlib C library uses that one as its system-call interface. The general idea is that libgloss is the layer between the C library and the operation system. As such, it also contains the startup files that the operation system jumps into. Both these libraries are part of the GNU binutils project. I've used them to do the interface for another OS and another processor, but there does not seem to be a libgloss port for Linux, so if you call system calls, you will have to do it on your own, as others already stated.

It is absolutely possible to write programs in the C programming language. The linux kernel is a good example of such a program. But also user programs are possible. But what is minimally required is a runtime library (if you want to do any serious stuff). Such one would contain really basic functions, like memcpy, basic macros and so on. The C Standard has a special conformance mode called freestanding, which requires only a very limited set of functionality, suitable also for kernels. Actually, i have no clue about x86 assembler, but i've tried my luck for a very simple C program:

/* gcc -nostdlib start.c */
int main(int, char**, char**);

void _start(int args)
{
    /* we do not care about arguments for main. start.S in 
     * glibc documents how the kernel passes them though.
     */
    int c = main(0,0,0);

    /* do the system-call for exit. */
    asm("movl   %0,%%ebx\n" /* first argument */
        "movl   $1,%%eax\n" /* syscall 1 */
        "int    $0x80"      /* fire interrupt */
        : : "r"(c) :"%eax", "%ebx");
}

int main(int argc, char** argv, char** env) {
    /* yeah here we can do some stuff */
    return 42;
}

We're happy, it actually compiles and runs :)

like image 100
Johannes Schaub - litb Avatar answered Sep 22 '22 21:09

Johannes Schaub - litb


Yes, it is possible, however you will have to make system calls and set up your entry point manually.

Example of a minimal program with entry point:

.globl _start
.text
_start:
    xorl %eax,%eax
    incl %eax
    movb $42, %bl
    int $0x80

Or in plain C (no exit):

void __attribute__((noreturn)) _start() {
    while(1);
}

Compiled with:

gcc -nostdlib -o example example.s
gcc -nostdlib -o example example.c
like image 29
Alex B Avatar answered Sep 22 '22 21:09

Alex B


In pure C? As others have said you still need a way to make syscalls, so you might need to drop down to inline asm for that. That said, if using gcc check out -ffreestanding.

like image 45
Logan Capaldo Avatar answered Sep 24 '22 21:09

Logan Capaldo