📄 dyn_arm_emul.cpp
字号:
sprintf(filename, "%s/libXcompiled_%u.so", cache_dir, ind); sprintf(funname, "compiled_%u", ind); if (showmsg) fprintf(stderr, "Loading %d for address %x.\n", ind, pblk << shiftval); /* not sure if the many libc functions below are thread-safe. * to save the trouble, use the big lock, many compilation * threads can call load_lib, so need to safe guard */ pthread_mutex_lock(&srv_mut); /* in the parallel version, load_lib is called by comm. threads, * need to guard with mutex since the main thread may call unload_lib * at the same time * if the program is not yet running, then it must be setting up cache */ if (blk_info[pblk].count != -1u && status != ST_RESET) { pthread_mutex_unlock(&srv_mut); return false; } /* check if it is already loaded */ map<unsigned, dll_info_t *>::iterator mit = DLL_INFO2->find(ind); if (mit != DLL_INFO2->end()) { (*mit).second->rcount++; blk_info[pblk].dll_fptr = (*mit).second->dll_fptr; blk_info[pblk].count = 0; pthread_mutex_unlock(&srv_mut); return true; } void *handle = dlopen(filename, RTLD_LAZY); if (!handle) { fputs(dlerror(), stderr); pthread_mutex_unlock(&srv_mut); return false; } fptr_t fptr = (fptr_t)dlsym(handle, funname); if ((error = dlerror())!= NULL) { fputs(error, stderr); pthread_mutex_unlock(&srv_mut); return false; } dll_info_t *ndll = (dll_info_t *)malloc(sizeof(dll_info_t)); if (ndll==NULL) { fputs("Out of memory\n", stderr); exit(1); } ndll->rcount = 1; ndll->handle = handle; ndll->index = ind; ndll->dll_fptr = fptr; DLL_INFO->insert(pair<fptr_t, dll_info_t *>(fptr, ndll)); DLL_INFO2->insert(pair<unsigned, dll_info_t *>(ind, ndll)); blk_info[pblk].dll_fptr = fptr; /* clear the count so whatever happens, it can still be interpreted */ blk_info[pblk].count = 0; pthread_mutex_unlock(&srv_mut); return true;}bool dyn_arm_emulator::unload_lib(unsigned pblk){ /* clear the block */ pthread_mutex_lock(&srv_mut); /* the block is still in compilation */ if (blk_info[pblk].count == -1u) { blk_info[pblk].count = 0; pthread_mutex_unlock(&srv_mut); return true; } map<fptr_t, dll_info_t *>::iterator mit = DLL_INFO->find(blk_info[pblk].dll_fptr); assert(mit != (DLL_INFO->end())); /* decrement the reference count */ if (--((*mit).second->rcount) == 0) { dlclose((*mit).second->handle); DLL_INFO2->erase((*mit).second->index); free((*mit).second); DLL_INFO->erase(mit); } blk_info[pblk].dll_fptr = NULL; blk_info[pblk].count = 0; pthread_mutex_unlock(&srv_mut); return true;}/************************************************************************ convenient routines for socket communication************************************************************************//* send nbytes to socket */static ssize_t sendall(int fd, const void *buf, size_t nbyte){ ssize_t nwrite = 0, n; do { if ((n = send(fd, (const char *)buf + nwrite, nbyte - nwrite, 0)) == (ssize_t)-1) { if (errno == EINTR) continue; else return -1; } nwrite += n; } while (nwrite < (ssize_t)nbyte); return nwrite;}/* receive up to nbytes from socket */static ssize_t recvall(int fd, void *buf, size_t nbyte){ ssize_t nread = 0, n; do { if ((n = recv(fd, (char *)buf + nread, nbyte - nread, 0)) == (ssize_t)-1) { if (errno == EINTR) continue; else return -1; } if (n == 0) return nread; nread += n; } while (nread < (ssize_t)nbyte); return nread;}void dyn_arm_emulator::com_thread(){ int my_index = SIMIT_MAX_SERVER; unsigned bufsize = 1 << shiftval; byte_t *buf = (byte_t *)malloc(bufsize); if (buf == NULL) { fprintf(stderr, "Error: Insufficient memory, thread terminates\n"); return; } pthread_mutex_lock(&srv_mut); /* find one spot that is not in use */ for (int ii=0; ii<SIMIT_MAX_SERVER; ii++) { if (srv_dir[ii].buf == NULL) { my_index = ii; srv_dir[ii].buf = buf; /* don't increment srv_count yet since connection may fail */ break; } } pthread_mutex_unlock(&srv_mut); /* too many threads, silently quit */ if (my_index == SIMIT_MAX_SERVER) return; struct sockaddr_in address; int my_socket; if ((my_socket = socket(AF_INET,SOCK_STREAM,0))>0) if (showmsg) fprintf(stderr, "The socket was created %d\n",my_socket); address.sin_family= AF_INET; address.sin_port = htons(srv_dir[my_index].portno); inet_pton(AF_INET, srv_dir[my_index].ipaddr, &address.sin_addr); if (showmsg) fprintf(stderr, "Trying to connect with server %s:%d...\n", srv_dir[my_index].ipaddr, srv_dir[my_index].portno); if (connect(my_socket, (struct sockaddr*)&address, sizeof(address))==0) { if (showmsg) fprintf(stderr, "Connection was accepted by server %s:%d.\n", srv_dir[my_index].ipaddr, srv_dir[my_index].portno); } else { fprintf(stderr, "Connection was rejected by server %s:%d.\n", srv_dir[my_index].ipaddr, srv_dir[my_index].portno); pthread_exit(NULL); } srv_dir[my_index].socket = my_socket; pthread_mutex_lock(&srv_mut); srv_count++; pthread_mutex_unlock(&srv_mut); while (true) { unsigned ind; // DLL number unsigned pblk; // physical address index get_block_to_compile(&ind, &pblk); // simulation has finished? if (com_done) break; if (showmsg) fprintf(stderr,"start to compile ...\n"); mem->read_block(buf, pblk << shiftval, bufsize); unsigned crc; unsigned dres = lookup_dict(buf, &crc); if (dres != -1u) { load_lib(pblk, dres); continue; } if (showmsg) fprintf(stderr, "sending the bufsize %d...\n", bufsize); /* unrecoverable connection error */ if (sendall(my_socket, &bufsize, sizeof(bufsize)) < 0) break; if (showmsg) fprintf(stderr, "sending the dll_ind %d...\n", ind); if (sendall(my_socket, &ind, sizeof(ind)) < 0) break; if (showmsg) fprintf(stderr, "sending the user_level %d...\n", user_level); if (sendall(my_socket, &user_level, sizeof(user_level)) < 0) break; if (showmsg) fprintf(stderr, "sending block of size %d...\n", bufsize); if (sendall(my_socket, buf, bufsize) < 0) break; int objsize, islinked; if (recvall(my_socket, &objsize, sizeof(int)) < 0) break; if (recvall(my_socket, &islinked, sizeof(int)) < 0) break; /* 0 means error, but still connected */ if (objsize == 0) { if (showmsg) fprintf(stderr, "server error encountered...\n"); continue; } srv_dir[my_index].count++; char pkt[1024]; char fname[1024]; if (islinked) sprintf(fname, "%s/libXcompiled_%u.so", cache_dir, ind); else sprintf(fname, "%s/Xcompiled_%u.o", cache_dir, ind); FILE* fp = fopen(fname, "w"); int rem = objsize, recd = 1; while (recd > 0 && rem > 0) { recd = recvall(my_socket, pkt, rem<1024?rem:1024); if (recd > 0) { fwrite(pkt, 1, recd, fp); rem -= recd; } } fclose(fp); if (recd < 0) break; if (showmsg) fprintf(stderr,"%d Compiled code received of size %d\n", my_index, objsize); sprintf(fname, "%s/Xcompiled_%u.dat", cache_dir, ind); fp = fopen(fname, "wb"); fwrite(buf, 1, 1 << shiftval, fp); fclose(fp); /* if code is not linked, link it */ if (islinked || ld_lib(ind)) { pthread_mutex_lock(&srv_mut); update_dll_dict(ind, crc); pthread_mutex_unlock(&srv_mut); if (!com_done && load_lib(pblk, ind)) { if (showmsg) fprintf(stderr, "File successfully loaded...\n"); } } } if (!com_done) { srv_count--; if (showmsg) fprintf(stderr, "Connection reset, thread %d exits.\n", my_index); } pthread_exit(NULL);}/* com_thread2 are local threads, we don't cancel, but join them on exit*/void dyn_arm_emulator::com_thread2(){ int my_index = SIMIT_MAX_SERVER; unsigned bufsize = 1 << shiftval; byte_t *buf = (byte_t *)malloc(bufsize); if (buf == NULL) { fprintf(stderr, "Error: Insufficient memory, thread terminates\n"); return; } pthread_mutex_lock(&srv_mut); /* find one spot that is not in use */ for (int ii=0; ii<SIMIT_MAX_SERVER; ii++) { /* donot use entries reserved for remote server */ if (srv_dir[ii].buf == NULL && srv_dir[ii].ipaddr[0] == 0) { my_index = ii; srv_dir[ii].buf = buf; srv_count++; break; } } pthread_mutex_unlock(&srv_mut); /* too many threads, silently quit */ if (my_index == SIMIT_MAX_SERVER) return; while (true) { unsigned ind; // DLL number unsigned pblk; // physical address index get_block_to_compile(&ind, &pblk); if (com_done) pthread_exit(NULL); if (showmsg) fprintf(stderr,"start to compile ...\n"); mem->read_block(buf, pblk << shiftval, bufsize); unsigned crc; unsigned dres = lookup_dict(buf, &crc); if (dres != -1u) { load_lib(pblk, dres); } else if (compile_block(buf, ind)) { srv_dir[my_index].count++; pthread_mutex_lock(&srv_mut); update_dll_dict(ind, crc); pthread_mutex_unlock(&srv_mut); if (!com_done && load_lib(pblk, ind)) { if (showmsg) fprintf(stderr, "File successfully loaded...\n"); } } }}void dyn_arm_emulator::com_cleanup(){ for (int ii=0; ii<SIMIT_MAX_SERVER; ii++) { if (srv_dir[ii].buf) { free(srv_dir[ii].buf); srv_dir[ii].buf = NULL; } }}/* this function reads the config file and populates the server database*/int dyn_arm_emulator::read_servers(const char* fname){ char buf1[64]; int ii = 0; if (fname==NULL) return 0; FILE* fp = fopen(fname,"r"); if (!fp) { fprintf(stderr, "Could not open config file %s\n", fname); return 0; } // donot use scanf %s since it is not safe while (fgets(buf1, 64, fp)!=NULL) { char *ptr; if ((ptr = strtok(buf1, "\n\t "))==NULL) return ii; strncpy(srv_dir[ii].ipaddr, ptr, 63); if ((ptr = strtok(NULL, "\n\t "))==NULL) return ii; srv_dir[ii].portno = atoi(ptr); /* read as many as I can remember. */ if (++ii==SIMIT_MAX_SERVER) break; } fclose(fp); return ii;}#include "read_elf.h"bool dyn_arm_emulator::setup_cache(const char *filename){ Elf32_Ehdr *hdr; Elf32_Phdr *phdr; Elf32_Shdr *shdr; char *string_table; Elf32_Shdr *shdr_new_section; Elf32_Word new_section_size, new_section_type, new_section_flags; Elf32_Addr new_section_addr; FILE *fobj; int i; if (!read_or_create_dll_dict()) return false; if (filename == NULL) return true; fobj = fopen(filename, "rb"); if(fobj == NULL) { fprintf(stderr, "Can't open executable: %s\n", filename); exit(1); } hdr = ReadElfHeader(fobj); if(hdr == NULL) { fprintf(stderr, "Could not read ELF32 header from file: %s.\n", filename); exit(1); }#ifndef EM_ARM#define EM_ARM 40#endif /* check if the file is for ARM */ if (hdr->e_type != ET_EXEC || hdr->e_machine != EM_ARM || hdr->e_ident[EI_DATA] != ELFDATA2LSB) { fprintf(stderr, "File is not ARM LSB executable: %s.\n", filename); exit(1); } phdr = ReadProgramHeaders(hdr, fobj); for(i=0; i<hdr->e_phnum; i++) { if ( (phdr[i].p_type == PT_LOAD) /* Loadable Program Segment */ && ((phdr->p_flags & PF_X) != 0 /* not text segment => data segment */)) { data_base = phdr[i].p_vaddr; data_size = phdr[i].p_memsz; } } prog_base = hdr->e_entry; shdr = ReadSectionHeaders(hdr, fobj); if(shdr == NULL) { fprintf(stderr, "Can't read section headers from executable\n"); exit(1); } string_table = LoadStringTable(hdr, shdr, fobj); for(i = 0; i < hdr->e_shnum; i++) { shdr_new_section = &shdr[i]; new_section_type = GetSectionType(shdr_new_section); new_section_flags = GetSectionFlags(shdr_new_section); if ((new_section_type == SHT_PROGBITS) && (new_section_flags & (SHF_EXECINSTR | SHF_ALLOC))) { new_section_size = shdr_new_section ? GetSectionSize(shdr_new_section) : 0; new_section_addr = GetSectionAddr(shdr_new_section); arm_addr_t new_section_end = new_section_addr + new_section_size; while (new_section_addr < new_section_end) { /* align memory address */ arm_addr_t fstart = (new_section_addr >> shiftval) << shiftval; mem->read_block(temp_buf1, fstart, 1 << shiftval); /* if not loaded yet */ if (blk_info[fstart >> shiftval].dll_fptr == NULL) { unsigned dres = lookup_dict(temp_buf1); if (dres != -1u) { req_num++; load_lib(fstart >> shiftval, dres); } } new_section_addr = fstart + (1 << shiftval); } } } free(string_table); free(phdr); free(shdr); free(hdr); fclose(fobj); return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -