usermode/library/mcore/src/module.c

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2011 Computer Sciences Department, 
00003     University of Wisconsin -- Madison
00004 
00005     ----------------------------------------------------------------------
00006 
00007     This file is part of Mnemosyne: Lightweight Persistent Memory, 
00008     originally developed at the University of Wisconsin -- Madison.
00009 
00010     Mnemosyne was originally developed primarily by Haris Volos
00011     with contributions from Andres Jaan Tack.
00012 
00013     ----------------------------------------------------------------------
00014 
00015     Mnemosyne is free software; you can redistribute it and/or
00016     modify it under the terms of the GNU General Public License
00017     as published by the Free Software Foundation, version 2
00018     of the License.
00019  
00020     Mnemosyne is distributed in the hope that it will be useful,
00021     but WITHOUT ANY WARRANTY; without even the implied warranty of
00022     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023     GNU General Public License for more details.
00024 
00025     You should have received a copy of the GNU General Public License
00026     along with this program; if not, write to the Free Software
00027     Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00028     Boston, MA  02110-1301, USA.
00029 
00030 ### END HEADER ###
00031 */
00032 
00039 #include <err.h>
00040 #include <fcntl.h>
00041 #include <gelf.h>
00042 #include <stdint.h>
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <sysexits.h>
00047 #include <sys/stat.h>
00048 #include <sys/types.h>
00049 #include <sys/mman.h>
00050 #include <unistd.h>
00051 #include "module.h"
00052 #include "files.h"
00053 #include "list.h"
00054 #include "debug.h"
00055 
00056 static m_result_t persistent_shdr_open(char *module_path, uint64_t module_inode, uintptr_t module_start, module_dsr_t *module_dsr);
00057 
00058 struct list_head module_dsr_list;
00059 
00067 void
00068 m_module_relocate_symbols(uintptr_t got_start,
00069                           uintptr_t got_end,
00070                           uintptr_t old_start, 
00071                           uintptr_t old_end, 
00072                           uintptr_t new_start, 
00073                           uintptr_t new_end)
00074 {
00075         uintptr_t entry;
00076         uintptr_t symbol_old_addr;
00077         uintptr_t symbol_new_addr;
00078 
00079         M_DEBUG_PRINT(M_DEBUG_SEGMENT, "relocate.got_start = %lx\n", got_start);
00080         M_DEBUG_PRINT(M_DEBUG_SEGMENT, "relocate.got_end   = %lx\n", got_end);
00081         M_DEBUG_PRINT(M_DEBUG_SEGMENT, "relocate.old_start = %lx\n", old_start);
00082         M_DEBUG_PRINT(M_DEBUG_SEGMENT, "relocate.old_end   = %lx\n", old_end);
00083         M_DEBUG_PRINT(M_DEBUG_SEGMENT, "relocate.new_start = %lx\n", new_start);
00084         M_DEBUG_PRINT(M_DEBUG_SEGMENT, "relocate.new_end   = %lx\n", new_end);
00085 
00086         mprotect(got_start - (got_start % 4096), got_end - (got_start - (got_start % 4096)), PROT_READ | PROT_WRITE | PROT_EXEC);
00087         
00088         for (entry = got_start; entry < got_end; entry+=sizeof(uintptr_t)) {
00089                 symbol_old_addr = *((uintptr_t *) entry);
00090                 /* Symbol in range? */
00091                 if (symbol_old_addr >= old_start && symbol_old_addr < old_end) {
00092                         symbol_new_addr = symbol_old_addr - old_start + new_start;
00093                         *((uintptr_t *) entry) = symbol_new_addr;
00094 
00095                         M_DEBUG_PRINT(M_DEBUG_SEGMENT, "relocate_symbol: %lx ==> %lx\n", symbol_old_addr, symbol_new_addr );
00096                 }
00097         }
00098 }
00099 
00100 
00116 static 
00117 m_result_t 
00118 persistent_shdr_open(char *module_path, 
00119                      uint64_t module_inode, 
00120                      uintptr_t module_start, 
00121                      module_dsr_t *module_dsr)
00122 {
00123         m_result_t result = M_R_FAILURE;
00124         int                fd;
00125         Elf                *e;
00126         char               *name;
00127     Elf_Scn            *scn;
00128         GElf_Shdr          shdr;
00129         size_t             shstrndx;
00130         GElf_Ehdr          ehdr;
00131         int                have_persistent = 0;
00132 
00133         if (module_dsr == NULL) {
00134                 result = M_R_INVALIDARG;
00135                 goto out;
00136         }
00137 
00138         if (elf_version(EV_CURRENT) == EV_NONE) {
00139                 errx(EX_SOFTWARE, "ELF library initialization failed: %s", elf_errmsg(-1));
00140         }
00141 
00142         if ((fd = open(module_path, O_RDONLY, 0)) < 0) {
00143                 result = M_R_INVALIDFILE;
00144                 goto out;
00145         }       
00146 
00147         if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
00148                 errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));
00149         }       
00150 
00151         if (elf_kind(e) != ELF_K_ELF) {
00152                 result = M_R_INVALIDFILE;
00153                 goto err_end;
00154         }
00155 
00156         gelf_getehdr(e, &ehdr);
00157         shstrndx = ehdr.e_shstrndx;
00158 
00159         scn = NULL;
00160         while ((scn = elf_nextscn(e, scn)) != NULL) {
00161                 if (gelf_getshdr(scn, &shdr) != &shdr) {
00162                         errx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
00163                 }       
00164                 if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) {
00165                         errx(EX_SOFTWARE, "elf_strptr() failed: %s.", elf_errmsg(-1));
00166                 }
00167                 if (strcmp(name, ".persistent") == 0) {
00168                         module_dsr->persistent_scn = scn;
00169                         memcpy((void *) &module_dsr->persistent_shdr, &shdr, sizeof(GElf_Shdr));
00170                         have_persistent = 1;
00171                         break;
00172                 }                       
00173         }
00174 
00175         if (have_persistent) {
00176                 strcpy(module_dsr->module_path, module_path);
00177                 module_dsr->module_start = module_start;
00178                 module_dsr->module_inode = module_inode;
00179                 module_dsr->fd = fd;
00180                 module_dsr->elf = e;
00181 
00182                 /* Find the global offset table */
00183                 scn = NULL;
00184                 while ((scn = elf_nextscn(e, scn)) != NULL) {
00185                         if (gelf_getshdr(scn, &shdr) != &shdr) {
00186                                 errx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
00187                         }       
00188                         if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) {
00189                                 errx(EX_SOFTWARE, "elf_strptr() failed: %s.", elf_errmsg(-1));
00190                         }
00191                         if (strcmp(name, ".got") == 0) {
00192                                 memcpy((void *) &module_dsr->GOT_shdr, &shdr, sizeof(GElf_Shdr));
00193                                 result = M_R_SUCCESS;
00194                                 goto out;
00195                         }
00196                 }
00197                 assert(0 && "PANIC: No GOT section\n");
00198         }
00199 err_end:
00200         (void) elf_end(e);
00201         (void) close(fd);
00202 out:    
00203         return result;
00204 }
00205 
00206 
00207 static 
00208 void
00209 persistent_shdr_close(module_dsr_t *module_dsr)
00210 {
00211         (void) elf_end(module_dsr->elf);
00212         (void) close(module_dsr->fd);
00213 }
00214 
00215 
00223 m_result_t 
00224 m_module_create_module_dsr_list(struct list_head *module_dsr_listp)
00225 {
00226         char      fname[64]; /* /proc/<pid>/exe */
00227         pid_t     pid;
00228         FILE      *f;
00229         char      buf[128+M_MODULE_PATH_MAX];
00230         char      perm[5], dev[6], mapname[M_MODULE_PATH_MAX];
00231         uint64_t  start, end, inode, foo;
00232         char      prev_mapname[M_MODULE_PATH_MAX];
00233         module_dsr_t *module_dsr = NULL;
00234 
00235         
00236         /* Get our PID and build the name of the link in /proc */
00237         pid = getpid();
00238         
00239         if (snprintf(fname, sizeof(fname), "/proc/%i/maps", pid) < 0) {
00240                 return M_R_FAILURE;
00241         }
00242         if ((f = fopen(fname, "r")) == NULL) {
00243                 return M_R_FAILURE;
00244         }
00245         INIT_LIST_HEAD(module_dsr_listp);
00246         
00247         while (!feof(f)) {
00248                 if(fgets(buf, sizeof(buf), f) == 0)
00249                         break;
00250                 mapname[0] = '\0';
00251                 sscanf(buf, "%lx-%lx %4s %lx %5s %lu %s", &start, &end, perm,
00252                        &foo, dev, &inode, mapname);
00253                 if (module_dsr == NULL) {          
00254                         if (!(module_dsr = (module_dsr_t *) malloc(sizeof(module_dsr_t)))) {
00255                                 /* FIXME: cleanup allocated memory */
00256                                 return M_R_FAILURE;
00257                         }
00258                 }
00259                 if (strlen(mapname) > 0 && strcmp(prev_mapname, mapname) != 0) {
00260                         if (persistent_shdr_open(mapname, inode, start, module_dsr)
00261                         == M_R_SUCCESS)
00262                         {
00263                                 list_add(&module_dsr->list, module_dsr_listp);
00264                                 module_dsr = NULL; /* to allocate a new module_dsr object */
00265                                 strcpy(prev_mapname, mapname);
00266                         }
00267                 }
00268         }
00269 
00270         /* Free the last module_dsr allocated object if it has not been used */
00271         if (module_dsr) {
00272                 free(module_dsr);
00273         }
00274         
00275         return M_R_SUCCESS;
00276 }

Generated on Sat Apr 23 11:43:36 2011 for Mnemosyne by  doxygen 1.4.7