meta: move photon/libc to root
This commit is contained in:
323
libc/sys/horizon/__elf.h
Normal file
323
libc/sys/horizon/__elf.h
Normal file
@@ -0,0 +1,323 @@
|
||||
#ifndef SYS_HORIZON_SYS___ELF_H_
|
||||
#define SYS_HORIZON_SYS___ELF_H_
|
||||
|
||||
#include <magenta/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ELF_LOAD_ERR -1
|
||||
#define ELF_LOADED_EXEC 0
|
||||
#define ELF_LOADED_INTERP 1
|
||||
|
||||
#define ELF_MAG0 0x7f
|
||||
#define ELF_MAG1 'E'
|
||||
#define ELF_MAG2 'L'
|
||||
#define ELF_MAG3 'F'
|
||||
#define ELF_NIDENT 16
|
||||
|
||||
#define SHT_NONE 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3
|
||||
#define SHT_RELA 4
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
#define SHT_DYNSYM 11
|
||||
|
||||
/** Little endian. */
|
||||
#define ELFDATA2LSB (1)
|
||||
|
||||
/** 64-bit. */
|
||||
#define ELFCLASS64 (2)
|
||||
|
||||
/** x86_64 machine type. */
|
||||
#define EM_X86_64 (62)
|
||||
|
||||
/** ELF current version. */
|
||||
#define EV_CURRENT (1)
|
||||
|
||||
/** Dynamic section tags. */
|
||||
#define DT_NULL 0
|
||||
#define DT_NEEDED 1
|
||||
#define DT_PLTRELSZ 2
|
||||
#define DT_PLTGOT 3
|
||||
#define DT_HASH 4
|
||||
#define DT_STRTAB 5
|
||||
#define DT_SYMTAB 6
|
||||
#define DT_RELA 7
|
||||
#define DT_RELASZ 8
|
||||
#define DT_RELAENT 9
|
||||
#define DT_STRSZ 10
|
||||
#define DT_SYMENT 11
|
||||
#define DT_INIT 12
|
||||
#define DT_FINI 13
|
||||
#define DT_REL 17
|
||||
#define DT_RELSZ 18
|
||||
#define DT_RELENT 19
|
||||
#define DT_PLTREL 20
|
||||
#define DT_JMPREL 23
|
||||
#define DT_GNU_HASH 0x6ffffef5
|
||||
#define DT_AUXILIARY 0x7ffffffd
|
||||
|
||||
#define R_386_32 1
|
||||
#define R_386_PC32 2
|
||||
#define R_386_GOT32 3
|
||||
#define R_386_PLT32 4
|
||||
#define R_386_GOTOFF 9
|
||||
#define R_386_GOTPC 10
|
||||
#define R_386_GOT32X 43
|
||||
|
||||
#define R_X86_64_64 1
|
||||
#define R_X86_64_PC32 2
|
||||
#define R_X86_64_GOT32 3
|
||||
#define R_X86_64_PLT32 4
|
||||
#define R_X86_64_COPY 5
|
||||
#define R_X86_64_GLOB_DAT 6
|
||||
#define R_X86_64_JUMP_SLOT 7
|
||||
#define R_X86_64_RELATIVE 8
|
||||
#define R_X86_64_GOTPCREL 9
|
||||
#define R_X86_64_32 10
|
||||
|
||||
#define STT_NOTYPE 0
|
||||
#define STT_OBJECT 1
|
||||
#define STT_FUNC 2
|
||||
#define STT_SECTION 3
|
||||
#define STT_FILE 4
|
||||
#define STT_LOPROC 13
|
||||
#define STT_HIPROC 15
|
||||
|
||||
/* Section flags */
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_ALLOC 0x2
|
||||
#define SHF_EXECINSTR 0x4
|
||||
|
||||
#define SHN_UNDEF 0
|
||||
|
||||
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||
#define ELF64_R_TYPE(i) ((elf_word_t)(i))
|
||||
#define ELF64_ST_BIND(i) ((i) >> 4)
|
||||
#define ELF64_ST_TYPE(i) ((i)&0xf)
|
||||
|
||||
#define STB_LOCAL 0
|
||||
#define STB_GLOBAL 1
|
||||
#define STB_WEAK 2
|
||||
#define STB_NUM 3
|
||||
|
||||
typedef uint64_t elf_addr_t;
|
||||
typedef uint64_t elf_off_t;
|
||||
typedef uint16_t elf_half_t;
|
||||
typedef uint32_t elf_word_t;
|
||||
typedef int32_t elf_sword_t;
|
||||
typedef uint64_t elf_xword_t;
|
||||
typedef int64_t elf_sxword_t;
|
||||
|
||||
/**
|
||||
* ELF file header.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t e_ident[ELF_NIDENT];
|
||||
elf_half_t e_type;
|
||||
elf_half_t e_machine;
|
||||
elf_word_t e_version;
|
||||
elf_addr_t e_entry;
|
||||
elf_off_t e_phoff;
|
||||
elf_off_t e_shoff;
|
||||
elf_word_t e_flags;
|
||||
elf_half_t e_ehsize;
|
||||
elf_half_t e_phentsize;
|
||||
elf_half_t e_phnum;
|
||||
elf_half_t e_shentsize;
|
||||
elf_half_t e_shnum;
|
||||
elf_half_t e_shstrndx;
|
||||
} elf_ehdr_t;
|
||||
|
||||
/**
|
||||
* ELF section header.
|
||||
*/
|
||||
typedef struct {
|
||||
elf_word_t sh_name;
|
||||
elf_word_t sh_type;
|
||||
elf_xword_t sh_flags;
|
||||
elf_addr_t sh_addr;
|
||||
elf_off_t sh_offset;
|
||||
elf_xword_t sh_size;
|
||||
elf_word_t sh_link;
|
||||
elf_word_t sh_info;
|
||||
elf_xword_t sh_addralign;
|
||||
elf_xword_t sh_entsize;
|
||||
} elf_shdr_t;
|
||||
|
||||
/**
|
||||
* ELF symbol.
|
||||
*/
|
||||
typedef struct {
|
||||
elf_word_t st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
elf_half_t st_shndx;
|
||||
elf_addr_t st_value;
|
||||
elf_xword_t st_size;
|
||||
} elf_sym_t;
|
||||
|
||||
/**
|
||||
* ELF program header.
|
||||
*/
|
||||
typedef struct {
|
||||
elf_word_t p_type;
|
||||
elf_word_t p_flags;
|
||||
elf_off_t p_offset;
|
||||
elf_addr_t p_vaddr;
|
||||
elf_addr_t p_paddr;
|
||||
elf_xword_t p_filesz;
|
||||
elf_xword_t p_memsz;
|
||||
elf_xword_t p_align;
|
||||
} elf_phdr_t;
|
||||
|
||||
/**
|
||||
* Extended ELF relocation information.
|
||||
*/
|
||||
typedef struct {
|
||||
elf_addr_t r_offset;
|
||||
elf_xword_t r_info;
|
||||
elf_sxword_t r_addend;
|
||||
} elf_rela_t;
|
||||
|
||||
/**
|
||||
* Dynamic section entries
|
||||
*/
|
||||
typedef struct {
|
||||
elf_sxword_t d_tag;
|
||||
union {
|
||||
elf_xword_t d_val;
|
||||
elf_addr_t d_ptr;
|
||||
} d_un;
|
||||
} elf_dyn_t;
|
||||
|
||||
/**
|
||||
* Section header types.
|
||||
*/
|
||||
enum elf_stype {
|
||||
ST_NONE = 0,
|
||||
ST_PROGBITS = 1,
|
||||
ST_SYMTAB = 2,
|
||||
ST_STRTAB = 3,
|
||||
ST_NOBITS = 8,
|
||||
ST_REL = 9
|
||||
};
|
||||
|
||||
/**
|
||||
* Program header types.
|
||||
*/
|
||||
enum elf_ptype {
|
||||
PT_NULL = 0,
|
||||
PT_LOAD = 1,
|
||||
PT_DYNAMIC = 2,
|
||||
PT_INTERP = 3,
|
||||
PT_NOTE = 4,
|
||||
PT_SHLIB = 5,
|
||||
PT_PHDR = 6
|
||||
};
|
||||
|
||||
#define PF_X 0x1
|
||||
#define PF_W 0x2
|
||||
#define PF_R 0x4
|
||||
|
||||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7FFFFFFF
|
||||
|
||||
/**
|
||||
* ELF identification byte locations.
|
||||
*/
|
||||
enum elf_ident {
|
||||
EI_MAG0 = 0,
|
||||
EI_MAG1 = 1,
|
||||
EI_MAG2 = 2,
|
||||
EI_MAG3 = 3,
|
||||
EI_CLASS = 4,
|
||||
EI_DATA = 5,
|
||||
EI_VERSION = 6,
|
||||
EI_OSABI = 7,
|
||||
EI_ABIVERSION = 8,
|
||||
EI_PAD = 9
|
||||
};
|
||||
|
||||
enum elf_type {
|
||||
ET_NONE = 0,
|
||||
ET_REL = 1,
|
||||
ET_EXEC = 2,
|
||||
ET_DYN = 3,
|
||||
};
|
||||
|
||||
#define AT_NULL 0
|
||||
#define AT_IGNORE 1
|
||||
#define AT_EXECFD 2
|
||||
#define AT_PHDR 3
|
||||
#define AT_PHENT 4
|
||||
#define AT_PHNUM 5
|
||||
#define AT_PAGESZ 6
|
||||
#define AT_BASE 7
|
||||
#define AT_FLAGS 8
|
||||
#define AT_ENTRY 9
|
||||
#define AT_NOTELF 10
|
||||
#define AT_UID 11
|
||||
#define AT_EUID 12
|
||||
#define AT_GID 13
|
||||
#define AT_EGID 14
|
||||
#define AT_CLKTCK 17
|
||||
#define AT_PLATFORM 15
|
||||
#define AT_HWCAP 16
|
||||
#define AT_FPUCW 18
|
||||
#define AT_DCACHEBSIZE 19
|
||||
#define AT_ICACHEBSIZE 20
|
||||
#define AT_UCACHEBSIZE 21
|
||||
#define AT_IGNOREPPC 22
|
||||
#define AT_SECURE 23
|
||||
#define AT_BASE_PLATFORM 24
|
||||
#define AT_RANDOM 25
|
||||
#define AT_HWCAP2 26
|
||||
#define AT_EXECFN 31
|
||||
#define AT_SYSINFO 32
|
||||
#define AT_SYSINFO_EHDR 33
|
||||
#define AT_L1I_CACHESHAPE 34
|
||||
#define AT_L1D_CACHESHAPE 35
|
||||
#define AT_L2_CACHESHAPE 36
|
||||
#define AT_L3_CACHESHAPE 37
|
||||
#define AT_ENTRY_COUNT 38
|
||||
|
||||
struct bootdata;
|
||||
struct bootfs_file;
|
||||
|
||||
struct elf_image {
|
||||
mx_handle_t image_vmo, rw_vmo;
|
||||
mx_vaddr_t local_base_addr, remote_base_addr;
|
||||
|
||||
mx_handle_t local_root_vmar, local_exec_vmar;
|
||||
mx_handle_t remote_root_vmar, remote_exec_vmar;
|
||||
size_t exec_vmar_size;
|
||||
|
||||
elf_ehdr_t hdr;
|
||||
uintptr_t dynstr_offset;
|
||||
size_t dynstr_len;
|
||||
|
||||
uintptr_t dynsym_offset;
|
||||
size_t dynsym_len, dynsym_entsz;
|
||||
|
||||
elf_phdr_t dynamic;
|
||||
|
||||
enum { NO_HASH, REG_HASH, GNU_HASH } hash_type;
|
||||
uintptr_t hash_offset;
|
||||
};
|
||||
|
||||
extern void __elf_image_init(mx_handle_t local_vmar, mx_handle_t remote_vmar, struct elf_image *out);
|
||||
extern int __elf_image_load_image(struct elf_image *image, mx_handle_t image_vmo);
|
||||
extern int __elf_get_interp_path(mx_handle_t exec_vmo, char *out, size_t max);
|
||||
extern int __elf_check_dependencies(struct elf_image *image);
|
||||
|
||||
extern mx_vaddr_t __elf_image_get_symbol(struct elf_image *image, const char *name);
|
||||
|
||||
extern int __elf_image_link(struct elf_image *exec, struct elf_image *vdso);
|
||||
extern mx_vaddr_t __elf_image_entry_point(struct elf_image *image);
|
||||
|
||||
extern void __elf_image_cleanup(struct elf_image *image);
|
||||
|
||||
#endif
|
||||
36
libc/sys/horizon/__fio.h
Normal file
36
libc/sys/horizon/__fio.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef SYS_HORIZON___FIO_H_
|
||||
#define SYS_HORIZON___FIO_H_
|
||||
|
||||
#define __FIO_BUFSZ 512
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct __io_file {
|
||||
char in_buf[__FIO_BUFSZ];
|
||||
char out_buf[__FIO_BUFSZ];
|
||||
unsigned long in_buf_ptr, in_buf_len;
|
||||
unsigned long out_buf_len;
|
||||
int fd, unget;
|
||||
char err, eof;
|
||||
};
|
||||
|
||||
extern int __fileno(struct __io_file *f);
|
||||
extern void __fio_init(int in, int out, int err);
|
||||
extern unsigned int __fio_read(struct __io_file *f, char *buf, unsigned int sz);
|
||||
extern unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz);
|
||||
extern unsigned int __fio_flush(struct __io_file *f);
|
||||
extern int __fio_error(struct __io_file *f);
|
||||
extern int __fio_eof(struct __io_file *f);
|
||||
extern int __fio_ungetc(struct __io_file *f, char c);
|
||||
|
||||
extern int __fio_fopen(const char *path, const char *mode, struct __io_file *out);
|
||||
extern int __fio_fclose(struct __io_file *in);
|
||||
extern int __fio_fdopen(int fd, const char *mode, struct __io_file *out);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
8
libc/sys/horizon/__heap.h
Normal file
8
libc/sys/horizon/__heap.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef SYS_HORIZON_HEAP_H_
|
||||
#define SYS_HORIZON_HEAP_H_
|
||||
|
||||
#include "__init.h"
|
||||
|
||||
extern int __heap_init();
|
||||
|
||||
#endif
|
||||
4
libc/sys/horizon/__init.h
Normal file
4
libc/sys/horizon/__init.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#ifndef SYS_HORIZON_INIT_H_
|
||||
#define SYS_HORIZON_INIT_H_
|
||||
|
||||
#endif
|
||||
14
libc/sys/horizon/__system.h
Normal file
14
libc/sys/horizon/__system.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef SYS_LINUX___SYSTEM_H_
|
||||
#define SYS_LINUX___SYSTEM_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern _Noreturn void __exit(int code);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
6
libc/sys/horizon/__time.h
Normal file
6
libc/sys/horizon/__time.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef SYS_HORIZON___TIME_H_
|
||||
#define SYS_HORIZON___TIME_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#endif
|
||||
0
libc/sys/horizon/config.cmake
Normal file
0
libc/sys/horizon/config.cmake
Normal file
157
libc/sys/horizon/dirent.c
Normal file
157
libc/sys/horizon/dirent.c
Normal file
@@ -0,0 +1,157 @@
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <mio/fs.h>
|
||||
#include <mio/dirent.h>
|
||||
|
||||
DIR *opendir(const char *path)
|
||||
{
|
||||
int fd = open(path, O_DIRECTORY);
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DIR *out = malloc(sizeof(*out));
|
||||
if (!out) {
|
||||
__set_errno(ENOMEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof(*out));
|
||||
out->fd = fd;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int closedir(DIR *d)
|
||||
{
|
||||
close(d->fd);
|
||||
for (int i = 0; i < d->cache_size; i++) {
|
||||
if (d->dent_cache[i].d_namep) {
|
||||
free(d->dent_cache[i].d_namep);
|
||||
}
|
||||
}
|
||||
|
||||
free(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear_cache(DIR *d)
|
||||
{
|
||||
for (int i = 0; i < d->cache_size; i++) {
|
||||
if (d->dent_cache[i].d_namep) {
|
||||
free(d->dent_cache[i].d_namep);
|
||||
}
|
||||
|
||||
d->dent_cache[i].d_namep = NULL;
|
||||
}
|
||||
|
||||
d->cache_size = d->cache_idx = 0;
|
||||
}
|
||||
|
||||
static int refill(DIR *d)
|
||||
{
|
||||
clear_cache(d);
|
||||
|
||||
for (int i = 0; i < d->cache_size; i++) {
|
||||
free(d->dent_cache[i].d_namep);
|
||||
d->dent_cache[i].d_namep = NULL;
|
||||
}
|
||||
|
||||
d->cache_size = d->cache_idx = 0;
|
||||
mio_dirent dent[__SYS_DENT_CACHE_SZ];
|
||||
|
||||
int r = mio_getdents(d->fd, dent, __SYS_DENT_CACHE_SZ);
|
||||
if (r < 0) {
|
||||
__set_errno(-r);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < r; i++) {
|
||||
struct __dentcache *cache_ent = &d->dent_cache[i];
|
||||
cache_ent->d_ino = dent[i].d_ino;
|
||||
cache_ent->d_type = dent[i].d_type;
|
||||
cache_ent->d_namep = strdup(dent[i].d_name);
|
||||
}
|
||||
|
||||
d->cache_idx = 0;
|
||||
d->cache_size = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fill_dirent(DIR *d, struct dirent *out)
|
||||
{
|
||||
if (d->cache_idx >= d->cache_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct __dentcache *cache_ent = &d->dent_cache[d->cache_idx];
|
||||
out->d_ino = cache_ent->d_ino;
|
||||
out->d_type = cache_ent->d_type;
|
||||
|
||||
if (cache_ent->d_namep) {
|
||||
strncpy(out->d_name, cache_ent->d_namep, sizeof out->d_name - 1);
|
||||
out->d_name[sizeof out->d_name - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
struct dirent *readdir(DIR *d)
|
||||
{
|
||||
if (d->cache_idx == d->cache_size) {
|
||||
if (refill(d) != 0 || !d->cache_size) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
fill_dirent(d, &d->cdent);
|
||||
d->cache_idx++;
|
||||
d->seek++;
|
||||
return &d->cdent;
|
||||
}
|
||||
|
||||
int readdir_r(DIR *d, struct dirent *entry, struct dirent **result)
|
||||
{
|
||||
if (d->cache_idx == d->cache_size) {
|
||||
if (refill(d) != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (d->cache_size == 0) {
|
||||
if (result) {
|
||||
*result = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
fill_dirent(d, entry);
|
||||
d->seek++;
|
||||
|
||||
if (result) {
|
||||
*result = entry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rewinddir(DIR *d)
|
||||
{
|
||||
d->seek = mio_seek(d->fd, 0, SEEK_SET);
|
||||
clear_cache(d);
|
||||
}
|
||||
|
||||
void seekdir(DIR *d, long int off)
|
||||
{
|
||||
d->seek = mio_seek(d->fd, off, SEEK_SET);
|
||||
clear_cache(d);
|
||||
}
|
||||
|
||||
long int telldir(DIR *d)
|
||||
{
|
||||
return d->seek;
|
||||
}
|
||||
56
libc/sys/horizon/dlfcn.c
Normal file
56
libc/sys/horizon/dlfcn.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <magenta/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <mio/fs.h>
|
||||
|
||||
__attribute__((weak)) void *dyld_load_object(const char *path, mx_handle_t handle, int mode) { return NULL; }
|
||||
__attribute__((weak)) void *dyld_get_symbol(void *handle, const char *name) { return NULL; }
|
||||
__attribute__((weak)) int dyld_close_object(void *handle) { return 0; }
|
||||
__attribute__((weak)) char *dyld_get_error(void) { return NULL; }
|
||||
|
||||
static char dl_error[512] = {};
|
||||
|
||||
void *dlopen(const char *path, int mode)
|
||||
{
|
||||
/* TODO include error message from errno */
|
||||
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
snprintf(dl_error, sizeof dl_error, "cannot open '%s'", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mx_handle_t image_vmo = MX_NULL_HANDLE;
|
||||
int err = mio_map_file(fd, &image_vmo);
|
||||
close(fd);
|
||||
|
||||
if (err != 0) {
|
||||
snprintf(dl_error, sizeof dl_error, "cannot load '%s'", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dl_error[0] = '\0';
|
||||
return dyld_load_object(path, image_vmo, mode);
|
||||
}
|
||||
|
||||
void *dlsym(void *handle, const char *name)
|
||||
{
|
||||
return dyld_get_symbol(handle, name);
|
||||
}
|
||||
|
||||
int dlclose(void *handle)
|
||||
{
|
||||
return dyld_close_object(handle);
|
||||
}
|
||||
|
||||
char *dlerror(void)
|
||||
{
|
||||
if (dl_error[0] != '\0') {
|
||||
return dl_error;
|
||||
}
|
||||
|
||||
return dyld_get_error();
|
||||
}
|
||||
673
libc/sys/horizon/elf.c
Normal file
673
libc/sys/horizon/elf.c
Normal file
@@ -0,0 +1,673 @@
|
||||
#include <magenta/misc.h>
|
||||
#include <magenta/errors.h>
|
||||
#include <magenta/handle.h>
|
||||
#include <magenta/vmo.h>
|
||||
#include <magenta/vmar.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "__elf.h"
|
||||
|
||||
#define HIDDEN __attribute__((visibility("hidden")))
|
||||
|
||||
#define VDSO_SONAME "mx.dylib"
|
||||
|
||||
#define NEEDS_NOTHING 0
|
||||
#define NEEDS_VDSO 1
|
||||
#define NEEDS_MORE 2
|
||||
|
||||
#define ACL (PF_R | PF_W | PF_X)
|
||||
#define ACCESS(x) ((x) & ACL)
|
||||
|
||||
/* TODO in case we ever support ELF32 images */
|
||||
#define elf_class_bits(x) (64)
|
||||
|
||||
#define PAGE_OFFSET(v) ((v) & (MX_PAGE_SIZE - 1))
|
||||
#define PAGE_ALIGN_DOWN(v) (v) &= ~(MX_PAGE_SIZE - 1)
|
||||
#define PAGE_ALIGN_UP(v) \
|
||||
do { \
|
||||
if ((v) & (MX_PAGE_SIZE - 1)) { \
|
||||
v &= ~(MX_PAGE_SIZE - 1); \
|
||||
v += MX_PAGE_SIZE; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#undef DEBUG_LOG
|
||||
|
||||
HIDDEN void __elf_image_init(mx_handle_t local_vmar, mx_handle_t remote_vmar, struct elf_image *out)
|
||||
{
|
||||
memset(out, 0x0, sizeof(*out));
|
||||
out->local_root_vmar = local_vmar;
|
||||
out->remote_root_vmar = remote_vmar;
|
||||
}
|
||||
|
||||
static int elf_validate_ehdr(elf_ehdr_t *hdr)
|
||||
{
|
||||
if (hdr->e_ident[EI_MAG0] != ELF_MAG0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->e_ident[EI_MAG1] != ELF_MAG1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->e_ident[EI_MAG2] != ELF_MAG2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->e_ident[EI_MAG3] != ELF_MAG3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->e_ident[EI_CLASS] != ELFCLASS64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->e_machine != EM_X86_64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->e_ident[EI_DATA] != ELFDATA2LSB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->e_ident[EI_VERSION] != EV_CURRENT) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_header(struct elf_image *image)
|
||||
{
|
||||
mx_status_t err = mx_vmo_read(image->image_vmo, (uint8_t *)&image->hdr, sizeof(image->hdr), 0);
|
||||
if (err != MX_OK) {
|
||||
printf("vmo_read %x error %s\n", image->image_vmo, mx_status_to_string(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return elf_validate_ehdr(&image->hdr);
|
||||
}
|
||||
|
||||
static mx_status_t allocate_vmar(struct elf_image *image, size_t size)
|
||||
{
|
||||
mx_status_t err = mx_vmar_allocate(image->local_root_vmar,
|
||||
MX_VM_CAN_MAP_READ | MX_VM_CAN_MAP_WRITE |
|
||||
MX_VM_CAN_MAP_EXEC | MX_VM_CAN_MAP_SPECIFIC,
|
||||
0, size, &image->local_exec_vmar, &image->local_base_addr);
|
||||
|
||||
if (err != MX_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mx_vmar_allocate(image->remote_root_vmar,
|
||||
MX_VM_CAN_MAP_READ | MX_VM_CAN_MAP_WRITE |
|
||||
MX_VM_CAN_MAP_EXEC | MX_VM_CAN_MAP_SPECIFIC,
|
||||
0, size, &image->remote_exec_vmar, &image->remote_base_addr);
|
||||
image->exec_vmar_size = size;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void deduce_dynsym_count(struct elf_image *image)
|
||||
{
|
||||
if (image->hash_type == REG_HASH) {
|
||||
image->dynsym_len = *(((uint32_t *)image->hash_offset) + 1);
|
||||
} else {
|
||||
/* We don't need to know the symbol count to use DT_GNU_HASH
|
||||
* (which is good because calculating it is a pain) */
|
||||
image->dynsym_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void read_dynamic_segment(struct elf_image *image)
|
||||
{
|
||||
elf_dyn_t *dyn_array = (elf_dyn_t *)(image->local_base_addr + image->dynamic.p_vaddr);
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
elf_dyn_t *dyn = &dyn_array[i];
|
||||
|
||||
if (dyn->d_tag == DT_NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dyn->d_tag) {
|
||||
case DT_STRTAB:
|
||||
image->dynstr_offset = dyn->d_un.d_ptr;
|
||||
dyn->d_un.d_ptr += image->remote_base_addr;
|
||||
break;
|
||||
case DT_STRSZ:
|
||||
image->dynstr_len = dyn->d_un.d_val;
|
||||
break;
|
||||
case DT_SYMTAB:
|
||||
image->dynsym_offset = dyn->d_un.d_ptr;
|
||||
dyn->d_un.d_ptr += image->remote_base_addr;
|
||||
break;
|
||||
case DT_SYMENT:
|
||||
image->dynsym_entsz = dyn->d_un.d_val;
|
||||
break;
|
||||
case DT_HASH:
|
||||
/* prefer the GNU hash table */
|
||||
if (image->hash_type == GNU_HASH) {
|
||||
continue;
|
||||
}
|
||||
image->hash_type = REG_HASH;
|
||||
image->hash_offset = dyn->d_un.d_ptr;
|
||||
dyn->d_un.d_ptr += image->remote_base_addr;
|
||||
break;
|
||||
case DT_GNU_HASH:
|
||||
image->hash_type = GNU_HASH;
|
||||
image->hash_offset = dyn->d_un.d_ptr;
|
||||
dyn->d_un.d_ptr += image->remote_base_addr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_memory_requirements(void *phdr_buf, int entsize, int nr_phdr,
|
||||
size_t *out_vmem, size_t *out_rw)
|
||||
{
|
||||
size_t vmem_max = 0;
|
||||
size_t rw_max = 0;
|
||||
|
||||
for (int i = 0; i < nr_phdr; i++) {
|
||||
elf_phdr_t *phdr = (elf_phdr_t *)((char *)phdr_buf + (i * entsize));
|
||||
if (phdr->p_type != PT_LOAD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t foffset = phdr->p_offset;
|
||||
size_t voffset = phdr->p_vaddr;
|
||||
PAGE_ALIGN_DOWN(foffset);
|
||||
PAGE_ALIGN_DOWN(voffset);
|
||||
|
||||
size_t vend = phdr->p_vaddr + phdr->p_memsz;
|
||||
PAGE_ALIGN_UP(vend);
|
||||
|
||||
size_t fsize = phdr->p_filesz;
|
||||
size_t vsize = vend - voffset;
|
||||
PAGE_ALIGN_UP(fsize);
|
||||
|
||||
if (phdr->p_flags & PF_W) {
|
||||
rw_max += vsize;
|
||||
}
|
||||
|
||||
if (vend > vmem_max) {
|
||||
vmem_max = vend;
|
||||
}
|
||||
}
|
||||
|
||||
*out_rw = rw_max;
|
||||
*out_vmem = vmem_max;
|
||||
}
|
||||
|
||||
static mx_status_t map_memory(struct elf_image *image,
|
||||
mx_off_t voffset, mx_off_t foffset, size_t sz, int flags, void **out_buf)
|
||||
{
|
||||
mx_status_t err = MX_OK;
|
||||
mx_flags_t options = MX_VM_SPECIFIC;
|
||||
mx_handle_t vmo = image->image_vmo;
|
||||
|
||||
if (flags & PF_R) {
|
||||
options |= MX_VM_PERM_READ;
|
||||
}
|
||||
|
||||
if (flags & PF_W) {
|
||||
options |= MX_VM_PERM_WRITE;
|
||||
vmo = image->rw_vmo;
|
||||
}
|
||||
|
||||
if (flags & PF_X) {
|
||||
options |= MX_VM_PERM_EXEC;
|
||||
}
|
||||
|
||||
mx_vaddr_t local_addr = 0, remote_addr = 0;
|
||||
*out_buf = NULL;
|
||||
|
||||
err = mx_vmar_map(image->local_exec_vmar, options, voffset, vmo, foffset, sz, &local_addr);
|
||||
if (err != MX_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mx_vmar_map(image->remote_exec_vmar, options, voffset, vmo, foffset, sz, &remote_addr);
|
||||
if (err != MX_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*out_buf = (void *)local_addr;
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
static mx_status_t map_image(struct elf_image *image,
|
||||
void *phdr_buf, int phdr_entsize, int phdr_num)
|
||||
{
|
||||
size_t rw_offset = 0;
|
||||
mx_status_t err = MX_OK;
|
||||
|
||||
for (int i = 0; i < phdr_num; i++) {
|
||||
elf_phdr_t *phdr = (elf_phdr_t *)((char *)phdr_buf + (i * phdr_entsize));
|
||||
if (phdr->p_type == PT_DYNAMIC) {
|
||||
image->dynamic = *phdr;
|
||||
}
|
||||
|
||||
if (phdr->p_type != PT_LOAD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t foffset = phdr->p_offset;
|
||||
size_t voffset = phdr->p_vaddr;
|
||||
PAGE_ALIGN_DOWN(foffset);
|
||||
PAGE_ALIGN_DOWN(voffset);
|
||||
|
||||
size_t vend = phdr->p_vaddr + phdr->p_memsz;
|
||||
PAGE_ALIGN_UP(vend);
|
||||
|
||||
size_t fsize = phdr->p_filesz;
|
||||
size_t vsize = vend - voffset;
|
||||
PAGE_ALIGN_UP(fsize);
|
||||
|
||||
if (phdr->p_flags & PF_W) {
|
||||
size_t rw_vmo_offset = rw_offset;
|
||||
size_t rw_vmo_size = vsize;
|
||||
|
||||
size_t bss_offset = phdr->p_vaddr + phdr->p_filesz;
|
||||
size_t bss_size = phdr->p_memsz - phdr->p_filesz;
|
||||
|
||||
void *segment_buf = NULL;
|
||||
err = map_memory(image, voffset, rw_vmo_offset, vsize, phdr->p_flags, &segment_buf);
|
||||
|
||||
if (err != MX_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
void *file_dest = (char *)image->local_base_addr + phdr->p_vaddr;
|
||||
void *bss_dest = (char *)image->local_base_addr + bss_offset;
|
||||
|
||||
mx_vmo_read(image->image_vmo, file_dest, phdr->p_filesz, phdr->p_offset);
|
||||
|
||||
if (bss_size) {
|
||||
memset(bss_dest, 0x0, bss_size);
|
||||
}
|
||||
|
||||
rw_offset += rw_vmo_size;
|
||||
} else {
|
||||
void *segment_buf = NULL;
|
||||
err = map_memory(image, voffset, foffset, vsize, phdr->p_flags, &segment_buf);
|
||||
|
||||
if (err != MX_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
HIDDEN int __elf_image_load_image(struct elf_image *image, mx_handle_t image_vmo)
|
||||
{
|
||||
image->image_vmo = image_vmo;
|
||||
|
||||
int status = read_header(image);
|
||||
|
||||
if (status != 0) {
|
||||
printf("read_header error\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t phdr_bufsz = image->hdr.e_phentsize * image->hdr.e_phnum;
|
||||
unsigned char phdr_buf[phdr_bufsz];
|
||||
|
||||
mx_vmo_read(image_vmo, phdr_buf, phdr_bufsz, image->hdr.e_phoff);
|
||||
|
||||
size_t rw_size, vmem_size;
|
||||
get_memory_requirements(phdr_buf, image->hdr.e_phentsize, image->hdr.e_phnum, &vmem_size, &rw_size);
|
||||
|
||||
if (allocate_vmar(image, vmem_size) != MX_OK) {
|
||||
printf("allocate_vmar error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rw_size) {
|
||||
mx_vmo_create(rw_size, MX_VM_PERM_READ | MX_VM_PERM_WRITE, &image->rw_vmo);
|
||||
}
|
||||
|
||||
mx_status_t err = map_image(image, phdr_buf, image->hdr.e_phentsize, image->hdr.e_phnum);
|
||||
if (err != MX_OK) {
|
||||
printf("map_image error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_dynamic_segment(image);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HIDDEN int __elf_get_interp_path(mx_handle_t image_vmo, char *out, size_t max)
|
||||
{
|
||||
elf_ehdr_t hdr;
|
||||
mx_vmo_read(image_vmo, (uint8_t *)&hdr, sizeof(hdr), 0);
|
||||
|
||||
if (elf_validate_ehdr(&hdr) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char phdr_buf[hdr.e_phentsize * hdr.e_phnum];
|
||||
mx_vmo_read(image_vmo, phdr_buf, hdr.e_phentsize * hdr.e_phnum, hdr.e_phoff);
|
||||
|
||||
uintptr_t dynamic_offset = 0, interp_offset = 0;
|
||||
size_t dynamic_sz = 0, interp_sz = 0;
|
||||
|
||||
for (size_t i = 0; i < hdr.e_phnum; i++) {
|
||||
elf_phdr_t *phdr = (elf_phdr_t *)(phdr_buf + i * hdr.e_phentsize);
|
||||
|
||||
switch (phdr->p_type) {
|
||||
case PT_DYNAMIC:
|
||||
dynamic_offset = phdr->p_offset;
|
||||
dynamic_sz = phdr->p_filesz;
|
||||
break;
|
||||
case PT_INTERP:
|
||||
interp_offset = phdr->p_offset;
|
||||
interp_sz = phdr->p_filesz;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dynamic_sz || !interp_offset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max > interp_sz) {
|
||||
max = interp_sz;
|
||||
}
|
||||
|
||||
mx_vmo_read(image_vmo, (uint8_t *)out, max, interp_offset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
HIDDEN int __elf_check_dependencies(struct elf_image *image)
|
||||
{
|
||||
elf_dyn_t *dyn_array = (elf_dyn_t *)(image->local_base_addr + image->dynamic.p_vaddr);
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
elf_dyn_t *dyn = &dyn_array[i];
|
||||
|
||||
if (dyn->d_tag == DT_NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (dyn->d_tag != DT_NEEDED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *lib_name = (const char *)(image->local_base_addr + image->dynstr_offset + dyn->d_un.d_ptr);
|
||||
if (strcmp(lib_name, VDSO_SONAME) != 0) {
|
||||
/* We can't load executables that link to libraries other than
|
||||
* libmx */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static elf_sym_t *get_dynsym_entry(struct elf_image *image, unsigned int idx)
|
||||
{
|
||||
return (elf_sym_t *)(image->local_base_addr + image->dynsym_offset + idx * image->dynsym_entsz);
|
||||
}
|
||||
|
||||
static const char *get_dynstr(struct elf_image *image, unsigned int idx)
|
||||
{
|
||||
return (const char *)(image->local_base_addr + image->dynstr_offset + idx);
|
||||
}
|
||||
|
||||
static int do_rela(struct elf_image *image, struct elf_image *lib, uintptr_t ptr, size_t sz, size_t entsz)
|
||||
{
|
||||
size_t entries = sz / entsz;
|
||||
|
||||
for (size_t i = 0; i < entries; i++) {
|
||||
elf_rela_t *rela = (elf_rela_t *)(image->local_base_addr + ptr + i * entsz);
|
||||
int sym_idx = ELF64_R_SYM(rela->r_info);
|
||||
int type = ELF64_R_TYPE(rela->r_info);
|
||||
|
||||
mx_vaddr_t sym_val = 0;
|
||||
if (type != R_X86_64_RELATIVE) {
|
||||
elf_sym_t *dynsym = get_dynsym_entry(image, sym_idx);
|
||||
const char *name = get_dynstr(image, dynsym->st_name);
|
||||
sym_val = __elf_image_get_symbol(image, name);
|
||||
if (!sym_val && lib) {
|
||||
sym_val = __elf_image_get_symbol(lib, name);
|
||||
}
|
||||
|
||||
if (!sym_val) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int ok = 1;
|
||||
mx_status_t status = MX_OK;
|
||||
|
||||
switch (type) {
|
||||
case R_X86_64_GLOB_DAT: {
|
||||
elf_xword_t val = sym_val;
|
||||
elf_xword_t *dest = (elf_xword_t *)((char *)image->local_base_addr + rela->r_offset);
|
||||
*dest = val;
|
||||
break;
|
||||
} case R_X86_64_64: {
|
||||
elf_xword_t val = sym_val + rela->r_addend;
|
||||
elf_xword_t *dest = (elf_xword_t *)((char *)image->local_base_addr + rela->r_offset);
|
||||
*dest = val;
|
||||
break;
|
||||
} case R_X86_64_JUMP_SLOT: {
|
||||
elf_xword_t val = sym_val;
|
||||
elf_xword_t *dest = (elf_xword_t *)((char *)image->local_base_addr + rela->r_offset);
|
||||
*dest = val;
|
||||
break;
|
||||
} case R_X86_64_RELATIVE: {
|
||||
elf_xword_t val = image->remote_base_addr + rela->r_addend;
|
||||
elf_xword_t *dest = (elf_xword_t *)((char *)image->local_base_addr + rela->r_offset);
|
||||
*dest = val;
|
||||
break;
|
||||
} default:
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ok || status != MX_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int relocate(struct elf_image *image, struct elf_image *lib)
|
||||
{
|
||||
elf_dyn_t *dyn_array = (elf_dyn_t *)(image->local_base_addr + image->dynamic.p_vaddr);
|
||||
|
||||
int result = 0;
|
||||
|
||||
uintptr_t rel_addr = 0, rela_addr = 0, plt_addr = 0;
|
||||
size_t rel_sz = 0, rel_entsz = 0;
|
||||
size_t rela_sz = 0, rela_entsz = 0;
|
||||
size_t plt_sz = 0, plt_entsz = 0;
|
||||
int plt_enttype;
|
||||
for (int i = 0;; i++) {
|
||||
elf_dyn_t *dyn = &dyn_array[i];
|
||||
|
||||
if (dyn->d_tag == DT_NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dyn->d_tag) {
|
||||
case DT_REL:
|
||||
rel_addr = dyn->d_un.d_ptr;
|
||||
break;
|
||||
case DT_RELSZ:
|
||||
rel_sz = dyn->d_un.d_val;
|
||||
break;
|
||||
case DT_RELENT:
|
||||
rel_entsz = dyn->d_un.d_val;
|
||||
break;
|
||||
case DT_RELA:
|
||||
rela_addr = dyn->d_un.d_ptr;
|
||||
break;
|
||||
case DT_RELASZ:
|
||||
rela_sz = dyn->d_un.d_val;
|
||||
break;
|
||||
case DT_RELAENT:
|
||||
rela_entsz = dyn->d_un.d_val;
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
plt_sz = dyn->d_un.d_val;
|
||||
break;
|
||||
case DT_JMPREL:
|
||||
plt_addr = dyn->d_un.d_ptr;
|
||||
break;
|
||||
case DT_PLTREL:
|
||||
plt_enttype = dyn->d_un.d_ptr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (dyn->d_tag != DT_NEEDED) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (rel_sz) {
|
||||
/* DT_REL is not supported */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (plt_enttype == DT_RELA) {
|
||||
plt_entsz = rela_entsz ? rela_entsz : sizeof(elf_rela_t);
|
||||
} else if (plt_enttype == DT_REL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int r;
|
||||
if (rela_sz) {
|
||||
r = do_rela(image, lib, rela_addr, rela_sz, rela_entsz);
|
||||
if (r != 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (plt_sz) {
|
||||
r = do_rela(image, lib, plt_addr, plt_sz, plt_entsz);
|
||||
if (r != 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HIDDEN int __elf_image_link(struct elf_image *exec, struct elf_image *vdso)
|
||||
{
|
||||
int status = relocate(vdso, NULL);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return relocate(exec, vdso);
|
||||
}
|
||||
|
||||
HIDDEN mx_vaddr_t __elf_image_entry_point(struct elf_image *image)
|
||||
{
|
||||
return image->remote_base_addr + image->hdr.e_entry;
|
||||
}
|
||||
|
||||
static uint32_t gnu_hash(const char *name)
|
||||
{
|
||||
uint32_t h = 5381;
|
||||
for (; *name; name++) {
|
||||
h = (h << 5) + h + *name;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static mx_vaddr_t sym_gnu_hash_search(struct elf_image *image, const char *name)
|
||||
{
|
||||
uint32_t hash = gnu_hash(name);
|
||||
uint32_t *hashtab = (uint32_t *)(image->local_base_addr + image->hash_offset);
|
||||
|
||||
uint32_t nbuckets = hashtab[0];
|
||||
uint32_t symoffset = hashtab[1];
|
||||
uint32_t bloom_size = hashtab[2];
|
||||
uint32_t bloom_shift = hashtab[3];
|
||||
uint64_t *bloom = (uint64_t *)&hashtab[4];
|
||||
uint32_t *buckets = (uint32_t *)&bloom[bloom_size];
|
||||
uint32_t *chain = &buckets[nbuckets];
|
||||
|
||||
uint64_t bloom_word =
|
||||
bloom[(hash / elf_class_bits(image)) % bloom_size];
|
||||
uint64_t bloom_mask =
|
||||
((uint64_t)1 << (hash % elf_class_bits(image))) |
|
||||
((uint64_t)1 << ((hash >> bloom_shift) % elf_class_bits(image)));
|
||||
|
||||
if ((bloom_word & bloom_mask) != bloom_mask) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t symix = buckets[hash % nbuckets];
|
||||
if (symix < symoffset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *strtab = (const char *)(image->local_base_addr + image->dynstr_offset);
|
||||
elf_sym_t *symtab = (elf_sym_t *)(image->local_base_addr + image->dynsym_offset);
|
||||
|
||||
while (1) {
|
||||
const char *symname = strtab + symtab[symix].st_name;
|
||||
uint32_t symhash = chain[symix - symoffset];
|
||||
|
||||
if ((symhash | 1) == (hash | 1) && !strcmp(symname, name)) {
|
||||
return image->remote_base_addr + symtab[symix].st_value;
|
||||
}
|
||||
|
||||
if (symhash & 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
symix++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HIDDEN mx_vaddr_t __elf_image_get_symbol(struct elf_image *image, const char *name)
|
||||
{
|
||||
switch (image->hash_type) {
|
||||
case GNU_HASH:
|
||||
return sym_gnu_hash_search(image, name);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
HIDDEN void __elf_image_cleanup(struct elf_image *image)
|
||||
{
|
||||
if (image->local_exec_vmar) {
|
||||
mx_vmar_unmap(image->local_exec_vmar, 0, image->exec_vmar_size);
|
||||
mx_vmar_destroy(image->local_exec_vmar);
|
||||
mx_handle_close(image->local_exec_vmar);
|
||||
image->local_exec_vmar = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (image->remote_exec_vmar) {
|
||||
mx_handle_close(image->remote_exec_vmar);
|
||||
image->remote_exec_vmar = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (image->rw_vmo) {
|
||||
mx_handle_close(image->rw_vmo);
|
||||
image->rw_vmo = MX_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
35
libc/sys/horizon/environ.c
Normal file
35
libc/sys/horizon/environ.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
extern const char **__crt_environ();
|
||||
|
||||
char *__crt_sys_getenv(const char *name)
|
||||
{
|
||||
const char **envp = __crt_environ();
|
||||
|
||||
for (int i = 0; envp[i] != NULL; i++) {
|
||||
int equal = -1;
|
||||
const char *env = envp[i];
|
||||
|
||||
for (int ii = 0; env[ii] != '\0'; ii++) {
|
||||
if (env[ii] == '=') {
|
||||
equal = ii;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (equal == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char env_name[equal + 1];
|
||||
memcpy(env_name, env, equal);
|
||||
env_name[equal] = '\0';
|
||||
|
||||
if (!strcmp(env_name, name)) {
|
||||
return (char *)(env + equal + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
31
libc/sys/horizon/fcntl.h
Normal file
31
libc/sys/horizon/fcntl.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef SYS_HORIZON_FCNTL_H_
|
||||
#define SYS_HORIZON_FCNTL_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define O_ACCMODE 0003
|
||||
#define O_RDONLY 00
|
||||
#define O_WRONLY 01
|
||||
#define O_RDWR 02
|
||||
#define O_CREAT 0100
|
||||
#define O_EXCL 0200
|
||||
#define O_NOCTTY 0400
|
||||
#define O_TRUNC 01000
|
||||
#define O_APPEND 02000
|
||||
#define O_NONBLOCK 04000
|
||||
#define O_NDELAY O_NONBLOCK
|
||||
#define O_SYNC 04010000
|
||||
#define O_FSYNC O_SYNC
|
||||
#define O_ASYNC 020000
|
||||
#define O_LARGEFILE 0100000
|
||||
|
||||
#define O_DIRECTORY 0200000
|
||||
#define O_NOFOLLOW 0400000
|
||||
#define O_CLOEXEC 02000000
|
||||
#define O_DIRECT 040000
|
||||
#define O_NOATIME 01000000
|
||||
#define O_PATH 010000000
|
||||
#define O_DSYNC 010000
|
||||
#define O_TMPFILE (020000000 | __O_DIRECTORY)
|
||||
|
||||
#endif
|
||||
202
libc/sys/horizon/fio.c
Normal file
202
libc/sys/horizon/fio.c
Normal file
@@ -0,0 +1,202 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "sys/types.h"
|
||||
#include "__fio.h"
|
||||
|
||||
static struct __io_file __stdin = {};
|
||||
static struct __io_file __stdout = {};
|
||||
static struct __io_file __stderr = {};
|
||||
|
||||
static int flags_from_mode(const char *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int refill(struct __io_file *fp)
|
||||
{
|
||||
ssize_t err = read(fp->fd, fp->in_buf, sizeof fp->in_buf);
|
||||
if (err < 0) {
|
||||
fp->err = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fp->in_buf_ptr = 0;
|
||||
fp->in_buf_len = err;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
FILE *__get_stdio_file(int i)
|
||||
{
|
||||
switch (i) {
|
||||
case 0:
|
||||
return &__stdin;
|
||||
case 1:
|
||||
return &__stdout;
|
||||
case 2:
|
||||
return &__stderr;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __fio_init(int in, int out, int err)
|
||||
{
|
||||
__stdin.fd = in;
|
||||
__stdout.fd = out;
|
||||
__stderr.fd = err;
|
||||
}
|
||||
|
||||
int __fio_fopen(const char *path, const char *mode, struct __io_file *fp)
|
||||
{
|
||||
/* TODO */
|
||||
int fd = open(path, 0);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fp->fd = fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __fio_fclose(struct __io_file *fp)
|
||||
{
|
||||
if (fp->fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fp->fd);
|
||||
fp->fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __fio_fdopen(int fd, const char *mode, struct __io_file *fp)
|
||||
{
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fp->fd = fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __fileno(struct __io_file *f)
|
||||
{
|
||||
return (int)f->fd;
|
||||
}
|
||||
|
||||
unsigned int __fio_read(struct __io_file *f, char *buf, unsigned int sz)
|
||||
{
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t r = 0;
|
||||
char *out = buf;
|
||||
|
||||
if (f->unget) {
|
||||
*out++ = f->unget;
|
||||
f->unget = 0;
|
||||
r++;
|
||||
sz--;
|
||||
}
|
||||
|
||||
size_t available = f->in_buf_len - f->in_buf_ptr;
|
||||
|
||||
size_t bufread = sz;
|
||||
if (bufread > available) {
|
||||
bufread = available;
|
||||
}
|
||||
|
||||
memcpy(out, f->in_buf + f->in_buf_ptr, bufread);
|
||||
f->in_buf_ptr += bufread;
|
||||
out += bufread;
|
||||
sz -= bufread;
|
||||
r += bufread;
|
||||
|
||||
if (sz == 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
refill(f);
|
||||
|
||||
available = f->in_buf_len - f->in_buf_ptr;
|
||||
if (available == 0) {
|
||||
f->eof = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
bufread = sz;
|
||||
if (bufread > available) {
|
||||
bufread = available;
|
||||
}
|
||||
|
||||
memcpy(out, f->in_buf + f->in_buf_ptr, bufread);
|
||||
f->in_buf_ptr += bufread;
|
||||
out += bufread;
|
||||
sz -= bufread;
|
||||
r += bufread;
|
||||
|
||||
if (sz == 0 || f->err || f->eof) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sz > 0) {
|
||||
f->eof = 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz)
|
||||
{
|
||||
for (unsigned int i = 0; i < sz; i++) {
|
||||
if (f->out_buf_len >= __FIO_BUFSZ) {
|
||||
__fio_flush(f);
|
||||
}
|
||||
|
||||
f->out_buf[f->out_buf_len++] = buf[i];
|
||||
if (buf[i] == '\n') {
|
||||
__fio_flush(f);
|
||||
}
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
int __fio_ungetc(struct __io_file *f, char c)
|
||||
{
|
||||
if (f->unget) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
f->unget = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int __fio_flush(struct __io_file *f)
|
||||
{
|
||||
ssize_t res = write(f->fd, f->out_buf, f->out_buf_len);
|
||||
if (res != f->out_buf_len) {
|
||||
f->err = 1;
|
||||
}
|
||||
|
||||
size_t flushed = f->out_buf_len;
|
||||
f->out_buf_len = 0;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
int __fio_error(struct __io_file *f)
|
||||
{
|
||||
return f->err != 0;
|
||||
}
|
||||
|
||||
int __fio_eof(struct __io_file *f)
|
||||
{
|
||||
return f->eof != 0;
|
||||
}
|
||||
101
libc/sys/horizon/heap.c
Normal file
101
libc/sys/horizon/heap.c
Normal file
@@ -0,0 +1,101 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <magenta/vmo.h>
|
||||
#include <magenta/bootstrap.h>
|
||||
#include <magenta/errors.h>
|
||||
#include <magenta/misc.h>
|
||||
#include <magenta/vmar.h>
|
||||
|
||||
/* 1 GiB */
|
||||
#define HEAP_REGION_SZ 0x40000000
|
||||
|
||||
#define ROUND_UP(x, b) x += (b) - ((x) % (b))
|
||||
|
||||
static uintptr_t heap_start = 0;
|
||||
static uintptr_t heap_end = 0;
|
||||
static uintptr_t heap_alloc_point = 0;
|
||||
static size_t heap_sz = 0;
|
||||
static mx_handle_t heap_vmo = MX_NULL_HANDLE;
|
||||
static mx_handle_t heap_vmar = MX_NULL_HANDLE;
|
||||
|
||||
void __crt_heap_init(size_t sz)
|
||||
{
|
||||
mx_handle_t root_vmar = mx_bootstrap_handle_get(MX_B_VMAR_ROOT);
|
||||
mx_vaddr_t heap = 0;
|
||||
|
||||
mx_status_t status = mx_vmar_allocate(root_vmar,
|
||||
MX_VM_CAN_MAP_READ | MX_VM_CAN_MAP_WRITE | MX_VM_CAN_MAP_SPECIFIC,
|
||||
0, HEAP_REGION_SZ, &heap_vmar, &heap);
|
||||
if (status != MX_OK) {
|
||||
fprintf(stderr, "fatal: cannot allocate heap virtual region (%s)\n", mx_status_to_string(status));
|
||||
abort();
|
||||
}
|
||||
|
||||
status = mx_vmo_create(
|
||||
sz,
|
||||
MX_VM_CAN_MAP_READ | MX_VM_CAN_MAP_WRITE | MX_VM_CAN_MAP_SPECIFIC,
|
||||
&heap_vmo);
|
||||
if (status != MX_OK) {
|
||||
fprintf(stderr, "fatal: cannot allocate heap (%s)\n", mx_status_to_string(status));
|
||||
abort();
|
||||
}
|
||||
|
||||
status = mx_vmar_map(heap_vmar,
|
||||
MX_VM_PERM_READ | MX_VM_PERM_WRITE | MX_VM_SPECIFIC,
|
||||
0, heap_vmo, 0, sz,
|
||||
&heap);
|
||||
if (status != MX_OK) {
|
||||
fprintf(stderr, "fatal: cannot map heap (%s)\n", mx_status_to_string(status));
|
||||
abort();
|
||||
}
|
||||
|
||||
heap_sz = sz;
|
||||
heap_start = heap;
|
||||
heap_end = heap + heap_sz;
|
||||
heap_alloc_point = heap_start;
|
||||
|
||||
memset((void *)heap, 0x0, heap_sz);
|
||||
}
|
||||
|
||||
void *__crt_heap_extend(size_t sz)
|
||||
{
|
||||
if (sz % MX_PAGE_SIZE) {
|
||||
sz &= (MX_PAGE_SIZE - 1);
|
||||
sz += MX_PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (!sz) {
|
||||
return (void *)heap_end;
|
||||
}
|
||||
|
||||
if (!heap_start) {
|
||||
__crt_heap_init(sz);
|
||||
return (void *)heap_start;
|
||||
}
|
||||
|
||||
mx_vmo_set_size(heap_vmo, heap_sz + sz);
|
||||
|
||||
mx_vaddr_t vmar_base, alloc_base;
|
||||
mx_vmar_bounds(heap_vmar, &vmar_base, NULL);
|
||||
size_t offset = heap_end - vmar_base;
|
||||
|
||||
mx_status_t err = mx_vmar_map(heap_vmar,
|
||||
MX_VM_PERM_READ | MX_VM_PERM_WRITE | MX_VM_SPECIFIC,
|
||||
offset, heap_vmo, heap_sz, sz, &alloc_base);
|
||||
|
||||
if (err != MX_OK) {
|
||||
fprintf(stderr, "fatal: cannot map extended heap (%s)\n", mx_status_to_string(err));
|
||||
abort();
|
||||
}
|
||||
|
||||
heap_sz += sz;
|
||||
|
||||
void *out = (void *)heap_end;
|
||||
memset(out, 0x0, sz);
|
||||
heap_end += sz;
|
||||
|
||||
return out;
|
||||
}
|
||||
378
libc/sys/horizon/init.c
Normal file
378
libc/sys/horizon/init.c
Normal file
@@ -0,0 +1,378 @@
|
||||
#include <magenta/task.h>
|
||||
#include <magenta/tunnel.h>
|
||||
#include <magenta/bootstrap.h>
|
||||
#include <magenta/signals.h>
|
||||
#include <magenta/errors.h>
|
||||
#include <magenta/handle.h>
|
||||
#include <magenta/misc.h>
|
||||
#include <magenta/object.h>
|
||||
#include <mio/object.h>
|
||||
#include <mio/fd.h>
|
||||
#include <mio/fs.h>
|
||||
#include <mio/namespace.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "__init.h"
|
||||
#include "__heap.h"
|
||||
#include "__fio.h"
|
||||
|
||||
/* maximum of 32 handles can be received sent as arguments */
|
||||
#define MAX_HANDLE_ARGS 32
|
||||
|
||||
/* maximum size of bootstrap message that can be received */
|
||||
#define MAX_MSG_SIZE 0x2000
|
||||
|
||||
#if 1
|
||||
#define dbg_log(...)
|
||||
#else
|
||||
static void dbg_log(const char *format, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
|
||||
int r = vsnprintf(buf, sizeof buf, format, arg);
|
||||
va_end(arg);
|
||||
|
||||
mx_console_write(buf, r);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DYLD_PARENT_IMAGE
|
||||
extern mx_vaddr_t dyld_load_exec(int argc, const char **argv);
|
||||
#endif
|
||||
|
||||
static const char **environ = NULL;
|
||||
static char arg_msg_buf[MAX_MSG_SIZE];
|
||||
static mx_bootstrap_handle_t arg_handles[MAX_HANDLE_ARGS];
|
||||
|
||||
const char **__crt_environ()
|
||||
{
|
||||
return environ;
|
||||
}
|
||||
|
||||
extern int main(int, const char **);
|
||||
extern void __crt_run_atexit();
|
||||
|
||||
static void extract_arg_handles(mx_bootstrap_msg_t *args,
|
||||
mx_handle_t *handles, int hndc, mx_bootstrap_handle_t *out)
|
||||
{
|
||||
uint32_t *hent = (uint32_t *)((char *)args + args->handle_info_off);
|
||||
|
||||
for (int i = 0; i < hndc; i++) {
|
||||
out[i].info = hent[i];
|
||||
out[i].handle = handles[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_args(mx_bootstrap_msg_t *args,
|
||||
const char **argv, const char **envp, const char **namep)
|
||||
{
|
||||
if (args->args_num > 0) {
|
||||
char *arg_buf = (char *)args + args->args_off;
|
||||
int arg_i = 0;
|
||||
int arg_off = 0;
|
||||
|
||||
for (int i = 0; ; i++) {
|
||||
if (arg_buf[i] == '\0') {
|
||||
argv[arg_i++] = arg_buf + arg_off;
|
||||
arg_off = i + 1;
|
||||
}
|
||||
|
||||
if (arg_i == (int)args->args_num) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args->environ_num > 0) {
|
||||
char *env_buf = (char *)args + args->environ_off;
|
||||
int env_i = 0;
|
||||
int env_off = 0;
|
||||
|
||||
for (int i = 0; ; i++) {
|
||||
if (env_buf[i] == '\0') {
|
||||
envp[env_i++] = env_buf + env_off;
|
||||
env_off = i + 1;
|
||||
}
|
||||
|
||||
if (env_i == (int)args->environ_num) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args->names_num) {
|
||||
char *name_buf = (char *)args + args->names_off;
|
||||
int name_i = 0;
|
||||
int name_off = 0;
|
||||
|
||||
for (int i = 0; ; i++) {
|
||||
if (name_buf[i] == '\0') {
|
||||
namep[name_i++] = name_buf + name_off;
|
||||
name_off = i + 1;
|
||||
}
|
||||
|
||||
if (name_i == (int)args->names_num) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hang()
|
||||
{
|
||||
while (1) {
|
||||
mx_nanosleep(mx_deadline_after(MX_SEC(1)));
|
||||
}
|
||||
}
|
||||
|
||||
static void init_stdio_fd(int fd, mx_handle_t *handles, size_t nhandles)
|
||||
{
|
||||
if (handles[0] == MX_NULL_HANDLE) {
|
||||
dbg_log("** photon: FD %d is closed\n", fd);
|
||||
return;
|
||||
}
|
||||
|
||||
mx_info_basic_t handle0_info;
|
||||
mx_status_t err = mx_object_get_info(handles[0], MX_INFO_HANDLE_BASIC, &handle0_info, sizeof(handle0_info));
|
||||
if (err != MX_OK) {
|
||||
/* bad handle. TODO report error somehow */
|
||||
return;
|
||||
}
|
||||
|
||||
mio_object *obj = NULL;
|
||||
|
||||
if (handle0_info.type == MX_OBJECT_PIPE) {
|
||||
obj = mio_pipe_create(handles[0]);
|
||||
dbg_log("** photon: FD %d is a pipe\n", fd);
|
||||
} else {
|
||||
/* just assume all other stdio handles implement the file protocol over a tunnel */
|
||||
obj = mio_file_create(handles[0]);
|
||||
dbg_log("** photon: FD %d is a file\n", fd);
|
||||
}
|
||||
|
||||
mio_fd_list_alloc_at(mio_global_fd_list(), obj, fd);
|
||||
}
|
||||
|
||||
static void init_stdio(mx_bootstrap_handle_t *handles, size_t nhandles)
|
||||
{
|
||||
dbg_log("** photon: initialising stdio\n");
|
||||
bool no_fds = true;
|
||||
int max_fd = 0;
|
||||
for (size_t i = 0; i < nhandles; i++) {
|
||||
uint32_t info = handles[i].info;
|
||||
if (MX_B_HND_TYPE(info) != MX_B_FD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
no_fds = false;
|
||||
int fd = MX_B_HND_ARG(info);
|
||||
if (fd > max_fd) {
|
||||
max_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
if (no_fds) {
|
||||
dbg_log("** photon: we've been given no FDs\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int nfds = max_fd + 1;
|
||||
dbg_log("** photon: we've been given up to %d FDs\n", nfds);
|
||||
|
||||
/* Supports up to two handles per FD */
|
||||
mx_handle_t fd_handles[nfds][2];
|
||||
memset(fd_handles, 0x0, sizeof(mx_handle_t) * 2 * nfds);
|
||||
|
||||
for (size_t i = 0; i < nhandles; i++) {
|
||||
uint32_t info = handles[i].info;
|
||||
if (MX_B_HND_TYPE(info) != MX_B_FD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int fd = MX_B_HND_ARG(info);
|
||||
mx_handle_t *this_fd_handles = fd_handles[fd];
|
||||
|
||||
if (this_fd_handles[0] != MX_NULL_HANDLE) {
|
||||
this_fd_handles[1] = handles[i].handle;
|
||||
} else {
|
||||
this_fd_handles[0] = handles[i].handle;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nfds; i++) {
|
||||
size_t n = 1;
|
||||
if (fd_handles[i][1] != MX_NULL_HANDLE) {
|
||||
n++;
|
||||
}
|
||||
|
||||
//dbg_log("** photon: handles for FD %d = { %x, %x }\n", i, fd_handles[i][0], fd_handles[i][1]);
|
||||
|
||||
init_stdio_fd(i, fd_handles[i], n);
|
||||
}
|
||||
|
||||
__fio_init(0, 1, 2);
|
||||
dbg_log("** photon: stdio init finished\n");
|
||||
}
|
||||
|
||||
static int do_init(mx_handle_t bootstrap, bool enable_fs, bool enable_stdio, int *out_argc, const char ***out_argv)
|
||||
{
|
||||
dbg_log("reading bootstrap message from %x\n", bootstrap);
|
||||
mx_signals_t sig = 0;
|
||||
mx_object_wait(bootstrap, MX_TUNNEL_READABLE, 0, &sig);
|
||||
if (!(sig & MX_TUNNEL_READABLE)) {
|
||||
dbg_log("no bootstrap message!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t msg_size = 0;
|
||||
size_t nr_handles = 0;
|
||||
|
||||
mx_handle_t handles[MAX_HANDLE_ARGS + 1];
|
||||
|
||||
dbg_log("receiving message from handle %lx\n", bootstrap);
|
||||
mx_status_t err = mx_tunnel_read(bootstrap,
|
||||
arg_msg_buf, MAX_MSG_SIZE,
|
||||
handles, MAX_HANDLE_ARGS,
|
||||
&msg_size, &nr_handles);
|
||||
|
||||
if (err != MX_OK) {
|
||||
dbg_log("error: cannot read bootstrap message from handle %lx (error %d)\n",
|
||||
bootstrap, err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mx_bootstrap_msg_t *msg = (mx_bootstrap_msg_t *)arg_msg_buf;
|
||||
|
||||
dbg_log("extracting handles\n");
|
||||
extract_arg_handles(msg, handles, nr_handles, arg_handles);
|
||||
#if 0
|
||||
arg_handles[nr_handles].handle = bootstrap;
|
||||
arg_handles[nr_handles].info = MX_B_HND(MX_B_TUNNEL_BTSTP, 0);
|
||||
nr_handles++;
|
||||
#endif
|
||||
|
||||
dbg_log("extracted %zu handles\n", nr_handles);
|
||||
|
||||
mx_bootstrap_handle_init(arg_handles, nr_handles);
|
||||
|
||||
const char **argv = NULL, **envp = NULL, **namep = NULL;
|
||||
|
||||
dbg_log("allocating buffers (%u, %u, %u)\n", msg->args_num, msg->environ_num, msg->names_num);
|
||||
|
||||
argv = calloc(sizeof *argv, msg->args_num + 1);
|
||||
envp = calloc(sizeof *envp, msg->environ_num + 1);
|
||||
namep = calloc(sizeof *namep, msg->names_num + 1);
|
||||
|
||||
environ = envp;
|
||||
|
||||
parse_args(msg, argv, envp, namep);
|
||||
|
||||
*out_argc = msg->args_num;
|
||||
*out_argv = argv;
|
||||
|
||||
if (enable_stdio) {
|
||||
init_stdio(arg_handles, nr_handles);
|
||||
} else {
|
||||
__fio_init(-1, -1, -1);
|
||||
}
|
||||
|
||||
if (!enable_fs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mio_namespace *ns = mio_namespace_create();
|
||||
|
||||
dbg_log("received %u names/%zu handles\n", msg->names_num, nr_handles);
|
||||
if (msg->names_num > 0) {
|
||||
for (size_t i = 0; i < nr_handles; i++) {
|
||||
int type = MX_B_HND_TYPE(arg_handles[i].info);
|
||||
int arg = MX_B_HND_ARG(arg_handles[i].info);
|
||||
|
||||
if (type != MX_B_NS_DIR && type != MX_B_TUNNEL_CWD) {
|
||||
dbg_log(" * wrong type %x\n", type);
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *path = namep[arg];
|
||||
dbg_log(" * %s = %x\n", path, arg_handles[i].handle);
|
||||
|
||||
if (type == MX_B_TUNNEL_CWD) {
|
||||
mio_set_cwd(arg_handles[i].handle, path);
|
||||
} else {
|
||||
mio_namespace_add_entry(ns, path, arg_handles[i].handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mio_set_global_namespace(ns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_run(mx_handle_t bootstrap)
|
||||
{
|
||||
int argc;
|
||||
const char **argv;
|
||||
|
||||
int err = do_init(bootstrap, true, true, &argc, &argv);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return main(argc, argv);
|
||||
}
|
||||
|
||||
#ifdef DYLD_PARENT_IMAGE
|
||||
static int do_load_and_run(mx_handle_t bootstrap)
|
||||
{
|
||||
int argc;
|
||||
const char **argv;
|
||||
|
||||
int err = do_init(bootstrap, false, true, &argc, &argv);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
mx_vaddr_t main_ptr = dyld_load_exec(argc, argv);
|
||||
if (!main_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mx_bootstrap_handle_cleanup();
|
||||
|
||||
err = do_init(bootstrap, true, true, &argc, &argv);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
int(*main_func)(int, const char **) = (int(*)(int, const char **))main_ptr;
|
||||
if (!main_func) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return main_func(argc, argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
int __crt_init(mx_handle_t bootstrap, mx_vaddr_t arg2)
|
||||
{
|
||||
#ifndef DYLD_PARENT_IMAGE
|
||||
int ret = do_run(bootstrap);
|
||||
#else
|
||||
int ret = do_load_and_run(bootstrap);
|
||||
#endif
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
__crt_run_atexit();
|
||||
mio_fd_cleanup();
|
||||
mio_fs_cleanup();
|
||||
mx_task_kill(mx_bootstrap_handle_get(MX_B_TASK_SELF), ret);
|
||||
|
||||
/* unreachable */
|
||||
hang();
|
||||
return 0;
|
||||
}
|
||||
1225
libc/sys/horizon/launch.c
Normal file
1225
libc/sys/horizon/launch.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
libc/sys/horizon/launch.tar.xz
Normal file
BIN
libc/sys/horizon/launch.tar.xz
Normal file
Binary file not shown.
18
libc/sys/horizon/machine/x86_64/crt0.s
Normal file
18
libc/sys/horizon/machine/x86_64/crt0.s
Normal file
@@ -0,0 +1,18 @@
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
.extern __crt_init
|
||||
.type __crt_init, @function
|
||||
|
||||
.extern main
|
||||
.type main, @function
|
||||
|
||||
_start:
|
||||
# Magenta aligns the stack to a page boundry and subtracts 8.
|
||||
# Add 8 to restore 16-byte alignment
|
||||
add $8, %rsp
|
||||
call __crt_init
|
||||
|
||||
# unreachable; __crt_init() will call mx_task_kill()
|
||||
.loop:
|
||||
jmp .loop
|
||||
11
libc/sys/horizon/machine/x86_64/pthread.s
Normal file
11
libc/sys/horizon/machine/x86_64/pthread.s
Normal file
@@ -0,0 +1,11 @@
|
||||
.global __pthread_self
|
||||
.type __pthread_self, @function
|
||||
|
||||
__pthread_self:
|
||||
push %rbp
|
||||
mov %rsp, %rbp
|
||||
|
||||
mov %fs:0, %rax
|
||||
|
||||
pop %rbp
|
||||
ret
|
||||
29
libc/sys/horizon/sys/_dirent.h
Normal file
29
libc/sys/horizon/sys/_dirent.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef SYS_HORIZON_SYS__DIRENT_H_
|
||||
#define SYS_HORIZON_SYS__DIRENT_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define __SYS_DENT_CACHE_SZ 4
|
||||
|
||||
struct __dentcache {
|
||||
ino_t d_ino;
|
||||
unsigned char d_type;
|
||||
char *d_namep;
|
||||
};
|
||||
|
||||
struct dirent {
|
||||
ino_t d_ino;
|
||||
unsigned char d_type;
|
||||
char d_name[NAME_MAX + 1];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
long seek;
|
||||
unsigned char cache_idx, cache_size;
|
||||
struct __dentcache dent_cache[__SYS_DENT_CACHE_SZ];
|
||||
struct dirent cdent;
|
||||
} DIR;
|
||||
|
||||
#endif
|
||||
136
libc/sys/horizon/sys/_errno.h
Normal file
136
libc/sys/horizon/sys/_errno.h
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef SYS_HORIZON_SYS__ERRNO_H_
|
||||
#define SYS_HORIZON_SYS__ERRNO_H_
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* Input/output error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file descriptor */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Resource temporarily unavailable */
|
||||
#define ENOMEM 12 /* Cannot allocate memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Invalid cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* Too many open files in system */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Inappropriate ioctl for device */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Numerical argument out of domain */
|
||||
#define ERANGE 34 /* Numerical result out of range */
|
||||
#define EDEADLK 35 /* Resource deadlock avoided */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many levels of symbolic links */
|
||||
#define ENOMSG 41 /* No message of desired type */
|
||||
#define EIDRM 42 /* Identifier removed */
|
||||
#define ECHRNG 43 /* Channel number out of range */
|
||||
#define EL2NSYNC 44 /* Level 2 not synchronized */
|
||||
#define EL3HLT 45 /* Level 3 halted */
|
||||
#define EL3RST 46 /* Level 3 reset */
|
||||
#define ELNRNG 47 /* Link number out of range */
|
||||
#define EUNATCH 48 /* Protocol driver not attached */
|
||||
#define ENOCSI 49 /* No CSI structure available */
|
||||
#define EL2HLT 50 /* Level 2 halted */
|
||||
#define EBADE 51 /* Invalid exchange */
|
||||
#define EBADR 52 /* Invalid request descriptor */
|
||||
#define EXFULL 53 /* Exchange full */
|
||||
#define ENOANO 54 /* No anode */
|
||||
#define EBADRQC 55 /* Invalid request code */
|
||||
#define EBADSLT 56 /* Invalid slot */
|
||||
#define EBFONT 57 /* Bad font file format */
|
||||
#define ENOSTR 58 /* Device not a stream */
|
||||
#define ENODATA 59 /* No data available */
|
||||
#define ETIME 60 /* Timer expired */
|
||||
#define ENOSR 61 /* Out of streams resources */
|
||||
#define ENONET 62 /* Machine is not on the network */
|
||||
#define ENOPKG 63 /* Package not installed */
|
||||
#define EREMOTE 64 /* Object is remote */
|
||||
#define ENOLINK 65 /* Link has been severed */
|
||||
#define EADV 66 /* Advertise error */
|
||||
#define ESRMNT 67 /* Srmount error */
|
||||
#define ECOMM 68 /* Communication error on send */
|
||||
#define EPROTO 69 /* Protocol error */
|
||||
#define EMULTIHOP 70 /* Multihop attempted */
|
||||
#define EDOTDOT 71 /* RFS specific error */
|
||||
#define EBADMSG 72 /* Bad message */
|
||||
#define EOVERFLOW 73 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 74 /* Name not unique on network */
|
||||
#define EBADFD 75 /* File descriptor in bad state */
|
||||
#define EREMCHG 76 /* Remote address changed */
|
||||
#define ELIBACC 77 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 78 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 79 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 80 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 81 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 82 /* Invalid or incomplete multibyte or wide character */
|
||||
#define ERESTART 83 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 84 /* Streams pipe error */
|
||||
#define EUSERS 85 /* Too many users */
|
||||
#define ENOTSOCK 86 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 87 /* Destination address required */
|
||||
#define EMSGSIZE 88 /* Message too long */
|
||||
#define EPROTOTYPE 89 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 90 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 91 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 92 /* Socket type not supported */
|
||||
#define ENOTSUP 93 /* Operation not supported */
|
||||
#define EPFNOSUPPORT 94 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 95 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 96 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 97 /* Cannot assign requested address */
|
||||
#define ENETDOWN 98 /* Network is down */
|
||||
#define ENETUNREACH 99 /* Network is unreachable */
|
||||
#define ENETRESET 100 /* Network dropped connection on reset */
|
||||
#define ECONNABORTED 101 /* Software caused connection abort */
|
||||
#define ECONNRESET 102 /* Connection reset by peer */
|
||||
#define ENOBUFS 103 /* No buffer space available */
|
||||
#define EISCONN 104 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 105 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 106 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 107 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 108 /* Connection timed out */
|
||||
#define ECONNREFUSED 109 /* Connection refused */
|
||||
#define EHOSTDOWN 110 /* Host is down */
|
||||
#define EHOSTUNREACH 111 /* No route to host */
|
||||
#define EALREADY 112 /* Operation already in progress */
|
||||
#define EINPROGRESS 113 /* Operation now in progress */
|
||||
#define ESTALE 114 /* Stale file handle */
|
||||
#define EUCLEAN 115 /* Structure needs cleaning */
|
||||
#define ENOTNAM 116 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 117 /* No XENIX semaphores available */
|
||||
#define EISNAM 118 /* Is a named type file */
|
||||
#define EREMOTEIO 119 /* Remote I/O error */
|
||||
#define EDQUOT 120 /* Disk quota exceeded */
|
||||
#define ENOMEDIUM 121 /* No medium found */
|
||||
#define EMEDIUMTYPE 122 /* Wrong medium type */
|
||||
#define ECANCELED 123 /* Operation canceled */
|
||||
#define ENOKEY 124 /* Required key not available */
|
||||
#define EKEYEXPIRED 125 /* Key has expired */
|
||||
#define EKEYREVOKED 126 /* Key has been revoked */
|
||||
#define EKEYREJECTED 127 /* Key was rejected by service */
|
||||
#define EOWNERDEAD 128 /* Owner died */
|
||||
#define ENOTRECOVERABLE 129 /* State not recoverable */
|
||||
#define ERFKILL 130 /* Operation not possible due to RF-kill */
|
||||
#define EHWPOISON 131 /* Memory page has hardware error */
|
||||
|
||||
#endif
|
||||
12
libc/sys/horizon/sys/_fconst.h
Normal file
12
libc/sys/horizon/sys/_fconst.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef SYS_HORIZON_SYS__FCONST_H_
|
||||
#define SYS_HORIZON_SYS__FCONST_H_
|
||||
|
||||
/* Must use the value of horizon.io.NAME_MAX */
|
||||
#define __FILENAME_MAX 255
|
||||
|
||||
/* Must use the values from horizon.io.Whence */
|
||||
#define __SEEK_SET 0
|
||||
#define __SEEK_CUR 1
|
||||
#define __SEEK_END 2
|
||||
|
||||
#endif
|
||||
20
libc/sys/horizon/sys/_time.h
Normal file
20
libc/sys/horizon/sys/_time.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef SYS_HORIZON___TIME_H_
|
||||
#define SYS_HORIZON___TIME_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <magenta/clock.h>
|
||||
|
||||
#define __SYS_CLOCKS_PER_SEC 1000000000
|
||||
#define __SYS_CLOCK_REALTIME MX_CLOCK_REALTIME
|
||||
#define __SYS_CLOCK_MONOTONIC MX_CLOCK_MONOTONIC
|
||||
|
||||
struct timespec;
|
||||
|
||||
extern clock_t __sys_clock(void);
|
||||
extern time_t __sys_time(void);
|
||||
|
||||
extern int __sys_clock_getres(clockid_t clk_id, struct timespec *res);
|
||||
extern int __sys_clock_gettime(clockid_t clk_id, struct timespec *tp);
|
||||
extern int __sys_clock_settime(clockid_t clk_id, const struct timespec *tp);
|
||||
|
||||
#endif
|
||||
51
libc/sys/horizon/sys/launch.h
Normal file
51
libc/sys/horizon/sys/launch.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef SYS_HORIZON_SYS_LAUNCH_H_
|
||||
#define SYS_HORIZON_SYS_LAUNCH_H_
|
||||
|
||||
#include <magenta/bootstrap.h>
|
||||
|
||||
#define FD_NONE -1
|
||||
#define FD_INHERIT -2
|
||||
|
||||
#define LAUNCH_MAX_FDS 3
|
||||
|
||||
#define NS_ENTRY_FD(p, f) { .path = (p), .src = NULL, .fd = (f), .handle = MX_NULL_HANDLE }
|
||||
#define NS_ENTRY_HANDLE(p, h) { .path = (p), .src = NULL, .fd = -1, .handle = (h) }
|
||||
#define NS_ENTRY_PATH(p, s) { .path = (p), .src = (s), .fd = -1, .handle = MX_NULL_HANDLE }
|
||||
|
||||
enum launch_flags {
|
||||
/* don't inherit parent task's namespace. */
|
||||
LAUNCH_SET_NS = 0x01u,
|
||||
/* use launch_info.fd as the new task's stdio file descriptors */
|
||||
LAUNCH_SET_FD = 0x02u,
|
||||
};
|
||||
|
||||
struct namespace_entry {
|
||||
const char *path, *src;
|
||||
|
||||
/* if this is not -1, handle must be MX_NULL_HANDLE */
|
||||
int fd;
|
||||
/* if this is not MX_NULL_HANDLE, fd must be -1 */
|
||||
mx_handle_t handle;
|
||||
};
|
||||
|
||||
struct launch_info {
|
||||
enum launch_flags flags;
|
||||
const char *path;
|
||||
|
||||
int argc;
|
||||
const char **argv;
|
||||
|
||||
int fd[LAUNCH_MAX_FDS];
|
||||
|
||||
struct namespace_entry cwd;
|
||||
const struct namespace_entry *ns;
|
||||
size_t ns_count;
|
||||
|
||||
const mx_bootstrap_handle_t *handles;
|
||||
size_t handle_count;
|
||||
};
|
||||
|
||||
extern int launch(const struct launch_info *info, mx_handle_t *out_task);
|
||||
extern const char *launch_error(void);
|
||||
|
||||
#endif
|
||||
16
libc/sys/horizon/sys/time.h
Normal file
16
libc/sys/horizon/sys/time.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef SYS_HORIZON_TIME_H_
|
||||
#define SYS_HORIZON_TIME_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
struct timeval {
|
||||
time_t tv_sec;
|
||||
suseconds_t tv_usec;
|
||||
};
|
||||
|
||||
struct timezone {
|
||||
int tz_minuteswest;
|
||||
int tz_dsttime;
|
||||
};
|
||||
|
||||
#endif
|
||||
27
libc/sys/horizon/sys/types.h
Normal file
27
libc/sys/horizon/sys/types.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef SYS_LINUX_SYS_TYPES_H_
|
||||
#define SYS_LINUX_SYS_TYPES_H_
|
||||
|
||||
#include <machine/_stdint.h>
|
||||
#include <mio/types.h>
|
||||
|
||||
typedef signed long long blkcnt_t;
|
||||
typedef signed long long blksize_t;
|
||||
typedef unsigned long long clock_t;
|
||||
typedef unsigned int clockid_t;
|
||||
typedef unsigned long long fsblkcnt_t;
|
||||
typedef unsigned long long fsfilcnt_t;
|
||||
typedef unsigned int gid_t;
|
||||
typedef unsigned int id_t;
|
||||
typedef unsigned int key_t;
|
||||
typedef unsigned int mode_t;
|
||||
typedef unsigned long long nlink_t;
|
||||
typedef __int64_t off64_t;
|
||||
typedef signed int pid_t;
|
||||
typedef unsigned long long time_t;
|
||||
typedef unsigned int timer_t;
|
||||
typedef unsigned int uid_t;
|
||||
typedef unsigned long useconds_t;
|
||||
typedef long suseconds_t;
|
||||
typedef unsigned long long dev_t;
|
||||
|
||||
#endif
|
||||
5
libc/sys/horizon/system.c
Normal file
5
libc/sys/horizon/system.c
Normal file
@@ -0,0 +1,5 @@
|
||||
_Noreturn void __exit(int code)
|
||||
{
|
||||
/* TODO Exit syscall */
|
||||
while (1) {}
|
||||
}
|
||||
78
libc/sys/horizon/time.c
Normal file
78
libc/sys/horizon/time.c
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <magenta/types.h>
|
||||
#include <magenta/misc.h>
|
||||
#include <magenta/errors.h>
|
||||
#include <magenta/clock.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
clock_t __sys_clock(void)
|
||||
{
|
||||
mx_time_val_t v;
|
||||
mx_clock_get_time(MX_CLOCK_MONOTONIC, &v);
|
||||
|
||||
return (v.sec * CLOCKS_PER_SEC) + v.nsec;
|
||||
}
|
||||
|
||||
time_t __sys_time(void)
|
||||
{
|
||||
mx_time_val_t v;
|
||||
mx_clock_get_time(MX_CLOCK_REALTIME, &v);
|
||||
|
||||
return v.sec;
|
||||
}
|
||||
|
||||
int nanosleep(const struct timespec *req, struct timespec *rem)
|
||||
{
|
||||
if (!req) {
|
||||
__set_errno(EFAULT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mx_nanosleep(mx_deadline_after(MX_SEC(req->tv_sec) + MX_NSEC(req->tv_nsec)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __sys_clock_getres(clockid_t clk_id, struct timespec *res)
|
||||
{
|
||||
mx_time_val_t v;
|
||||
mx_status_t s = mx_clock_get_resolution(clk_id, &v);
|
||||
|
||||
if (s != MX_OK) {
|
||||
/* TODO set errno */
|
||||
return -1;
|
||||
}
|
||||
|
||||
res->tv_sec = v.sec;
|
||||
res->tv_nsec = v.nsec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __sys_clock_gettime(clockid_t clk_id, struct timespec *tp)
|
||||
{
|
||||
mx_time_val_t v;
|
||||
mx_status_t s = mx_clock_get_time(clk_id, &v);
|
||||
|
||||
if (s != MX_OK) {
|
||||
/* TODO set errno */
|
||||
return -1;
|
||||
}
|
||||
|
||||
tp->tv_sec = v.sec;
|
||||
tp->tv_nsec = v.nsec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __sys_clock_settime(clockid_t clk_id, const struct timespec *tp)
|
||||
{
|
||||
mx_time_val_t v = { .sec = tp->tv_sec, .nsec = tp->tv_nsec };
|
||||
mx_status_t s = mx_clock_set_time(clk_id, &v);
|
||||
|
||||
if (s != MX_OK) {
|
||||
/* TODO set errno */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
86
libc/sys/horizon/unistd.c
Normal file
86
libc/sys/horizon/unistd.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <magenta/object.h>
|
||||
#include <magenta/bootstrap.h>
|
||||
#include <magenta/errors.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <mio/fs.h>
|
||||
|
||||
int open(const char *pathname, int flags, ...)
|
||||
{
|
||||
int ret = mio_open(pathname, flags);
|
||||
if (ret < 0) {
|
||||
__set_errno(-ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__set_errno(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int openat(int dirfd, const char *pathname, int flags, ...)
|
||||
{
|
||||
int ret = mio_openat(dirfd, pathname, flags);
|
||||
if (ret < 0) {
|
||||
__set_errno(-ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__set_errno(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t read(int fd, void *buf, size_t count)
|
||||
{
|
||||
ssize_t ret = mio_read(fd, buf, count);
|
||||
if (ret < 0) {
|
||||
__set_errno(-(int)ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__set_errno(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
ssize_t ret = mio_write(fd, buf, count);
|
||||
if (ret < 0) {
|
||||
__set_errno(-(int)ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__set_errno(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int close(int fd)
|
||||
{
|
||||
int ret = mio_close(fd);
|
||||
if (ret < 0) {
|
||||
__set_errno(-ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__set_errno(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pid_t getpid(void)
|
||||
{
|
||||
mx_info_task_t task_info;
|
||||
mx_status_t status = mx_object_get_info(
|
||||
mx_bootstrap_handle_get(MX_B_TASK_SELF),
|
||||
MX_INFO_TASK,
|
||||
&task_info, sizeof task_info);
|
||||
return status == MX_OK ? task_info.leader_id : (pid_t)-1;
|
||||
}
|
||||
|
||||
pid_t gettid(void)
|
||||
{
|
||||
mx_info_task_t task_info;
|
||||
mx_status_t status = mx_object_get_info(
|
||||
mx_bootstrap_handle_get(MX_B_TASK_SELF),
|
||||
MX_INFO_TASK,
|
||||
&task_info, sizeof task_info);
|
||||
return status == MX_OK ? task_info.id : (pid_t)-1;
|
||||
}
|
||||
24
libc/sys/horizon/unistd.h
Normal file
24
libc/sys/horizon/unistd.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef SYS_LINUX_UNISTD_H_
|
||||
#define SYS_LINUX_UNISTD_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <mio/types.h>
|
||||
|
||||
struct stat;
|
||||
struct pollfd;
|
||||
|
||||
extern int open(const char *pathname, int flags, ...);
|
||||
extern int openat(int dirfd, const char *pathname, int flags, ...);
|
||||
|
||||
extern ssize_t read(int fd, void *buf, size_t count);
|
||||
extern ssize_t write(int fd, const void *buf, size_t count);
|
||||
extern int close(int fd);
|
||||
|
||||
extern off_t lseek(int fd, off_t off, int whence);
|
||||
|
||||
extern pid_t getpid(void);
|
||||
extern pid_t gettid(void);
|
||||
|
||||
#endif
|
||||
33
libc/sys/linux/__fio.h
Normal file
33
libc/sys/linux/__fio.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef SYS_LINUX___FIO_H_
|
||||
#define SYS_LINUX___FIO_H_
|
||||
|
||||
#define __FIO_BUFSZ 512
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct __io_file {
|
||||
char buf[__FIO_BUFSZ];
|
||||
unsigned int buf_idx;
|
||||
unsigned int fd;
|
||||
char err;
|
||||
};
|
||||
|
||||
extern int __fileno(struct __io_file *f);
|
||||
extern void __fio_init();
|
||||
extern unsigned int __fio_read(struct __io_file *f, char *buf, unsigned int sz);
|
||||
extern unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz);
|
||||
extern unsigned int __fio_flush(struct __io_file *f);
|
||||
extern int __fio_error(struct __io_file *f);
|
||||
extern int __fio_ungetc(struct __io_file *f, char c);
|
||||
|
||||
extern int __fio_fopen(const char *path, const char *mode, struct __io_file *out);
|
||||
extern int __fio_fclose(struct __io_file *in);
|
||||
extern int __fio_fdopen(int fd, const char *mode, struct __io_file *out);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
17
libc/sys/linux/__syscall.h
Normal file
17
libc/sys/linux/__syscall.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef SYS_LINUX___SYSCALL_H_
|
||||
#define SYS_LINUX___SYSCALL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern intptr_t __syscall0(uintptr_t id);
|
||||
extern intptr_t __syscall1(uintptr_t id, uintptr_t p0);
|
||||
extern intptr_t __syscall2(uintptr_t id, uintptr_t p0, uintptr_t p1);
|
||||
extern intptr_t __syscall3(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2);
|
||||
extern intptr_t __syscall4(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2,
|
||||
uintptr_t p3);
|
||||
extern intptr_t __syscall5(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2,
|
||||
uintptr_t p3, uintptr_t p4);
|
||||
extern intptr_t __syscall6(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2,
|
||||
uintptr_t p3, uintptr_t p4, uintptr_t p5);
|
||||
|
||||
#endif
|
||||
14
libc/sys/linux/__system.h
Normal file
14
libc/sys/linux/__system.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef SYS_LINUX___SYSTEM_H_
|
||||
#define SYS_LINUX___SYSTEM_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern _Noreturn void __exit(int code);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
0
libc/sys/linux/config.cmake
Normal file
0
libc/sys/linux/config.cmake
Normal file
56
libc/sys/linux/fcntl.h
Normal file
56
libc/sys/linux/fcntl.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef SYS_LINUX_FCNTL_H_
|
||||
#define SYS_LINUX_FCNTL_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct flock
|
||||
{
|
||||
short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
|
||||
short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
|
||||
off_t l_start; /* Offset where the lock begins. */
|
||||
off_t l_len; /* Size of the locked area; zero means until EOF. */
|
||||
pid_t l_pid; /* Process holding the lock. */
|
||||
};
|
||||
|
||||
struct flock64
|
||||
{
|
||||
short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
|
||||
short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
|
||||
off64_t l_start; /* Offset where the lock begins. */
|
||||
off64_t l_len; /* Size of the locked area; zero means until EOF. */
|
||||
pid_t l_pid; /* Process holding the lock. */
|
||||
};
|
||||
|
||||
#define O_ACCMODE 0003
|
||||
#define O_RDONLY 00
|
||||
#define O_WRONLY 01
|
||||
#define O_RDWR 02
|
||||
#define O_CREAT 0100 /* Not fcntl. */
|
||||
#define O_EXCL 0200 /* Not fcntl. */
|
||||
#define O_NOCTTY 0400 /* Not fcntl. */
|
||||
#define O_TRUNC 01000 /* Not fcntl. */
|
||||
#define O_APPEND 02000
|
||||
#define O_NONBLOCK 04000
|
||||
#define O_NDELAY O_NONBLOCK
|
||||
#define O_SYNC 04010000
|
||||
#define O_FSYNC O_SYNC
|
||||
#define O_ASYNC 020000
|
||||
#define O_LARGEFILE 0100000
|
||||
|
||||
#define O_DIRECTORY 0200000
|
||||
#define O_NOFOLLOW 0400000
|
||||
#define O_CLOEXEC 02000000
|
||||
#define O_DIRECT 040000
|
||||
#define O_NOATIME 01000000
|
||||
#define O_PATH 010000000
|
||||
#define O_DSYNC 010000
|
||||
#define O_TMPFILE (020000000 | __O_DIRECTORY)
|
||||
|
||||
#define F_GETLK 5 /* Get record locking info. */
|
||||
#define F_SETLK 6 /* Set record locking info (non-blocking). */
|
||||
#define F_SETLKW 7 /* Set record locking info (blocking). */
|
||||
#define F_GETLK64 12 /* Get record locking info. */
|
||||
#define F_SETLK64 13 /* Set record locking info (non-blocking). */
|
||||
#define F_SETLKW64 14 /* Set record locking info (blocking). */
|
||||
|
||||
#endif
|
||||
49
libc/sys/linux/fio.c
Normal file
49
libc/sys/linux/fio.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "__fio.h"
|
||||
#include "__syscall.h"
|
||||
#include "unistd.h"
|
||||
|
||||
struct __io_file __stdin = { .fd = 0 };
|
||||
struct __io_file __stdout = { .fd = 1 };
|
||||
struct __io_file __stderr = { .fd = 2 };
|
||||
|
||||
struct __io_file *stdin = &__stdin;
|
||||
struct __io_file *stdout = &__stdout;
|
||||
struct __io_file *stderr = &__stderr;
|
||||
|
||||
int __fileno(struct __io_file *f)
|
||||
{
|
||||
return f->fd;
|
||||
}
|
||||
|
||||
unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz)
|
||||
{
|
||||
for (unsigned int i = 0; i < sz; i++) {
|
||||
if (f->buf_idx >= __FIO_BUFSZ) {
|
||||
__fio_flush(f);
|
||||
}
|
||||
|
||||
f->buf[f->buf_idx++] = buf[i];
|
||||
if (buf[i] == '\n') {
|
||||
__fio_flush(f);
|
||||
}
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
unsigned int __fio_flush(struct __io_file *f)
|
||||
{
|
||||
ssize_t res = write(f->fd, f->buf, f->buf_idx);
|
||||
if (res != f->buf_idx) {
|
||||
f->err = 1;
|
||||
}
|
||||
|
||||
size_t flushed = f->buf_idx;
|
||||
f->buf_idx = 0;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
int __fio_error(struct __io_file *f)
|
||||
{
|
||||
return f->err != 0;
|
||||
}
|
||||
20
libc/sys/linux/machine/x86_64/crt0.s
Normal file
20
libc/sys/linux/machine/x86_64/crt0.s
Normal file
@@ -0,0 +1,20 @@
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
.extern __fio_init
|
||||
.type __fio_init, @function
|
||||
|
||||
.extern main
|
||||
.type main, @function
|
||||
|
||||
_start:
|
||||
xor %ebp, %ebp
|
||||
mov (%rsp), %edi
|
||||
lea 8(%rsp), %rsi
|
||||
lea 16(%rsp, %rdi, 8), %rdx
|
||||
xor %eax, %eax
|
||||
|
||||
call main
|
||||
movq %rax, %rdi
|
||||
movq $60, %rax
|
||||
syscall
|
||||
108
libc/sys/linux/machine/x86_64/syscall.c
Normal file
108
libc/sys/linux/machine/x86_64/syscall.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include <stdint.h>
|
||||
|
||||
intptr_t __syscall0(uintptr_t id)
|
||||
{
|
||||
intptr_t ret = 0;
|
||||
asm volatile("mov %1, %%rax; syscall; mov %%rax, %0"
|
||||
: "=m" (ret)
|
||||
: "m" (id));
|
||||
return ret;
|
||||
}
|
||||
|
||||
intptr_t __syscall1(uintptr_t id, uintptr_t p0)
|
||||
{
|
||||
intptr_t ret = 0;
|
||||
asm volatile(
|
||||
"mov %1, %%rax;"
|
||||
"mov %2, %%rdi;"
|
||||
"syscall;"
|
||||
"mov %%rax, %0"
|
||||
: "=m" (ret)
|
||||
: "m" (id), "m" (p0));
|
||||
return ret;
|
||||
}
|
||||
|
||||
intptr_t __syscall2(uintptr_t id, uintptr_t p0, uintptr_t p1)
|
||||
{
|
||||
intptr_t ret = 0;
|
||||
asm volatile(
|
||||
"mov %1, %%rax;"
|
||||
"mov %2, %%rdi;"
|
||||
"mov %3, %%rsi;"
|
||||
"syscall;"
|
||||
"mov %%rax, %0"
|
||||
: "=m" (ret)
|
||||
: "m" (id), "m" (p0), "m" (p1));
|
||||
return ret;
|
||||
}
|
||||
|
||||
intptr_t __syscall3(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2)
|
||||
{
|
||||
intptr_t ret = 0;
|
||||
asm volatile(
|
||||
"movq %1, %%rax;"
|
||||
"mov %2, %%rdi;"
|
||||
"mov %3, %%rsi;"
|
||||
"mov %4, %%rdx;"
|
||||
"syscall;"
|
||||
"mov %%rax, %0"
|
||||
: "=m" (ret)
|
||||
: "m" (id), "m" (p0), "m" (p1), "m" (p2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
intptr_t __syscall4(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2,
|
||||
uintptr_t p3)
|
||||
{
|
||||
intptr_t ret = 0;
|
||||
asm volatile(
|
||||
"mov %1, %%rax;"
|
||||
"mov %2, %%rdi;"
|
||||
"mov %3, %%rsi;"
|
||||
"mov %4, %%rdx;"
|
||||
"mov %5, %%r10;"
|
||||
"syscall;"
|
||||
"mov %%rax, %0"
|
||||
: "=m" (ret)
|
||||
: "m" (id), "m" (p0), "m" (p1), "m" (p2), "m" (p3));
|
||||
return ret;
|
||||
}
|
||||
|
||||
intptr_t __syscall5(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2,
|
||||
uintptr_t p3, uintptr_t p4)
|
||||
{
|
||||
intptr_t ret = 0;
|
||||
asm volatile(
|
||||
"mov %1, %%rax;"
|
||||
"mov %2, %%rdi;"
|
||||
"mov %3, %%rsi;"
|
||||
"mov %4, %%rdx;"
|
||||
"mov %5, %%r10;"
|
||||
"mov %6, %%r8;"
|
||||
"syscall;"
|
||||
"mov %%rax, %0"
|
||||
: "=m" (ret)
|
||||
: "m" (id), "m" (p0), "m" (p1), "m" (p2), "m" (p3), "m" (p4));
|
||||
return ret;
|
||||
}
|
||||
|
||||
intptr_t __syscall6(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2,
|
||||
uintptr_t p3, uintptr_t p4, uintptr_t p5)
|
||||
{
|
||||
intptr_t ret = 0;
|
||||
asm volatile(
|
||||
"mov %1, %%rax;"
|
||||
"mov %2, %%rdi;"
|
||||
"mov %3, %%rsi;"
|
||||
"mov %4, %%rdx;"
|
||||
"mov %5, %%r10;"
|
||||
"mov %6, %%r8;"
|
||||
"mov %7, %%r9;"
|
||||
"syscall;"
|
||||
"mov %%rax, %0"
|
||||
: "=m" (ret)
|
||||
: "m" (id), "m" (p0), "m" (p1), "m" (p2), "m" (p3), "m" (p4),
|
||||
"m" (p5));
|
||||
return ret;
|
||||
}
|
||||
|
||||
33
libc/sys/linux/poll.h
Normal file
33
libc/sys/linux/poll.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef SYS_LINUX_POLL_H_
|
||||
#define SYS_LINUX_POLL_H_
|
||||
|
||||
#define POLLIN 0x1
|
||||
#define POLLPRI 0x2
|
||||
#define POLLOUT 0x4
|
||||
#define POLLERR 0x8
|
||||
#define POLLHUP 0x10
|
||||
#define POLLNVAL 0x20
|
||||
#define POLLRDNORM 0x40
|
||||
#define POLLRDBAND 0x80
|
||||
#define POLLWRNORM 0x100
|
||||
#define POLLWRBAND 0x200
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned long long nfds_t;
|
||||
|
||||
struct pollfd {
|
||||
int fd;
|
||||
short events;
|
||||
short revents;
|
||||
};
|
||||
|
||||
extern int poll(struct pollfd *fds, nfds_t nfds, int timeout);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
22
libc/sys/linux/sbrk.c
Normal file
22
libc/sys/linux/sbrk.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "unistd.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void *__curr_brk = NULL;
|
||||
|
||||
void *sbrk(intptr_t increment)
|
||||
{
|
||||
if (!__curr_brk) {
|
||||
brk(NULL);
|
||||
}
|
||||
|
||||
uintptr_t end = (uintptr_t)__curr_brk + increment;
|
||||
void *start = __curr_brk;
|
||||
int res = brk((void *)end);
|
||||
|
||||
if (res == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
39
libc/sys/linux/sys/_errno.h
Normal file
39
libc/sys/linux/sys/_errno.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef SYS_MAGENTA_SYS__ERRNO_H_
|
||||
#define SYS_MAGENTA_SYS__ERRNO_H_
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
|
||||
#endif
|
||||
10
libc/sys/linux/sys/_fconst.h
Normal file
10
libc/sys/linux/sys/_fconst.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef SYS_LINUX_SYS__FCONST_H_
|
||||
#define SYS_LINUX_SYS__FCONST_H_
|
||||
|
||||
#define __FILENAME_MAX 1024
|
||||
|
||||
#define __SEEK_SET 0
|
||||
#define __SEEK_CUR 1
|
||||
#define __SEEK_END 2
|
||||
|
||||
#endif
|
||||
131
libc/sys/linux/sys/mman.h
Normal file
131
libc/sys/linux/sys/mman.h
Normal file
@@ -0,0 +1,131 @@
|
||||
#ifndef SYS_LINUX_SYS_MMAN_H_
|
||||
#define SYS_LINUX_SYS_MMAN_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define MAP_GROWSDOWN 0x00100
|
||||
#define MAP_DENYWRITE 0x00800
|
||||
#define MAP_EXECUTABLE 0x01000
|
||||
#define MAP_LOCKED 0x02000
|
||||
#define MAP_NORESERVE 0x04000
|
||||
#define MAP_POPULATE 0x08000
|
||||
#define MAP_NONBLOCK 0x10000
|
||||
#define MAP_STACK 0x20000
|
||||
#define MAP_HUGETLB 0x40000
|
||||
#define MAP_SYNC 0x80000
|
||||
#define MAP_FIXED_NOREPLACE 0x100000
|
||||
|
||||
#define PROT_READ 0x1
|
||||
#define PROT_WRITE 0x2
|
||||
#define PROT_EXEC 0x4
|
||||
#define PROT_NONE 0x0
|
||||
#define PROT_GROWSDOWN 0x01000000
|
||||
#define PROT_GROWSUP 0x02000000
|
||||
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_SHARED_VALIDATE 0x03
|
||||
#define MAP_TYPE 0x0f
|
||||
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_FILE 0
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#define MAP_HUGE_SHIFT 26
|
||||
#define MAP_HUGE_MASK 0x3f
|
||||
|
||||
#define MS_ASYNC 1
|
||||
#define MS_SYNC 4
|
||||
#define MS_INVALIDATE 2
|
||||
|
||||
#define MADV_NORMAL 0
|
||||
#define MADV_RANDOM 1
|
||||
#define MADV_SEQUENTIAL 2
|
||||
#define MADV_WILLNEED 3
|
||||
#define MADV_DONTNEED 4
|
||||
#define MADV_FREE 8
|
||||
#define MADV_REMOVE 9
|
||||
#define MADV_DONTFORK 10
|
||||
#define MADV_DOFORK 11
|
||||
#define MADV_MERGEABLE 12
|
||||
#define MADV_UNMERGEABLE 13
|
||||
#define MADV_HUGEPAGE 14
|
||||
#define MADV_NOHUGEPAGE 15
|
||||
#define MADV_DONTDUMP 16
|
||||
#define MADV_DODUMP 17
|
||||
#define MADV_WIPEONFORK 18
|
||||
#define MADV_KEEPONFORK 19
|
||||
#define MADV_COLD 20
|
||||
#define MADV_PAGEOUT 21
|
||||
#define MADV_HWPOISON 100
|
||||
|
||||
#define MCL_CURRENT 1
|
||||
#define MCL_FUTURE 2
|
||||
#define MCL_ONFAULT 4
|
||||
#define PROT_READ 0x1
|
||||
#define PROT_WRITE 0x2
|
||||
#define PROT_EXEC 0x4
|
||||
#define PROT_NONE 0x0
|
||||
#define PROT_GROWSDOWN 0x01000000
|
||||
#define PROT_GROWSUP 0x02000000
|
||||
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_SHARED_VALIDATE 0x03
|
||||
#define MAP_TYPE 0x0f
|
||||
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_FILE 0
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#define MAP_HUGE_SHIFT 26
|
||||
#define MAP_HUGE_MASK 0x3f
|
||||
|
||||
#define MS_ASYNC 1
|
||||
#define MS_SYNC 4
|
||||
#define MS_INVALIDATE 2
|
||||
|
||||
#define MADV_NORMAL 0
|
||||
#define MADV_RANDOM 1
|
||||
#define MADV_SEQUENTIAL 2
|
||||
#define MADV_WILLNEED 3
|
||||
#define MADV_DONTNEED 4
|
||||
#define MADV_FREE 8
|
||||
#define MADV_REMOVE 9
|
||||
#define MADV_DONTFORK 10
|
||||
#define MADV_DOFORK 11
|
||||
#define MADV_MERGEABLE 12
|
||||
#define MADV_UNMERGEABLE 13
|
||||
#define MADV_HUGEPAGE 14
|
||||
#define MADV_NOHUGEPAGE 15
|
||||
#define MADV_DONTDUMP 16
|
||||
#define MADV_DODUMP 17
|
||||
#define MADV_WIPEONFORK 18
|
||||
#define MADV_KEEPONFORK 19
|
||||
#define MADV_COLD 20
|
||||
#define MADV_PAGEOUT 21
|
||||
#define MADV_HWPOISON 100
|
||||
|
||||
#define MCL_CURRENT 1
|
||||
#define MCL_FUTURE 2
|
||||
#define MCL_ONFAULT 4
|
||||
|
||||
#define MAP_FAILED ((void *) -1)
|
||||
|
||||
extern void *mmap (void *addr, size_t len, int prot,
|
||||
int flags, int fd, off_t offset);
|
||||
|
||||
extern int munmap (void *addr, size_t len);
|
||||
extern int mprotect (void *addr, size_t len, int prot) ;
|
||||
extern int msync (void *addr, size_t len, int flags);
|
||||
|
||||
extern int madvise (void *addr, size_t len, int advice) ;
|
||||
extern int mlock (const void *addr, size_t len) ;
|
||||
extern int munlock (const void *addr, size_t len) ;
|
||||
extern int mlockall (int flags) ;
|
||||
extern int munlockall (void) ;
|
||||
|
||||
extern int mincore (void *start, size_t len, unsigned char *vec);
|
||||
|
||||
#endif
|
||||
85
libc/sys/linux/sys/param.h
Normal file
85
libc/sys/linux/sys/param.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef SYS_LINUX_SYS_PARAM_H_
|
||||
#define SYS_LINUX_SYS_PARAM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef ARG_MAX
|
||||
# define __undef_ARG_MAX
|
||||
#endif
|
||||
|
||||
#include <linux/limits.h>
|
||||
#include <linux/param.h>
|
||||
|
||||
#ifdef __undef_ARG_MAX
|
||||
#undef ARG_MAX
|
||||
#undef __undef_ARG_MAX
|
||||
#endif
|
||||
|
||||
#define MAXSYMLINKS 20
|
||||
|
||||
#define NOFILE 256
|
||||
#define NCARGS 131072
|
||||
|
||||
#define NBBY CHAR_BIT
|
||||
|
||||
#if !defined NGROUPS && defined NGROUPS_MAX
|
||||
#define NGROUPS NGROUPS_MAX
|
||||
#endif
|
||||
#if !defined MAXSYMLINKS && defined SYMLOOP_MAX
|
||||
#define MAXSYMLINKS SYMLOOP_MAX
|
||||
#endif
|
||||
#if !defined CANBSIZ && defined MAX_CANON
|
||||
#define CANBSIZ MAX_CANON
|
||||
#endif
|
||||
#if !defined MAXPATHLEN && defined PATH_MAX
|
||||
#define MAXPATHLEN PATH_MAX
|
||||
#endif
|
||||
#if !defined NOFILE && defined OPEN_MAX
|
||||
#define NOFILE OPEN_MAX
|
||||
#endif
|
||||
#if !defined MAXHOSTNAMELEN && defined HOST_NAME_MAX
|
||||
#define MAXHOSTNAMELEN HOST_NAME_MAX
|
||||
#endif
|
||||
#ifndef NCARGS
|
||||
#ifdef ARG_MAX
|
||||
#define NCARGS ARG_MAX
|
||||
#else
|
||||
#define NCARGS INT_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NOGROUP
|
||||
#define NOGROUP 65535 /* Marker for empty group set member. */
|
||||
#endif
|
||||
#ifndef NODEV
|
||||
#define NODEV ((dev_t) -1) /* Non-existent device. */
|
||||
#endif
|
||||
|
||||
#ifndef DEV_BSIZE
|
||||
#define DEV_BSIZE 512
|
||||
#endif
|
||||
|
||||
#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
|
||||
#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
|
||||
#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
|
||||
#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
#define roundup(x, y) (__builtin_constant_p (y) && powerof2 (y) \
|
||||
? (((x) + (y) - 1) & ~((y) - 1)) \
|
||||
: ((((x) + ((y) - 1)) / (y)) * (y)))
|
||||
#else
|
||||
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
|
||||
#endif
|
||||
#define powerof2(x) ((((x) - 1) & (x)) == 0)
|
||||
|
||||
/* Macros for min/max. */
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
|
||||
#endif
|
||||
24
libc/sys/linux/sys/stat.h
Normal file
24
libc/sys/linux/sys/stat.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef SYS_LINUX_SYS_STAT_H_
|
||||
#define SYS_LINUX_SYS_STAT_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct stat {
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
mode_t st_mode;
|
||||
nlink_t st_nlink;
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
dev_t st_rdev;
|
||||
off_t st_size;
|
||||
blksize_t st_blksize;
|
||||
blkcnt_t st_blocks;
|
||||
|
||||
struct timespec st_atim;
|
||||
struct timespec st_mtim;
|
||||
struct timespec st_ctim;
|
||||
};
|
||||
|
||||
#endif
|
||||
24
libc/sys/linux/sys/syscall.h
Normal file
24
libc/sys/linux/sys/syscall.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef SYS_LINUX_SYSCALL_H_
|
||||
#define SYS_LINUX_SYSCALL_H_
|
||||
|
||||
#define SYS_read 0
|
||||
#define SYS_write 1
|
||||
#define SYS_open 2
|
||||
#define SYS_close 3
|
||||
#define SYS_stat 4
|
||||
#define SYS_fstat 5
|
||||
#define SYS_lstat 6
|
||||
#define SYS_poll 7
|
||||
#define SYS_lseek 8
|
||||
#define SYS_mmap 9
|
||||
#define SYS_mprotect 10
|
||||
#define SYS_munmap 11
|
||||
#define SYS_brk 12
|
||||
#define SYS_rt_sigaction 13
|
||||
#define SYS_rt_sigprocmask 14
|
||||
#define SYS_rt_sigreturn 15
|
||||
#define SYS_ioctl 16
|
||||
#define SYS_mremap 25
|
||||
#define SYS__exit 60
|
||||
|
||||
#endif
|
||||
32
libc/sys/linux/sys/types.h
Normal file
32
libc/sys/linux/sys/types.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef SYS_LINUX_SYS_TYPES_H_
|
||||
#define SYS_LINUX_SYS_TYPES_H_
|
||||
|
||||
#include <machine/_stdint.h>
|
||||
|
||||
typedef signed long long blkcnt_t;
|
||||
typedef signed long long blksize_t;
|
||||
typedef unsigned long long clock_t;
|
||||
typedef unsigned int clockid_t;
|
||||
typedef unsigned long long fsblkcnt_t;
|
||||
typedef unsigned long long fsfilcnt_t;
|
||||
typedef unsigned int gid_t;
|
||||
typedef unsigned int id_t;
|
||||
typedef unsigned long long ino_t;
|
||||
typedef unsigned int key_t;
|
||||
typedef unsigned int mode_t;
|
||||
typedef unsigned long long nlink_t;
|
||||
typedef signed long long off_t;
|
||||
typedef __int64_t off64_t;
|
||||
typedef signed int pid_t;
|
||||
typedef unsigned long long time_t;
|
||||
typedef unsigned int timer_t;
|
||||
typedef unsigned int uid_t;
|
||||
typedef unsigned long useconds_t;
|
||||
typedef unsigned long long dev_t;
|
||||
|
||||
#ifndef __SIZE_T_DEFINED
|
||||
typedef __uintptr_t size_t;
|
||||
#define __SIZE_T_DEFINED
|
||||
#endif
|
||||
|
||||
#endif
|
||||
164
libc/sys/linux/syscall.c
Normal file
164
libc/sys/linux/syscall.c
Normal file
@@ -0,0 +1,164 @@
|
||||
#include "poll.h"
|
||||
#include "sys/syscall.h"
|
||||
#include "__syscall.h"
|
||||
#include "unistd.h"
|
||||
|
||||
extern void *__curr_brk;
|
||||
|
||||
ssize_t read(int fd, void *buf, size_t count)
|
||||
{
|
||||
intptr_t res = __syscall3(SYS_read, (uintptr_t)fd, (uintptr_t)buf,
|
||||
(uintptr_t)count);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (ssize_t)res;
|
||||
}
|
||||
|
||||
ssize_t write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
intptr_t res = __syscall3(SYS_write, (uintptr_t)fd, (uintptr_t)buf,
|
||||
(uintptr_t)count);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (ssize_t)res;
|
||||
}
|
||||
|
||||
int open(const char *pathname, int flags)
|
||||
{
|
||||
intptr_t res = __syscall3(SYS_open, (uintptr_t)pathname,
|
||||
(uintptr_t)flags, 0);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
int close(int fd)
|
||||
{
|
||||
intptr_t res = __syscall1(SYS_close, (uintptr_t)fd);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
int stat(const char *pathname, struct stat *statbuf)
|
||||
{
|
||||
intptr_t res = __syscall2(SYS_stat, (uintptr_t)pathname,
|
||||
(uintptr_t)statbuf);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
int fstat(int fd, struct stat *statbuf)
|
||||
{
|
||||
intptr_t res = __syscall2(SYS_fstat, (uintptr_t)fd,
|
||||
(uintptr_t)statbuf);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
int lstat(const char *pathname, struct stat *statbuf)
|
||||
{
|
||||
intptr_t res = __syscall2(SYS_lstat, (uintptr_t)pathname,
|
||||
(uintptr_t)statbuf);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
||||
{
|
||||
intptr_t res = __syscall3(SYS_poll, (uintptr_t)fds,
|
||||
(uintptr_t)nfds, (uintptr_t)timeout);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
off_t lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
intptr_t res = __syscall3(SYS_lseek, (uintptr_t)fd,
|
||||
(uintptr_t)offset, (uintptr_t)whence);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off)
|
||||
{
|
||||
intptr_t res = __syscall6(SYS_mmap, (uintptr_t)addr, (uintptr_t)len,
|
||||
(uintptr_t)prot, (uintptr_t)flags, (uintptr_t)fd, (uintptr_t)off);
|
||||
if (res < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)res;
|
||||
}
|
||||
|
||||
int mprotect(void *addr, size_t len, int prot)
|
||||
{
|
||||
intptr_t res = __syscall3(SYS_mprotect, (uintptr_t)addr, (uintptr_t)len,
|
||||
(uintptr_t)prot);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
int munmap(void *addr, size_t length)
|
||||
{
|
||||
intptr_t res = __syscall2(SYS_munmap, (uintptr_t)addr, (uintptr_t)length);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
int brk(void *addr)
|
||||
{
|
||||
intptr_t res = __syscall1(SYS_brk, (uintptr_t)addr);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
__curr_brk = (void *)res;
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
int ioctl(int fd, unsigned long req, void *arg)
|
||||
{
|
||||
intptr_t res = __syscall3(SYS_ioctl, (uintptr_t)fd, (uintptr_t)req,
|
||||
(uintptr_t)arg);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
void _exit(int code)
|
||||
{
|
||||
__syscall1(SYS__exit, code);
|
||||
}
|
||||
7
libc/sys/linux/system.c
Normal file
7
libc/sys/linux/system.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "unistd.h"
|
||||
|
||||
_Noreturn void __exit(int code)
|
||||
{
|
||||
_exit(code);
|
||||
while (1) {}
|
||||
}
|
||||
30
libc/sys/linux/unistd.h
Normal file
30
libc/sys/linux/unistd.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef SYS_LINUX_UNISTD_H_
|
||||
#define SYS_LINUX_UNISTD_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct stat;
|
||||
struct pollfd;
|
||||
|
||||
typedef __intptr_t ssize_t;
|
||||
|
||||
extern ssize_t read(int fd, void *buf, size_t count);
|
||||
extern ssize_t write(int fd, const void *buf, size_t count);
|
||||
extern int open(const char *pathname, int flags);
|
||||
extern int close(int fd);
|
||||
extern int stat(const char *pathname, struct stat *statbuf);
|
||||
extern int fstat(int fd, struct stat *statbuf);
|
||||
extern int lstat(const char *pathname, struct stat *statbuf);
|
||||
extern off_t lseek(int fd, off_t offset, int whence);
|
||||
extern void *mmap(void *addr, size_t length, int prot, int flags,
|
||||
int fd, off_t offset);
|
||||
extern int mprotect(void *addr, size_t len, int prot);
|
||||
extern int munmap(void *addr, size_t length);
|
||||
extern int brk(void *addr);
|
||||
extern void *sbrk(intptr_t increment);
|
||||
extern int ioctl(int fd, unsigned long request, void *arg);
|
||||
extern void _exit(int code);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user