U0 LoadOneImport(U8 **_src, U8 *module_base, I64 ld_flags) { U8 *src = *_src, *ptr2, *st_ptr; I64 i, etype; CHashExport *tmpex = NULL; CHashImport *tmpiss; Bool first = TRUE; while (etype = *src++) { i = *src(U32 *)++; st_ptr = src; src += StrLen(st_ptr) + 1; if (*st_ptr) { if (!first) { *_src = st_ptr - 5; return; } else { first = FALSE; if (!(tmpex = HashFind(st_ptr, Fs->hash_table, HTG_ALL - HTT_IMPORT_SYS_SYM))) { if (!(ld_flags & LDF_SILENT)) "Unresolved Reference:%s\n", st_ptr; tmpiss = CAlloc(sizeof(CHashImport)); tmpiss->str = StrNew(st_ptr); tmpiss->type = HTT_IMPORT_SYS_SYM; tmpiss->module_header_entry = st_ptr - 5; tmpiss->module_base = module_base; HashAdd(tmpiss, Fs->hash_table); } } } if (tmpex) { ptr2 = module_base+i; if (tmpex->type & HTT_FUN) i = tmpex(CHashFun *)->exe_addr; else if (tmpex->type & HTT_GLOBAL_VAR) i = tmpex(CHashGlobalVar *)->data_addr; else i = tmpex->val; switch (etype) { case IET_REL_I8: *ptr2(U8 *) = i - ptr2 - 1; break; case IET_IMM_U8: *ptr2(U8 *) = i; break; case IET_REL_I16: *ptr2(U16 *) = i - ptr2 - 2; break; case IET_IMM_U16: *ptr2(U16 *) = i; break; case IET_REL_I32: *ptr2(U32 *) = i - ptr2 - 4; break; case IET_IMM_U32: *ptr2(U32 *) = i; break; case IET_REL_I64: *ptr2(I64 *) = i - ptr2 - 8; break; case IET_IMM_I64: *ptr2(I64 *) = i; break; } } } *_src = src - 1; } U0 SysSymImportsResolve(U8 *st_ptr, I64 ld_flags) { CHashImport *tmpiss; U8 *ptr; while (tmpiss = HashSingleTableFind(st_ptr, Fs->hash_table, HTT_IMPORT_SYS_SYM)) { ptr = tmpiss->module_header_entry; LoadOneImport(&ptr, tmpiss->module_base, ld_flags); tmpiss->type = HTT_INVALID; } } U0 LoadPass1(U8 *src, U8 *module_base, I64 ld_flags) { U8 *ptr2, *ptr3, *st_ptr; I64 i, j, count, etype; CHashExport *tmpex = NULL; while (etype = *src++) { i = *src(U32 *)++; st_ptr = src; src += StrLen(st_ptr) + 1; switch (etype) { case IET_REL32_EXPORT: case IET_IMM32_EXPORT: case IET_REL64_EXPORT: case IET_IMM64_EXPORT: tmpex = CAlloc(sizeof(CHashExport)); tmpex->str = StrNew(st_ptr); tmpex->type = HTT_EXPORT_SYS_SYM | HTF_IMM; if (etype == IET_IMM32_EXPORT || etype == IET_IMM64_EXPORT) tmpex->val = i; else tmpex->val = i + module_base; HashAdd(tmpex, Fs->hash_table); SysSymImportsResolve(st_ptr, ld_flags); break; case IET_REL_I0 ... IET_IMM_I64: src = st_ptr - 5; LoadOneImport(&src, module_base, ld_flags); break; case IET_ABS_ADDR: if (ld_flags & LDF_NO_ABSS) src += i * sizeof(U32); else { count = i; for (j = 0; j < count; j++) { ptr2 = module_base + *src(U32 *)++; *ptr2(U32 *) += module_base; } } break; start: case IET_CODE_HEAP: ptr3 = MAlloc(*src(I32 *)++, Fs->code_heap); break; case IET_ZEROED_CODE_HEAP: ptr3 = CAlloc(*src(I32 *)++, Fs->code_heap); break; end: if (*st_ptr) { tmpex = CAlloc(sizeof(CHashExport)); tmpex->str = StrNew(st_ptr); tmpex->type = HTT_EXPORT_SYS_SYM | HTF_IMM; tmpex->val = ptr3; HashAdd(tmpex, Fs->hash_table); } count = i; for (j = 0; j < count; j++) { ptr2 = module_base + *src(U32 *)++; *ptr2(I32 *) += ptr3; } break; start: case IET_DATA_HEAP: ptr3 = MAlloc(*src(I64 *)++); break; case IET_ZEROED_DATA_HEAP: ptr3 = CAlloc(*src(I64 *)++); break; end: if (*st_ptr) { tmpex = CAlloc(sizeof(CHashExport)); tmpex->str = StrNew(st_ptr); tmpex->type = HTT_EXPORT_SYS_SYM | HTF_IMM; tmpex->val = ptr3; HashAdd(tmpex, Fs->hash_table); } count = i; for (j = 0; j < count; j++) { ptr2 = module_base + *src(U32 *)++; *ptr2(I64 *) += ptr3; } break; } } } U0 LoadPass2(U8 *src, U8 *module_base, I64) { U8 *st_ptr; I64 i, etype; while (etype = *src++) { i = *src(U32 *)++; st_ptr = src; src += StrLen(st_ptr) + 1; switch (etype) { case IET_MAIN: Call(i + module_base); break; case IET_ABS_ADDR: src += sizeof(U32) * i; break; case IET_CODE_HEAP: case IET_ZEROED_CODE_HEAP: src += 4 + sizeof(U32) * i; break; case IET_DATA_HEAP: case IET_ZEROED_DATA_HEAP: src += 8 + sizeof(U32) * i; break; } } } CZXE *Load(U8 *filename, I64 ld_flags=0, CZXE *zxe_addr=INVALID_PTR) {//Load a .ZXE file module into memory. //zxe_addr==INVALID_PTR means don't care what load address. U8 *fbuf, *module_base, *absname; I64 size, module_align, misalignment; CZXE *zxe; fbuf = ExtDefault(filename, "ZXE"); if (!(zxe = FileRead(fbuf, &size))) { Free(fbuf); return NULL; } //See Patch Table Generation module_align = 1 << zxe->module_align_bits; if (!module_align || zxe->signature != ZXE_SIGNATURE_VAL) { Free(zxe); Free(fbuf); throw('ZXEModul'); } if (zxe_addr == INVALID_PTR) { if (zxe->org == INVALID_PTR) { misalignment = module_align - sizeof(CZXE); if (misalignment < 0) misalignment &= module_align - 1; if (Fs->code_heap != Fs->data_heap) { if (module_align < 16) module_align = 16; zxe_addr = MAllocAligned(size, module_align, Fs->code_heap, misalignment); } else if (module_align > 8) zxe_addr = MAllocAligned(size, module_align,, misalignment); else {//Less than 2Gig system memory zxe_addr = zxe; goto lo_skip; //File is already in code heap area, don't copy. } } else zxe_addr = zxe->org; } MemCopy(zxe_addr, zxe, size); Free(zxe); lo_skip: module_base = zxe_addr(U8 *) + sizeof(CZXE); absname = FileNameAbs(fbuf); Free(fbuf); fbuf = StrNew(absname); FileExtRemove(fbuf); if (fbuf[1] == ':' && StrLen(fbuf) > 2) HashGenericAdd(fbuf + 2, HTT_MODULE | HTF_PUBLIC, zxe_addr); LoadPass1(zxe_addr(U8 *) + zxe_addr->patch_table_offset, module_base, ld_flags); if (!(ld_flags & LDF_JUST_LOAD)) LoadPass2(zxe_addr(U8 *) + zxe_addr->patch_table_offset, module_base, ld_flags); Free(absname); Free(fbuf); return zxe_addr; } U0 LoadKernel() { HashGenericAdd(KERNEL_MODULE_NAME, HTT_MODULE | HTF_PUBLIC, mem_boot_base - sizeof(CZXE)); //Abs patches done here CPatchTableAbsAddr. LoadPass1(sys_boot_patch_table_base, mem_boot_base, LDF_NO_ABSS | LDF_SILENT); //No main routines // LoadPass2(sys_boot_patch_table_base,mem_boot_base,0); }