diff --git a/doc/src/app/return-value.md b/doc/src/app/return-value.md new file mode 100644 index 0000000..e04275b --- /dev/null +++ b/doc/src/app/return-value.md @@ -0,0 +1,51 @@ + +# 应用程序返回值 + +应用程序返回值是一个 32 位整数(即使在 64 位系统上也是如此)。
+The application return value is a 32-bit integer (even on 64-bit systems). + +应用程序返回值的高 16 位不应当被应用程序设置,而只应被操作系统或系统库设置。
+The high 16 bits of the application return value should not be set by the application, but only by the operating system or system library. + +应用程序退出码应当是一个 8 位无符号整数,如果需要也可以是一个 16 位无符号整数。
+The application exit code should be an 8-bit unsigned integer, and can be a 16-bit unsigned integer if necessary. + +- `0-7`: 应用程序退出码 / Application exit code. +- `8-15`: 可用 / Available. +- `16-23`: 错误码 / Error code. +- `24-28`: 保留 / Reserved. +- `29`: 链接错误 / Link error. +- `30`: 非应用程序主动退出 / Non-application initiated exit. +- `31`: 保留 / Reserved. + +第 31 位永远不会被使用,第 24-28 位可能在未来被使用。
+The 31st bit will never be used, and the 16th-28th bits may be used in the future. + +第 30 位标记为非应用程序主动退出,可能是因为启动时链接错误、未处理信号、因某些原因被杀死等。
+The 30th bit is marked as a non-application initiated exit, which may be due to a link error at startup, unhandled signals, being killed for some reason, etc. + +第 29 位标记为链接错误,可能是因为未找到依赖库、文件数据错误等。
+The 29th bit is marked as a link error, which may be due to missing dependent libraries, file data errors, etc. + +第 16-23 位是错误码,用于标记应用程序的错误类型。
+The 16th-23rd bits are error codes used to mark the error type of the application. + +非应用程序主动退出时低 16 位将被填充为 0xffff。
+When a non-application initiated exit occurs, the low 16 bits will be filled with 0xffff. + +应用程序退出码的值应当在 0 到 255 之间,其中 0 表示成功,非 0 表示失败。
+The value of the application exit code should be between 0 and 255, where 0 indicates success and non-zero indicates failure. + +## 链接错误 + +- `0` 未知错误 / Unknown error. +- `1` 未定义入口点 / Entry point undefined. +- `2` 无法找到文件 / Unable to find file. +- `3` 无法读取文件 / Unable to read file. +- `4` 无法解析文件 / Unable to parse file. +- `5` 无法找到依赖库 / Unable to find dependent library. +- `6` 无法读取依赖库 / Unable to read dependent library. +- `7` 无法解析依赖库 / Unable to parse dependent library. +- `8` 内存不足 / Out of memory. +- `9` 架构不匹配 / Architecture mismatch. +- `255` 传入参数错误 / Invalid input parameters. diff --git a/include/libc-base/asm/asm.h b/include/libc-base/asm/asm.h index f1943c3..1f5315e 100755 --- a/include/libc-base/asm/asm.h +++ b/include/libc-base/asm/asm.h @@ -21,7 +21,13 @@ #define asm_setreg(reg, value) ({ asm volatile("mov %0, %%" #reg "\n\t" ::"r"((size_t)(value))); }) -#define used_val(value) ({ asm volatile("" ::"r,m"(value) : "memory"); }) +#define used_val1(value) ({ asm volatile("" ::"r,m"(value)); }) +#define used_val2(value, ...) ({ used_val1(value), used_val1(__VA_ARGS__); }) +#define used_val3(value, ...) ({ used_val1(value), used_val2(__VA_ARGS__); }) +#define used_val4(value, ...) ({ used_val1(value), used_val3(__VA_ARGS__); }) +#define used_val5(value, ...) ({ used_val1(value), used_val4(__VA_ARGS__); }) +#define used_val6(value, ...) ({ used_val1(value), used_val5(__VA_ARGS__); }) +#define used_val(...) CONCAT(used_val, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__) /** *\brief 加载 GDT diff --git a/src/kernel/cpu/gdtidt.c b/src/kernel/cpu/gdtidt.c index edb04b9..81409ac 100755 --- a/src/kernel/cpu/gdtidt.c +++ b/src/kernel/cpu/gdtidt.c @@ -38,7 +38,7 @@ size_t syscall(size_t eax, size_t ebx, size_t ecx, size_t edx, size_t esi, size_ FASTCALL void inthandler(i32 id, regs32 *regs) { kassert(id < 256); - if (id != 0x07 && id != 0x2d) asm_set_ts; + if (fpu_using_task != null && id != 0x07 && id != 0x2d) asm_set_ts; if (id >= 0x20 && id < 0x30) send_eoi(id - 0x20); if (acpi_inited) { @@ -55,7 +55,7 @@ FASTCALL void inthandler(i32 id, regs32 *regs) { klogw("Unknown interrupt %02x (%d)", id, id); } - if (id != 0x07 && id != 0x2d) { + if (fpu_using_task != null && id != 0x07 && id != 0x2d) { val from_usermod = (regs->cs & 3) == 3; (current_task == fpu_using_task && fpu_ctx_usermod == from_usermod) ? asm_clr_ts : asm_set_ts; } diff --git a/src/kernel/exec/exec.c b/src/kernel/exec/exec.c index ecb7117..9ddd440 100755 --- a/src/kernel/exec/exec.c +++ b/src/kernel/exec/exec.c @@ -71,15 +71,13 @@ void task_to_user_mode_elf() { struct args args = {.cmdline = current_task->command_line, .sp = (void *)TASK_ARGS_ADDR}; parse_args(&args); + used_val(*args.argv, *args.envp); klogd("argc: %d", args.argc); - klogd("argv: %p", args.argv); - klogd("argv: %p", args.envp); for (int i = 0; i < args.argc; i++) { klogd("argv[%d]: %s", i, args.argv[i]); } vfs_node_t file = vfs_open("/fatfs0/ld-plos.bin"); - // vfs_node_t file = vfs_open(args.argv[0]); if (file == null) { if (mouse_use_task == current_task) mouse_sleep(&mdec); kloge(); diff --git a/src/kernel/task/basetask.c b/src/kernel/task/basetask.c index a6332fa..37e8b5e 100755 --- a/src/kernel/task/basetask.c +++ b/src/kernel/task/basetask.c @@ -39,23 +39,26 @@ static plff_t load_font(cstr path) { } void plty_set_default(plty_t plty); + void stdout_read() {} void stdout_write(int drive, u8 *buffer, u32 number, u32 lba) { for (int i = 0; i < number; i++) { putchar(buffer[i]); } } + void random_read(int drive, u8 *buffer, u32 number, u32 lba) { for (int i = 0; i < number; i++) { buffer[i] = krandb(); } } -void random_write(int drive, u8 *buffer, u32 number, u32 lba) {} +void random_write(int drive, u8 *buffer, u32 number, u32 lba) {} + char *GetSVGACharOEMString(); bool is_vbox = false; static void check_device() { - char *s = strdup(GetSVGACharOEMString()); + char *s = GetSVGACharOEMString(); info("VIDEO CARD: %s", s); if (strstr(s, "VirtualBox")) { info("VirtualBox detected"); @@ -64,16 +67,6 @@ static void check_device() { is_vbox = false; info("VirtualBox not detected"); } - free(s); -} - -static void draw(int n) { - u32 *buf = vbe_backbuffer; - for (size_t y = 0; y < screen_h; y++) { - for (size_t x = 0; x < screen_w; x++) { - buf[y * screen_w + x] = (0xff8000 + x + n) & 0xffffff; - } - } } extern bool debug_enabled; diff --git a/src/ld-plos/ld-plos.c b/src/ld-plos/ld-plos.c index cd70dbf..f56988d 100644 --- a/src/ld-plos/ld-plos.c +++ b/src/ld-plos/ld-plos.c @@ -2,37 +2,36 @@ #include #include +#include "ld-plos.h" + // 一个在没有标准库的环境下加载动态链接 elf 文件的程序 -#define syscall(...) __syscall(__VA_ARGS__) +static int argc; +static char **argv; +static char **envp; -#ifdef __x86_64__ +// 加载完毕后运行应用程序 +static __attr(noreturn) void run(usize entry) { + asm("mov %0, %%edi\n\t" ::"r"(argc)); + asm("mov %0, %%esi\n\t" ::"r"(argv)); + asm("mov %0, %%edx\n\t" ::"r"(envp)); + asm volatile("jmp *%0" ::"r"(entry)); + __builtin_unreachable(); +} -static void load_elf32(const Elf32Header *elf) {} -static void load_elf64(const Elf64Header *elf) {} +#ifdef __x86_64__ -#else +static int load_elf32(const Elf32Header *elf) { + return 0; +} -void print_num(usize num) { - static char buffer[32]; - char *buf = buffer + 32; - *--buf = '\0'; - *--buf = '\n'; - while (num) { - int digit = num % 16; - *--buf = (digit < 10) ? digit + '0' : digit - 10 + 'a'; - num /= 16; - } - syscall(SYSCALL_PRINT, buf); +static int load_elf64(const Elf64Header *elf) { + return 0; } +#else + int load_segment(const Elf32ProgramHeader *prog, const void *elf) { - print_num(prog->type); - print_num(prog->offset); - print_num(prog->vaddr); - print_num(prog->filesz); - print_num(prog->memsz); - print_num(prog->flags); if (prog->type != ELF_PROGRAM_TYPE_LOAD) return 0; usize hi = PADDING_UP(prog->vaddr + prog->memsz, PAGE_SIZE); usize lo = PADDING_DOWN(prog->vaddr, PAGE_SIZE); @@ -42,45 +41,51 @@ int load_segment(const Elf32ProgramHeader *prog, const void *elf) { return 0; } -static void load_elf32(const Elf32Header *elf) { +static int load_elf32(const Elf32Header *elf) { var prog = (const Elf32ProgramHeader *)((usize)elf + elf->phoff); for (usize i = 0; i < elf->phnum; i++) { - if (load_segment(prog + i, elf) < 0) return; + if (load_segment(prog + i, elf) < 0) return LDE_FILE_UNPARSABLE; } - asm volatile("jmp *%0" : : "r"(elf->entry)); + run(elf->entry); } -static void load_elf64(const void *elf) { + +static int load_elf64(const void *elf) { // Can't load 64-bit ELF in 32-bit system. + return LDE_ARCH_MISSMATCH; } #endif -void __linker_main(int argc, char **argv, char **envp) { - if (argc <= 0 || argv == null || envp == null) return; - if (argv[0] == null) return; +int __linker_main(int argc, char **argv, char **envp) { + if (argc <= 0 || argv == null || envp == null || argv[0] == null) return LDE_INVALID_INPUT; - usize size = syscall(SYSCALL_FILE_SIZE, argv[0]); + isize size = syscall(SYSCALL_FILE_SIZE, argv[0]); + if (size < 0) return LDE_FILE_NOT_FOUND; void *file = (void *)syscall(SYSCALL_MMAP, null, size); - syscall(SYSCALL_LOAD_FILE, argv[0], file, size); + if (file == null) return LDE_OUT_OF_MEMORY; + if (syscall(SYSCALL_LOAD_FILE, argv[0], file, size) < 0) return LDE_FILE_UNREADABLE; + + const Elf32Header *elf = (Elf32Header *)file; + const ElfIdent *ident = (ElfIdent *)file; + if (ident->magic != ELF_MAGIC) return 1; - const ElfIdent *ident = (ElfIdent *)file; - if (ident->magic != ELF_MAGIC) return; if (ident->class == ELF_CLASS_32) { - load_elf32(file); - } else if (ident->class == ELF_CLASS_64) { - load_elf64(file); + if (elf->machine != ELF_MACHINE_IA32) return LDE_ARCH_MISSMATCH; + return load_elf32(file); + } + if (ident->class == ELF_CLASS_64) { + if (elf->machine != ELF_MACHINE_AMD64) return LDE_ARCH_MISSMATCH; + return load_elf64(file); } + return LDE_FILE_UNPARSABLE; } void __linker_start() { - int volatile argc; - char **volatile argv; - char **volatile envp; asm("mov %%edi, %0\n\t" : "=r"(argc)); asm("mov %%esi, %0\n\t" : "=r"(argv)); asm("mov %%edx, %0\n\t" : "=r"(envp)); - __linker_main(argc, argv, envp); + int errcode = __linker_main(argc, argv, envp); - syscall(SYSCALL_EXIT, INT_MAX); + syscall(SYSCALL_EXIT, MASK(30) | MASK(29) | (errcode << 16)); } diff --git a/src/ld-plos/ld-plos.h b/src/ld-plos/ld-plos.h new file mode 100644 index 0000000..4783a59 --- /dev/null +++ b/src/ld-plos/ld-plos.h @@ -0,0 +1,16 @@ +#pragma once + +// 动态链接器错误 +#define LDE_UNKNOWN 0 // 未知错误 +#define LDE_ENTRY_POINT 1 // 未定义入口点 +#define LDE_FILE_NOT_FOUND 2 // 无法找到文件 +#define LDE_FILE_UNREADABLE 3 // 无法读取文件 +#define LDE_FILE_UNPARSABLE 4 // 无法解析文件 +#define LDE_DEP_LIB_NOT_FOUND 5 // 无法找到依赖库 +#define LDE_DEP_LIB_UNREADABLE 6 // 无法读取依赖库 +#define LDE_DEP_LIB_UNPARSABLE 7 // 无法解析依赖库 +#define LDE_OUT_OF_MEMORY 8 // 内存不足 +#define LDE_ARCH_MISSMATCH 9 // 架构不匹配 +#define LDE_INVALID_INPUT 255 // 传入参数错误 + +#define syscall(...) __syscall(__VA_ARGS__)