Changeset a33f0a6 in mainline for uspace/app/taskdump/elf_core.c
- Timestamp:
- 2011-08-03T17:34:57Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1940326
- Parents:
- 52a79081 (diff), 3fab770 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/taskdump/elf_core.c
r52a79081 ra33f0a6 1 1 /* 2 * Copyright (c) 201 0Jiri Svoboda2 * Copyright (c) 2011 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 38 38 * Looking at core files produced by Linux, these don't have section headers, 39 39 * only program headers, although objdump shows them as having sections. 40 * Basically at the beginning there should be a note segment (which we 41 * do not write) and one loadable segment per memory area (which we do write). 42 * 43 * The note segment probably contains register state, etc. -- we don't 44 * deal with these yet. Nevertheless you can use these core files with 45 * objdump or gdb. 46 */ 47 40 * Basically at the beginning there should be a note segment followed 41 * by one loadable segment per memory area. 42 * 43 * The note segment contains a series of records with register state, 44 * process info etc. We only write one record NT_PRSTATUS which contains 45 * process/register state (anything which is not register state we fill 46 * with zeroes). 47 */ 48 49 #include <align.h> 50 #include <elf/elf.h> 51 #include <elf/elf_linux.h> 48 52 #include <stdio.h> 49 53 #include <stdlib.h> … … 58 62 #include <udebug.h> 59 63 #include <macros.h> 60 61 #include <elf.h> 62 #include " include/elf_core.h"63 64 static off64_t align_foff_up(off64_t foff, uintptr_t vaddr, size_t page_size);65 static int write_all(int fd, void *data, size_t len);66 static int write_mem_area(int fd, as_area_info_t *area, int phoneid);64 #include <libarch/istate.h> 65 66 #include "elf_core.h" 67 68 static off64_t align_foff_up(off64_t, uintptr_t, size_t); 69 static int align_pos(int, size_t); 70 static int write_mem_area(int, as_area_info_t *, async_sess_t *); 67 71 68 72 #define BUFFER_SIZE 0x1000 … … 71 75 /** Save ELF core file. 72 76 * 73 * @param file_name Name of file to save to. 74 * @param ainfo Array of @a n memory area info structures. 75 * @param n Number of memory areas. 76 * @param phoneid Debugging phone. 77 * 78 * @return EOK on sucess, ENOENT if file cannot be created, 79 * ENOMEM on out of memory, EIO on write error. 80 */ 81 int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n, int phoneid) 77 * @param file_name Name of file to save to. 78 * @param ainfo Array of @a n memory area info structures. 79 * @param n Number of memory areas. 80 * @param sess Debugging session. 81 * 82 * @return EOK on sucess. 83 * @return ENOENT if file cannot be created. 84 * @return ENOMEM on out of memory. 85 * @return EIO on write error. 86 * 87 */ 88 int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n, 89 async_sess_t *sess, istate_t *istate) 82 90 { 83 91 elf_header_t elf_hdr; … … 86 94 elf_word flags; 87 95 elf_segment_header_t *p_hdr; 96 elf_prstatus_t pr_status; 97 elf_note_t note; 98 size_t word_size; 88 99 89 100 int fd; 90 int rc;101 ssize_t rc; 91 102 unsigned int i; 92 103 93 n_ph = n; 94 95 p_hdr = malloc(sizeof(elf_segment_header_t) * n); 104 #ifdef __32_BITS__ 105 word_size = 4; 106 #endif 107 #ifdef __64_BITS__ 108 /* 109 * This should be 8 per the 64-bit ELF spec, but the Linux kernel 110 * screws up and uses 4 anyway (and screws up elf_note_t as well) 111 * and we are trying to be compatible with Linux GDB target. Sigh. 112 */ 113 word_size = 4; 114 #endif 115 memset(&pr_status, 0, sizeof(pr_status)); 116 istate_to_elf_regs(istate, &pr_status.regs); 117 118 n_ph = n + 1; 119 120 p_hdr = malloc(sizeof(elf_segment_header_t) * n_ph); 96 121 if (p_hdr == NULL) { 97 122 printf("Failed allocating memory.\n"); … … 111 136 * ELF header 112 137 * program headers 138 * note segment 113 139 * repeat: 114 140 * (pad for alignment) 115 * segment data141 * core segment 116 142 * end repeat 117 143 */ … … 143 169 foff = elf_hdr.e_phoff + n_ph * sizeof(elf_segment_header_t); 144 170 145 for (i = 1; i <= n; ++i) { 146 foff = align_foff_up(foff, ainfo[i - 1].start_addr, PAGE_SIZE); 171 memset(&p_hdr[0], 0, sizeof(p_hdr[0])); 172 p_hdr[0].p_type = PT_NOTE; 173 p_hdr[0].p_offset = foff; 174 p_hdr[0].p_vaddr = 0; 175 p_hdr[0].p_paddr = 0; 176 p_hdr[0].p_filesz = sizeof(elf_note_t) 177 + ALIGN_UP((str_size("CORE") + 1), word_size) 178 + ALIGN_UP(sizeof(elf_prstatus_t), word_size); 179 p_hdr[0].p_memsz = 0; 180 p_hdr[0].p_flags = 0; 181 p_hdr[0].p_align = 1; 182 183 foff += p_hdr[0].p_filesz; 184 185 for (i = 0; i < n; ++i) { 186 foff = align_foff_up(foff, ainfo[i].start_addr, PAGE_SIZE); 147 187 148 188 flags = 0; 149 if (ainfo[i - 1].flags & AS_AREA_READ)189 if (ainfo[i].flags & AS_AREA_READ) 150 190 flags |= PF_R; 151 if (ainfo[i - 1].flags & AS_AREA_WRITE)191 if (ainfo[i].flags & AS_AREA_WRITE) 152 192 flags |= PF_W; 153 if (ainfo[i - 1].flags & AS_AREA_EXEC)193 if (ainfo[i].flags & AS_AREA_EXEC) 154 194 flags |= PF_X; 155 195 156 memset(&p_hdr[i - 1], 0, sizeof(p_hdr[i -1]));157 p_hdr[i -1].p_type = PT_LOAD;158 p_hdr[i -1].p_offset = foff;159 p_hdr[i - 1].p_vaddr = ainfo[i - 1].start_addr;160 p_hdr[i -1].p_paddr = 0;161 p_hdr[i - 1].p_filesz = ainfo[i - 1].size;162 p_hdr[i - 1].p_memsz = ainfo[i - 1].size;163 p_hdr[i -1].p_flags = flags;164 p_hdr[i -1].p_align = PAGE_SIZE;165 166 foff += ainfo[i - 1].size;196 memset(&p_hdr[i + 1], 0, sizeof(p_hdr[i + 1])); 197 p_hdr[i + 1].p_type = PT_LOAD; 198 p_hdr[i + 1].p_offset = foff; 199 p_hdr[i + 1].p_vaddr = ainfo[i].start_addr; 200 p_hdr[i + 1].p_paddr = 0; 201 p_hdr[i + 1].p_filesz = ainfo[i].size; 202 p_hdr[i + 1].p_memsz = ainfo[i].size; 203 p_hdr[i + 1].p_flags = flags; 204 p_hdr[i + 1].p_align = PAGE_SIZE; 205 206 foff += ainfo[i].size; 167 207 } 168 208 169 209 rc = write_all(fd, &elf_hdr, sizeof(elf_hdr)); 170 if (rc != EOK) {210 if (rc != sizeof(elf_hdr)) { 171 211 printf("Failed writing ELF header.\n"); 172 212 free(p_hdr); … … 176 216 for (i = 0; i < n_ph; ++i) { 177 217 rc = write_all(fd, &p_hdr[i], sizeof(p_hdr[i])); 178 if (rc != EOK) {218 if (rc != sizeof(p_hdr[i])) { 179 219 printf("Failed writing program header.\n"); 180 220 free(p_hdr); … … 183 223 } 184 224 185 for (i = 0; i < n_ph; ++i) { 225 if (lseek(fd, p_hdr[0].p_offset, SEEK_SET) == (off64_t) -1) { 226 printf("Failed writing memory data.\n"); 227 free(p_hdr); 228 return EIO; 229 } 230 231 /* 232 * Write note header 233 */ 234 note.namesz = str_size("CORE") + 1; 235 note.descsz = sizeof(elf_prstatus_t); 236 note.type = NT_PRSTATUS; 237 238 rc = write_all(fd, ¬e, sizeof(elf_note_t)); 239 if (rc != sizeof(elf_note_t)) { 240 printf("Failed writing note header.\n"); 241 free(p_hdr); 242 return EIO; 243 } 244 245 rc = write_all(fd, "CORE", note.namesz); 246 if (rc != (ssize_t) note.namesz) { 247 printf("Failed writing note header.\n"); 248 free(p_hdr); 249 return EIO; 250 } 251 252 rc = align_pos(fd, word_size); 253 if (rc != EOK) { 254 printf("Failed writing note header.\n"); 255 free(p_hdr); 256 return EIO; 257 } 258 259 rc = write_all(fd, &pr_status, sizeof(elf_prstatus_t)); 260 if (rc != sizeof(elf_prstatus_t)) { 261 printf("Failed writing register data.\n"); 262 free(p_hdr); 263 return EIO; 264 } 265 266 for (i = 1; i < n_ph; ++i) { 186 267 if (lseek(fd, p_hdr[i].p_offset, SEEK_SET) == (off64_t) -1) { 187 268 printf("Failed writing memory data.\n"); … … 189 270 return EIO; 190 271 } 191 if (write_mem_area(fd, &ainfo[i ], phoneid) != EOK) {272 if (write_mem_area(fd, &ainfo[i - 1], sess) != EOK) { 192 273 printf("Failed writing memory data.\n"); 193 274 free(p_hdr); … … 206 287 off64_t rva = vaddr % page_size; 207 288 off64_t rfo = foff % page_size; 208 289 209 290 if (rva >= rfo) 210 291 return (foff + (rva - rfo)); 211 292 212 293 return (foff + (page_size + (rva - rfo))); 213 294 } … … 215 296 /** Write memory area from application to core file. 216 297 * 217 * @param fd File to write to. 218 * @param area Memory area info structure. 219 * @param phoneid Debugging phone. 220 * 221 * @return EOK on success, EIO on failure. 222 */ 223 static int write_mem_area(int fd, as_area_info_t *area, int phoneid) 298 * @param fd File to write to. 299 * @param area Memory area info structure. 300 * @param sess Debugging session. 301 * 302 * @return EOK on success, EIO on failure. 303 * 304 */ 305 static int write_mem_area(int fd, as_area_info_t *area, async_sess_t *sess) 224 306 { 225 307 size_t to_copy; 226 308 size_t total; 227 309 uintptr_t addr; 228 int rc;310 ssize_t rc; 229 311 230 312 addr = area->start_addr; … … 233 315 while (total < area->size) { 234 316 to_copy = min(area->size - total, BUFFER_SIZE); 235 rc = udebug_mem_read( phoneid, buffer, addr, to_copy);317 rc = udebug_mem_read(sess, buffer, addr, to_copy); 236 318 if (rc < 0) { 237 319 printf("Failed reading task memory.\n"); … … 240 322 241 323 rc = write_all(fd, buffer, to_copy); 242 if (rc != EOK) {324 if (rc != (ssize_t) to_copy) { 243 325 printf("Failed writing memory contents.\n"); 244 326 return EIO; … … 252 334 } 253 335 254 /** Write until the buffer is written in its entirety. 255 * 256 * This function fails if it cannot write exactly @a len bytes to the file. 257 * 258 * @param fd The file to write to. 259 * @param buf Data, @a len bytes long. 260 * @param len Number of bytes to write. 261 * 262 * @return EOK on error, return value from write() if writing 263 * failed. 264 */ 265 static int write_all(int fd, void *data, size_t len) 336 static int align_pos(int fd, size_t align) 266 337 { 267 int cnt = 0;268 269 do { 270 data += cnt;271 len -= cnt;272 cnt = write(fd, data, len);273 } while (cnt > 0 && (len - cnt) > 0); 274 275 if (cnt < 0)276 return cnt; 277 278 if ( len - cnt >0)279 return EIO;338 off64_t cur_pos; 339 size_t rem, adv; 340 341 cur_pos = lseek(fd, 0, SEEK_CUR); 342 if (cur_pos < 0) 343 return -1; 344 345 rem = cur_pos % align; 346 adv = align - rem; 347 348 cur_pos = lseek(fd, adv, SEEK_CUR); 349 if (cur_pos < 0) 350 return -1; 280 351 281 352 return EOK; 282 353 } 283 354 284 285 355 /** @} 286 356 */
Note:
See TracChangeset
for help on using the changeset viewer.