00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
00110
00111
00112
00113
00114
00115
00116
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
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