void slirp_init(int restricted, const char *special_ip) { #if DEBUG int slirp_logmask = 0; char slirp_logfile[512]; { const char* env = getenv( "ANDROID_SLIRP_LOGMASK" ); if (env != NULL) slirp_logmask = atoi(env); else if (VERBOSE_CHECK(slirp)) slirp_logmask = DEBUG_DEFAULT; } { char* p = slirp_logfile; char* end = p + sizeof(slirp_logfile); p = bufprint_temp_file( p, end, "slirp.log" ); if (p >= end) { dprint( "cannot create slirp log file in temporary directory" ); slirp_logmask = 0; } } if (slirp_logmask) { dprint( "sending slirp logs with mask %x to %s", slirp_logmask, slirp_logfile ); debug_init( slirp_logfile, slirp_logmask ); } #endif link_up = 1; slirp_restrict = restricted; if_init(); ip_init(); m_init(); inet_strtoip("127.0.0.1", &loopback_addr_ip); if (dns_addr_count == 0) { if (slirp_get_system_dns_servers() < 0) { dns_addr[0] = loopback_addr_ip; dns_addr_count = 1; fprintf (stderr, "Warning: No DNS servers found\n"); } } inet_strtoip(CTL_SPECIAL, &special_addr_ip); alias_addr_ip = special_addr_ip | CTL_ALIAS; getouraddr(); register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL); slirp_net_forward_init(); }
void user_event_key(unsigned code, unsigned down) { if(code == 0) { return; } if (VERBOSE_CHECK(keys)) printf(">> KEY [0x%03x,%s]\n", (code & 0x1ff), down ? "down" : " up " ); user_event_keycode((code & 0x1ff) | (down ? 0x200 : 0)); }
void android_keycodes_flush(AKeycodeBuffer* keycodes) { if (keycodes->keycode_count > 0) { if (VERBOSE_CHECK(keys)) { int nn; printf(">> KEY" ); for (nn = 0; nn < keycodes->keycode_count; nn++) { int code = keycodes->keycodes[nn]; printf(" [0x%03x,%s]", (code & 0x1ff), (code & 0x200) ? "down" : " up " ); } printf( "\n" ); } user_event_keycodes(keycodes->keycodes, keycodes->keycode_count); keycodes->keycode_count = 0; } }
void nand_add_dev(const char *arg) { uint64_t dev_size = 0; const char *next_arg; const char *value; size_t arg_len, value_len; nand_dev *new_devs, *dev; char *devname = NULL; size_t devname_len = 0; char *initfilename = NULL; char *rwfilename = NULL; int initfd = -1; int rwfd = -1; int read_only = 0; int pad; ssize_t read_size; uint32_t page_size = 2048; uint32_t extra_size = 64; uint32_t erase_pages = 64; VERBOSE_PRINT(init, "%s: %s", __FUNCTION__, arg); while(arg) { next_arg = strchr(arg, ','); value = strchr(arg, '='); if(next_arg != NULL) { arg_len = next_arg - arg; next_arg++; if(value >= next_arg) value = NULL; } else arg_len = strlen(arg); if(value != NULL) { size_t new_arg_len = value - arg; value_len = arg_len - new_arg_len - 1; arg_len = new_arg_len; value++; } else value_len = 0; if(devname == NULL) { if(value != NULL) goto bad_arg_and_value; devname_len = arg_len; devname = malloc(arg_len+1); if(devname == NULL) goto out_of_memory; memcpy(devname, arg, arg_len); devname[arg_len] = 0; } else if(value == NULL) { if(arg_match("readonly", arg, arg_len)) { read_only = 1; } else { XLOG("bad arg: %.*s\n", arg_len, arg); exit(1); } } else { if(arg_match("size", arg, arg_len)) { char *ep; dev_size = strtoull(value, &ep, 0); if(ep != value + value_len) goto bad_arg_and_value; } else if(arg_match("pagesize", arg, arg_len)) { char *ep; page_size = strtoul(value, &ep, 0); if(ep != value + value_len) goto bad_arg_and_value; } else if(arg_match("extrasize", arg, arg_len)) { char *ep; extra_size = strtoul(value, &ep, 0); if(ep != value + value_len) goto bad_arg_and_value; } else if(arg_match("erasepages", arg, arg_len)) { char *ep; erase_pages = strtoul(value, &ep, 0); if(ep != value + value_len) goto bad_arg_and_value; } else if(arg_match("initfile", arg, arg_len)) { initfilename = malloc(value_len + 1); if(initfilename == NULL) goto out_of_memory; memcpy(initfilename, value, value_len); initfilename[value_len] = '\0'; } else if(arg_match("file", arg, arg_len)) { rwfilename = malloc(value_len + 1); if(rwfilename == NULL) goto out_of_memory; memcpy(rwfilename, value, value_len); rwfilename[value_len] = '\0'; } else { goto bad_arg_and_value; } } arg = next_arg; } if (rwfilename == NULL) { /* we create a temporary file to store everything */ TempFile* tmp = tempfile_create(); if (tmp == NULL) { XLOG("could not create temp file for %.*s NAND disk image: %s\n", devname_len, devname, strerror(errno)); exit(1); } rwfilename = (char*) tempfile_path(tmp); if (VERBOSE_CHECK(init)) dprint( "mapping '%.*s' NAND image to %s", devname_len, devname, rwfilename); } if(rwfilename) { if (initfilename) { /* Overwrite with content of the 'initfilename'. */ if (read_only) { /* Cannot be readonly when initializing the device from another file. */ XLOG("incompatible read only option is requested while initializing %.*s from %s\n", devname_len, devname, initfilename); exit(1); } rwfd = open(rwfilename, O_BINARY | O_TRUNC | O_RDWR); } else { rwfd = open(rwfilename, O_BINARY | (read_only ? O_RDONLY : O_RDWR)); } if(rwfd < 0) { XLOG("could not open file %s, %s\n", rwfilename, strerror(errno)); exit(1); } /* this could be a writable temporary file. use atexit_close_fd to ensure * that it is properly cleaned up at exit on Win32 */ if (!read_only) atexit_close_fd(rwfd); } if(initfilename) { initfd = open(initfilename, O_BINARY | O_RDONLY); if(initfd < 0) { XLOG("could not open file %s, %s\n", initfilename, strerror(errno)); exit(1); } if(dev_size == 0) { dev_size = do_lseek(initfd, 0, SEEK_END); do_lseek(initfd, 0, SEEK_SET); } } new_devs = realloc(nand_devs, sizeof(nand_devs[0]) * (nand_dev_count + 1)); if(new_devs == NULL) goto out_of_memory; nand_devs = new_devs; dev = &new_devs[nand_dev_count]; dev->page_size = page_size; dev->extra_size = extra_size; dev->erase_size = erase_pages * (page_size + extra_size); pad = dev_size % dev->erase_size; if (pad != 0) { dev_size += (dev->erase_size - pad); D("rounding devsize up to a full eraseunit, now %llx\n", dev_size); } dev->devname = devname; dev->devname_len = devname_len; dev->max_size = dev_size; dev->data = malloc(dev->erase_size); if(dev->data == NULL) goto out_of_memory; dev->flags = read_only ? NAND_DEV_FLAG_READ_ONLY : 0; #ifdef TARGET_I386 dev->flags |= NAND_DEV_FLAG_BATCH_CAP; #endif if (initfd >= 0) { do { read_size = do_read(initfd, dev->data, dev->erase_size); if(read_size < 0) { XLOG("could not read file %s, %s\n", initfilename, strerror(errno)); exit(1); } if(do_write(rwfd, dev->data, read_size) != read_size) { XLOG("could not write file %s, %s\n", rwfilename, strerror(errno)); exit(1); } } while(read_size == dev->erase_size); close(initfd); } dev->fd = rwfd; nand_dev_count++; return; out_of_memory: XLOG("out of memory\n"); exit(1); bad_arg_and_value: XLOG("bad arg: %.*s=%.*s\n", arg_len, arg, value_len, value); exit(1); }
void memcheck_guest_alloc(target_ulong guest_address) { MallocDescEx desc; MallocDescEx replaced; RBTMapResult insert_res; ProcDesc* proc; ThreadDesc* thread; uint32_t indx; // Copy allocation descriptor from guest to emulator. memcheck_get_malloc_descriptor(&desc.malloc_desc, guest_address); desc.flags = 0; desc.call_stack = NULL; desc.call_stack_count = 0; proc = get_process_from_pid(desc.malloc_desc.allocator_pid); if (proc == NULL) { ME("memcheck: Unable to obtain process for allocation pid=%u", desc.malloc_desc.allocator_pid); memcheck_fail_alloc(guest_address); return; } if (!procdesc_is_executing(proc)) { desc.flags |= MDESC_FLAG_TRANSITION_ENTRY; } /* Copy thread's calling stack to the allocation descriptor. */ thread = get_current_thread(); desc.call_stack_count = thread->call_stack_count; if (desc.call_stack_count) { desc.call_stack = g_malloc(desc.call_stack_count * sizeof(target_ulong)); if (desc.call_stack == NULL) { ME("memcheck: Unable to allocate %u bytes for the calling stack", desc.call_stack_count * sizeof(target_ulong)); return; } } /* Thread's calling stack is in descending order (i.e. first entry in the * thread's stack is the most distant routine from the current one). On the * other hand, we keep calling stack entries in allocation descriptor in * assending order. */ for (indx = 0; indx < thread->call_stack_count; indx++) { desc.call_stack[indx] = thread->call_stack[thread->call_stack_count - 1 - indx].call_address; } // Save malloc descriptor in the map. insert_res = procdesc_add_malloc(proc, &desc, &replaced); if (insert_res == RBT_MAP_RESULT_ENTRY_INSERTED) { // Invalidate TLB cache for the allocated block. if (memcheck_instrument_mmu) { invalidate_tlb_cache(desc.malloc_desc.ptr, mallocdesc_get_alloc_end(&desc.malloc_desc)); } } else if (insert_res == RBT_MAP_RESULT_ENTRY_REPLACED) { /* We don't expect to have another entry in the map that matches * inserting entry. This is an error condition for us, indicating * that we somehow lost track of memory allocations. */ ME("memcheck: Duplicate allocation blocks:"); if (VERBOSE_CHECK(memcheck)) { printf(" New block:\n"); memcheck_dump_malloc_desc(&desc, 1, 1); printf(" Replaced block:\n"); memcheck_dump_malloc_desc(&replaced, 1, 1); } if (replaced.call_stack != NULL) { g_free(replaced.call_stack); } } else { ME("memcheck: Unable to insert an entry to the allocation map:"); if (VERBOSE_CHECK(memcheck)) { memcheck_dump_malloc_desc(&desc, 1, 1); } memcheck_fail_alloc(guest_address); return; } }
extern SkinSurface* skin_surface_create_window(int x, int y, int w, int h, int original_w, int original_h, int is_fullscreen) { static SkinSurface* result = NULL; SDL_Window* window = skin_winsys_get_window(); SDL_Renderer* renderer = globals_get_renderer(); D("%s: x=%d y=%d w=%d h=%d original_w=%d original_h=%d is_fullscreen=%d", __FUNCTION__, x, y, w, h, original_w, original_h, is_fullscreen); // Textures do not survive window resize events, so globals_foreach_surface(&_skin_surface_destroy_texture, NULL); if (!window) { // NOTE: Don't use SDL_WINDOW_ALLOW_HIGHDPI here. On OS X, this will // make mouse event coordinates twice smaller than needed // when running on a high-dpi machine (e.g. recent MacBook Pro), // making the UI unusable. Note that this doesn't happen on a // 'low-dpi' device such as a MacPro connected to a 30" monitor. int window_flags = SDL_WINDOW_OPENGL; if (is_fullscreen) { window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } window = SDL_CreateWindow("Android emulator", x, y, w, h, window_flags); if (!window) { panic("Could not create SDL2 window: %s\n", SDL_GetError()); } skin_winsys_set_window(window); } else { if (is_fullscreen) { SDL_CHECK(SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP)); #if DEBUG #endif } else { SDL_CHECK(SDL_SetWindowFullscreen(window, 0)); SDL_SetWindowPosition(window, x, y); SDL_SetWindowSize(window, w, h); } } // Generate renderer if (!renderer) { SDL_CHECK(SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear")); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED| SDL_RENDERER_PRESENTVSYNC| SDL_RENDERER_TARGETTEXTURE); if (!renderer) { panic("Could not create renderer: %s\n", SDL_GetError()); } globals_set_renderer(renderer); } SDL_CHECK(SDL_RenderSetLogicalSize(renderer, original_w, original_h)); if (DEBUG && VERBOSE_CHECK(surface)) { SDL_RendererInfo info; SDL_CHECK(SDL_GetRendererInfo(renderer, &info)); printf("renderer.name = %s\n", info.name); printf("renderer.flags = 0x%x\n", info.flags); printf("renderer.num_texture_formats = %d\n", info.num_texture_formats); int nn; for (nn = 0; nn < info.num_texture_formats; ++nn) { printf(" 0x%x (%s)\n", info.texture_formats[nn], SDL_GetPixelFormatName(info.texture_formats[nn])); } printf("renderer.max_texture_width = %d\n", info.max_texture_width); printf("renderer.max_texture_height = %d\n", info.max_texture_height); } // Compute scaling parameters. { int window_x, window_y, window_w, window_h; SDL_GetWindowSize(window, &window_w, &window_h); SDL_GetWindowPosition(window, &window_x, &window_y); D("Window pos=(%d,%d) size=(%d,%d)", window_x, window_y, window_w, window_h); double x_scale = window_w * 1.0 / original_w; double y_scale = window_h * 1.0 / original_h; double scale = (x_scale <= y_scale) ? x_scale : y_scale; double effective_x = 0.; double effective_y = 0.; if (is_fullscreen) { effective_x = (window_w - original_w * scale) * 0.5; effective_y = (window_h - original_h * scale) * 0.5; } globals_set_window_scale(scale, effective_x, effective_y); } SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, original_w, original_h); if (!texture) { panic("Could not create window texture: %s", SDL_GetError()); } SDL_CHECK(SDL_SetRenderTarget(renderer, texture)); SDL_CHECK(SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255)); SDL_CHECK(SDL_RenderClear(renderer)); SDL_CHECK(SDL_SetRenderTarget(renderer, NULL)); SDL_CHECK(SDL_SetRenderDrawColor(renderer, 0, 0, 128, 255)); SDL_CHECK(SDL_RenderClear(renderer)); SDL_CHECK(SDL_RenderCopy(renderer, texture, NULL, NULL)); SDL_RenderPresent(renderer); if (!result) { result = _skin_surface_create(NULL, texture, original_w, original_h); } else { result->texture = texture; result->w = original_w; result->h = original_h; } skin_surface_ref(result); // Ensure all textures are regenerated properly. globals_foreach_surface(&_skin_surface_reset_texture, renderer); return result; }