qboolean Rank_OpenRankings(void) { char syspath[MAX_OSPATH]; size_t result; qboolean created; if (!rankfile) { if (!*rank_filename.string) { return false; } if (!FS_NativePath(rank_filename.string, FS_GAMEONLY, syspath, sizeof(syspath))) return false; rankfile = FS_OpenVFS(rank_filename.string, "r+b", FS_GAMEONLY); if (!rankfile) //hmm... try creating { rankfile = FS_OpenVFS(rank_filename.string, "w+b", FS_GAMEONLY); created = true; } else created = false; if (!rankfile) return false; //couldn't open file. memset(&rankfileheader, 0, sizeof(rankfileheader)); VFS_SEEK(rankfile, 0); result = VFS_READ(rankfile, &rankfileheader, sizeof(rankfileheader_t)); if (result != sizeof(rankfileheader_t)) Con_Printf("Rank_OpenRankings() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(rankfileheader_t),(unsigned int)result, rank_filename.string); rankfileheader.version = swaplong(rankfileheader.version); rankfileheader.usedslots = swaplong(rankfileheader.usedslots); rankfileheader.leader = swaplong(rankfileheader.leader); rankfileheader.freeslot = swaplong(rankfileheader.freeslot); if (!created && (rankfileheader.version != RANKFILE_VERSION || rankfileheader.ident != RANKFILE_IDENT)) { Con_Printf("Rank file is version %i not %i\nEither delete the file or use an equivelent version of " FULLENGINENAME "\n", rankfileheader.version, RANKFILE_VERSION); VFS_CLOSE(rankfile); rankfile = NULL; return false; } return true; //success. } return true; //already open }
static void WRITEHEADER(void) { rankfileheader_t nh; nh.ident = RANKFILE_IDENT; nh.version = swaplong(RANKFILE_VERSION); nh.usedslots = swaplong(rankfileheader.usedslots); nh.leader = swaplong(rankfileheader.leader); nh.freeslot = swaplong(rankfileheader.freeslot); VFS_SEEK(rankfile, 0); VFS_WRITE(rankfile, &nh, sizeof(rankfileheader_t)); }
static void WRITE_PLAYERHEADER(int x, rankheader_t *oh) { rankheader_t nh; VFS_SEEK(rankfile, sizeof(rankfileheader_t)+((x-1)*sizeof(rankinfo_t))); nh.prev = swaplong(oh->prev); //score is held for convineance. nh.next = swaplong(oh->next); Q_strncpyz(nh.name, oh->name, sizeof(nh.name)); nh.pwd = swaplong(oh->pwd); nh.score = swapfloat(oh->score); VFS_WRITE(rankfile, &nh, sizeof(rankheader_t)); }
static int prcparse(UBYTE *prcfile,size_t_68k prcsize){ palmdb meep; meep.numrecords = prcfile[0x4C] << 8 | prcfile[0x4C + 1]; memcpy(meep.name,prcfile,32); memcpy(&meep.flags,prcfile + 0x20,2); swapword(meep.flags); memcpy(&meep.version,prcfile + 0x22,2); swapword(meep.version); memcpy(&meep.modnum,prcfile + 0x30,4); swaplong(meep.modnum); memcpy(&meep.appinfo,prcfile + 0x34,4); swaplong(meep.appinfo); memcpy(&meep.sortinfo,prcfile + 0x38,4); swaplong(meep.sortinfo); memcpy(meep.type.typec,prcfile + 0x3C,4); memcpy(meep.creator.typec,prcfile + 0x40,4); memcpy(&meep.uuidseed,prcfile + 0x44,4); swaplong(meep.uuidseed); memcpy(&meep.nextrecordlist,prcfile + 0x48,4); swaplong(meep.nextrecordlist); //get the needed 68k memory curmemloc = getnewlinearchunks(NUM_BANKS(prcsize + meep.numrecords * 4)) << 16; if(curmemloc != 0){ avbytes = NUM_BANKS(prcsize + meep.numrecords * 4) * SIZEOFBANK; currealaddr = (UBYTE*)get_real_address(curmemloc); } else return FAILEDMALLOC; meep.open = false; meep.resdb = true; apps.push_back(meep); unsigned int robin; for(robin = 0;robin < meep.numrecords;robin++){ unpackprcresource(robin,prcfile,prcsize,apps.size() - 1); } apps[apps.size() - 1].intmain = getresource(apps.size() - 1,1,'code'); if(apps[apps.size() - 1].intmain != 0){ apps[apps.size() - 1].exe = true; hasbootableapp = true; } return WORKED; }
static void READ_PLAYERHEADER(int x, rankheader_t *oh) { size_t result; VFS_SEEK(rankfile, sizeof(rankfileheader_t)+((x-1)*sizeof(rankinfo_t))); result = VFS_READ(rankfile, oh, sizeof(rankheader_t)); if (result != sizeof(rankheader_t)) Con_Printf("READ_PLAYERHEADER() fread: expected %lu, result was %u\n",(long unsigned int)sizeof(rankheader_t),(unsigned int)result); oh->prev = swaplong(oh->prev); //score is held for convineance. oh->next = swaplong(oh->next); // strcpy(oh->name, oh->name); oh->pwd = swaplong(oh->pwd); oh->score = swapfloat(oh->score); }
static CTL_MSG swapmsg(CTL_MSG req) { CTL_MSG swapreq; if (req.ctl_addr.sin_family == swapshort(AF_INET)) { swapreq = req; swapreq.id_num = swaplong(req.id_num); swapreq.pid = swaplong(req.pid); swapreq.addr.sin_family = swapshort(req.addr.sin_family); swapreq.ctl_addr.sin_family = swapshort(req.ctl_addr.sin_family); return (swapreq); } else { return (req); } }
static void WRITE_PLAYERSTATS(int x, rankstats_t *os) { rankstats_t ns; int i; VFS_SEEK(rankfile, sizeof(rankfileheader_t)+sizeof(rankheader_t)+((x-1)*sizeof(rankinfo_t))); ns.kills = swaplong(os->kills); ns.deaths = swaplong(os->deaths); for (i = 0; i < NUM_RANK_SPAWN_PARMS; i++) ns.parm[i] = swapfloat(os->parm[i]); ns.timeonserver = swapfloat(os->timeonserver); ns.flags1 = (os->flags1); ns.trustlevel = (os->trustlevel); ns.pad2 = (os->pad2); ns.pad3 = (os->pad3); VFS_WRITE(rankfile, &ns, sizeof(rankstats_t)); }
static void READ_PLAYERSTATS(int x, rankstats_t *os) { int i; size_t result; VFS_SEEK(rankfile, sizeof(rankfileheader_t)+sizeof(rankheader_t)+((x-1)*sizeof(rankinfo_t))); result = VFS_READ(rankfile, os, sizeof(rankstats_t)); if (result != sizeof(rankstats_t)) Con_Printf("READ_PLAYERSTATS() fread: expected %lu, result was %u\n",(long unsigned int)sizeof(rankstats_t),(unsigned int)result); os->kills = swaplong(os->kills); os->deaths = swaplong(os->deaths); for (i = 0; i < NUM_RANK_SPAWN_PARMS; i++) os->parm[i] = swapfloat(os->parm[i]); os->timeonserver = swapfloat(os->timeonserver); // os->flags1 = (os->flags1); // os->trustlevel = (os->trustlevel); // os->pad2 = (os->pad2); // os->pad3 = (os->pad3); }
/* basic opening of WAD file and creation of node in Wad linked list */ WadPtr BasicWadOpen( char *filename) { WadPtr curw, prevw; /* find the WAD file in the Wad file list */ prevw = WadFileList; if (prevw) { curw = prevw->next; while (curw && strcmp( filename, curw->filename)) { prevw = curw; curw = prevw->next; } } else curw = NULL; /* if this entry doesn't exist, add it to the WadFileList */ if (! curw) { curw = (WadPtr) GetMemory( sizeof( struct WadFileInfo)); if (! prevw) WadFileList = curw; else prevw->next = curw; curw->next = NULL; curw->filename = filename; } /* open the file */ if ((curw->fileinfo = fopen( filename, "rb")) == NULL) { if (! prevw) WadFileList = NULL; else prevw->next = curw->next; FreeMemory( curw); ProgError( "error opening \"%s\"", filename); } /* read in the WAD directory info */ BasicWadRead( curw, curw->type, 4); if (strncmp( curw->type, "IWAD", 4) && strncmp( curw->type, "PWAD", 4)) ProgError( "\"%s\" is not a valid WAD file", filename); BasicWadRead( curw, &curw->dirsize, sizeof( curw->dirsize)); swaplong( &(curw->dirsize)); BasicWadRead( curw, &curw->dirstart, sizeof( curw->dirstart)); swaplong( &(curw->dirstart)); /* read in the WAD directory itself */ curw->directory = (DirPtr) GetMemory( sizeof( struct Directory) * curw->dirsize); BasicWadSeek( curw, curw->dirstart); BasicWadRead( curw, curw->directory, sizeof( struct Directory) * curw->dirsize); #ifdef BIGEND { int i; for (i = 0; i < curw->dirsize; i++) { DirPtr d = &(curw->directory[ i]); swaplong( &(d->start)); swaplong( &(d->size)); } } #endif /* all done */ return curw; }
void decompile(wadfile_t *wf, int num) { char name[9]; unsigned char *sprite; short width; short height; short xoff; short yoff; short *p1; int *columns; unsigned char *post; int x; int y; int n; int i; name[0] = '\0'; strncat(name, wf->lp->lumps[num]->name, 8); /* get sprite lump */ if ((sprite = (unsigned char *)get_lump_by_num(wf, num)) == NULL) { fprintf(stderr, "can't find sprite lump %s\n", name); exit(1); } /* clear the pixel buffer */ memset(img_buf, 255, 320 * 200); /* get width, height and offsets from the lump header */ p1 = (short *) sprite; width = *p1++; swapint(&width); height = *p1++; swapint(&height); xoff = *p1++; swapint(&xoff); yoff = *p1++; swapint(&yoff); printf(" got sprite %s, width=%d, height=%d\n", name, width, height); /* copy picture data into pixel buffer */ columns = (int *) (sprite + 8); for (x = 0; x < width; x++) { swaplong(&columns); post = sprite + *columns++; y = (int) *post++; while (y != 255) { n = (int) *post++; post++; /* first byte unused */ for (i = 0; i < n; i++) { img_buf[(y+i) * width + x] = *post; post++; } post++; /* last byte unused */ y = (int) *post++; } } /* free sprite lump memory */ free(sprite); /* write image buffer into ppm file */ write_ppm(name, width, height); }
/* * list_wad - list the contents of one wad file */ static int list_wad(const char *file) { wadinfo_t wad_header; filelump_t lump; FILE *fp; int list_flats = 0; int i, j; int n, m; int toff; char name[9]; long old_off, tex_off, sav_off; /* try to open WAD file */ if ((fp = fopen(file, "rb")) == NULL) { err(file, "can't open (%s)", strerror (errno)); return 1; } /* read WAD file header */ if (fread((void *)&wad_header, sizeof(wadinfo_t), 1, fp) != 1) { err(file, "can't read WAD header"); return 1; } swaplong(&(wad_header.numlumps)); swaplong(&(wad_header.infotableofs)); /* is this a WAD file? */ if (strncmp(wad_header.identification, "IWAD", 4) && strncmp(wad_header.identification, "PWAD", 4)) { err(file, "not a WAD file"); return 1; } if (verbose) { printf("WAD type = %c%c%c%c\n", wad_header.identification[0], wad_header.identification[1], wad_header.identification[2], wad_header.identification[3]); printf("no. of lumps: %d\n", wad_header.numlumps); printf("directory offset: %d\n", wad_header.infotableofs); } /* now seek to the directory */ if (fseek(fp, (long)wad_header.infotableofs, SEEK_SET) == -1) { err(file, "can't seek to directory"); return 1; } /* now read the directory entries */ for (i = 0; i < wad_header.numlumps; i++) { if (fread((void *)&lump, sizeof(filelump_t), 1, fp) != 1) { err(file, "can't read lump directory entry"); return 1; } swaplong(&(lump.filepos)); swaplong(&(lump.size)); /* list contents of PNAMES lump? */ if (pflag) { if (strncmp(&lump.name[0], "PNAMES", 6)) { continue; } else { if (verbose) { printf("\nContents of PNAMES:\n"); } if (fseek(fp, (long)lump.filepos, SEEK_SET) == -1) { err(file, "can't seek to PNAMES"); return 1; } n = getlong(fp); memset(&name[0], 0, 9); for (i = 0; i < n; i++) { fread((void *)&name[0], 8, 1, fp); printf("%s\n", &name[0]); } break; } /* list contents of TEXTUREx lumps? */ } else if (tflag) { if (strncmp(&lump.name[0], "TEXTURE1", 8) && strncmp(&lump.name[0], "TEXTURE2", 8)) { continue; } else { old_off = ftell(fp); memset(&name[0], 0, 9); strncpy(&name[0], &lump.name[0], 8); if (verbose) { printf("\nContents of %s:\n", &name[0]); } if (fseek(fp, (long)lump.filepos, SEEK_SET) == -1) { err(file, "can't seek to %s", file, &name[0]); return 1; } tex_off = ftell(fp); n = getlong(fp); for (j = 0; j < n; j++) { toff = getlong(fp); sav_off = ftell(fp); if (fseek(fp, tex_off + toff, SEEK_SET) == -1) { err(file, "can't seek to texture"); return 1; } fread((void *)&name[0], 8, 1, fp); printf("%s", &name[0]); if (lstflag) { m = getshort(fp); /* always 0 */ m = getshort(fp); /* always 0 */ m = getshort(fp); /* width */ printf("\t%d", (int)m); m = getshort(fp); /* height */ printf("\t%d", (int)m); m = getshort(fp); /* always 0 */ m = getshort(fp); /* always 0 */ m = getshort(fp); /* number of patches */ printf("\t%d", (int)m); } putchar('\n'); fseek(fp, sav_off, SEEK_SET); } fseek(fp, old_off, SEEK_SET); } /* list flats between F_START and F_END? */ } else if (fflag) { if (!strncmp(&lump.name[0], "F_START", 7)) { list_flats = 1; continue; } else if (!strncmp(&lump.name[0], "F_END", 5)) { list_flats = 0; break; } else { if (list_flats && (lump.size > 0)) { print_name(&lump.name[0]); putchar('\n'); } } /* list contents of the whole WAD file */ } else { print_name(&lump.name[0]); if (lstflag || sflag) { if (kflag) { printf("\t%8d", (lump.size + 512) / 1024); } else if (Hflag) { printf("\t%08Xh", lump.size); } else { printf("\t%8d", lump.size); } } if (lstflag) { if (hflag) { printf("\t%08Xh", lump.filepos); } else { printf("\t%8d", lump.filepos); } } putchar('\n'); } } return 0; }
CPWad::CPWad (XString name) : file (name, O_RDWR | O_BINARY), currentmap(0) { if (file.IsOpen()) { // -=- read the pwad header -=- cout << "Opened '" << name << "'" << endl; cdebug.out << "Opened '" << name << "'" << endl; file.Read (&header, sizeof(PWAD_HEADER)); swaplong((int *)&(header.dir_offset)); swaplong((int *)&(header.dir_entries)); if (memcmp ("PWAD", header.signature, 4) != 0) { cout << "Not a PWAD!" << "\n"; cdebug.out << "Not a PWAD!" << "\n"; Fail (); return; } else { cdebug.out << "File size: " << file.Size() << endl; cdebug.out << "Directory Offset: " << header.dir_offset << endl; cdebug.out << "Directory Entries: " << header.dir_entries << endl; } // -=- read the directory -=- file.Seek (header.dir_offset); MemHandle dirbuff = file.Read ((size_t)(header.dir_entries * sizeof(DIR_ENTRY))); if (dirbuff.Size () != (header.dir_entries * sizeof(DIR_ENTRY))) { cout << "Error Reading PWAD Directory." << endl; cdebug.out << "Error Reading PWAD Directory." << endl; Fail (); } else { cout << "Building directory...." << flush; swap_lump_list((void *)dirbuff.Buffer(), header.dir_entries); // -=- go through each dir entry and add it to our internal dir -=- DIR_ENTRY *entry_ptr = (DIR_ENTRY *)dirbuff.Buffer(); for (int n = 0; n < header.dir_entries; n++) { AddEntry (entry_ptr[n]); } cout << "Done." << endl; // -=- print out directory used for debugging -=- CDirEntry *de; CDirEntry *sde; de = (CDirEntry *)directory.FirstItem (); while (de) { cdebug.out << de->GetKey() << " " << de->Size() << " bytes\t @" << de->Offset() << endl; sde = (CDirEntry *)de->subdir.FirstItem (); while (sde) { cdebug.out << " " << sde->GetKey() << " " << sde->Size() << " bytes\t @" << sde->Offset() << endl; sde = (CDirEntry *)sde->Next(); } de = (CDirEntry *)de->Next(); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- } } else { cout << "Cannot open '" << name << "'" << endl; cdebug.out << "Cannot open '" << name << "'" << endl; Fail (); } }
/** * @brief Copy the PLT of an ET_EXEC object for the ALTPLT technique. * and the GOT of an ET_EXEC object for the ALTGOT technique. * @param file Host file. * @param mod Always inject sections with size being a multiple of mod. * @return Success (0) or Error (-1). */ int elfsh_relink_plt(elfshobj_t *file, u_int mod) { elfshsect_t *got; elfshsect_t *plt; elfshsect_t *symtab; elfshsect_t *dynsym; elfshsect_t *prolog; elfshsect_t *extplt = NULL; elfshsect_t *altgot = NULL; /* shut the nice talkative */ elfshsect_t *enew = NULL; /* compiler also know as gcc */ elfsh_Shdr hdr; elfsh_Sym *sym; elfsh_Sym newsym; char buf[BUFSIZ]; u_int off; u_int entsz; int mode; eresi_Addr addr; char *prologdata; u_int sz; char *name; u_char ostype; eresi_Addr diff; u_int extplt_size; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Get PLT */ if (file->secthash[ELFSH_SECTION_ALTPLT] != NULL) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); plt = elfsh_get_plt(file, NULL); if (NULL == plt) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "PLT section not found", -1); entsz = elfsh_get_pltentsz(file); if (entsz < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to get PLT entry size", -1); /* Get GOT (recent ld call it .got.plt) */ got = elfsh_get_gotsct(file); if (NULL == got) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "GOT section not found", -1); /* Get symtabs */ if (NULL == elfsh_get_dynsymtab(file, NULL)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "DYNSYM not found", -1); if (NULL == elfsh_get_symtab(file, NULL)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "SYMTAB not found", -1); /* Some fingerprint */ ostype = elfsh_get_ostype(file); if (ostype == ELFSH_OS_ERROR) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid OS target", -1); /* Insert alternative .plt */ dynsym = file->secthash[ELFSH_SECTION_DYNSYM]; symtab = file->secthash[ELFSH_SECTION_SYMTAB]; /* FreeBSD and BeoS is incompatible with pre-interp injection */ /* Solaris needs self-mutating code for ALTPLT technique */ /* %gp offsets on ALPHA/MIPS requires data injection */ ELFSH_SELECT_INJECTION(file,NULL,mode); /* Map .alt.plt.prolog on ALPHA, or .alt.got.prolog on MIPS */ if (FILE_IS_MIPS(file) || FILE_IS_ALPHA64(file)) { if (FILE_IS_MIPS(file)) { name = ELFSH_SECTION_NAME_ALTGOTPROLOG; sz = 28; } else { name = ELFSH_SECTION_NAME_ALTPLTPROLOG; sz = 48; } prolog = elfsh_create_section(name); hdr = elfsh_create_shdr(0, SHT_PROGBITS, SHF_EXECINSTR | SHF_ALLOC, 0, 0, sz, 0, 0, 0, 0); XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, sz, -1); if (elfsh_insert_mapped_section(file, prolog, hdr, prologdata, mode, mod) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ".alt.{plt,got}.prolog insertion failed", -1); enew = elfsh_get_section_by_name(file, name, NULL, NULL, NULL); if (enew == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ".alt.{plt,got}.prolog insertion failed", -1); file->secthash[ELFSH_SECTION_ALTPLTPROLOG] = enew; } /* Map .alt.plt (or .pad.got on MIPS) On MIPS we use .pad.got in order to align .alt.got on a 0x1000 bound boundary. On ALPHA and SPARC, .alt.plt will be relocated instead of .plt */ sz = plt->shdr->sh_size; if (FILE_IS_MIPS(file)) { addr = enew->shdr->sh_addr + enew->shdr->sh_size; if ((addr - (got->shdr->sh_addr)) % 1024) sz = 1024 - ((addr - (got->shdr->sh_addr)) % 1024); XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, sz, -1); memset(prologdata, 0x00, sz); name = ELFSH_SECTION_NAME_PADGOT; } else { XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, sz, -1); memcpy(prologdata, elfsh_readmem(plt), sz); name = ELFSH_SECTION_NAME_ALTPLT; } enew = elfsh_create_section(name); hdr = elfsh_create_shdr(0, SHT_PROGBITS, SHF_EXECINSTR | SHF_ALLOC, 0, 0, sz, 0, 0, 0, 0); if (elfsh_insert_mapped_section(file, enew, hdr, prologdata, mode, mod) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ".alt.plt|.pad.got insertion failed", -1); enew = elfsh_get_section_by_name(file, name, NULL, NULL, NULL); if (enew == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ".alt.plt|.pad.got insertion failed", -1); file->secthash[ELFSH_SECTION_ALTPLT] = enew; /* Map .alt.got (all architectures except SPARC) */ /* On IA32, remap GOT with a doubled size for non-present symbol resolving */ if (FILE_IS_MIPS(file) || FILE_IS_ALPHA64(file) || FILE_IS_IA32(file)) { sz = (FILE_IS_MIPS(file) ? got->shdr->sh_size : FILE_IS_IA32(file) ? got->shdr->sh_size * 4 : plt->shdr->sh_size / elfsh_get_pltentsz(file) * sizeof(eresi_Addr)); altgot = elfsh_create_section(ELFSH_SECTION_NAME_ALTGOT); hdr = elfsh_create_shdr(0, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE, 0, 0, sz, 0, 0, 0, sizeof(eresi_Addr)); XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, sz, -1); memcpy(prologdata, elfsh_readmem(got), got->shdr->sh_size); if (elfsh_insert_mapped_section(file, altgot, hdr, prologdata, ELFSH_DATA_INJECTION, mod) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ".alt.got insertion failed", -1); altgot = elfsh_get_section_by_name(file, ELFSH_SECTION_NAME_ALTGOT, NULL, NULL, NULL); if (altgot == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ".alt.got insertion failed", -1); file->secthash[ELFSH_SECTION_ALTGOT] = altgot; altgot->curend = got->shdr->sh_size; memset(elfsh_readmem(altgot) + got->shdr->sh_size, 0x00, got->shdr->sh_size); altgot->shdr->sh_entsize = sizeof(eresi_Addr); } /* Insert EXTPLT in order to be able to resolve non present symbols */ if (FILE_IS_IA32(file)) { extplt_size = plt->shdr->sh_size * 2; extplt = elfsh_create_section(ELFSH_SECTION_NAME_EXTPLT); hdr = elfsh_create_shdr(0, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0, 0, extplt_size, 0, 0, 0, 0); XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, plt->shdr->sh_size, -1); memcpy(prologdata, elfsh_readmem(plt), plt->shdr->sh_size); if (elfsh_insert_mapped_section(file, extplt, hdr, prologdata, mode, mod) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ".ext.plt insertion failed", -1); extplt = elfsh_get_section_by_name(file, ELFSH_SECTION_NAME_EXTPLT, NULL, NULL, NULL); if (extplt == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ".ext.plt insertion failed", -1); file->secthash[ELFSH_SECTION_EXTPLT] = extplt; extplt->curend = elfsh_get_first_pltentsz(file); } /* Loop on .plt and inject 'old_symnam' symbols */ for (off = 0; off < plt->shdr->sh_size; off += entsz) { /* SPARC does not have ALTGOT */ if (FILE_IS_MIPS(file) || FILE_IS_ALPHA64(file) || FILE_IS_IA32(file)) diff = (uint32_t) altgot->shdr->sh_addr - got->shdr->sh_addr; else diff = 0; /* Special case for the first plt entry */ if (off == 0 && elfsh_altplt_firstent(enew, &off, symtab, file, extplt, plt, diff) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "ALTPLT on first entry failed", -1); else if (off == 0) continue; /* Get the existing symbol name for this plt entry ... */ sym = elfsh_get_sym_by_value(elfsh_readmem(dynsym), dynsym->shdr->sh_size / sizeof(elfsh_Sym), plt->shdr->sh_addr + off, NULL, ELFSH_EXACTSYM); /* New versions of ld do not fill the vaddr of dynamic symbols, do it ourself. Do not insert old symbol in emergency cases */ if (sym == NULL) { if ((sym = elfsh_restore_dynsym(file, plt, off, dynsym)) == NULL) continue; name = elfsh_get_dynsymbol_name(file, sym); /* __gmon_start__ should not be resolved if it was not already done by gcc */ if (name && !strcmp(name, "__gmon_start__")) sym->st_value = 0x0; } /* ... and we inject the 'old' occurence symbol pointing in .alt.plt (.plt on MIPS) */ if (!FILE_IS_MIPS(file)) addr = enew->shdr->sh_addr + off; else addr = plt->shdr->sh_addr + off; #if __BYTE_ORDER == __BIG_ENDIAN if (file->hdr->e_ident[EI_DATA] == ELFDATA2LSB) #elif __BYTE_ORDER == __LITTLE_ENDIAN if (file->hdr->e_ident[EI_DATA] == ELFDATA2MSB) #else #error Unexpected __BYTE_ORDER ! #endif addr = swaplong(addr); /* Injection */ name = elfsh_get_dynsymbol_name(file, sym); newsym = elfsh_create_symbol(addr, entsz, STT_FUNC, 0, 0, 0); snprintf(buf, BUFSIZ, "old_%s", name); if (elfsh_insert_symbol(symtab, &newsym, buf) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "old_* symbol injection failed", -1); #if __DEBUG_COPYPLT__ printf("[DEBUG_COPYPLT] Symbol at .plt + %u injected" " succesfully (%s) \n", off, buf); #endif /* On ALPHA, shift the relocation offset from .got to .alt.got to avoid hooks removing when calling back the original function. */ if (FILE_IS_ALPHA64(file) && elfsh_shift_alpha_relocs(file, name, altgot, off) < 0) continue; /* Reencode the PLT entry to use the alternative GOT */ /* This condition is for compatibility with other archs where EXTPLT is not yet supported. For those we do not enter the hook */ if (FILE_IS_IA32(file)) { diff = (eresi_Addr) altgot->shdr->sh_addr - got->shdr->sh_addr; elfsh_encodeplt(file, plt, diff, off); if (file->hdr->e_type == ET_DYN) elfsh_encodeplt(file, file->secthash[ELFSH_SECTION_ALTPLT], diff, off); diff = (eresi_Addr) altgot->shdr->sh_addr - got->shdr->sh_addr + got->shdr->sh_size; elfsh_encodeplt(file, extplt, diff, off); } } /* Activate ALTGOT */ if (elfsh_redirect_pltgot(file, altgot, got, plt, enew) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "PLTGOT redirection failed", -1); /* Activate EXTPLT */ if (elfsh_extplt_mirror_sections(file) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Section mirroring failed", -1); #if __DEBUG_COPYPLT__ printf("[DEBUG_COPYPLT] Section Mirrored Successfully ! \n"); #endif /* Everything is 0k4y */ if (elfsh_sync_sorted_symtab(symtab) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "symtab synchronisation failed", -1); if (elfsh_sync_sorted_symtab(dynsym) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "dynsym synchronisation failed", -1); elfsh_sync_sectnames(file); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Change endianess of .dynamic * @param newent * @return */ int elfsh_endianize_dynamic(elfshsect_t *newent) { elfsh_Dyn *dyn; u_int idx; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Sanity check */ if (!newent) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid NULL parameter", -1); #if __BYTE_ORDER == __LITTLE_ENDIAN if (newent->parent->hdr->e_ident[EI_DATA] == ELFDATA2MSB) { #elif __BYTE_ORDER == __BIG_ENDIAN if (newent->parent->hdr->e_ident[EI_DATA] == ELFDATA2LSB) { #else #error Unexpected __BYTE_ORDER ! #endif dyn = (elfsh_Dyn *) elfsh_readmem(newent); for (idx = 0; idx < newent->shdr->sh_size / sizeof(elfsh_Dyn); idx++) { dyn[idx].d_tag = swaplong(dyn[idx].d_tag); dyn[idx].d_un.d_val = swaplong(dyn[idx].d_un.d_val); } } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); } /** * Return a ptr on the dynamic section * @param file * @param num * @return */ elfsh_Dyn *elfsh_get_dynamic(elfshobj_t *file, u_int *num) { elfshsect_t *newent = NULL; /* to shut gcc up with -Wall */ int nbr; elfsh_Dyn *ret; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (file->secthash[ELFSH_SECTION_DYNAMIC] == NULL) { newent = elfsh_get_section_by_type(file, SHT_DYNAMIC, NULL, NULL, &nbr, 0); if (newent == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to get .dynamic by type", NULL); file->secthash[ELFSH_SECTION_DYNAMIC] = newent; } newent = file->secthash[ELFSH_SECTION_DYNAMIC]; nbr = file->secthash[ELFSH_SECTION_DYNAMIC]->shdr->sh_size / sizeof(elfsh_Dyn); if (num != NULL) *num = nbr; if (newent->data == NULL) { newent->data = elfsh_load_section(file, newent->shdr); if (newent->data == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to load .dynamic", NULL); elfsh_endianize_dynamic(newent); } ret = (elfsh_Dyn *) elfsh_readmem(newent); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, ret); }
/* * returns 0 on success, non-zero if not all textures were properly extracted. */ int decompile(listitem_t *wadlist, char *section, void *texture, void *pnames) { int rc = 0; int i, j; int patches_found; int *p1; char *p2; short *p3; int num_tex; int off_tex; short dummy; short width, height, num_pat; short xoff, yoff, pnum; char tname[9]; FILE *fp = NULL; char fn[50]; /* initialize */ memset(&tname[0], 0, sizeof tname); /* get number of textures in texture lump */ p1 = (int *) texture; num_tex = *p1; swaplong(&num_tex); printf(" found %d textures\n", num_tex); /* loop over all textures */ for (i = 0; i < num_tex; i++) { /* offset for texture in lump */ p1 = (int *) texture + i + 1; off_tex = *p1; swaplong(&off_tex); p2 = (char *) texture + off_tex; /* get name of texture */ strncpy(&tname[0], p2, 8); { int n; for (n = 0; n < sizeof tname; n++) tname[n] = toupper(((unsigned char *) tname)[n]); } if (wildcard != NULL && fnmatch(wildcard, tname, 0) != 0) continue; /* get texture composition */ p3 = (short *) (p2 + 8); dummy = *p3++; /* always 0 */ dummy = *p3++; /* always 0 */ width = *p3++; swapint(&width); height = *p3++; swapint(&height); dummy = *p3++; /* always 0 */ dummy = *p3++; /* always 0 */ num_pat = *p3++; swapint(&num_pat); printf(" decompiling texture %s, %d patches, %dx%d\n", &tname[0], num_pat, width, height); /* grow the texture buffer if necessary */ { unsigned long newsize = width * height; if ((size_t) newsize != newsize) { err("Texture too big, size_t overflow (%hd x %hd). Skipping.", width, height); rc = 1; continue; } if (newsize > img_buf_sz) { unsigned char *newbuf = realloc(img_buf, newsize); if (newbuf == NULL) { err("Texture too big, not enough memory (%d x %d). Skipping.", width, height); rc = 1; continue; } img_buf_sz = newsize; img_buf = newbuf; } } /* want text file too? */ if (tflag) { strcpy(&fn[0], "textures/"); if (preserve_case) strcat(&fn[0], &tname[0]); else strlcat(&fn[0], &tname[0]); strcat(&fn[0], ".wgc"); if ((fp = fopen(&fn[0], "w")) == NULL) { err("can't open %s for writing", &fn[0]); exit(1); } fprintf(fp, "%s_START\n", section); fprintf(fp, " %s %d %d %d\n", &tname[0], width, height, num_pat); } /* clear pixel buffer */ memset(img_buf, 255, img_buf_sz); /* loop over all patches for the texture */ patches_found = 0; for (j = 0; j < num_pat; j++) { const char *patchname = NULL; listitem_t *wad; xoff = *p3++; swapint(&xoff); yoff = *p3++; swapint(&yoff); if (yoff < 0) yoff = 0; pnum = *p3++; swapint(&pnum); dummy = *p3++; /* always 1, stepdir? what is that?? */ dummy = *p3++; /* always 0 for colormap 0 */ for (wad = wadlist; wad != NULL; wad = wad->next) { if (get_patch(wad->wf, fp, pnames, width, height, xoff, yoff, pnum, &patchname) == 0) { patches_found++; break; } } if (wad == NULL) printf(" Warning: patch \"%.8s\" is missing\n", patchname); } if (patches_found == 0 && mpatch_policy != OIT_ALWAYS) { printf(" Warning: skipping void texture \"%s\".\n", tname); rc = 1; } else if (patches_found < num_pat && mpatch_policy == OIT_IF_ALL) { printf(" Warning: skipping incomplete texture \"%s\".\n", tname); rc = 1; } else if (extract) write_ppm(&tname[0], width, height); /* terminate and close the text file too */ if (tflag) { fprintf(fp, "%s_END\n", section); if (fclose(fp)) { err("%s: %s", fn, strerror(errno)); exit(1); } } } return rc; }
int get_patch(wadfile_t *wf, FILE *fp, void *pnames, short width, short height, short xoff, short yoff, short pnum, const char **patchname) { int i; int x, y; int n; int *p1; char *p2; int p_num; char name[9]; unsigned char *picture; short pwidth; int *columns; unsigned char *post; /* initialization */ memset(&name[0], 0, 9); /* number of patches in PNAMES */ p1 = (int *) pnames; p_num = *p1++; swaplong(&p_num); if (pnum > p_num) { err("texture uses patch %d, but PNAMES has %d patches only", pnum, p_num); exit(1); } /* lookup name for that patch */ p2 = ((char *) p1) + 8 * pnum; *patchname = (const char *) p2; strncpy(&name[0], p2, 8); for (i = 0; i < 8; i++) { name[i] = toupper(name[i]); } /* and get that picture lump */ if ((picture=(unsigned char *)get_lump_by_name(wf, &name[0])) == NULL) { return 1; } /* copy picture data into pixel buffer */ pwidth = *((short *) picture); swapint(&pwidth); printf(" Got patch %s, width %d, x=%d y=%d\n", &name[0], pwidth, xoff, yoff); columns = (int *) (picture + 8); for (x = 0; x < pwidth; x++) { swaplong(columns); post = picture + *columns++; y = (int) *post++; while (y != 255) { n = (int) *post++; post++; /* first byte unused */ for (i = 0; i < n; i++) { if ((y+yoff+i >= 0) && (x+xoff >= 0) && (y+yoff+i < height) && (x+xoff < width)) img_buf[(y+yoff+i) * width + (x+xoff)] = *post; post++; } post++; /* last byte unused */ y = (int) *post++; } } /* text file too? */ if (tflag) { fprintf(fp, " %s %d %d\n", &name[0], xoff, yoff); } /* free picture lump memory */ free(picture); return 0; }