A. Akkari A. Akkari - 9 months ago 52
C Question

Can't preload a function in C program

I wrote some code in nasm and I'm trying to implement it in a C program as a replacement of strlen through a shared library, but it doesn't work.

nasm code:

section .text
global strlen:function

strlen:
mov rax, 42
ret


C code:

#include <stdio.h>

size_t strlen(const char *s);

int main()
{
printf("%zu\n", strlen("foobar"));
return (0);
}


I compile the C program just using gcc without any arguments, and I create the shared library with the following commands:

nasm -f elf64 strlen.asm
gcc -shared -fPIC -o libasm.so strlen.o


Finally, I include the shared library:

export LD_PRELOAD=`pwd`/libasm.so


But it displays '6' where I expect it to display '42'.
I don't think the problem comes from my library, because I get segmentation fault when I execute the ls command with LD_PRELOAD.

I'm working on Ubuntu 16.04.

Answer Source

This is not related to nasm at all. A C equivalent of your strlen() function does not work either.

$ cat strlen.c 
#include <stddef.h>

size_t strlen(const char *s)
{
    return 43;
}

$ cat s.c
#include <stdio.h>

size_t strlen(const char *s);

int main()
{
    printf("%zu\n", strlen("foobar"));

    return 0;
}

$ make s
cc     s.c   -o s

$ gcc -shared -fPIC -o strlen.so strlen.c

$ LD_PRELOAD=$PWD/strlen.so ./s
6

What is happening here is that gcc is using its own built-in version of strlen() that cannot be overridden. If the C program that calls strlen() is recompiled to not use this built-in version of strlen(), then your shared library can override it.

$ rm s
$ make s CFLAGS=-fno-builtin-strlen
cc -fno-builtin-strlen    s.c   -o s

$ LD_PRELOAD=$PWD/strlen.so ./s
43

$ LD_PRELOAD=$PWD/libasm.so ./s
42