Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
SUSE:SLE-12:Update
ltrace
ltrace-ppc64le_git10.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File ltrace-ppc64le_git10.patch of Package ltrace
--- libltrace.c.ori +++ libltrace.c @@ -1,6 +1,6 @@ /* * This file is part of ltrace. - * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. + * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc. * Copyright (C) 2009 Juan Cespedes * * This program is free software; you can redistribute it and/or @@ -136,9 +136,9 @@ ltrace_init(int argc, char **argv) { if (command) { /* Check that the binary ABI is supported before * calling execute_program. */ - struct ltelf lte = {}; - open_elf(<e, command); - do_close_elf(<e); + struct ltelf lte; + ltelf_init(<e, command); + ltelf_destroy(<e); pid_t pid = execute_program(command, argv); struct Process *proc = open_program(command, pid); --- ltrace-elf.c.ori +++ ltrace-elf.c @@ -318,8 +318,9 @@ need_data(Elf_Data *data, GElf_Xword offset, GElf_Xword size) #undef DEF_READER int -open_elf(struct ltelf *lte, const char *filename) +ltelf_init(struct ltelf *lte, const char *filename) { + memset(lte, 0, sizeof *lte); lte->fd = open(filename, O_RDONLY); if (lte->fd == -1) return 1; @@ -369,9 +370,20 @@ open_elf(struct ltelf *lte, const char *filename) exit(EXIT_FAILURE); } + VECT_INIT(<e->plt_relocs, GElf_Rela); + return 0; } +void +ltelf_destroy(struct ltelf *lte) +{ + debug(DEBUG_FUNCTION, "close_elf()"); + elf_end(lte->elf); + close(lte->fd); + VECT_DESTROY(<e->plt_relocs, GElf_Rela, NULL, NULL); +} + static void read_symbol_table(struct ltelf *lte, const char *filename, Elf_Scn *scn, GElf_Shdr *shdr, const char *name, @@ -409,13 +421,86 @@ read_symbol_table(struct ltelf *lte, const char *filename, } static int -do_init_elf(struct ltelf *lte, const char *filename) +rel_to_rela(struct ltelf *lte, const GElf_Rel *rel, GElf_Rela *rela) +{ + rela->r_offset = rel->r_offset; + rela->r_info = rel->r_info; + + Elf_Scn *sec; + GElf_Shdr shdr; + if (elf_get_section_covering(lte, rel->r_offset, &sec, &shdr) < 0 + || sec == NULL) + return -1; + + Elf_Data *data = elf_loaddata(sec, &shdr); + if (data == NULL) + return -1; + + GElf_Xword offset = rel->r_offset - shdr.sh_addr - data->d_off; + uint64_t value; + if (lte->ehdr.e_ident[EI_CLASS] == ELFCLASS32) { + uint32_t tmp; + if (elf_read_u32(data, offset, &tmp) < 0) + return -1; + value = tmp; + } else if (elf_read_u64(data, offset, &value) < 0) { + return -1; + } + + rela->r_addend = value; + return 0; +} + +int +read_relplt(struct ltelf *lte, Elf_Scn *scn, GElf_Shdr *shdr, + struct vect *rela_vec) +{ + if (vect_reserve_additional(rela_vec, lte->ehdr.e_shnum) < 0) + return -1; + + Elf_Data *relplt = elf_loaddata(scn, shdr); + if (relplt == NULL) { + fprintf(stderr, "Couldn't load .rel*.plt data.\n"); + return -1; + } + + if ((shdr->sh_size % shdr->sh_entsize) != 0) { + fprintf(stderr, ".rel*.plt size (%" PRIx64 "d) not a multiple " + "of its sh_entsize (%" PRIx64 "d).\n", + shdr->sh_size, shdr->sh_entsize); + return -1; + } + + GElf_Xword relplt_count = shdr->sh_size / shdr->sh_entsize; + GElf_Xword i; + for (i = 0; i < relplt_count; ++i) { + GElf_Rela rela; + if (relplt->d_type == ELF_T_REL) { + GElf_Rel rel; + if (gelf_getrel(relplt, i, &rel) == NULL + || rel_to_rela(lte, &rel, &rela) < 0) + return -1; + + } else if (gelf_getrela(relplt, i, &rela) == NULL) { + return -1; + } + + if (VECT_PUSHBACK(rela_vec, &rela) < 0) + return -1; + } + + return 0; +} + +static int +ltelf_read_elf(struct ltelf *lte, const char *filename) { int i; GElf_Addr relplt_addr = 0; GElf_Addr soname_offset = 0; + GElf_Xword relplt_size = 0; - debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename); + debug(DEBUG_FUNCTION, "ltelf_read_elf(filename=%s)", filename); debug(1, "Reading ELF from %s...", filename); for (i = 1; i < lte->ehdr.e_shnum; ++i) { @@ -474,7 +559,7 @@ do_init_elf(struct ltelf *lte, const char *filename) if (dyn.d_tag == DT_JMPREL) relplt_addr = dyn.d_un.d_ptr; else if (dyn.d_tag == DT_PLTRELSZ) - lte->relplt_size = dyn.d_un.d_val; + relplt_size = dyn.d_un.d_val; else if (dyn.d_tag == DT_SONAME) soname_offset = dyn.d_un.d_val; } @@ -507,14 +592,9 @@ do_init_elf(struct ltelf *lte, const char *filename) if (!relplt_addr || !lte->plt_addr) { debug(1, "%s has no PLT relocations", filename); - lte->relplt = NULL; - lte->relplt_count = 0; - } else if (lte->relplt_size == 0) { + } else if (relplt_size == 0) { debug(1, "%s has unknown PLT size", filename); - lte->relplt = NULL; - lte->relplt_count = 0; } else { - for (i = 1; i < lte->ehdr.e_shnum; ++i) { Elf_Scn *scn; GElf_Shdr shdr; @@ -527,12 +607,9 @@ do_init_elf(struct ltelf *lte, const char *filename) exit(EXIT_FAILURE); } if (shdr.sh_addr == relplt_addr - && shdr.sh_size == lte->relplt_size) { - lte->relplt = elf_getdata(scn, NULL); - lte->relplt_count = - shdr.sh_size / shdr.sh_entsize; - if (lte->relplt == NULL - || elf_getdata(scn, lte->relplt) != NULL) { + && shdr.sh_size == relplt_size) { + if (read_relplt(lte, scn, &shdr, + <e->plt_relocs) < 0) { fprintf(stderr, "Couldn't get .rel*.plt" " data from \"%s\": %s\n", filename, elf_errmsg(-1)); @@ -548,9 +625,9 @@ do_init_elf(struct ltelf *lte, const char *filename) filename); exit(EXIT_FAILURE); } - - debug(1, "%s %zd PLT relocations", filename, lte->relplt_count); } + debug(1, "%s %zd PLT relocations", filename, + vect_size(<e->plt_relocs)); if (soname_offset != 0) lte->soname = lte->dynstr + soname_offset; @@ -558,51 +635,13 @@ do_init_elf(struct ltelf *lte, const char *filename) return 0; } -void -do_close_elf(struct ltelf *lte) -{ - debug(DEBUG_FUNCTION, "do_close_elf()"); - arch_elf_destroy(lte); - elf_end(lte->elf); - close(lte->fd); -} - -int -elf_get_sym_info(struct ltelf *lte, const char *filename, - size_t sym_index, GElf_Rela *rela, GElf_Sym *sym) -{ - int i = sym_index; - GElf_Rel rel; - void *ret; - - if (lte->relplt->d_type == ELF_T_REL) { - ret = gelf_getrel(lte->relplt, i, &rel); - rela->r_offset = rel.r_offset; - rela->r_info = rel.r_info; - rela->r_addend = 0; - } else { - ret = gelf_getrela(lte->relplt, i, rela); - } - - if (ret == NULL - || ELF64_R_SYM(rela->r_info) >= lte->dynsym_count - || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela->r_info), - sym) == NULL) { - fprintf(stderr, - "Couldn't get relocation from \"%s\": %s\n", - filename, elf_errmsg(-1)); - exit(EXIT_FAILURE); - } - - return 0; -} - #ifndef ARCH_HAVE_GET_SYMINFO int arch_get_sym_info(struct ltelf *lte, const char *filename, size_t sym_index, GElf_Rela *rela, GElf_Sym *sym) { - return elf_get_sym_info(lte, filename, sym_index, rela, sym); + return gelf_getsym(lte->dynsym, + ELF64_R_SYM(rela->r_info), sym) != NULL ? 0 : -1; } #endif @@ -649,12 +688,13 @@ populate_plt(struct Process *proc, const char *filename, struct ltelf *lte, struct library *lib, int latent_plts) { + size_t count = vect_size(<e->plt_relocs); size_t i; - for (i = 0; i < lte->relplt_count; ++i) { - GElf_Rela rela; + for (i = 0; i < count; ++i) { + GElf_Rela *rela = VECT_ELEMENT(<e->plt_relocs, GElf_Rela, i); GElf_Sym sym; - if (arch_get_sym_info(lte, filename, i, &rela, &sym) < 0) + if (arch_get_sym_info(lte, filename, i, rela, &sym) < 0) continue; /* Skip this entry. */ char const *name = lte->dynstr + sym.st_name; @@ -664,14 +704,14 @@ populate_plt(struct Process *proc, const char *filename, struct library_symbol *libsym = NULL; switch (arch_elf_add_plt_entry(proc, lte, name, - &rela, i, &libsym)) { + rela, i, &libsym)) { case plt_fail: return -1; case plt_default: /* Add default entry to the beginning of LIBSYM. */ if (default_elf_add_plt_entry(proc, lte, name, - &rela, i, &libsym) < 0) + rela, i, &libsym) < 0) return -1; /* fall-through */ case plt_ok: @@ -951,8 +991,8 @@ static int read_module(struct library *lib, struct Process *proc, const char *filename, GElf_Addr bias, int main) { - struct ltelf lte = {}; - if (open_elf(<e, filename) < 0) + struct ltelf lte; + if (ltelf_init(<e, filename) < 0) return -1; /* XXX When we abstract ABI into a module, this should instead @@ -960,8 +1000,8 @@ read_module(struct library *lib, struct Process *proc, * * proc->abi = arch_get_abi(lte.ehdr); * - * The code in open_elf needs to be replaced by this logic. - * Be warned that libltrace.c calls open_elf as well to + * The code in ltelf_init needs to be replaced by this logic. + * Be warned that libltrace.c calls ltelf_init as well to * determine whether ABI is supported. This is to get * reasonable error messages when trying to run 64-bit binary * with 32-bit ltrace. It is desirable to preserve this. */ @@ -976,6 +1016,8 @@ read_module(struct library *lib, struct Process *proc, if (process_get_entry(proc, &entry, NULL) < 0) { fprintf(stderr, "Couldn't find entry of PIE %s\n", filename); + fail: + ltelf_destroy(<e); return -1; } /* XXX The double cast should be removed when @@ -1000,19 +1042,18 @@ read_module(struct library *lib, struct Process *proc, fprintf(stderr, "Couldn't determine base address of %s\n", filename); - return -1; + goto fail; } } - if (do_init_elf(<e, filename) < 0) - return -1; + if (ltelf_read_elf(<e, filename) < 0) + goto fail; if (arch_elf_init(<e, lib) < 0) { fprintf(stderr, "Backend initialization failed.\n"); - return -1; + goto fail; } - int status = 0; if (lib == NULL) goto fail; @@ -1078,13 +1119,9 @@ read_module(struct library *lib, struct Process *proc, symtabs, exports) < 0) goto fail; -done: - do_close_elf(<e); - return status; - -fail: - status = -1; - goto done; + arch_elf_destroy(<e); + ltelf_destroy(<e); + return 0; } int --- ltrace-elf.h.ori +++ ltrace-elf.h @@ -28,6 +28,7 @@ #include <stdlib.h> #include <callback.h> #include "sysdep.h" +#include "vect.h" struct Process; struct library; @@ -49,9 +50,11 @@ struct ltelf { GElf_Addr plt_addr; GElf_Word plt_flags; size_t plt_size; - Elf_Data *relplt; Elf_Data *plt_data; - size_t relplt_count; + + /* Vector of GElf_Rela with PLT relocations. */ + struct vect plt_relocs; + Elf_Data *symtab; const char *strtab; const char *soname; @@ -61,15 +64,14 @@ struct ltelf { size_t opd_size; GElf_Addr dyn_addr; size_t dyn_sz; - size_t relplt_size; GElf_Addr bias; GElf_Addr entry_addr; GElf_Addr base_addr; struct arch_ltelf_data arch; }; -int open_elf(struct ltelf *lte, const char *filename); -void do_close_elf(struct ltelf *lte); +int ltelf_init(struct ltelf *lte, const char *filename); +void ltelf_destroy(struct ltelf *lte); /* XXX is it possible to put breakpoints in VDSO and VSYSCALL * pseudo-libraries? For now we assume that all libraries can be @@ -92,11 +94,6 @@ int default_elf_add_plt_entry(struct Process *proc, struct ltelf *lte, const char *a_name, GElf_Rela *rela, size_t ndx, struct library_symbol **ret); -/* The base implementation of backend.h (arch_get_sym_info). - * See backend.h for details. */ -int elf_get_sym_info(struct ltelf *lte, const char *filename, - size_t sym_index, GElf_Rela *rela, GElf_Sym *sym); - Elf_Data *elf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr); int elf_get_section_covering(struct ltelf *lte, GElf_Addr addr, Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr); --- sysdeps/linux-gnu/mipsel/plt.c.ori +++ sysdeps/linux-gnu/mipsel/plt.c @@ -158,8 +158,9 @@ int { const char *name; - if (mips_elf_is_cpic(lte->ehdr.e_flags)) { - return elf_get_sym_info(lte, filename, sym_index, rela, sym); + if (mips_elf_is_cpic(lte->ehdr.e_flags)) { + return gelf_getsym(lte->dynsym, ELF64_R_SYM(rela->r_info), + sym) != NULL ? 0 : -1; } /* Fixup the offset. */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor