示例#1
0
struct sr_operating_system *
sr_operating_system_new()
{
    struct sr_operating_system *operating_system = sr_malloc(sizeof(struct sr_operating_system));
    sr_operating_system_init(operating_system);
    return operating_system;
}
示例#2
0
struct sr_core_stacktrace *
sr_core_stacktrace_new()
{
    struct sr_core_stacktrace *stacktrace =
        sr_malloc(sizeof(struct sr_core_stacktrace));

    sr_core_stacktrace_init(stacktrace);
    return stacktrace;
}
示例#3
0
struct sr_ruby_frame *
sr_ruby_frame_new()
{
    struct sr_ruby_frame *frame =
        sr_malloc(sizeof(struct sr_ruby_frame));

    sr_ruby_frame_init(frame);
    return frame;
}
示例#4
0
文件: java_frame.c 项目: abrt/satyr
struct sr_java_frame *
sr_java_frame_new_exception()
{
    struct sr_java_frame *frame =
        sr_malloc(sizeof(*frame));

    sr_java_frame_init(frame);
    frame->is_exception = true;
    return frame;
}
示例#5
0
文件: disasm.c 项目: abrt/satyr
char *
sr_disasm_binary_to_text(struct sr_disasm_state *state,
                         uint64_t start_offset,
                         uint64_t size,
                         char **error_message)
{
#if HAVE_LIBOPCODES
    asection *section = state->info.section;
    if (start_offset < section->vma
        || (start_offset + size) > section->vma + section->size)
    {
        *error_message = sr_asprintf(
            "Invalid function range: 0x%"PRIx64" - 0x%"PRIx64,
            start_offset,
            start_offset + size);

        return NULL;
    }

    char *code = sr_malloc(size);
    bool success = bfd_get_section_contents(state->bfd_file,
                                            state->info.section,
                                            code,
                                            start_offset - section->vma,
                                            size);

    if (!success)
    {
        *error_message = sr_strdup("Failed to get section contents.");
        return NULL;
    }

    struct sr_strbuf *strbuf = sr_strbuf_new();
    for (int i = 0; i < size; ++i)
    {
        sr_strbuf_append_strf(strbuf, "0x%02x ", (unsigned)code[i]);
        if ((i + 1) % 12 == 0)
            sr_strbuf_append_char(strbuf, '\n');
    }

    free(code);
    return sr_strbuf_free_nobuf(strbuf);
#else // HAVE_LIBOPCODES
    *error_message = sr_asprintf("satyr compiled without libopcodes");
    return NULL;
#endif // HAVE_LIBOPCODES
}
示例#6
0
文件: distance.c 项目: lkundrak/satyr
struct sr_distances *
sr_distances_new(int m, int n)
{
    struct sr_distances *distances = sr_malloc(sizeof(struct sr_distances));

    /* The number of rows has to be smaller than columns. */
    if (m >= n)
        m = n - 1;

    assert(m > 0 && n > 1 && m < n);

    distances->m = m;
    distances->n = n;
    distances->distances = sr_malloc_array(
                               get_distance_position(distances, m - 1, n - 1) + 1,
                               sizeof(*distances->distances)
                           );

    return distances;
}
示例#7
0
int so_scheduler_add(soscheduler *s , void *db)
{
    sr_mutexlock(&s->lock);
    so *e = s->env;
    int count = s->count + 1;
    void **i = sr_malloc(&e->a, count * sizeof(void*));
    if (srunlikely(i == NULL)) {
        sr_mutexunlock(&s->lock);
        return -1;
    }
    memcpy(i, s->i, s->count * sizeof(void*));
    i[s->count] = db;
    void *iprev = s->i;
    s->i = i;
    s->count = count;
    sr_mutexunlock(&s->lock);
    if (iprev)
        sr_free(&e->a, iprev);
    return 0;
}
示例#8
0
int so_scheduler_del(soscheduler *s, void *db)
{
    if (srunlikely(s->i == NULL))
        return 0;
    sr_mutexlock(&s->lock);
    so *e = s->env;
    int count = s->count - 1;
    if (srunlikely(count == 0)) {
        s->count = 0;
        sr_free(&e->a, s->i);
        s->i = NULL;
        sr_mutexunlock(&s->lock);
        return 0;
    }
    void **i = sr_malloc(&e->a, count * sizeof(void*));
    if (srunlikely(i == NULL)) {
        sr_mutexunlock(&s->lock);
        return -1;
    }
    int j = 0;
    int k = 0;
    while (j < s->count) {
        if (s->i[j] == db) {
            j++;
            continue;
        }
        i[k] = s->i[j];
        k++;
        j++;
    }
    void *iprev = s->i;
    s->i = i;
    s->count = count;
    if (srunlikely(s->rr >= s->count))
        s->rr = 0;
    sr_mutexunlock(&s->lock);
    sr_free(&e->a, iprev);
    return 0;
}
示例#9
0
sinode *si_nodenew(sr *r)
{
	sinode *n = (sinode*)sr_malloc(r->a, sizeof(sinode));
	if (srunlikely(n == NULL)) {
		sr_malfunction(r->e, "%s", "memory allocation failed");
		return NULL;
	}
	n->recover = 0;
	n->backup = 0;
	n->flags = 0;
	n->update_time = 0;
	n->used = 0;
	si_branchinit(&n->self);
	n->branch = NULL;
	n->branch_count = 0;
	sr_fileinit(&n->file, r->a);
	sv_indexinit(&n->i0);
	sv_indexinit(&n->i1);
	sr_rbinitnode(&n->node);
	sr_rqinitnode(&n->nodecompact);
	sr_rqinitnode(&n->nodebranch);
	sr_listinit(&n->commit);
	return n;
}
示例#10
0
文件: elves.c 项目: abrt/satyr
struct sr_elf_fde *
sr_elf_get_eh_frame(const char *filename,
                    char **error_message)
{
#ifdef WITH_ELFUTILS
    /* Open the input file. */
    int fd = open(filename, O_RDONLY);
    if (fd < 0)
    {
        *error_message = sr_asprintf("Failed to open file %s: %s",
                                     filename,
                                     strerror(errno));
        return NULL;
    }

    /* Initialize libelf on the opened file. */
    Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
    if (!elf)
    {
        *error_message = sr_asprintf("Failed to run elf_begin on file %s: %s",
                                     filename,
                                     elf_errmsg(-1));
        close(fd);
        return NULL;
    }

    unsigned char *e_ident = (unsigned char *)elf_getident(elf, NULL);
    if (!e_ident)
    {
        *error_message = sr_asprintf("elf_getident failed for %s: %s",
                                     filename,
                                     elf_errmsg(-1));
        elf_end(elf);
        close(fd);
        return NULL;
    }

    /* Look up the .eh_frame section */
    GElf_Shdr shdr;
    Elf_Data *section_data;
    char *find_section_error_message;
    if (!find_elf_section_by_name(elf,
                                  ".eh_frame",
                                  &section_data,
                                  &shdr,
                                  &find_section_error_message))
    {
        *error_message = sr_asprintf("Failed to find .eh_frame section for %s: %s",
                                     filename,
                                     find_section_error_message);

        free(find_section_error_message);
        elf_end(elf);
        close(fd);
        return NULL;
    }

    /* Get the address at which the executable segment is loaded.  If
     * the .eh_frame addresses are absolute, this is used to convert
     * them to relative to the beginning of executable segment.  We
     * are looking for the first LOAD segment that is executable, I
     * hope this is sufficient.
     */
    size_t phnum;
    if (elf_getphdrnum(elf, &phnum) != 0)
    {
        *error_message = sr_asprintf("elf_getphdrnum failed for %s: %s",
                                     filename,
                                     elf_errmsg(-1));
        elf_end(elf);
        close(fd);
        return NULL;
    }

    uint64_t exec_base = -1;
    int i;
    for (i = 0; i < phnum; i++)
    {
        GElf_Phdr phdr;
        if (gelf_getphdr(elf, i, &phdr) != &phdr)
        {
            *error_message = sr_asprintf("gelf_getphdr failed for %s: %s",
                                         filename,
                                         elf_errmsg(-1));
            elf_end(elf);
            close(fd);
            return NULL;
        }

        if (phdr.p_type == PT_LOAD && phdr.p_flags & PF_X)
        {
            exec_base = phdr.p_vaddr;
            break;
        }
    }

    if (-1 == exec_base)
    {
        *error_message = sr_asprintf("Can't determine executable base for %s",
                                     filename);

        elf_end(elf);
        close(fd);
        return NULL;
    }

    /* We now have a handle to .eh_frame data. We'll use
     * dwarf_next_cfi to iterate through all FDEs looking for those
     * matching the addresses we have.
     *
     * Some info on .eh_frame can be found at
     * http://www.airs.com/blog/archives/460 and in DWARF
     * documentation for .debug_frame. The initial_location and
     * address_range decoding is 'inspired' by elfutils source.
     *
     * @todo If this linear scan is too slow, we can do binary search
     * on .eh_frame_hdr -- see http://www.airs.com/blog/archives/462
     */

    struct sr_elf_fde *result = NULL, *last = NULL;
    struct cie *cie_list = NULL, *cie_list_last = NULL;

    Dwarf_Off cfi_offset_next = 0;
    while (true)
    {
        Dwarf_CFI_Entry cfi;
        Dwarf_Off cfi_offset = cfi_offset_next;
        int ret = dwarf_next_cfi(e_ident,
                                 section_data,
                                 1,
                                 cfi_offset,
                                 &cfi_offset_next,
                                 &cfi);

        if (ret > 0)
        {
            /* We're at the end. */
            break;
        }

        if (ret < 0)
        {
            /* Error. If cfi_offset_next was updated, we may skip the
             * erroneous cfi. */
            if (cfi_offset_next > cfi_offset)
                continue;

            *error_message = sr_asprintf("dwarf_next_cfi failed for %s: %s",
                                         filename,
                                         dwarf_errmsg(-1));

            cie_free(cie_list);
            sr_elf_eh_frame_free(result);
            elf_end(elf);
            close(fd);
            return NULL;
        }

        if (dwarf_cfi_cie_p(&cfi))
        {
            /* Current CFI is a CIE. We store its offset and FDE encoding
             * attributes to be used when reading FDEs.
             */

            /* Default FDE encoding (i.e. no R in augmentation string) is
             * DW_EH_PE_absptr.
             */
            char *cie_error_message;
            struct cie *cie = read_cie(&cfi,
                                       cfi_offset,
                                       e_ident,
                                       &cie_error_message);
            if (!cie)
            {
                *error_message = sr_asprintf("CIE reading failed for %s: %s",
                                             filename,
                                             cie_error_message);

                free(cie_error_message);
                cie_free(cie_list);
                sr_elf_eh_frame_free(result);
                elf_end(elf);
                close(fd);
                return NULL;
            }

            /* Append the newly parsed CIE to our list of CIEs. */
            if (cie_list)
            {
                cie_list_last->next = cie;
                cie_list_last = cie;
            }
            else
                cie_list = cie_list_last = cie;
        }
        else
        {
            /* Current CFI is an FDE.
             */
            struct cie *cie = cie_list;

            /* Find the CIE data that we should have saved earlier. */
            while (cie)
            {
                /* In .eh_frame, CIE_pointer is relative, but libdw converts it
                 * to absolute offset. */
                if (cfi.fde.CIE_pointer == cie->cie_offset)
                    break; /* Found. */

                cie = cie->next;
            }

            if (!cie)
            {
                *error_message = sr_asprintf("CIE not found for FDE %jx in %s",
                                             (uintmax_t)cfi_offset,
                                             filename);

                cie_free(cie_list);
                sr_elf_eh_frame_free(result);
                elf_end(elf);
                close(fd);
                return NULL;
            }

            /* Read the two numbers we need and if they are PC-relative,
             * compute the offset from VMA base
             */

            uint64_t initial_location = fde_read_address(cfi.fde.start,
                                                         cie->ptr_len);

            uint64_t address_range = fde_read_address(cfi.fde.start + cie->ptr_len,
                                                      cie->ptr_len);

            if (cie->pcrel)
            {
                /* We need to determine how long is the 'length' (and
                 * consequently CIE id) field of this FDE -- it can be
                 * either 4 or 12 bytes long. */
                uint64_t length = fde_read_address(section_data->d_buf + cfi_offset, 4);
                uint64_t skip = (length == 0xffffffffUL ? 12 : 4);
                uint64_t mask = (cie->ptr_len == 4 ? 0xffffffffUL : 0xffffffffffffffffUL);
                initial_location += shdr.sh_offset + cfi_offset + 2 * skip;
                initial_location &= mask;
            }
            else
            {
                /* Assuming that not pcrel means absolute address
                 * (what if the file is a library?).  Convert to
                 * text-section-start-relative.
                 */
                initial_location -= exec_base;
            }

            struct sr_elf_fde *fde = sr_malloc(sizeof(struct sr_elf_fde));
            fde->exec_base = exec_base;
            fde->start_address = initial_location;
            fde->length = address_range;
            fde->next = NULL;

            /* Append the newly parsed Frame Description Entry to our
             * list of FDEs.
             */
            if (result)
            {
                last->next = fde;
                last = fde;
            }
            else
                result = last = fde;
        }
    }

    cie_free(cie_list);
    elf_end(elf);
    close(fd);
    return result;
#else /* WITH_ELFUTILS */
    *error_message = sr_asprintf("satyr compiled without elfutils");
    return NULL;
#endif /* WITH_ELFUTILS */
}
示例#11
0
文件: elves.c 项目: abrt/satyr
struct sr_elf_plt_entry *
sr_elf_get_procedure_linkage_table(const char *filename,
                                   char **error_message)
{
#ifdef WITH_ELFUTILS
    /* Open the input file. */
    int fd = open(filename, O_RDONLY);
    if (fd < 0)
    {
        *error_message = sr_asprintf("Failed to open file %s: %s",
                                     filename,
                                     strerror(errno));

        return NULL;
    }

    /* Initialize libelf on the opened file. */
    Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
    if (!elf)
    {
        *error_message = sr_asprintf("Failed to run elf_begin on file %s: %s",
                                     filename,
                                     elf_errmsg(-1));

        close(fd);
        return NULL;
    }

    /* Find the .plt section. */
    GElf_Shdr shdr;
    Elf_Data *plt_data;
    char *find_section_error_message;
    size_t plt_section_index = find_elf_section_by_name(elf,
                                                        ".plt",
                                                        &plt_data,
                                                        &shdr,
                                                        &find_section_error_message);
    if (0 == plt_section_index)
    {
        *error_message = sr_asprintf("Failed to find .plt section for %s: %s",
                                     filename,
                                     find_section_error_message);

        free(find_section_error_message);
        elf_end(elf);
        close(fd);
        return NULL;
    }

    /* Find the relocation section for .plt (typically .rela.plt), together
     * with its symbol and string table
     */
    uint64_t plt_base = shdr.sh_addr;
    Elf_Data *rela_plt_data = NULL;
    Elf_Data *plt_symbols = NULL;
    size_t stringtable = 0;
    Elf_Scn *section = NULL;
    while ((section = elf_nextscn(elf, section)) != NULL)
    {
        if (gelf_getshdr(section, &shdr) != &shdr)
        {
            *error_message = sr_asprintf("gelf_getshdr failed for %s: %s",
                                         filename,
                                         elf_errmsg(-1));

            elf_end(elf);
            close(fd);
            return NULL;
        }

        if (shdr.sh_type == SHT_RELA &&
            shdr.sh_info == plt_section_index)
        {
            rela_plt_data = elf_getdata(section, NULL);
            if (!rela_plt_data)
            {
                *error_message = sr_asprintf("elf_getdata failed for %s: %s",
                                             filename,
                                             elf_errmsg(-1));

                elf_end(elf);
                close(fd);
                return NULL;
            }

            /* Get symbol section for .rela.plt */
            Elf_Scn *symbol_section = elf_getscn(elf, shdr.sh_link);
            if (!symbol_section)
            {
                *error_message = sr_asprintf("elf_getscn failed for %s: %s",
                                             filename,
                                             elf_errmsg(-1));

                elf_end(elf);
                close(fd);
                return NULL;
            }

            plt_symbols = elf_getdata(symbol_section, NULL);
            if (!plt_symbols)
            {
                *error_message = sr_asprintf("elf_getdata failed for %s: %s",
                                             filename,
                                             elf_errmsg(-1));

                elf_end(elf);
                close(fd);
                return NULL;
            }

            /* Get string table for the symbol table. */
            if (gelf_getshdr(symbol_section, &shdr) != &shdr)
            {
                *error_message = sr_asprintf("gelf_getshdr failed for %s: %s",
                                             filename,
                                             elf_errmsg(-1));

                elf_end(elf);
                close(fd);
                return NULL;
            }

            stringtable = shdr.sh_link;
            break;
        }
    }

    if (0 == stringtable)
    {
        *error_message = sr_asprintf("Unable to read symbol table for .plt for file %s",
                                     filename);

        elf_end(elf);
        close(fd);
        return NULL;
    }

    /* PLT looks like this (see also AMD64 ABI, page 78):
     *
     * Disassembly of section .plt:
     *
     * 0000003463e01010 <attr_removef@plt-0x10>:
     *   3463e01010:   ff 35 2a 2c 20 00       pushq  0x202c2a(%rip)         <-- here is plt_base
     *   3463e01016:   ff 25 2c 2c 20 00       jmpq   *0x202c2c(%rip)            each "slot" is 16B wide
     *   3463e0101c:   0f 1f 40 00             nopl   0x0(%rax)                  0-th slot is skipped
     *
     * 0000003463e01020 <attr_removef@plt>:
     *   3463e01020:   ff 25 2a 2c 20 00       jmpq   *0x202c2a(%rip)
     *   3463e01026:   68 00 00 00 00          pushq  $0x0                   <-- this is the number we want
     *   3463e0102b:   e9 e0 ff ff ff          jmpq   3463e01010 <_init+0x18>
     *
     * 0000003463e01030 <fgetxattr@plt>:
     *   3463e01030:   ff 25 22 2c 20 00       jmpq   *0x202c22(%rip)
     *   3463e01036:   68 01 00 00 00          pushq  $0x1
     *   3463e0103b:   e9 d0 ff ff ff          jmpq   3463e01010 <_init+0x18>
     */
    struct sr_elf_plt_entry *result = NULL, *last = NULL;
    for (unsigned plt_offset = 16; plt_offset < plt_data->d_size; plt_offset += 16)
    {
        uint32_t *plt_index = (uint32_t*)(plt_data->d_buf + plt_offset + 7);

        GElf_Rela rela;
        if (gelf_getrela(rela_plt_data, *plt_index, &rela) != &rela)
        {
            *error_message = sr_asprintf("gelf_getrela failed for %s: %s",
                                         filename,
                                         elf_errmsg(-1));

            sr_elf_procedure_linkage_table_free(result);
            elf_end(elf);
            close(fd);
            return NULL;
        }

        GElf_Sym symb;
        if (gelf_getsym(plt_symbols, GELF_R_SYM(rela.r_info), &symb) != &symb)
        {
            *error_message = sr_asprintf("gelf_getsym failed for %s: %s",
                                         filename,
                                         elf_errmsg(-1));

            sr_elf_procedure_linkage_table_free(result);
            elf_end(elf);
            close(fd);
            return NULL;
        }

        struct sr_elf_plt_entry *entry = sr_malloc(sizeof(struct sr_elf_plt_entry));
        entry->symbol_name = sr_strdup(elf_strptr(elf, stringtable,
                                                  symb.st_name));

        entry->address = (uint64_t)(plt_base + plt_offset);
        entry->next = NULL;

        if (result)
        {
            last->next = entry;
            last = entry;
        }
        else
            result = last = entry;
    }

    elf_end(elf);
    close(fd);
    return result;
#else /* WITH_ELFUTILS */
    *error_message = sr_asprintf("satyr compiled without elfutils");
    return NULL;
#endif /* WITH_ELFUTILS */
}
示例#12
0
文件: disasm.c 项目: abrt/satyr
struct sr_disasm_state *
sr_disasm_init(const char *file_name,
               char **error_message)
{
#if HAVE_LIBOPCODES
    struct sr_disasm_state *state =
        sr_malloc(sizeof(struct sr_disasm_state));

    state->bfd_file = bfd_openr(file_name, NULL);
    if (!state->bfd_file)
    {
        *error_message = sr_asprintf("Failed to open file %s: %s",
                                     file_name,
                                     bfd_errmsg(bfd_get_error()));
        free(state);
        return NULL;
    }

    if (!bfd_check_format(state->bfd_file, bfd_object))
    {
        *error_message = sr_asprintf("Invalid file format of %s: %s",
                                     file_name,
                                     bfd_errmsg(bfd_get_error()));
        bfd_close(state->bfd_file);
        free(state);
        return NULL;
    }

    asection *section =
        bfd_get_section_by_name(state->bfd_file, ".text");

    if (!section)
    {
        *error_message = sr_asprintf(
            "Failed to find .text section in %s: %s",
            file_name,
            bfd_errmsg(bfd_get_error()));

        bfd_close(state->bfd_file);
        free(state);
        return NULL;
    }

    state->disassembler = disassembler(state->bfd_file);
    if (!state->disassembler)
    {
        *error_message = sr_asprintf(
            "Unable to find disassembler for %s",
            file_name);

        bfd_close(state->bfd_file);
        free(state);
        return NULL;
    }

    init_disassemble_info(&state->info, NULL, buffer_printf);
    state->info.arch = bfd_get_arch(state->bfd_file);
    state->info.mach = bfd_get_mach(state->bfd_file);
    state->info.buffer_vma = section->vma;
    state->info.buffer_length = section->size;
    state->info.section = section;
    /* TODO: memory error func */
    bfd_malloc_and_get_section(state->bfd_file, section,
                               &state->info.buffer);

    disassemble_init_for_target(&state->info);
    return state;
#else // HAVE_LIBOPCODES
    *error_message = sr_asprintf("satyr compiled without libopcodes");
    return NULL;
#endif // HAVE_LIBOPCODES
}
示例#13
0
static struct sr_core_thread *
unwind_thread(struct UCD_info *ui,
              unw_addr_space_t as,
              Dwfl *dwfl,
              int thread_no,
              char **error_msg)
{
    int ret;
    unw_cursor_t c;
    struct sr_core_frame *trace = NULL;

    _UCD_select_thread(ui, thread_no);

    ret = unw_init_remote(&c, as, ui);
    if (ret < 0)
    {
        set_error("unw_init_remote failed: %s", unw_strerror(ret));
        return NULL;
    }

    int count = 1000;
    while (--count > 0)
    {
        unw_word_t ip;
        ret = unw_get_reg(&c, UNW_REG_IP, &ip);
        if (ret < 0)
            warn("unw_get_reg(UNW_REG_IP) failed: %s", unw_strerror(ret));

        /* Seen this happen when unwinding thread that did not start
         * in main(). */
        if (ip == 0)
            break;

        struct sr_core_frame *entry = resolve_frame(dwfl, ip, false);

        if (!entry->function_name)
        {
            size_t funcname_len = 512;
            char *funcname = sr_malloc(funcname_len);

            if (unw_get_proc_name(&c, funcname, funcname_len, NULL) == 0)
                entry->function_name = funcname;
            else
                free(funcname);
        }

        trace = sr_core_frame_append(trace, entry);
        /*
        printf("%s 0x%llx %s %s -\n",
                (ip_seg && ip_seg->build_id) ? ip_seg->build_id : "-",
                (unsigned long long)(ip_seg ? ip - ip_seg->vaddr : ip),
                (entry->symbol ? entry->symbol : "-"),
                (ip_seg && ip_seg->filename) ? ip_seg->filename : "-");
        */

        /* Do not unwind below __libc_start_main. */
        if (0 == sr_strcmp0(entry->function_name, "__libc_start_main"))
            break;

        ret = unw_step(&c);
        if (ret == 0)
            break;

        if (ret < 0)
        {
            warn("unw_step failed: %s", unw_strerror(ret));
            break;
        }
    }

    if (error_msg && !*error_msg && !trace)
    {
        set_error("No frames found for thread %d", thread_no);
    }

    struct sr_core_thread *thread = sr_core_thread_new();
    thread->frames = trace;
    return thread;
}