NEWLIB: page fault (malloc always return NULL)
Posted: Mon Nov 13, 2017 1:24 pm
Hello,
I ported newlib 2.5.0 thanks to the tutorial of this site. No error at complation but at execution, newlib crashes (page fault around 0x00000000 like 0x0000000e, 0x0000001e...) on functions like close_r, malloc_r, or sfvwrite_r. All these functions are reentrant and I think that's where the problem comes from.
My ELF charger well intializes the BSS segment to 0.
my crt0.c
my brk code
My test code (also crash with binutils)
When executing:
I have a null pointer dereference, probably.
If you need more information, don't hesitate to ask me.
Thank you for you help.
EDIT: I'v found a problem: malloc always return NULL, but sbrk return correct value and the kernel alloctatif this correctly. Why ?
EDIT2: Found the fautif code in stdlib/mallocr.c:
But i don't now why i have this error.
PS: Sorry for my English but i'm French
I ported newlib 2.5.0 thanks to the tutorial of this site. No error at complation but at execution, newlib crashes (page fault around 0x00000000 like 0x0000000e, 0x0000001e...) on functions like close_r, malloc_r, or sfvwrite_r. All these functions are reentrant and I think that's where the problem comes from.
My ELF charger well intializes the BSS segment to 0.
my crt0.c
Code: Select all
#include <fcntl.h>
extern void exit(int code);
extern int main(int argc, char *argv[], char *env);
extern char __bss_start;
extern char _end;
extern char **environ;
void _start(int argc, char *argv[], char *env[])
{
environ = env;
exit(main(argc, argv, env))
}
Code: Select all
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/times.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <stdio.h>
#include <errno.h>
#undef errno
#define SYSCALL_RESERVED 0
#define SYSCALL_EXIT 1
#define SYSCALL_OPEN 2
#define SYSCALL_CLOSE 3
#define SYSCALL_MOUNT 4
#define SYSCALL_UMOUNT 5
#define SYSCALL_READ 6
#define SYSCALL_WRITE 7
#define SYSCALL_SEEK 8
#define SYSCALL_READDIR 9
#define SYSCALL_FORK 10
#define SYSCALL_FORKEXEC 11 // Mélange entre fork et exec (mais en plus optimisé), pas encore supporté
#define SYSCALL_MKDIR 12
#define SYSCALL_RMDIR 13
#define SYSCALL_UNLINK 14
#define SYSCALL_EXEC 15
#define SYSCALL_MKNOD 16
#define SYSCALL_IOCTL 17
#define SYSCALL_BRK 18
#define SYSCALL_CHDIR 19
#define SYSCALL_GETCWD 20
#define SYSCALL_DUP 21
#define SYSCALL_DUP2 22
#define SYSCALL_GETPID 23
#define SYSCALL_ISATTY 24
#define SYSCALL_TIME 25
#define SYSCALL_WAITPID 26
#define SYSCALL_KILL 27
#define SYSCALL_SIGACTION 28
#define SYSCALL_SIGRETURN 29
static unsigned int brk_end = 0;
int syscall3(int id, unsigned int arg0, unsigned int arg1, unsigned int arg2)
{
int retval;
asm volatile("mov %1, %%eax \n\
mov %2, %%ebx \n\
mov %3, %%ecx \n\
mov %4, %%edx \n\
int $0x80 \n\
mov %%eax, %0" : "=m"(retval) : "m"(id), "m"(arg0), "m"(arg1), "m"(arg2));
return retval;
}
int syscall0(int id)
{
return syscall3(id, 0, 0, 0);
}
int syscall1(int id, unsigned int arg0)
{
return syscall3(id, arg0, 0, 0);
}
int syscall2(int id, unsigned int arg0, unsigned int arg1)
{
return syscall3(id, arg0, arg1, 0);
}
int haoudos_brk(void *addr)
{
unsigned int result = syscall1(SYSCALL_BRK, (unsigned int)addr);
if (result == 0)
return -1;
brk_end = (unsigned int)result;
return 0;
}
caddr_t sbrk(int incr)
{
if(brk_end == 0)
haoudos_brk(NULL); // Initialise le heap
unsigned int old_brk_end = brk_end;
int result = haoudos_brk((void *)(brk_end + incr));
if (result == -1)
return 0;
return old_brk_end;
}
Code: Select all
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("Test de printf\n");
exit(0);
return 0;
}
I have a null pointer dereference, probably.
If you need more information, don't hesitate to ask me.
Thank you for you help.
EDIT: I'v found a problem: malloc always return NULL, but sbrk return correct value and the kernel alloctatif this correctly. Why ?
EDIT2: Found the fautif code in stdlib/mallocr.c:
Code: Select all
2577 if (chunksize(top) < nb || remainder_size < (long)MINSIZE)
2579 MALLOC_UNLOCK;
2580 return 0; /* propagate failure */
PS: Sorry for my English but i'm French