예제 #1
0
파일: elves.c 프로젝트: abrt/satyr
/**
 * Finds a section by its name in an ELF file.
 * @param elf
 *   A libelf handle representing the file.
 * @param section_name
 *   Name of section to be found.
 * @param data_dest
 *   Save the resulting elf data pointer here.  Cannot be NULL.
 * @param shdr_dest
 *   Save the section header here. Cannot be NULL.
 * @param error_message
 *   Will be filled by an error message if the function fails (returns
 *   zero).  Caller is responsible for calling free() on the string
 *   pointer.  If function succeeds, the pointer is not touched by the
 *   function.
 * @returns
 *   Zero on error, index of the section on success.
 */
static unsigned
find_elf_section_by_name(Elf *elf,
                         const char *section_name,
                         Elf_Data **data_dest,
                         GElf_Shdr *shdr_dest,
                         char **error_message)
{
    /* Find the string table index */
    size_t shdr_string_index;
    if (0 != elf_getshdrstrndx(elf, &shdr_string_index))
    {
        *error_message = sr_asprintf("elf_getshdrstrndx failed");
        return 0;
    }

    unsigned section_index = 0;
    Elf_Scn *section = NULL;
    while ((section = elf_nextscn(elf, section)) != NULL)
    {
        /* Starting index is 1. */
        ++section_index;

        GElf_Shdr shdr;
        if (gelf_getshdr(section, &shdr) != &shdr)
        {
            *error_message = sr_asprintf("gelf_getshdr failed");
            return 0;
        }

        const char *current_section_name = elf_strptr(elf,
                                                      shdr_string_index,
                                                      shdr.sh_name);

        if (!current_section_name)
        {
            *error_message = sr_asprintf("elf_strptr failed");
            return 0;
        }

        if (0 == strcmp(current_section_name, section_name))
        {
            /* We found the right section!  Save the data. */
            *data_dest = elf_getdata(section, NULL);
            if (!*data_dest)
            {
                *error_message = sr_asprintf("elf_getdata failed");
                return 0;
            }

            /* Save the section header. */
            *shdr_dest = shdr;
            return section_index;
        }
    }

    *error_message = sr_asprintf("Section %s not found", section_name);
    return 0;
}
예제 #2
0
파일: abrt.c 프로젝트: airtimemedia/satyr
struct sr_rpm_package *
sr_abrt_rpm_packages_from_dir(const char *directory,
                              char **error_message)
{

    char *epoch_str = file_contents(directory, "pkg_epoch", error_message);
    if (!epoch_str)
    {
        return NULL;
    }
    unsigned long epoch = strtoul(epoch_str, NULL, 10);
    if (epoch == ULONG_MAX)
    {
        *error_message = sr_asprintf("Epoch '%s' is not a number", epoch_str);
        return NULL;
    }
    free(epoch_str);

    struct sr_rpm_package *packages = sr_rpm_package_new();

    packages->epoch = (uint32_t)epoch;
    packages->name = file_contents(directory, "pkg_name", error_message);
    packages->version = file_contents(directory, "pkg_version", error_message);
    packages->release = file_contents(directory, "pkg_release", error_message);
    packages->architecture = file_contents(directory, "pkg_arch", error_message);
    packages->role = SR_ROLE_AFFECTED;

    if (!(packages->name && packages->version && packages->release &&
          packages->architecture))
    {
        sr_rpm_package_free(packages, false);
        return NULL;
    }

    /* Workaround abrt-action-save-kernel-data appending trailing \n for
     * koopses. */
    strip_newline(packages->name);
    strip_newline(packages->version);
    strip_newline(packages->release);
    strip_newline(packages->architecture);

    char *dso_list_contents = file_contents(directory, "dso_list",
                                            error_message);
    if (dso_list_contents)
    {
        struct sr_rpm_package *dso_packages =
            sr_abrt_parse_dso_list(dso_list_contents);

        if (dso_packages)
        {
            packages = sr_rpm_package_append(packages, dso_packages);
            packages = sr_rpm_package_sort(packages);
            packages = sr_rpm_package_uniq(packages);
        }

        free(dso_list_contents);
    }

    return packages;
}
예제 #3
0
char *
sr_core_stacktrace_get_reason(struct sr_core_stacktrace *stacktrace)
{
    char *prog = stacktrace->executable ? stacktrace->executable : "<unknown>";

    return sr_asprintf("Program %s was terminated by signal %"PRIu16, prog, stacktrace->signal);
}
예제 #4
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
}
예제 #5
0
파일: core_unwind.c 프로젝트: credmon/satyr
struct sr_core_stacktrace *
sr_parse_coredump(const char *coredump_filename,
                  const char *executable_filename,
                  char **error_message)
{
    *error_message = sr_asprintf("satyr is built without unwind support");
    return NULL;
}
예제 #6
0
파일: core_unwind.c 프로젝트: credmon/satyr
struct sr_core_stacktrace *
sr_core_stacktrace_from_core_hook(pid_t thread_id,
                                  const char *executable_filename,
                                  int signum,
                                  char **error_message)
{
    *error_message = sr_asprintf("satyr is built without live process unwind support");
    return NULL;
}
예제 #7
0
char *
sr_koops_stacktrace_get_reason(struct sr_koops_stacktrace *stacktrace)
{
    char *func = "<unknown>";
    char *result;

    struct sr_koops_stacktrace *copy = sr_koops_stacktrace_dup(stacktrace);
    sr_normalize_koops_stacktrace(copy);

    if (copy->frames && copy->frames->function_name)
        func = copy->frames->function_name;

    if (copy->frames && copy->frames->module_name)
    {
        result = sr_asprintf("Kernel oops in %s [%s]", func,
                copy->frames->module_name);
    }
    else
        result = sr_asprintf("Kernel oops in %s", func);

    sr_koops_stacktrace_free(copy);

    return result;
}
예제 #8
0
char *
sr_python_stacktrace_get_reason(struct sr_python_stacktrace *stacktrace)
{
    char *exc = "Unknown error";
    char *file = "<unknown>";
    uint32_t line = 0;

    struct sr_python_frame *frame = stacktrace->frames;
    while (frame && frame->next)
        frame = frame->next;

    if (frame)
    {
        file = frame->file_name;
        line = frame->file_line;
    }

    if (stacktrace->exception_name)
        exc = stacktrace->exception_name;

    return sr_asprintf("%s in %s:%"PRIu32, exc, file, line);
}
예제 #9
0
void
sr_normalize_gdb_paired_unknown_function_names(struct sr_gdb_thread *thread1,
                                               struct sr_gdb_thread *thread2)

{
    if (!thread1->frames || !thread2->frames)
    {
        return;
    }

    int i = 0;
    struct sr_gdb_frame *curr_frame1 = thread1->frames;
    struct sr_gdb_frame *curr_frame2 = thread2->frames;

    if (0 == sr_strcmp0(curr_frame1->function_name, "??") &&
        0 == sr_strcmp0(curr_frame2->function_name, "??") &&
        !(curr_frame1->library_name && curr_frame2->library_name &&
          strcmp(curr_frame1->library_name, curr_frame2->library_name)) &&
        next_functions_similar(curr_frame1, curr_frame2))
    {
        free(curr_frame1->function_name);
        curr_frame1->function_name = sr_asprintf("__unknown_function_%d", i);
        free(curr_frame2->function_name);
        curr_frame2->function_name = sr_asprintf("__unknown_function_%d", i);
        i++;
    }

    struct sr_gdb_frame *prev_frame1 = curr_frame1;
    struct sr_gdb_frame *prev_frame2 = curr_frame2;
    curr_frame1 = curr_frame1->next;
    curr_frame2 = curr_frame2->next;

    while (curr_frame1)
    {
        if (0 == sr_strcmp0(curr_frame1->function_name, "??"))
        {
            while (curr_frame2)
            {
                if (0 == sr_strcmp0(curr_frame2->function_name, "??") &&
                    !(curr_frame1->library_name && curr_frame2->library_name &&
                      strcmp(curr_frame1->library_name, curr_frame2->library_name)) &&
                    0 != sr_strcmp0(prev_frame2->function_name, "??") &&
                    next_functions_similar(curr_frame1, curr_frame2) &&
                    0 == sr_strcmp0(prev_frame1->function_name,
                                     prev_frame2->function_name) &&
                    !(prev_frame1->library_name && prev_frame2->library_name &&
                      strcmp(prev_frame1->library_name, prev_frame2->library_name)))
                {
                    free(curr_frame1->function_name);
                    curr_frame1->function_name = sr_asprintf("__unknown_function_%d", i);
                    free(curr_frame2->function_name);
                    curr_frame2->function_name = sr_asprintf("__unknown_function_%d", i);
                    i++;
                    break;
                }
                prev_frame2 = curr_frame2;
                curr_frame2 = curr_frame2->next;
            }
        }
        prev_frame1 = curr_frame1;
        curr_frame1 = curr_frame1->next;
        prev_frame2 = thread2->frames;
        curr_frame2 = prev_frame2->next;
    }
}
예제 #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
static struct cie *
read_cie(Dwarf_CFI_Entry *cfi,
         Dwarf_Off cfi_offset,
         unsigned char *e_ident,
         char **error_message)
{
    /* Default FDE encoding (i.e. no R in augmentation string) is
     * DW_EH_PE_absptr.
     */
    struct cie *cie = sr_mallocz(sizeof(struct cie));
    cie->cie_offset = cfi_offset;
    cie->ptr_len = encoded_size(DW_EH_PE_absptr, e_ident);

    /* Search the augmentation data for FDE pointer encoding.
     * Unfortunately, 'P' can come before 'R' (which we are looking
     * for), so we may have to parse the whole thing. See the
     * abovementioned blog post for details.
     */
    const char *augmentation = cfi->cie.augmentation;
    const uint8_t *augmentation_data = cfi->cie.augmentation_data;
    if (*augmentation == 'z')
        ++augmentation;

    while (*augmentation != '\0')
    {
        switch (*augmentation)
        {
        case 'R':
            cie->ptr_len = encoded_size(*augmentation_data, e_ident);
            if (cie->ptr_len != 4 && cie->ptr_len != 8)
            {
                *error_message = sr_asprintf("Unknown FDE encoding (CIE %jx)",
                                             (uintmax_t)cfi_offset);
                free(cie);
                return NULL;
            }

            if ((*augmentation_data & 0x70) == DW_EH_PE_pcrel)
                cie->pcrel = true;

            return cie;
        case 'L':
            ++augmentation_data;
            break;
        case 'P':
        {
            unsigned size = encoded_size(*augmentation_data, e_ident);
            if (0 == size)
            {
                *error_message = sr_asprintf("Unknown size for personality encoding (CIE %jx)",
                                             (uintmax_t)cfi_offset);

                free(cie);
                return NULL;
            }

            augmentation_data += size + 1;
            break;
        }
        default:
            *error_message = sr_asprintf("Unknown augmentation char (CIE %jx)",
                                         (uintmax_t)cfi_offset);
            free(cie);
            return NULL;
        }

        ++augmentation;
    }

    return cie;
}
예제 #12
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 */
}
예제 #13
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
}
예제 #14
0
파일: python_frame.c 프로젝트: abrt/satyr
struct sr_python_frame *
sr_python_frame_parse(const char **input,
                      struct sr_location *location)
{
    const char *local_input = *input;

    if (0 == sr_skip_string(&local_input, "  File \""))
    {
        location->message = sr_asprintf("Frame header not found.");
        return NULL;
    }

    location->column += strlen("  File \"");
    struct sr_python_frame *frame = sr_python_frame_new();

    /* Parse file name */
    if (!sr_parse_char_cspan(&local_input, "\"", &frame->file_name))
    {
        location->message = sr_asprintf("Unable to find the '\"' character "
                "identifying the beginning of file name.");

        goto fail;
    }

    if (strlen(frame->file_name) > 0 &&
        frame->file_name[0] == '<' &&
        frame->file_name[strlen(frame->file_name)-1] == '>')
    {
        frame->special_file = true;
        frame->file_name[strlen(frame->file_name)-1] = '\0';
        char *inside = sr_strdup(frame->file_name + 1);
        free(frame->file_name);
        frame->file_name = inside;
    }

    frame->file_name = anonymize_path(frame->file_name);

    location->column += strlen(frame->file_name);

    if (0 == sr_skip_string(&local_input, "\", line "))
    {
        location->message = sr_asprintf("Line separator not found.");
        goto fail;
    }

    location->column += strlen("\", line ");

    /* Parse line number */
    int length = sr_parse_uint32(&local_input, &frame->file_line);
    if (0 == length)
    {
        location->message = sr_asprintf("Line number not found.");
        goto fail;
    }

    location->column += length;

    if (0 == sr_skip_string(&local_input, ", in "))
    {
        if (local_input[0] != '\n')
        {
            location->message = sr_asprintf("Function name separator not found.");
            goto fail;
        }

        /* The last frame of SyntaxError stack trace does not have
         * function name on its line. For the sake of simplicity, we will
         * believe that we are dealing with such a frame now.
         */
        frame->function_name = sr_strdup("syntax");
        frame->special_function = true;
    }
    else
    {
        location->column += strlen(", in ");

        /* Parse function name */
        if (!sr_parse_char_cspan(&local_input, "\n", &frame->function_name))
        {
            location->message = sr_asprintf("Unable to find the newline character "
                    "identifying the end of function name.");

            goto fail;
        }

        location->column += strlen(frame->function_name);

        if (strlen(frame->function_name) > 0 &&
            frame->function_name[0] == '<' &&
            frame->function_name[strlen(frame->function_name)-1] == '>')
        {
            frame->special_function = true;
            frame->function_name[strlen(frame->function_name)-1] = '\0';
            char *inside = sr_strdup(frame->function_name + 1);
            free(frame->function_name);
            frame->function_name = inside;
        }
    }

    if (sr_skip_char(&local_input, '\n'))
        sr_location_add(location, 1, 0);

    /* Parse source code line (optional). */
    if (4 == sr_skip_string(&local_input, "    "))
    {
        if (sr_parse_char_cspan(&local_input, "\n", &frame->line_contents)
                && sr_skip_char(&local_input, '\n'))
            sr_location_add(location, 1, 0);
    }

    *input = local_input;
    return frame;

fail:
    sr_python_frame_free(frame);
    return NULL;
}