Sanitize interface of arch_get_sym_info/elf_get_sym_info
- <0 for errors, ==0 for OK, 1 for skip. Errors are now propagated
and can be handled as necessary without cancelling tracing.
- Clarify the comment at arch_get_sym_info.
diff --git a/backend.h b/backend.h
index 6edc948..44eea6d 100644
--- a/backend.h
+++ b/backend.h
@@ -277,17 +277,17 @@
/* The following callback has to be implemented in backend if arch.h
* defines ARCH_HAVE_GET_SYM_INFO.
*
- * This is called for every PLT relocation R in ELF file LTE, that
- * ltrace is about to add to it's internal representation of the
- * program under trace.
- * The corresponding PLT entry is for SYM_INDEX-th relocation in the file.
+ * This is called for every PLT relocation RELA in ELF file LTE (which
+ * is named FILENAME), that ltrace is about to add. The corresponding
+ * PLT entry is for SYM_INDEX-th relocation in the file. This call is
+ * supposed to initialize SYM and RELA. It returns 0 if there were no
+ * errors and given symbol should be used, 1 if the symbol should not
+ * be used, or a negative value if there were errors.
*
- * The callback is responsible for initializing RELA and SYM.
- *
- * Return 0 if OK.
- * Return a negative value if this symbol (SYM_INDEX) should be ignored. */
-int arch_get_sym_info(struct ltelf *lte, const char *filename,
- size_t sym_index, GElf_Rela *rela, GElf_Sym *sym);
+ * The backend implementation can delegate some of the work to default
+ * implementation in elf_get_sym_info. */
+int arch_get_sym_info(struct ltelf *lte, const char *filename, size_t sym_index,
+ GElf_Rela *rela, GElf_Sym *sym);
enum plt_status {
PLT_FAIL,
diff --git a/ltrace-elf.c b/ltrace-elf.c
index 93e0d5e..b42f27a 100644
--- a/ltrace-elf.c
+++ b/ltrace-elf.c
@@ -548,28 +548,23 @@
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);
+ if (gelf_getrel(lte->relplt, sym_index, &rel) == NULL)
+ return -1;
rela->r_offset = rel.r_offset;
rela->r_info = rel.r_info;
rela->r_addend = 0;
- } else {
- ret = gelf_getrela(lte->relplt, i, rela);
+
+ } else if (gelf_getrela(lte->relplt, sym_index, rela) == NULL) {
+ return -1;
}
- 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);
- }
+ if (ELF64_R_SYM(rela->r_info) >= lte->dynsym_count
+ || gelf_getsym(lte->dynsym,
+ ELF64_R_SYM(rela->r_info), sym) == NULL)
+ return -1;
return 0;
}
@@ -602,8 +597,18 @@
GElf_Rela rela;
GElf_Sym sym;
- if (arch_get_sym_info(lte, filename, i, &rela, &sym) < 0)
+ switch (arch_get_sym_info(lte, filename, i, &rela, &sym)) {
+ default:
+ fprintf(stderr,
+ "Couldn't get relocation for symbol #%zd"
+ " from \"%s\": %s\n",
+ i, filename, elf_errmsg(-1));
+ /* Fall through. */
+ case 1:
continue; /* Skip this entry. */
+ case 0:
+ break;
+ }
char const *name = lte->dynstr + sym.st_name;
diff --git a/ltrace-elf.h b/ltrace-elf.h
index 5bf72ed..1287bc1 100644
--- a/ltrace-elf.h
+++ b/ltrace-elf.h
@@ -91,8 +91,8 @@
/* 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);
+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);
diff --git a/sysdeps/linux-gnu/mips/plt.c b/sysdeps/linux-gnu/mips/plt.c
index e8527d7..3a95089 100644
--- a/sysdeps/linux-gnu/mips/plt.c
+++ b/sysdeps/linux-gnu/mips/plt.c
@@ -1,7 +1,7 @@
/*
* This file is part of ltrace.
+ * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
* Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
- * Copyright (C) 2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2008,2009 Juan Cespedes
* Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
*
@@ -157,24 +157,19 @@
arch_get_sym_info(struct ltelf *lte, const char *filename,
size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
{
- const char *name;
-
- if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+ if (mips_elf_is_cpic(lte->ehdr.e_flags))
return elf_get_sym_info(lte, filename, sym_index, rela, sym);
- }
/* Fixup the offset. */
sym_index += lte->arch.mips_gotsym;
- if (gelf_getsym(lte->dynsym, sym_index, sym) == NULL){
- error(EXIT_FAILURE, 0,
- "Couldn't get relocation from \"%s\"", filename);
- }
-
- name = lte->dynstr + sym->st_name;
- if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) {
- debug(2, "sym %s not a function", name);
+ if (gelf_getsym(lte->dynsym, sym_index, sym) == NULL)
return -1;
+
+ if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) {
+ const char *name = lte->dynstr + sym->st_name;
+ debug(2, "sym %s not a function", name);
+ return 1;
}
return 0;