Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/taskdump/elf_core.c

    red903174 r74e6b1f  
    11/*
    2  * Copyright (c) 2010 Jiri Svoboda
     2 * Copyright (c) 2011 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3838 * Looking at core files produced by Linux, these don't have section headers,
    3939 * 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>
    4852#include <stdio.h>
    4953#include <stdlib.h>
     
    5862#include <udebug.h>
    5963#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
     68static off64_t align_foff_up(off64_t, uintptr_t, size_t);
     69static int align_pos(int, size_t);
     70static int write_mem_area(int, as_area_info_t *, async_sess_t *);
    6771
    6872#define BUFFER_SIZE 0x1000
     
    7175/** Save ELF core file.
    7276 *
    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 */
     88int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n,
     89    async_sess_t *sess, istate_t *istate)
    8290{
    8391        elf_header_t elf_hdr;
     
    8694        elf_word flags;
    8795        elf_segment_header_t *p_hdr;
     96        elf_prstatus_t pr_status;
     97        elf_note_t note;
     98        size_t word_size;
    8899
    89100        int fd;
    90         int rc;
     101        ssize_t rc;
    91102        unsigned int i;
    92103
    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);
    96121        if (p_hdr == NULL) {
    97122                printf("Failed allocating memory.\n");
     
    111136         *      ELF header
    112137         *      program headers
     138         *      note segment
    113139         * repeat:
    114140         *      (pad for alignment)
    115          *      segment data
     141         *      core segment
    116142         * end repeat
    117143         */
     
    143169        foff = elf_hdr.e_phoff + n_ph * sizeof(elf_segment_header_t);
    144170
    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);
    147187
    148188                flags = 0;
    149                 if (ainfo[i - 1].flags & AS_AREA_READ)
     189                if (ainfo[i].flags & AS_AREA_READ)
    150190                        flags |= PF_R;
    151                 if (ainfo[i - 1].flags & AS_AREA_WRITE)
     191                if (ainfo[i].flags & AS_AREA_WRITE)
    152192                        flags |= PF_W;
    153                 if (ainfo[i - 1].flags & AS_AREA_EXEC)
     193                if (ainfo[i].flags & AS_AREA_EXEC)
    154194                        flags |= PF_X;
    155195
    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;
    167207        }
    168208
    169209        rc = write_all(fd, &elf_hdr, sizeof(elf_hdr));
    170         if (rc != EOK) {
     210        if (rc != sizeof(elf_hdr)) {
    171211                printf("Failed writing ELF header.\n");
    172212                free(p_hdr);
     
    176216        for (i = 0; i < n_ph; ++i) {
    177217                rc = write_all(fd, &p_hdr[i], sizeof(p_hdr[i]));
    178                 if (rc != EOK) {
     218                if (rc != sizeof(p_hdr[i])) {
    179219                        printf("Failed writing program header.\n");
    180220                        free(p_hdr);
     
    183223        }
    184224
    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, &note, 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) {
    186267                if (lseek(fd, p_hdr[i].p_offset, SEEK_SET) == (off64_t) -1) {
    187268                        printf("Failed writing memory data.\n");
     
    189270                        return EIO;
    190271                }
    191                 if (write_mem_area(fd, &ainfo[i], phoneid) != EOK) {
     272                if (write_mem_area(fd, &ainfo[i - 1], sess) != EOK) {
    192273                        printf("Failed writing memory data.\n");
    193274                        free(p_hdr);
     
    206287        off64_t rva = vaddr % page_size;
    207288        off64_t rfo = foff % page_size;
    208        
     289
    209290        if (rva >= rfo)
    210291                return (foff + (rva - rfo));
    211        
     292
    212293        return (foff + (page_size + (rva - rfo)));
    213294}
     
    215296/** Write memory area from application to core file.
    216297 *
    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 */
     305static int write_mem_area(int fd, as_area_info_t *area, async_sess_t *sess)
    224306{
    225307        size_t to_copy;
    226308        size_t total;
    227309        uintptr_t addr;
    228         int rc;
     310        ssize_t rc;
    229311
    230312        addr = area->start_addr;
     
    233315        while (total < area->size) {
    234316                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);
    236318                if (rc < 0) {
    237319                        printf("Failed reading task memory.\n");
     
    240322
    241323                rc = write_all(fd, buffer, to_copy);
    242                 if (rc != EOK) {
     324                if (rc != (ssize_t) to_copy) {
    243325                        printf("Failed writing memory contents.\n");
    244326                        return EIO;
     
    252334}
    253335
    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)
     336static int align_pos(int fd, size_t align)
    266337{
    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;
    280351
    281352        return EOK;
    282353}
    283354
    284 
    285355/** @}
    286356 */
Note: See TracChangeset for help on using the changeset viewer.