642 lines
16 KiB

* \brief Stub for compiling GCC support libraries without libc
* \author Norman Feske
* \date 2011-08-31
* The target components of GCC tool chains (i.e. libsupc++, libgcc_eh, and
* libstdc++) depend on the presence of libc includes. For this reason, a C
* library for the target platform is normally regarded as a prerequisite for
* building a complete tool chain. However, for low-level operating-system
* code, this prerequisite is not satisfied.
* There are two traditional solutions to this problem. The first is to leave
* out those target components from the tool chain and live without full C++
* support (using '-fno-rtti' and '-fno-exceptions'). Because Genode relies on
* such C++ features however, this is no option. The other traditional solution
* is to use a tool chain compiled for a different target platform such as
* Linux. However, this approach calls for subtle problems because the target
* components are compiled against glibc and make certain presumptions about
* the underlying OS environment. E.g., the 'libstdc++' library of a Linux tool
* chain contains references to glibc's 'stderr' symbol, which does not exist
* on Genode's libc derived from FreeBSD. More critical assumptions are related
* to the mechanism used for thread-local storage.
* This header file overcomes these problems by providing all function
* prototypes and type declarations that are mandatory for compiling GCC's
* target components. Using this libc stub, all GCC target components can be
* built without the need for additional libc support. Of course, for actually
* using these target components, the target OS has to provide the
* implementation of a small subset of functions declared herein. On Genode,
* this subset is provided by the 'cxx' library.
* The code of the target components expects usual C header file names such as
* 'stdio.h'. It does not include 'libgcc_libc_stub.h'. By creating symlinks
* for all those file names pointing to this file, we ensure that this file is
* always included on the first occurrence of the inclusion of any libc header
* file. The set of symlinks pointing to this libc stub are created
* automatically by the 'tool_chain' script.
* Copyright (C) 2011-2013 Genode Labs GmbH
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
#ifndef _LIBC_STUB_H_
#define _LIBC_STUB_H_
/* used for vararg, comes with GCC */
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
** sys/types.h **
typedef __SIZE_TYPE__ size_t;
#ifndef ssize_t
#define ssize_t long /* xxx 64bit */
typedef unsigned long off_t; /* XXX 64bit */
#define pid_t int
typedef unsigned short mode_t; /* XXX 64bit */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#define NULL ((void *)0)
#endif /* __cplusplus */
#endif /* defined NULL */
typedef long clock_t; /* XXX not on 64bit */
#ifdef _LP64
typedef signed char __int8_t;
typedef signed short __int16_t;
typedef signed int __int32_t;
typedef signed long __int64_t;
typedef unsigned char __uint8_t;
typedef unsigned short __uint16_t;
typedef unsigned int __uint32_t;
typedef unsigned long __uint64_t;
#else /* _LP64 */
typedef signed char __int8_t;
typedef signed short __int16_t;
typedef signed long __int32_t;
typedef unsigned char __uint8_t;
typedef unsigned short __uint16_t;
typedef unsigned long __uint32_t;
#ifndef __STRICT_ANSI__
typedef signed long long __int64_t;
typedef unsigned long long __uint64_t;
#endif /* __STRICT_ANSI__ */
#endif /* _LP64 */
typedef __int64_t intmax_t;
typedef __int32_t int_fast8_t;
typedef __int32_t int_fast16_t;
typedef __int32_t int_fast32_t;
typedef __int64_t int_fast64_t;
typedef __int8_t int_least8_t;
typedef __int16_t int_least16_t;
typedef __int32_t int_least32_t;
typedef __int64_t int_least64_t;
typedef __uint64_t uintmax_t;
#ifdef _LP64
typedef __int64_t time_t;
typedef __int64_t intptr_t;
typedef __uint64_t uintptr_t;
typedef __int32_t time_t;
typedef __int32_t intptr_t;
typedef __uint32_t uintptr_t;
typedef __uint32_t uint_fast8_t;
typedef __uint32_t uint_fast16_t;
typedef __uint32_t uint_fast32_t;
typedef __uint64_t uint_fast64_t;
typedef __uint8_t uint_least8_t;
typedef __uint16_t uint_least16_t;
typedef __uint32_t uint_least32_t;
typedef __uint64_t uint_least64_t;
struct timeval {
time_t tv_sec;
long tv_usec; /* XXX 64bit */
** sys/stat.h **
struct stat
unsigned long st_dev;
unsigned long st_ino;
unsigned short st_mode;
#define S_ISREG(m) (((m) & 0170000) == 0100000)
** time.h **
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
long tm_gmtoff;
char *tm_zone;
clock_t clock(void);
double difftime(time_t time1, time_t time0);
struct tm *localtime(const time_t *timep);
char *asctime(const struct tm *tm);
time_t mktime(struct tm *tm);
char *ctime(const time_t *timep);
struct tm *gmtime(const time_t *timep);
time_t time(time_t *t);
size_t strftime(char *s, size_t max, const char *format,
const struct tm *tm);
** string.h **
int memcmp(const void *s1, const void *s2, size_t n);
size_t strlen(const char *s);
void *memcpy(void *dest, const void *src, size_t n);
char *strchr(const char *s, int c);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
void *memchr(const void *s, int c, size_t n);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
void *memset(void *s, int c, size_t n);
size_t strcspn(const char *s, const char *reject);
char *strstr(const char *haystack, const char *needle);
size_t strspn(const char *s, const char *accept);
char *strpbrk(const char *s, const char *accept);
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
/* for compiling 'libsupc++/' */
void *memmove(void *dest, const void *src, size_t n);
int strcoll(const char *s1, const char *s2);
char *strerror(int errnum);
char *strtok(char *str, const char *delim);
size_t strxfrm(char *dest, const char *src, size_t n);
char *strrchr(const char *s, int c);
** strings.h **
void bcopy(const void *src, void *dest, size_t n);
void bzero(void *s, size_t n);
** stdlib.h **
void free(void *ptr);
void *realloc(void *ptr, size_t size);
void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void abort(void);
void exit(int);
int atoi(const char *nptr);
void *alloca(size_t size);
/* for compiling 'libsupc++/' */
typedef struct { int quot; int rem; } div_t;
typedef struct { long quot; long rem; } ldiv_t;
int abs(int j);
long int labs(long int j);
double atof(const char *nptr);
long atol(const char *nptr);
div_t div(int numerator, int denominator);
ldiv_t ldiv(long numerator, long denominator);
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
int rand(void);
void srand(unsigned int seed);
int system(const char *command);
#ifdef _ANSIDECL_H
/* special case provided specifically for compiling libiberty's 'strtod.c' */
double strtod(char *nptr, char **endptr);
double strtod(const char *nptr, char **endptr);
long int strtol(const char *nptr, char **endptr, int base);
unsigned long int strtoul(const char *nptr, char **endptr, int base);
char *getenv(const char *name);
int atexit(void (*function)(void));
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
** stdio.h **
typedef struct __sFILE { int dummy; } FILE;
extern FILE *__stderrp;
extern FILE *__stdinp;
extern FILE *__stdoutp;
#define stderr __stderrp
#define stdin __stdinp
#define stdout __stdoutp
/* must not be enum values */
#define EOF (-1)
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
enum { _IONBF = 2 };
enum { BUFSIZ = 1024 };
FILE *fopen(const char *path, const char *mode);
int fclose(FILE *fp);
int fprintf(FILE *stream, const char *format, ...);
int fputs(const char *s, FILE *stream);
int sscanf(const char *str, const char *format, ...);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
int ferror(FILE *stream);
int sprintf(char *str, const char *format, ...);
FILE *fdopen(int fd, const char *mode);
int fileno(FILE *);
/* for compiling 'libsupc++/' */
typedef off_t fpos_t;
void clearerr(FILE *stream);
int feof(FILE *stream);
int ferror(FILE *stream);
int fflush(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int fgetc(FILE *stream);
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
long ftell(FILE *stream);
int fseek(FILE *stream, long offset, int whence);
void rewind(FILE *stream);
int fputc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);
int putc(int c, FILE *stream);
int rename(const char *oldpath, const char *newpath);
int remove(const char *pathname);
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
FILE *freopen(const char *path, const char *mode, FILE *stream);
int fscanf(FILE *stream, const char *format, ...);
int scanf(const char *format, ...);
int getc(FILE *stream);
int getchar(void);
char *gets(char *s);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
void perror(const char *s);
int printf(const char *format, ...);
void setbuf(FILE *stream, char *buf);
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
FILE *tmpfile(void);
char *tmpnam(char *s);
int ungetc(int c, FILE *stream);
** unistd.h **
int close(int fd);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
pid_t fork(void);
int unlink(const char *pathname);
void _exit(int status);
int link(const char *oldpath, const char *newpath);
pid_t getpid(void);
int pipe(int pipefd[2]);
int dup2(int oldfd, int newfd);
pid_t wait(int *status);
unsigned int sleep(unsigned int seconds);
off_t lseek(int fd, off_t offset, int whence);
** errno.h **
#define errno (* __error())
int *__error(void);
* Error codes corresponding to those of FreeBSD
enum {
EPERM = 1,
ESRCH = 3,
EINTR = 4,
EIO = 5,
ENXIO = 6,
E2BIG = 7,
EBADF = 9,
ECHILD = 10,
EXDEV = 18,
ENOMEM = 12,
EACCES = 13,
EFAULT = 14,
EBUSY = 16,
EEXIST = 17,
ENODEV = 19,
EISDIR = 21,
EINVAL = 22,
ENFILE = 23,
EMFILE = 24,
ENOTTY = 25,
EFBIG = 27,
ENOSPC = 28,
ESPIPE = 29,
EROFS = 30,
EPIPE = 32,
EDOM = 33,
ERANGE = 34,
EAGAIN = 35,
EMLINK = 31,
ELOOP = 62,
ENOLCK = 77,
ENOSYS = 78,
ENOMSG = 83,
** fcntl.h **
enum {
O_RDONLY = 0x0000,
O_WRONLY = 0x0001,
O_RDWR = 0x0002,
O_CREAT = 0x0200,
O_TRUNC = 0x0400,
O_EXCL = 0x0800
enum { F_SETFD = 2 };
enum { FD_CLOEXEC = 1 };
int open(const char *pathname, int flags, ...);
int fcntl(int fd, int cmd, ... /* arg */ );
** signal.h **
enum { SIGTERM = 15 };
int kill(pid_t pid, int sig);
** ctype.h **
int isalnum(int c);
int isalpha(int c);
int isascii(int c);
int isblank(int c);
int iscntrl(int c);
int isdigit(int c);
int isgraph(int c);
int islower(int c);
int isprint(int c);
int ispunct(int c);
int isspace(int c);
int isupper(int c);
int isxdigit(int c);
int toupper(int c);
int tolower(int c);
** locale.h **
struct lconv;
char *setlocale(int category, const char *locale);
struct lconv *localeconv(void);
enum {
LC_ALL = 0,
** math.h **
double acos(double x);
double asin(double x);
double atan(double x);
double atan2(double y, double x);
double ceil(double x);
double cos(double x);
double cosh(double x);
double exp(double x);
double fabs(double x);
double floor(double x);
double fmod(double x, double y);
double frexp(double x, int *exp);
double ldexp(double x, int exp);
double log(double x);
double log10(double x);
double modf(double x, double *iptr);
double pow(double x, double y);
double sin(double x);
double sinh(double x);
double sqrt(double x);
double tan(double x);
double tanh(double x);
** assert.h **
#define assert(e) ((void)0)
** elf.h **
* The following defines and types are solely needed to compile libgcc's
* 'unwind-dw2-fde-glibc.c' in libc mode. This is needed because Genode's
* dynamic linker relies on the the "new" exception mechanism, which is not
* compiled-in when compiling libgcc with the 'inhibit_libc' flag.
* The following types are loosely based on glibc's 'link.h' and 'elf.h'.
typedef __uint32_t Elf64_Word;
typedef __uint64_t Elf64_Addr;
typedef __uint64_t Elf64_Xword;
typedef __uint64_t Elf64_Off;
typedef __uint16_t Elf64_Half;
typedef struct
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf64_Xword p_filesz;
Elf64_Xword p_memsz;
Elf64_Xword p_align;
} Elf64_Phdr;
typedef __uint32_t Elf32_Word;
typedef __uint32_t Elf32_Addr;
typedef __uint64_t Elf32_Xword;
typedef __uint32_t Elf32_Off;
typedef __uint16_t Elf32_Half;
typedef struct
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_LOOS 0x60000000
** link.h **
/* definitions according to glibc */
#ifdef _LP64
#define ElfW(type) Elf64_##type
#define ElfW(type) Elf32_##type
#endif /* _LP64 */
struct dl_phdr_info
ElfW(Addr) dlpi_addr;
const char *dlpi_name;
const ElfW(Phdr) *dlpi_phdr;
ElfW(Half) dlpi_phnum;
unsigned long long int dlpi_adds;
unsigned long long int dlpi_subs;
size_t dlpi_tls_modid;
void *dlpi_tls_data;
extern int dl_iterate_phdr(int (*__callback) (struct dl_phdr_info *,
size_t, void *), void *__data);
** features.h **
/* let check at the beginning of 'gcc/unwind-dw2-fde-glibc.c' pass */
#define __GLIBC__ 99
#ifdef __cplusplus
#endif /* _LIBC_STUB_H_ */