summaryrefslogtreecommitdiff
path: root/sysdeps/linux-gnu
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2013-11-04 22:48:38 -0500
committerChanho Park <chanho61.park@samsung.com>2014-08-22 20:38:23 +0900
commitbf95c098bba38573ee9b3f8918b0cdca30e6d5fc (patch)
tree5d81ee11f77db95b3a0a0d58be3c5d126efa8e2a /sysdeps/linux-gnu
parent391db0f031d2c15ae2eef1b3edab76e80d5c0979 (diff)
downloadltrace-bf95c098bba38573ee9b3f8918b0cdca30e6d5fc.tar.gz
ltrace-bf95c098bba38573ee9b3f8918b0cdca30e6d5fc.tar.bz2
ltrace-bf95c098bba38573ee9b3f8918b0cdca30e6d5fc.zip
In ARM backend, move hooks for ltrace_elf and library to plt.c
- That's the customary location for backend hooks.
Diffstat (limited to 'sysdeps/linux-gnu')
-rw-r--r--sysdeps/linux-gnu/arm/fetch.c188
-rw-r--r--sysdeps/linux-gnu/arm/plt.c194
2 files changed, 192 insertions, 190 deletions
diff --git a/sysdeps/linux-gnu/arm/fetch.c b/sysdeps/linux-gnu/arm/fetch.c
index 5081d78..b500448 100644
--- a/sysdeps/linux-gnu/arm/fetch.c
+++ b/sysdeps/linux-gnu/arm/fetch.c
@@ -32,200 +32,12 @@
#include "backend.h"
#include "fetch.h"
#include "library.h"
-#include "ltrace-elf.h"
#include "proc.h"
#include "ptrace.h"
#include "regs.h"
#include "type.h"
#include "value.h"
-static int
-get_hardfp(uint64_t abi_vfp_args)
-{
- if (abi_vfp_args == 2)
- fprintf(stderr,
- "Tag_ABI_VFP_args value 2 (tool chain-specific "
- "conventions) not supported.\n");
- return abi_vfp_args == 1;
-}
-
-int
-arch_elf_init(struct ltelf *lte, struct library *lib)
-{
- /* Nothing in this section is strictly critical. It's not
- * that much of a deal if we fail to guess right whether the
- * ABI is softfp or hardfp. */
- unsigned hardfp = 0;
-
- Elf_Scn *scn;
- Elf_Data *data;
- GElf_Shdr shdr;
- if (elf_get_section_type(lte, SHT_ARM_ATTRIBUTES, &scn, &shdr) < 0
- || (scn != NULL && (data = elf_loaddata(scn, &shdr)) == NULL)) {
- fprintf(stderr,
- "Error when obtaining ARM attribute section: %s\n",
- elf_errmsg(-1));
- goto done;
-
- } else if (scn != NULL && data != NULL) {
- GElf_Xword offset = 0;
- uint8_t version;
- if (elf_read_next_u8(data, &offset, &version) < 0) {
- goto done;
- } else if (version != 'A') {
- fprintf(stderr, "Unsupported ARM attribute section "
- "version %d ('%c').\n", version, version);
- goto done;
- }
-
- do {
- const char signature[] = "aeabi";
- /* N.B. LEN is including the length field
- * itself. */
- uint32_t sec_len;
- if (elf_read_u32(data, offset, &sec_len) < 0
- || !elf_can_read_next(data, offset, sec_len)) {
- goto done;
- }
- const GElf_Xword next_offset = offset + sec_len;
- offset += 4;
-
- if (sec_len < 4 + sizeof signature
- || strcmp(signature, data->d_buf + offset) != 0)
- goto skip;
- offset += sizeof signature;
-
- const GElf_Xword offset0 = offset;
- uint64_t tag;
- uint32_t sub_len;
- if (elf_read_next_uleb128(data, &offset, &tag) < 0
- || elf_read_next_u32(data, &offset, &sub_len) < 0
- || !elf_can_read_next(data, offset0, sub_len))
- goto done;
-
- if (tag != 1)
- /* IHI0045D_ABI_addenda: "section and
- * symbol attributes are deprecated
- * [...] consumers are permitted to
- * ignore them." */
- goto skip;
-
- while (offset < offset0 + sub_len) {
- if (elf_read_next_uleb128(data,
- &offset, &tag) < 0)
- goto done;
-
- switch (tag) {
- uint64_t v;
- case 6: /* Tag_CPU_arch */
- case 7: /* Tag_CPU_arch_profile */
- case 8: /* Tag_ARM_ISA_use */
- case 9: /* Tag_THUMB_ISA_use */
- case 10: /* Tag_FP_arch */
- case 11: /* Tag_WMMX_arch */
- case 12: /* Tag_Advanced_SIMD_arch */
- case 13: /* Tag_PCS_config */
- case 14: /* Tag_ABI_PCS_R9_use */
- case 15: /* Tag_ABI_PCS_RW_data */
- case 16: /* Tag_ABI_PCS_RO_data */
- case 17: /* Tag_ABI_PCS_GOT_use */
- case 18: /* Tag_ABI_PCS_wchar_t */
- case 19: /* Tag_ABI_FP_rounding */
- case 20: /* Tag_ABI_FP_denormal */
- case 21: /* Tag_ABI_FP_exceptions */
- case 22: /* Tag_ABI_FP_user_exceptions */
- case 23: /* Tag_ABI_FP_number_model */
- case 24: /* Tag_ABI_align_needed */
- case 25: /* Tag_ABI_align_preserved */
- case 26: /* Tag_ABI_enum_size */
- case 27: /* Tag_ABI_HardFP_use */
- case 28: /* Tag_ABI_VFP_args */
- case 29: /* Tag_ABI_WMMX_args */
- case 30: /* Tag_ABI_optimization_goals */
- case 31: /* Tag_ABI_FP_optimization_goals */
- case 32: /* Tag_compatibility */
- case 34: /* Tag_CPU_unaligned_access */
- case 36: /* Tag_FP_HP_extension */
- case 38: /* Tag_ABI_FP_16bit_format */
- case 42: /* Tag_MPextension_use */
- case 70: /* Tag_MPextension_use as well */
- case 44: /* Tag_DIV_use */
- case 64: /* Tag_nodefaults */
- case 66: /* Tag_T2EE_use */
- case 68: /* Tag_Virtualization_use */
- uleb128:
- if (elf_read_next_uleb128
- (data, &offset, &v) < 0)
- goto done;
- if (tag == 28)
- hardfp = get_hardfp(v);
- if (tag != 32)
- continue;
-
- /* Tag 32 has two arguments,
- * fall through. */
-
- case 4: /* Tag_CPU_raw_name */
- case 5: /* Tag_CPU_name */
- case 65: /* Tag_also_compatible_with */
- case 67: /* Tag_conformance */
- ntbs:
- offset += strlen(data->d_buf
- + offset) + 1;
- continue;
- }
-
- /* Handle unknown tags in a generic
- * manner, if possible. */
- if (tag <= 32) {
- fprintf(stderr,
- "Unknown tag %lld "
- "at offset %#llx "
- "of ARM attribute section.",
- tag, offset);
- goto skip;
- } else if (tag % 2 == 0) {
- goto uleb128;
- } else {
- goto ntbs;
- }
- }
-
- skip:
- offset = next_offset;
-
- } while (elf_can_read_next(data, offset, 1));
-
- }
-
-done:
- lib->arch.hardfp = hardfp;
- return 0;
-}
-
-void
-arch_elf_destroy(struct ltelf *lte)
-{
-}
-
-int
-arch_library_init(struct library *lib)
-{
- return 0;
-}
-
-void
-arch_library_destroy(struct library *lib)
-{
-}
-
-int
-arch_library_clone(struct library *retp, struct library *lib)
-{
- retp->arch = lib->arch;
- return 0;
-}
-
enum {
/* How many (double) VFP registers the AAPCS uses for
* parameter passing. */
diff --git a/sysdeps/linux-gnu/arm/plt.c b/sysdeps/linux-gnu/arm/plt.c
index d1bf7ca..649f73a 100644
--- a/sysdeps/linux-gnu/arm/plt.c
+++ b/sysdeps/linux-gnu/arm/plt.c
@@ -20,20 +20,192 @@
*/
#include <gelf.h>
+#include <stdio.h>
+#include <string.h>
#include "proc.h"
#include "library.h"
#include "ltrace-elf.h"
static int
+get_hardfp(uint64_t abi_vfp_args)
+{
+ if (abi_vfp_args == 2)
+ fprintf(stderr,
+ "Tag_ABI_VFP_args value 2 (tool chain-specific "
+ "conventions) not supported.\n");
+ return abi_vfp_args == 1;
+}
+
+int
+arch_elf_init(struct ltelf *lte, struct library *lib)
+{
+ /* Nothing in this section is strictly critical. It's not
+ * that much of a deal if we fail to guess right whether the
+ * ABI is softfp or hardfp. */
+ unsigned hardfp = 0;
+
+ Elf_Scn *scn;
+ Elf_Data *data;
+ GElf_Shdr shdr;
+ if (elf_get_section_type(lte, SHT_ARM_ATTRIBUTES, &scn, &shdr) < 0
+ || (scn != NULL && (data = elf_loaddata(scn, &shdr)) == NULL)) {
+ fprintf(stderr,
+ "Error when obtaining ARM attribute section: %s\n",
+ elf_errmsg(-1));
+ goto done;
+
+ } else if (scn != NULL && data != NULL) {
+ GElf_Xword offset = 0;
+ uint8_t version;
+ if (elf_read_next_u8(data, &offset, &version) < 0) {
+ goto done;
+ } else if (version != 'A') {
+ fprintf(stderr, "Unsupported ARM attribute section "
+ "version %d ('%c').\n", version, version);
+ goto done;
+ }
+
+ do {
+ const char signature[] = "aeabi";
+ /* N.B. LEN is including the length field
+ * itself. */
+ uint32_t sec_len;
+ if (elf_read_u32(data, offset, &sec_len) < 0
+ || !elf_can_read_next(data, offset, sec_len)) {
+ goto done;
+ }
+ const GElf_Xword next_offset = offset + sec_len;
+ offset += 4;
+
+ if (sec_len < 4 + sizeof signature
+ || strcmp(signature, data->d_buf + offset) != 0)
+ goto skip;
+ offset += sizeof signature;
+
+ const GElf_Xword offset0 = offset;
+ uint64_t tag;
+ uint32_t sub_len;
+ if (elf_read_next_uleb128(data, &offset, &tag) < 0
+ || elf_read_next_u32(data, &offset, &sub_len) < 0
+ || !elf_can_read_next(data, offset0, sub_len))
+ goto done;
+
+ if (tag != 1)
+ /* IHI0045D_ABI_addenda: "section and
+ * symbol attributes are deprecated
+ * [...] consumers are permitted to
+ * ignore them." */
+ goto skip;
+
+ while (offset < offset0 + sub_len) {
+ if (elf_read_next_uleb128(data,
+ &offset, &tag) < 0)
+ goto done;
+
+ switch (tag) {
+ uint64_t v;
+ case 6: /* Tag_CPU_arch */
+ case 7: /* Tag_CPU_arch_profile */
+ case 8: /* Tag_ARM_ISA_use */
+ case 9: /* Tag_THUMB_ISA_use */
+ case 10: /* Tag_FP_arch */
+ case 11: /* Tag_WMMX_arch */
+ case 12: /* Tag_Advanced_SIMD_arch */
+ case 13: /* Tag_PCS_config */
+ case 14: /* Tag_ABI_PCS_R9_use */
+ case 15: /* Tag_ABI_PCS_RW_data */
+ case 16: /* Tag_ABI_PCS_RO_data */
+ case 17: /* Tag_ABI_PCS_GOT_use */
+ case 18: /* Tag_ABI_PCS_wchar_t */
+ case 19: /* Tag_ABI_FP_rounding */
+ case 20: /* Tag_ABI_FP_denormal */
+ case 21: /* Tag_ABI_FP_exceptions */
+ case 22: /* Tag_ABI_FP_user_exceptions */
+ case 23: /* Tag_ABI_FP_number_model */
+ case 24: /* Tag_ABI_align_needed */
+ case 25: /* Tag_ABI_align_preserved */
+ case 26: /* Tag_ABI_enum_size */
+ case 27: /* Tag_ABI_HardFP_use */
+ case 28: /* Tag_ABI_VFP_args */
+ case 29: /* Tag_ABI_WMMX_args */
+ case 30: /* Tag_ABI_optimization_goals */
+ case 31: /* Tag_ABI_FP_optimization_goals */
+ case 32: /* Tag_compatibility */
+ case 34: /* Tag_CPU_unaligned_access */
+ case 36: /* Tag_FP_HP_extension */
+ case 38: /* Tag_ABI_FP_16bit_format */
+ case 42: /* Tag_MPextension_use */
+ case 70: /* Tag_MPextension_use as well */
+ case 44: /* Tag_DIV_use */
+ case 64: /* Tag_nodefaults */
+ case 66: /* Tag_T2EE_use */
+ case 68: /* Tag_Virtualization_use */
+ uleb128:
+ if (elf_read_next_uleb128
+ (data, &offset, &v) < 0)
+ goto done;
+ if (tag == 28)
+ hardfp = get_hardfp(v);
+ if (tag != 32)
+ continue;
+
+ /* Tag 32 has two arguments,
+ * fall through. */
+
+ case 4: /* Tag_CPU_raw_name */
+ case 5: /* Tag_CPU_name */
+ case 65: /* Tag_also_compatible_with */
+ case 67: /* Tag_conformance */
+ ntbs:
+ offset += strlen(data->d_buf
+ + offset) + 1;
+ continue;
+ }
+
+ /* Handle unknown tags in a generic
+ * manner, if possible. */
+ if (tag <= 32) {
+ fprintf(stderr,
+ "Unknown tag %lld "
+ "at offset %#llx "
+ "of ARM attribute section.",
+ tag, offset);
+ goto skip;
+ } else if (tag % 2 == 0) {
+ goto uleb128;
+ } else {
+ goto ntbs;
+ }
+ }
+
+ skip:
+ offset = next_offset;
+
+ } while (elf_can_read_next(data, offset, 1));
+
+ }
+
+done:
+ lib->arch.hardfp = hardfp;
+ return 0;
+}
+
+void
+arch_elf_destroy(struct ltelf *lte)
+{
+}
+
+static int
arch_plt_entry_has_stub(struct ltelf *lte, size_t off) {
- uint16_t op = *(uint16_t *)((char *)lte->relplt->d_buf + off);
+ char *buf = (char *) lte->arch.jmprel_data->d_buf;
+ uint16_t op = *(uint16_t *) (buf + off);
return op == 0x4778;
}
GElf_Addr
arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
- size_t start = lte->relplt->d_size + 12;
+ size_t start = lte->arch.jmprel_data->d_size + 12;
size_t off = start + 20, i;
for (i = 0; i < ndx; i++)
off += arch_plt_entry_has_stub(lte, off) ? 16 : 12;
@@ -47,3 +219,21 @@ sym2addr(struct process *proc, struct library_symbol *sym)
{
return sym->enter_addr;
}
+
+int
+arch_library_init(struct library *lib)
+{
+ return 0;
+}
+
+void
+arch_library_destroy(struct library *lib)
+{
+}
+
+int
+arch_library_clone(struct library *retp, struct library *lib)
+{
+ retp->arch = lib->arch;
+ return 0;
+}