txScript* fxLoadBinary(txMachine* the, txString path) { int error = 0; txScript* script = NULL; FILE* file = NULL; Atom atom; txByte version[4]; script = c_malloc(sizeof(txScript)); bailElse(script); c_memset(script, 0, sizeof(txScript)); file = fopen(path, "rb"); bailElse(file); fxLoadBinaryAtom(the, file, &atom); bailAssert(atom.atomType == XS_ATOM_BINARY); fxLoadBinaryAtom(the, file, &atom); bailAssert(atom.atomType == XS_ATOM_VERSION); bailElse(fread(script->version, sizeof(version), 1, file) == 1); bailAssert(script->version[0] == XS_MAJOR_VERSION); bailAssert(script->version[1] == XS_MINOR_VERSION); bailAssert(script->version[2] == XS_PATCH_VERSION); bailAssert(script->version[3] != -1); fxLoadBinaryAtom(the, file, &atom); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); script->symbolsSize = atom.atomSize - sizeof(atom); script->symbolsBuffer = c_malloc(script->symbolsSize); bailElse(fread(script->symbolsBuffer, script->symbolsSize, 1, file) == 1); fxLoadBinaryAtom(the, file, &atom); bailAssert(atom.atomType == XS_ATOM_CODE); script->codeSize = atom.atomSize - sizeof(atom); script->codeBuffer = c_malloc(script->codeSize); bailElse(fread(script->codeBuffer, script->codeSize, 1, file) == 1); fclose(file); return script; bail: if (file) fclose(file); if (script) fxDeleteScript(script); return C_NULL; }
void fxLoadModuleJSB(txMachine* the, txString path, txID moduleID) { FskErr err = kFskErrNone; txScript* script = NULL; FskFile fref = NULL; Atom atom; bailIfError(FskMemPtrNewClear(sizeof(txScript), &script)); bailIfError(FskFileOpen(path, kFskFilePermissionReadOnly, &fref)); bailIfError(fxLoadModuleJSBAtom(the, fref, &atom)); bailAssert(atom.atomType == XS_ATOM_BINARY); bailIfError(fxLoadModuleJSBAtom(the, fref, &atom)); bailAssert(atom.atomType == XS_ATOM_VERSION); bailIfError(FskFileRead(fref, sizeof(script->version), script->version, NULL)); bailAssert(script->version[0] == XS_MAJOR_VERSION); bailAssert(script->version[1] == XS_MINOR_VERSION); bailAssert(script->version[2] == XS_PATCH_VERSION); bailAssert(script->version[3] != -1); bailIfError(fxLoadModuleJSBAtom(the, fref, &atom)); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); script->symbolsSize = atom.atomSize - sizeof(atom); bailIfError(FskMemPtrNew(script->symbolsSize, &script->symbolsBuffer)); bailIfError(FskFileRead(fref, script->symbolsSize, script->symbolsBuffer, NULL)); bailIfError(fxLoadModuleJSBAtom(the, fref, &atom)); bailAssert(atom.atomType == XS_ATOM_CODE); script->codeSize = atom.atomSize - sizeof(atom); bailIfError(FskMemPtrNew(script->codeSize, &script->codeBuffer)); bailIfError(FskFileRead(fref, script->codeSize, script->codeBuffer, NULL)); bail: if (fref) FskFileClose(fref); if (err) { if (script) { fxDeleteScript(script); script = NULL; } } fxResolveModule(the, moduleID, script, NULL, NULL); }
void* fxMapArchive(txString base, txCallbackAt callbackAt) { int error = 0; txArchive* archive = C_NULL; #if mxWindows #else struct stat statbuf; #endif txString p; Atom atom; int c, i; txString* symbol; txScript* script; archive = c_malloc(sizeof(txArchive)); bailElse(archive); c_memset(archive, 0, sizeof(txArchive)); c_strcpy(archive->base, base); #if mxWindows archive->file = CreateFile(base, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); bailElse(archive->file != INVALID_HANDLE_VALUE); archive->size = GetFileSize(archive->file, &archive->size); bailElse(archive->size != INVALID_FILE_SIZE); archive->mapping = CreateFileMapping(archive->file, NULL, PAGE_READONLY, 0, (SIZE_T)archive->size, NULL); bailElse(archive->mapping != INVALID_HANDLE_VALUE); archive->address = MapViewOfFile(archive->mapping, FILE_MAP_READ, 0, 0, (SIZE_T)archive->size); bailElse(archive->address != NULL); #else archive->fd = open(base, O_RDONLY); bailElse(archive->fd >= 0); fstat(archive->fd, &statbuf); archive->size = statbuf.st_size; archive->address = mmap(NULL, archive->size, PROT_READ, MAP_SHARED, archive->fd, 0); bailElse(archive->address != MAP_FAILED); #endif p = archive->address; p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_ARCHIVE); p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_VERSION); bailAssert(*p++ == XS_MAJOR_VERSION); bailAssert(*p++ == XS_MINOR_VERSION); bailAssert(*p++ == XS_PATCH_VERSION); if ((*p++) && !callbackAt) { char* dot; dot = c_strrchr(archive->base, '.'); if (dot) *dot = 0; #if mxWindows c_strcat(archive->base, ".dll"); archive->library = LoadLibrary(archive->base); bailElse(archive->library); callbackAt = (txCallbackAt)GetProcAddress(archive->library, "xsHostModuleAt"); bailElse(callbackAt); #else c_strcat(archive->base, ".so"); archive->library = dlopen(archive->base, RTLD_NOW); if (!archive->library) fprintf(stderr, "%s\n", dlerror()); bailElse(archive->library); callbackAt = (txCallbackAt)dlsym(archive->library, "xsHostModuleAt"); bailElse(callbackAt); #endif archive->keys = callbackAt(0); } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); c = archive->symbolCount = ntohs(*((unsigned short*)p)); p += 2; if (c) { symbol = archive->symbols = c_malloc(c * sizeof(txString)); for (i = 0; i < c; i++) { *symbol = p; p += c_strlen(p) + 1; symbol++; } } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_PATHS); c = archive->scriptCount = ntohs(*((unsigned short*)p)); p += 2; script = archive->scripts = c_malloc(c * sizeof(txScript)); c_memset(script, 0, c * sizeof(txScript)); for (i = 1; i <= c; i++) { if (callbackAt) script->callback = callbackAt(i); script->path = p; p += c_strlen(p) + 1; script++; } script = archive->scripts; for (i = 0; i < c; i++) { p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_CODE); script->codeSize = atom.atomSize - sizeof(atom); script->codeBuffer = (txS1*)p; p += script->codeSize; script++; } p = c_strrchr(archive->base, mxSeparator); if (p) { p++; *p = 0; archive->baseLength = p - archive->base; } bail: if (error) { fxUnmapArchive(archive); archive = C_NULL; } return archive; }
int main(int argc, char* argv[]) { int error = 0; typedef struct { long atomSize; unsigned long atomType; } Atom; FILE* aFile = NULL; size_t aSize; txS1* aBuffer = NULL; Atom atom; txByte isArchive; txByte hasC; txS1* codeBuffer; size_t codeSize; txS1* p; int c, i; int symbolsCount; txS1** symbols = NULL; txUsage* usages = NULL; txS1** paths = NULL; txS1** hosts = NULL; if (argc < 2) { fprintf(stderr, "### No input!\n"); return 1; } aFile = fopen(argv[1], "rb"); bailElse(aFile); bailElse(fseek(aFile, 0, SEEK_END) == 0); aSize = ftell(aFile); bailElse(fseek(aFile, 0, SEEK_SET) == 0); aBuffer = malloc(aSize); bailElse(aBuffer != NULL); bailElse(fread(aBuffer, aSize, 1, aFile) == 1); p = aBuffer; atom.atomSize = ntohl(((Atom*)p)->atomSize); atom.atomType = ntohl(((Atom*)p)->atomType); fprintf(stdout, "%4.4s %8ld\n", (char*)(p + sizeof(long)), atom.atomSize); if (atom.atomType == XS_ATOM_ARCHIVE) isArchive = 1; else if (atom.atomType == XS_ATOM_BINARY) isArchive = 0; else { error = EINVAL; goto bail; } p += sizeof(atom); atom.atomSize = ntohl(((Atom*)p)->atomSize); atom.atomType = ntohl(((Atom*)p)->atomType); bailAssert(atom.atomType == XS_ATOM_VERSION); fprintf(stdout, "%4.4s %8ld %d %d %d %d\n", (char*)(p + sizeof(long)), atom.atomSize, *(p + sizeof(atom)), *(p + sizeof(atom) + 1), *(p + sizeof(atom) + 2), *(p + sizeof(atom) + 3)); p += sizeof(atom); bailAssert(*p++ == XS_MAJOR_VERSION); bailAssert(*p++ == XS_MINOR_VERSION); bailAssert(*p++ == XS_PATCH_VERSION); hasC = *p++; atom.atomSize = ntohl(((Atom*)p)->atomSize); atom.atomType = ntohl(((Atom*)p)->atomType); fprintf(stdout, "%4.4s %8ld\n", (char*)(p + sizeof(long)), atom.atomSize); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); p += sizeof(atom); c = symbolsCount = ntohs(*((unsigned short*)p)); p += 2; if (c) { symbols = malloc(c * sizeof(txS1*)); usages = malloc(c * sizeof(txUsage)); for (i = 0; i < c; i++) { symbols[i] = p; usages[i].name = p; usages[i].debug = 0; usages[i].property = 0; usages[i].variable = 0; p += c_strlen((char*)p) + 1; } } atom.atomSize = ntohl(((Atom*)p)->atomSize); atom.atomType = ntohl(((Atom*)p)->atomType); fprintf(stdout, "%4.4s %8ld\n", (char*)(p + sizeof(long)), atom.atomSize); if (isArchive) { bailAssert(atom.atomType == XS_ATOM_PATHS); p += sizeof(atom); c = ntohs(*((unsigned short*)p)); p += 2; if (c) { paths = malloc(c * sizeof(txS1*)); for (i = 0; i < c; i++) { paths[i] = p; p += c_strlen((char*)p) + 1; } for (i = 0; i < c; i++) { atom.atomSize = ntohl(((Atom*)p)->atomSize); atom.atomType = ntohl(((Atom*)p)->atomType); bailAssert(atom.atomType == XS_ATOM_CODE); fprintf(stdout, "%4.4s %8ld %s\n", (char*)(p + sizeof(long)), atom.atomSize, paths[i]); fxDumpCode(paths[i], symbols, usages, hosts, (txS1*)(p + sizeof(atom)), atom.atomSize - sizeof(atom)); p += atom.atomSize; } } } else { bailAssert(atom.atomType == XS_ATOM_CODE); codeBuffer = p + sizeof(atom); codeSize = atom.atomSize - sizeof(atom); if (hasC == -1) { p += atom.atomSize; atom.atomSize = ntohl(((Atom*)p)->atomSize); atom.atomType = ntohl(((Atom*)p)->atomType); fprintf(stdout, "%4.4s %8ld\n", (char*)(p + sizeof(long)), atom.atomSize); bailAssert(atom.atomType == XS_ATOM_HOSTS); p += sizeof(atom); c = ntohs(*((unsigned short*)p)); p += 2; if (c) { hosts = malloc(c * sizeof(txS1*)); for (i = 0; i < c; i++) { hosts[i] = p; p += c_strlen((char*)p) + 1; } } } fxDumpCode((txS1*)argv[1], symbols, usages, hosts, codeBuffer, codeSize); } if (symbolsCount) { qsort(usages, symbolsCount, sizeof(txUsage), compareUsages); fprintf(stdout, "DEBUG\tPROP\tVAR\n"); for (i = 0; i < symbolsCount; i++) { txUsage* usage = &usages[i]; if (usage->debug || usage->property || usage->variable) fprintf(stdout, "%5ld\t%5ld\t%5ld\t%s\n", usage->debug, usage->property, usage->variable, usage->name); } } bail: if (aFile) fclose(aFile); return error; }
void* fxMapArchive(txString base, txCallbackAt callbackAt) { FskErr err = kFskErrNone; txArchive* archive = NULL; txString p; Atom atom; int c, i; txString* symbol; txScript* script; bailIfError(FskMemPtrNewClear(sizeof(txArchive), &archive)); c_strcpy(archive->base, base); bailIfError(FskFileMap(base, (unsigned char**)&(archive->address), &(archive->size), 0, &(archive->map))); p = archive->address; p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_ARCHIVE); p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_VERSION); bailAssert(*p++ == XS_MAJOR_VERSION); bailAssert(*p++ == XS_MINOR_VERSION); bailAssert(*p++ == XS_PATCH_VERSION); if ((*p++) && !callbackAt) { char* dot; dot = c_strrchr(archive->base, '.'); if (dot) *dot = 0; #if mxWindows c_strcat(archive->base, ".dll"); #else c_strcat(archive->base, ".so"); #endif bailIfError(FskLibraryLoad(&(archive->library), archive->base)); bailIfError(FskLibraryGetSymbolAddress(archive->library, "xsHostModuleAt", &callbackAt)); archive->keys = callbackAt(0); } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); mxDecode2(p, archive->symbolCount); c = archive->symbolCount; if (c) { bailIfError(FskMemPtrNew(c * sizeof(txString), &(archive->symbols))); symbol = archive->symbols; for (i = 0; i < c; i++) { *symbol = p; p += c_strlen(p) + 1; symbol++; } } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_PATHS); mxDecode2(p, archive->scriptCount); c = archive->scriptCount; bailIfError(FskMemPtrNewClear(c * sizeof(txScript), &(archive->scripts))); script = archive->scripts; for (i = 1; i <= c; i++) { if (callbackAt) script->callback = callbackAt(i); script->path = p; bailIfNULL(script->path); p += c_strlen(p) + 1; script++; } script = archive->scripts; for (i = 0; i < c; i++) { p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_CODE); script->codeSize = atom.atomSize - sizeof(atom); script->codeBuffer = (txS1*)p; p += script->codeSize; script++; } p = c_strrchr(archive->base, '/'); if (p) { p++; *p = 0; archive->baseLength = p - archive->base; } bail: if (err) { fxUnmapArchive(archive); archive = NULL; } return archive; }