mirror of
https://github.com/ish-app/ish.git
synced 2026-01-25 14:06:40 +00:00
Make Hello World with libc and ld work
IF you want to understand how amazing this is, watch https://www.twitch.tv/videos/152115137
This commit is contained in:
parent
c90e717a40
commit
559ae4cbcc
10
emu/cpu.c
10
emu/cpu.c
@ -183,6 +183,9 @@ restart:
|
||||
do_cpuid(&cpu->eax, &cpu->ebx, &cpu->ecx, &cpu->edx);
|
||||
break;
|
||||
|
||||
case 0xa3: TRACEI("bt reg, modrm\t");
|
||||
READMODRM; BT(modrm_reg, modrm_val); break;
|
||||
|
||||
case 0xa5: TRACEI("shld cl, reg, modrm");
|
||||
READMODRM; SHLD(cpu->cl, modrm_reg, modrm_val); break;
|
||||
|
||||
@ -259,8 +262,13 @@ restart:
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x11: TRACEI("adc reg, modrm");
|
||||
READMODRM; ADC(modrm_reg, modrm_val_w); break;
|
||||
|
||||
case 0x19: TRACEI("sbb reg, modrm");
|
||||
READMODRM; SBB(modrm_reg, modrm_val); break;
|
||||
case 0x1b: TRACEI("sbb modrm, reg");
|
||||
READMODRM; SBB(modrm_val, modrm_reg); break;
|
||||
|
||||
case 0x21: TRACEI("and reg, modrm");
|
||||
READMODRM; AND(modrm_reg, modrm_val_w); break;
|
||||
@ -379,7 +387,7 @@ restart:
|
||||
case 0x6a: TRACEI("push imm8\t");
|
||||
READIMM8; PUSH((int8_t) imm8); break;
|
||||
case 0x6b: TRACEI("imul imm8\t");
|
||||
READMODRM; READIMM8; MUL3((int8_t) imm8, (int8_t) modrm_val, modrm_reg); break;
|
||||
READMODRM; READIMM8; MUL3((int8_t) imm8, (int32_t) modrm_val, modrm_reg); break;
|
||||
|
||||
case 0x70: TRACEI("jo rel8\t");
|
||||
READIMM8; J_REL(O, (int8_t) imm8); break;
|
||||
|
||||
@ -115,6 +115,8 @@
|
||||
OR(src, dst##_w); break; \
|
||||
case 2: TRACE("adc"); \
|
||||
ADC(src, dst##_w); break; \
|
||||
case 3: TRACE("sbb"); \
|
||||
SBB(src, dst##_w); break; \
|
||||
case 4: TRACE("and"); \
|
||||
AND(src, dst##_w); break; \
|
||||
case 5: TRACE("sub"); \
|
||||
@ -203,6 +205,9 @@
|
||||
case 7: TRACE("undefined"); return INT_UNDEFINED; \
|
||||
}
|
||||
|
||||
#define BT(bit, val) \
|
||||
cpu->cf = (val) & (1 << bit)
|
||||
|
||||
#define BUMP_SI(size) \
|
||||
if (!cpu->df) \
|
||||
cpu->esi += size; \
|
||||
|
||||
18
emu/memory.c
18
emu/memory.c
@ -44,6 +44,7 @@ int pt_map(struct mem *mem, page_t start, pages_t pages, void *memory, unsigned
|
||||
pt_unmap(mem, page, 1);
|
||||
}
|
||||
struct pt_entry *entry = malloc(sizeof(struct pt_entry));
|
||||
// FIXME this could allocate some of the memory and then abort
|
||||
if (entry == NULL) return _ENOMEM;
|
||||
entry->data = memory;
|
||||
entry->refcount = 1;
|
||||
@ -57,7 +58,10 @@ int pt_map(struct mem *mem, page_t start, pages_t pages, void *memory, unsigned
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pt_unmap(struct mem *mem, page_t start, pages_t pages) {
|
||||
int pt_unmap(struct mem *mem, page_t start, pages_t pages) {
|
||||
for (page_t page = start; page < start + pages; page++)
|
||||
if (mem->pt[page] == NULL)
|
||||
return -1;
|
||||
for (page_t page = start; page < start + pages; page++) {
|
||||
struct pt_entry *entry = mem->pt[page];
|
||||
mem->pt[page] = NULL;
|
||||
@ -67,6 +71,7 @@ void pt_unmap(struct mem *mem, page_t start, pages_t pages) {
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pt_map_nothing(struct mem *mem, page_t start, pages_t pages, unsigned flags) {
|
||||
@ -84,6 +89,17 @@ int pt_map_file(struct mem *mem, page_t start, pages_t pages, int fd, off_t off,
|
||||
return pt_map(mem, start, pages, memory, flags);
|
||||
}
|
||||
|
||||
// FIXME this can overwrite P_GROWSDOWN or P_GUARD
|
||||
int pt_set_flags(struct mem *mem, page_t start, pages_t pages, int flags) {
|
||||
for (page_t page = start; page < start + pages; page++)
|
||||
if (mem->pt[page] == NULL)
|
||||
return _ENOMEM;
|
||||
for (page_t page = start; page < start + pages; page++) {
|
||||
mem->pt[page]->flags = flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pt_dump(struct mem *mem) {
|
||||
for (unsigned i = 0; i < PT_SIZE; i++) {
|
||||
if (mem->pt[i] != NULL) {
|
||||
|
||||
@ -50,8 +50,10 @@ int pt_map(struct mem *mem, page_t start, pages_t pages, void *memory, unsigned
|
||||
int pt_map_file(struct mem *mem, page_t start, pages_t pages, int fd, off_t off, unsigned flags);
|
||||
// Map empty space into fake memory
|
||||
int pt_map_nothing(struct mem *mem, page_t page, pages_t pages, unsigned flags);
|
||||
// Unmap fake memory
|
||||
void pt_unmap(struct mem *mem, page_t page, pages_t pages);
|
||||
// Unmap fake memory, return -1 if any part of the range isn't mapped and 0 otherwise
|
||||
int pt_unmap(struct mem *mem, page_t start, pages_t pages);
|
||||
// Set the flags on memory
|
||||
int pt_set_flags(struct mem *mem, page_t start, pages_t pages, int flags);
|
||||
|
||||
void pt_dump(struct mem *mem);
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ static void copy_stat(struct statbuf *fake_stat, struct stat *real_stat) {
|
||||
fake_stat->nlink = real_stat->st_nlink;
|
||||
fake_stat->uid = real_stat->st_uid;
|
||||
fake_stat->gid = real_stat->st_gid;
|
||||
fake_stat->rdev = real_stat->st_dev;
|
||||
fake_stat->rdev = real_stat->st_rdev;
|
||||
fake_stat->size = real_stat->st_size;
|
||||
fake_stat->blksize = real_stat->st_blksize;
|
||||
fake_stat->blocks = real_stat->st_blocks;
|
||||
@ -91,7 +91,7 @@ static int realfs_mmap(struct fd *fd, off_t offset, size_t len, int prot, int fl
|
||||
int mmap_flags = 0;
|
||||
if (flags & MMAP_PRIVATE) mmap_flags |= MAP_PRIVATE;
|
||||
// TODO more flags are probably needed
|
||||
void *mem = mmap(NULL, len, prot, flags, fd->real_fd, offset);
|
||||
void *mem = mmap(NULL, len, prot, mmap_flags, fd->real_fd, offset);
|
||||
if (mem == MAP_FAILED)
|
||||
return err_map(errno);
|
||||
*mem_out = mem;
|
||||
|
||||
@ -45,4 +45,4 @@ subdir('tests')
|
||||
# ptraceomatic et al
|
||||
subdir('tools')
|
||||
|
||||
executable('thingy', ['main.c'], dependencies: [ish])
|
||||
executable('ish', ['main.c'], dependencies: [ish])
|
||||
|
||||
2
misc.h
2
misc.h
@ -9,7 +9,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
// debug output utilities
|
||||
#if 1
|
||||
#if 0
|
||||
#define TRACE(msg, ...) printf(msg, ##__VA_ARGS__)
|
||||
#else
|
||||
#define TRACE(msg, ...) (void)NULL
|
||||
|
||||
@ -22,8 +22,12 @@ syscall_t syscall_table[] = {
|
||||
[41] = (syscall_t) sys_dup,
|
||||
[45] = (syscall_t) sys_brk,
|
||||
[85] = (syscall_t) sys_readlink,
|
||||
[90] = (syscall_t) sys_mmap,
|
||||
[91] = (syscall_t) sys_munmap,
|
||||
[122] = (syscall_t) _sys_uname,
|
||||
[192] = (syscall_t) sys_mmap,
|
||||
[125] = (syscall_t) sys_mprotect,
|
||||
[146] = (syscall_t) sys_writev,
|
||||
[192] = (syscall_t) sys_mmap2,
|
||||
[197] = (syscall_t) sys_fstat64,
|
||||
[243] = (syscall_t) sys_set_thread_area,
|
||||
[252] = (syscall_t) sys_exit_group,
|
||||
|
||||
@ -27,8 +27,13 @@ dword_t sys_fstat64(fd_t fd_no, addr_t statbuf_addr);
|
||||
dword_t sys_access(addr_t pathname_addr, dword_t mode);
|
||||
dword_t sys_readlink(addr_t pathname, addr_t buf, dword_t bufsize);
|
||||
|
||||
struct io_vec {
|
||||
addr_t base;
|
||||
uint_t len;
|
||||
};
|
||||
dword_t sys_read(fd_t fd_no, addr_t buf_addr, dword_t size);
|
||||
dword_t sys_write(fd_t fd_no, addr_t buf_addr, dword_t size);
|
||||
dword_t sys_writev(fd_t fd_no, addr_t iovec_addr, dword_t iovec_count);
|
||||
|
||||
dword_t sys_dup(fd_t fd);
|
||||
|
||||
@ -37,8 +42,12 @@ int handle_pagefault(addr_t addr);
|
||||
|
||||
#define MMAP_SHARED 0x1
|
||||
#define MMAP_PRIVATE 0x2
|
||||
#define MMAP_FIXED 0x10
|
||||
#define MMAP_ANONYMOUS 0x20
|
||||
addr_t sys_mmap(addr_t addr, dword_t len, dword_t prot, dword_t flags, fd_t fd_no, dword_t offset);
|
||||
addr_t sys_mmap2(addr_t addr, dword_t len, dword_t prot, dword_t flags, fd_t fd_no, dword_t offset);
|
||||
int_t sys_munmap(addr_t addr, uint_t len);
|
||||
int_t sys_mprotect(addr_t addr, uint_t len, int_t prot);
|
||||
|
||||
#define UNAME_LENGTH 65
|
||||
struct uname {
|
||||
|
||||
14
sys/fs.c
14
sys/fs.c
@ -69,6 +69,20 @@ dword_t sys_write(fd_t fd_no, addr_t buf_addr, dword_t size) {
|
||||
return fd->ops->write(fd, buf, size);
|
||||
}
|
||||
|
||||
dword_t sys_writev(fd_t fd_no, addr_t iovec_addr, dword_t iovec_count) {
|
||||
struct io_vec iovecs[iovec_count];
|
||||
user_get_count(iovec_addr, iovecs, sizeof(iovecs));
|
||||
int res;
|
||||
dword_t count = 0;
|
||||
for (unsigned i = 0; i < iovec_count; i++) {
|
||||
res = sys_write(fd_no, iovecs[i].base, iovecs[i].len);
|
||||
if (res < 0)
|
||||
return res;
|
||||
count += res;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
dword_t sys_fstat64(fd_t fd_no, addr_t statbuf_addr) {
|
||||
struct fd *fd = current->files[fd_no];
|
||||
struct statbuf stat;
|
||||
|
||||
42
sys/mmap.c
42
sys/mmap.c
@ -3,6 +3,10 @@
|
||||
#include "emu/process.h"
|
||||
#include "emu/memory.h"
|
||||
|
||||
addr_t sys_mmap2(addr_t addr, dword_t len, dword_t prot, dword_t flags, fd_t fd_no, dword_t offset) {
|
||||
return sys_mmap(addr, len, prot, flags, fd_no, offset << PAGE_BITS);
|
||||
}
|
||||
|
||||
addr_t sys_mmap(addr_t addr, dword_t len, dword_t prot, dword_t flags, fd_t fd_no, dword_t offset) {
|
||||
int err;
|
||||
|
||||
@ -10,16 +14,22 @@ addr_t sys_mmap(addr_t addr, dword_t len, dword_t prot, dword_t flags, fd_t fd_n
|
||||
return _EINVAL;
|
||||
if (prot & ~(P_READ | P_WRITE | P_EXEC))
|
||||
return _EINVAL;
|
||||
if (!(flags & MMAP_PRIVATE))
|
||||
// TODO MMAP_SHARED
|
||||
return _EINVAL;
|
||||
if (addr != 0)
|
||||
if (!(flags & MMAP_PRIVATE)) {
|
||||
TODO("MMAP_SHARED");
|
||||
return _EINVAL;
|
||||
}
|
||||
|
||||
pages_t pages = PAGE_ROUND_UP(len);
|
||||
page_t page = pt_find_hole(&curmem, pages);
|
||||
if (page == BAD_PAGE)
|
||||
return _ENOMEM;
|
||||
page_t page;
|
||||
if (addr == 0) {
|
||||
page = pt_find_hole(&curmem, pages);
|
||||
if (page == BAD_PAGE)
|
||||
return _ENOMEM;
|
||||
} else {
|
||||
if (OFFSET(addr) != 0)
|
||||
return _EINVAL;
|
||||
page = PAGE(addr);
|
||||
}
|
||||
if (flags & MMAP_ANONYMOUS) {
|
||||
if ((err = pt_map_nothing(&curmem, page, pages, prot)) < 0)
|
||||
return err;
|
||||
@ -39,3 +49,21 @@ addr_t sys_mmap(addr_t addr, dword_t len, dword_t prot, dword_t flags, fd_t fd_n
|
||||
return page << PAGE_BITS;
|
||||
}
|
||||
|
||||
int_t sys_munmap(addr_t addr, uint_t len) {
|
||||
if (OFFSET(addr) != 0)
|
||||
return _EINVAL;
|
||||
if (len == 0)
|
||||
return _EINVAL;
|
||||
if (pt_unmap(&curmem, PAGE(addr), PAGE_ROUND_UP(len)) < 0)
|
||||
return _EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int_t sys_mprotect(addr_t addr, uint_t len, int_t prot) {
|
||||
if (OFFSET(addr) != 0)
|
||||
return _EINVAL;
|
||||
if (prot & ~(P_READ | P_WRITE | P_EXEC))
|
||||
return _EINVAL;
|
||||
pages_t pages = PAGE_ROUND_UP(len);
|
||||
return pt_set_flags(&curmem, PAGE(addr), pages, prot);
|
||||
}
|
||||
|
||||
@ -4,9 +4,9 @@ executable('hello-libc-static', ['hello-clib.c'], c_args: ['-m32'], link_args: [
|
||||
executable('hello-libc', ['hello-clib.c'], c_args: ['-m32'], link_args: ['-m32'])
|
||||
|
||||
# simple benchmark
|
||||
executable('looper', ['looper.c', 'nothing.c'], c_args: ['-m32'], link_args: ['-m32', '-static'])
|
||||
executable('fibbonaci', ['fibbonaci.c'], c_args: ['-m32'], link_args: ['-m32', '-static'])
|
||||
executable('looper', ['looper.c', 'nothing.c'], c_args: ['-m32'], link_args: ['-m32'])
|
||||
executable('fibbonaci', ['fibbonaci.c'], c_args: ['-m32'], link_args: ['-m32'])
|
||||
|
||||
# filesystem motivation
|
||||
executable('cat', ['cat.c'], c_args: ['-m32'], link_args: ['-m32', '-static'])
|
||||
executable('stat', ['stat.c'], c_args: ['-m32', '-D_FILE_OFFSET_BITS=64'], link_args: ['-m32', '-static'])
|
||||
executable('cat', ['cat.c'], c_args: ['-m32'], link_args: ['-m32'])
|
||||
executable('stat', ['stat.c'], c_args: ['-m32', '-D_FILE_OFFSET_BITS=64'], link_args: ['-m32'])
|
||||
|
||||
@ -210,6 +210,7 @@ restart:
|
||||
pt_copy(pid, regs.rcx, sizeof(struct newstat64));
|
||||
break;
|
||||
|
||||
case 90: // mmap
|
||||
case 192: // mmap2
|
||||
if (cpu->eax < 0xfffff000 && cpu->edi != (dword_t) -1) {
|
||||
// fake mmap didn't fail, change fd
|
||||
@ -220,7 +221,7 @@ restart:
|
||||
|
||||
// some syscalls need to just happen
|
||||
case 45: // brk
|
||||
case 90: // mmap
|
||||
case 125: // mprotect
|
||||
case 243: // set_thread_area
|
||||
goto do_step;
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ name:
|
||||
after_name:
|
||||
.balign 4
|
||||
note:
|
||||
.long 0x010000 // let's pretend we're linux 2.0.0
|
||||
.long 0x020620 // let's pretend we're linux 2.6.32
|
||||
after_note:
|
||||
.balign 4
|
||||
.popsection
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user