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