elf_core.c

00001 /*
00002  * Copyright (c) 2010 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <errno.h>
00051 #include <sys/types.h>
00052 #include <sys/stat.h>
00053 #include <unistd.h>
00054 #include <fcntl.h>
00055 #include <mem.h>
00056 #include <stdint.h>
00057 #include <as.h>
00058 #include <udebug.h>
00059 #include <macros.h>
00060 
00061 #include <elf.h>
00062 #include "include/elf_core.h"
00063 
00064 static off64_t align_foff_up(off64_t foff, uintptr_t vaddr, size_t page_size);
00065 static int write_all(int fd, void *data, size_t len);
00066 static int write_mem_area(int fd, as_area_info_t *area, int phoneid);
00067 
00068 #define BUFFER_SIZE 0x1000
00069 static uint8_t buffer[BUFFER_SIZE];
00070 
00081 int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n, int phoneid)
00082 {
00083         elf_header_t elf_hdr;
00084         off64_t foff;
00085         size_t n_ph;
00086         elf_word flags;
00087         elf_segment_header_t *p_hdr;
00088 
00089         int fd;
00090         int rc;
00091         unsigned int i;
00092 
00093         n_ph = n;
00094 
00095         p_hdr = malloc(sizeof(elf_segment_header_t) * n);
00096         if (p_hdr == NULL) {
00097                 printf("Failed allocating memory.\n");
00098                 return ENOMEM;
00099         }
00100 
00101         fd = open(file_name, O_CREAT | O_WRONLY, 0644);
00102         if (fd < 0) {
00103                 printf("Failed opening file.\n");
00104                 free(p_hdr);
00105                 return ENOENT;
00106         }
00107 
00108         /*
00109          * File layout:
00110          *
00111          *      ELF header
00112          *      program headers
00113          * repeat:
00114          *      (pad for alignment)
00115          *      segment data
00116          * end repeat
00117          */
00118 
00119         memset(&elf_hdr, 0, sizeof(elf_hdr));
00120         elf_hdr.e_ident[EI_MAG0] = ELFMAG0;
00121         elf_hdr.e_ident[EI_MAG1] = ELFMAG1;
00122         elf_hdr.e_ident[EI_MAG2] = ELFMAG2;
00123         elf_hdr.e_ident[EI_MAG3] = ELFMAG3;
00124         elf_hdr.e_ident[EI_CLASS] = ELF_CLASS;
00125         elf_hdr.e_ident[EI_DATA] = ELF_DATA_ENCODING;
00126         elf_hdr.e_ident[EI_VERSION] = EV_CURRENT;
00127 
00128         elf_hdr.e_type = ET_CORE;
00129         elf_hdr.e_machine = ELF_MACHINE;
00130         elf_hdr.e_version = EV_CURRENT;
00131         elf_hdr.e_entry = 0;
00132         elf_hdr.e_phoff = sizeof(elf_header_t);
00133         elf_hdr.e_shoff = 0;
00134         elf_hdr.e_flags = 0;
00135         elf_hdr.e_ehsize = sizeof(elf_hdr);
00136         elf_hdr.e_phentsize = sizeof(elf_segment_header_t);
00137         elf_hdr.e_phnum = n_ph;
00138         elf_hdr.e_shentsize = 0;
00139         elf_hdr.e_shnum = 0;
00140         elf_hdr.e_shstrndx = 0;
00141 
00142         /* foff is used for allocation of file space for segment data. */
00143         foff = elf_hdr.e_phoff + n_ph * sizeof(elf_segment_header_t);
00144 
00145         for (i = 1; i <= n; ++i) {
00146                 foff = align_foff_up(foff, ainfo[i - 1].start_addr, PAGE_SIZE);
00147 
00148                 flags = 0;
00149                 if (ainfo[i - 1].flags & AS_AREA_READ)
00150                         flags |= PF_R;
00151                 if (ainfo[i - 1].flags & AS_AREA_WRITE)
00152                         flags |= PF_W;
00153                 if (ainfo[i - 1].flags & AS_AREA_EXEC)
00154                         flags |= PF_X;
00155 
00156                 memset(&p_hdr[i - 1], 0, sizeof(p_hdr[i - 1]));
00157                 p_hdr[i - 1].p_type = PT_LOAD;
00158                 p_hdr[i - 1].p_offset = foff;
00159                 p_hdr[i - 1].p_vaddr = ainfo[i - 1].start_addr;
00160                 p_hdr[i - 1].p_paddr = 0;
00161                 p_hdr[i - 1].p_filesz = ainfo[i - 1].size;
00162                 p_hdr[i - 1].p_memsz = ainfo[i - 1].size;
00163                 p_hdr[i - 1].p_flags = flags;
00164                 p_hdr[i - 1].p_align = PAGE_SIZE;
00165 
00166                 foff += ainfo[i - 1].size;
00167         }
00168 
00169         rc = write_all(fd, &elf_hdr, sizeof(elf_hdr));
00170         if (rc != EOK) {
00171                 printf("Failed writing ELF header.\n");
00172                 free(p_hdr);
00173                 return EIO;
00174         }
00175 
00176         for (i = 0; i < n_ph; ++i) {
00177                 rc = write_all(fd, &p_hdr[i], sizeof(p_hdr[i]));
00178                 if (rc != EOK) {
00179                         printf("Failed writing program header.\n");
00180                         free(p_hdr);
00181                         return EIO;
00182                 }
00183         }
00184 
00185         for (i = 0; i < n_ph; ++i) {
00186                 if (lseek(fd, p_hdr[i].p_offset, SEEK_SET) == (off64_t) -1) {
00187                         printf("Failed writing memory data.\n");
00188                         free(p_hdr);
00189                         return EIO;
00190                 }
00191                 if (write_mem_area(fd, &ainfo[i], phoneid) != EOK) {
00192                         printf("Failed writing memory data.\n");
00193                         free(p_hdr);
00194                         return EIO;
00195                 }
00196         }
00197 
00198         free(p_hdr);
00199 
00200         return EOK;
00201 }
00202 
00204 static off64_t align_foff_up(off64_t foff, uintptr_t vaddr, size_t page_size)
00205 {
00206         off64_t rva = vaddr % page_size;
00207         off64_t rfo = foff % page_size;
00208         
00209         if (rva >= rfo)
00210                 return (foff + (rva - rfo));
00211         
00212         return (foff + (page_size + (rva - rfo)));
00213 }
00214 
00223 static int write_mem_area(int fd, as_area_info_t *area, int phoneid)
00224 {
00225         size_t to_copy;
00226         size_t total;
00227         uintptr_t addr;
00228         int rc;
00229 
00230         addr = area->start_addr;
00231         total = 0;
00232 
00233         while (total < area->size) {
00234                 to_copy = min(area->size - total, BUFFER_SIZE);
00235                 rc = udebug_mem_read(phoneid, buffer, addr, to_copy);
00236                 if (rc < 0) {
00237                         printf("Failed reading task memory.\n");
00238                         return EIO;
00239                 }
00240 
00241                 rc = write_all(fd, buffer, to_copy);
00242                 if (rc != EOK) {
00243                         printf("Failed writing memory contents.\n");
00244                         return EIO;
00245                 }
00246 
00247                 addr += to_copy;
00248                 total += to_copy;
00249         }
00250 
00251         return EOK;
00252 }
00253 
00265 static int write_all(int fd, void *data, size_t len)
00266 {
00267         int cnt = 0;
00268 
00269         do {
00270                 data += cnt;
00271                 len -= cnt;
00272                 cnt = write(fd, data, len);
00273         } while (cnt > 0 && (len - cnt) > 0);
00274 
00275         if (cnt < 0)
00276                 return cnt;
00277 
00278         if (len - cnt > 0)
00279                 return EIO;
00280 
00281         return EOK;
00282 }
00283 
00284 

Generated on Thu Jun 2 07:45:43 2011 for HelenOS/USB by  doxygen 1.4.7