[Ltrace-devel] [PATCH] xtensa: add xtensa support
Max Filippov
jcmvbkbc at gmail.com
Tue Jun 17 09:41:29 UTC 2014
Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
---
configure.ac | 2 +
proc.c | 2 +-
sysdeps/linux-gnu/Makefile.am | 2 +-
sysdeps/linux-gnu/xtensa/Makefile.am | 35 ++++
sysdeps/linux-gnu/xtensa/arch.h | 69 +++++++
sysdeps/linux-gnu/xtensa/breakpoint.c | 71 +++++++
sysdeps/linux-gnu/xtensa/plt.c | 192 ++++++++++++++++++
sysdeps/linux-gnu/xtensa/ptrace.h | 21 ++
sysdeps/linux-gnu/xtensa/regs.c | 52 +++++
sysdeps/linux-gnu/xtensa/signalent.h | 52 +++++
sysdeps/linux-gnu/xtensa/syscallent.h | 357 ++++++++++++++++++++++++++++++++++
sysdeps/linux-gnu/xtensa/trace.c | 100 ++++++++++
12 files changed, 953 insertions(+), 2 deletions(-)
create mode 100644 sysdeps/linux-gnu/xtensa/Makefile.am
create mode 100644 sysdeps/linux-gnu/xtensa/arch.h
create mode 100644 sysdeps/linux-gnu/xtensa/breakpoint.c
create mode 100644 sysdeps/linux-gnu/xtensa/plt.c
create mode 100644 sysdeps/linux-gnu/xtensa/ptrace.h
create mode 100644 sysdeps/linux-gnu/xtensa/regs.c
create mode 100644 sysdeps/linux-gnu/xtensa/signalent.h
create mode 100644 sysdeps/linux-gnu/xtensa/syscallent.h
create mode 100644 sysdeps/linux-gnu/xtensa/trace.c
diff --git a/configure.ac b/configure.ac
index 4f360c8..55c5c84 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,6 +47,7 @@ case "${host_cpu}" in
sun4u|sparc64) HOST_CPU="sparc" ;;
s390x) HOST_CPU="s390" ;;
i?86|x86_64) HOST_CPU="x86" ;;
+ xtensa*) HOST_CPU="xtensa" ;;
*) HOST_CPU="${host_cpu}" ;;
esac
AC_SUBST(HOST_CPU)
@@ -412,6 +413,7 @@ AC_CONFIG_FILES([
sysdeps/linux-gnu/s390/Makefile
sysdeps/linux-gnu/sparc/Makefile
sysdeps/linux-gnu/x86/Makefile
+ sysdeps/linux-gnu/xtensa/Makefile
testsuite/Makefile
testsuite/ltrace.main/Makefile
testsuite/ltrace.minor/Makefile
diff --git a/proc.c b/proc.c
index 5385510..cc0b150 100644
--- a/proc.c
+++ b/proc.c
@@ -813,7 +813,7 @@ breakpoint_for_symbol(struct library_symbol *libsym, struct process *proc)
* http://lists.alioth.debian.org/pipermail/ltrace-devel/2012-November/000764.html
* http://lists.alioth.debian.org/pipermail/ltrace-devel/2012-November/000770.html
*/
-#ifndef __mips__
+#if !defined(__mips__) && !defined(__xtensa__)
assert(bp->libsym == NULL);
bp->libsym = libsym;
#endif
diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am
index ec26162..857f2da 100644
--- a/sysdeps/linux-gnu/Makefile.am
+++ b/sysdeps/linux-gnu/Makefile.am
@@ -18,7 +18,7 @@
# 02110-1301 USA
DIST_SUBDIRS = aarch64 alpha arm cris ia64 m68k metag mips ppc s390 \
- sparc x86
+ sparc x86 xtensa
SUBDIRS = \
$(HOST_CPU)
diff --git a/sysdeps/linux-gnu/xtensa/Makefile.am b/sysdeps/linux-gnu/xtensa/Makefile.am
new file mode 100644
index 0000000..7d83ab0
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/Makefile.am
@@ -0,0 +1,35 @@
+# This file is part of ltrace.
+# Copyright (C) 2014 Cadence Design Systems Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ breakpoint.c \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/xtensa/arch.h b/sysdeps/linux-gnu/xtensa/arch.h
new file mode 100644
index 0000000..1e85385
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/arch.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifdef __XTENSA_EL__
+
+# define ARCH_ENDIAN_LITTLE
+
+# define BREAKPOINT_VALUE { 0x00, 0x40, 0x00 }
+# define DENSITY_BREAKPOINT_VALUE { 0x2d, 0xf0 }
+
+# define XTENSA_OP0_MASK 0xf
+# define XTENSA_DENSITY_FIRST 0x8
+# define XTENSA_DENSITY_LAST 0xe
+# define XTENSA_SYSCALL_MASK 0xff500f
+# define XTENSA_SYSCALL_VALUE 0x005000
+
+#elif defined(__XTENSA_EB__)
+
+# define ARCH_ENDIAN_BIG
+
+# define BREAKPOINT_VALUE { 0x00, 0x04, 0x00 }
+# define DENSITY_BREAKPOINT_VALUE { 0xd2, 0x0f }
+
+# define XTENSA_OP0_MASK 0xf0
+# define XTENSA_DENSITY_FIRST 0x80
+# define XTENSA_DENSITY_LAST 0xe0
+# define XTENSA_SYSCALL_MASK 0xf005ff00
+# define XTENSA_SYSCALL_VALUE 0x00050000
+
+#else
+# error __XTENSA_EL__ or __XTENSA_EB__ must be defined
+#endif
+
+#define BREAKPOINT_LENGTH 3
+#define DENSITY_BREAKPOINT_LENGTH 2
+
+#define DECR_PC_AFTER_BREAK 0
+
+#define LT_ELFCLASS ELFCLASS32
+#define LT_ELF_MACHINE EM_XTENSA
+
+#define ARCH_HAVE_LTELF_DATA
+struct arch_ltelf_data {
+};
+
+#define ARCH_HAVE_LIBRARY_SYMBOL_DATA
+struct arch_library_symbol_data {
+ void *resolved_addr;
+};
+
+#define ARCH_HAVE_SYMBOL_RET
+#define ARCH_HAVE_ENABLE_BREAKPOINT
diff --git a/sysdeps/linux-gnu/xtensa/breakpoint.c b/sysdeps/linux-gnu/xtensa/breakpoint.c
new file mode 100644
index 0000000..8425d20
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/breakpoint.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <sys/ptrace.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "common.h"
+#include "backend.h"
+#include "sysdep.h"
+#include "breakpoint.h"
+#include "proc.h"
+#include "library.h"
+
+void
+arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
+{
+ static unsigned char break_insn[] = BREAKPOINT_VALUE;
+ static unsigned char density_break_insn[] = DENSITY_BREAKPOINT_VALUE;
+ unsigned char *bytes;
+ long a;
+
+ debug(DEBUG_PROCESS,
+ "arch_enable_breakpoint: pid=%d, addr=%p, symbol=%s",
+ pid, sbp->addr, breakpoint_name(sbp));
+
+ a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr, 0);
+ if (a == -1 && errno) {
+ fprintf(stderr, "enable_breakpoint"
+ " pid=%d, addr=%p, symbol=%s: %s\n",
+ pid, sbp->addr, breakpoint_name(sbp),
+ strerror(errno));
+ return;
+ }
+ bytes = (unsigned char *)&a;
+ memcpy(sbp->orig_value, bytes, BREAKPOINT_LENGTH);
+ if ((bytes[0] & XTENSA_OP0_MASK) >= XTENSA_DENSITY_FIRST &&
+ (bytes[0] & XTENSA_OP0_MASK) < XTENSA_DENSITY_LAST) {
+ memcpy(bytes, density_break_insn, DENSITY_BREAKPOINT_LENGTH);
+ } else {
+ memcpy(bytes, break_insn, BREAKPOINT_LENGTH);
+ }
+ a = ptrace(PTRACE_POKETEXT, pid, sbp->addr, a);
+ if (a == -1) {
+ fprintf(stderr, "enable_breakpoint"
+ " pid=%d, addr=%p, symbol=%s: %s\n",
+ pid, sbp->addr, breakpoint_name(sbp),
+ strerror(errno));
+ return;
+ }
+}
diff --git a/sysdeps/linux-gnu/xtensa/plt.c b/sysdeps/linux-gnu/xtensa/plt.c
new file mode 100644
index 0000000..51a6296
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/plt.c
@@ -0,0 +1,192 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <errno.h>
+#include <error.h>
+#include <gelf.h>
+#include <string.h>
+#include <sys/ptrace.h>
+
+#include "common.h"
+#include "debug.h"
+#include "proc.h"
+#include "library.h"
+#include "breakpoint.h"
+#include "backend.h"
+
+int
+arch_elf_init(struct ltelf *lte, struct library *lib)
+{
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+
+ if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
+ || scn == NULL) {
+ fail:
+ error(0, 0, "Couldn't get SHT_DYNAMIC: %s",
+ elf_errmsg(-1));
+ return -1;
+ }
+
+ Elf_Data *data = elf_loaddata(scn, &shdr);
+ if (data == NULL)
+ goto fail;
+
+ size_t i;
+ GElf_Addr relplt_addr;
+ GElf_Xword relplt_size;
+
+ for (i = 0; i < shdr.sh_size / shdr.sh_entsize; ++i) {
+ GElf_Dyn dyn;
+
+ if (gelf_getdyn(data, i, &dyn) == NULL)
+ goto fail;
+
+ if (dyn.d_tag == DT_JMPREL) {
+ relplt_addr = dyn.d_un.d_ptr;
+ } else if (dyn.d_tag == DT_PLTRELSZ) {
+ relplt_size = dyn.d_un.d_val;
+ }
+ }
+
+ for (i = 1; i < lte->ehdr.e_shnum; ++i) {
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+
+ scn = elf_getscn(lte->elf, i);
+ if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
+ fprintf(stderr, "Couldn't get section header: %s\n",
+ elf_errmsg(-1));
+ exit(EXIT_FAILURE);
+ }
+ if (shdr.sh_addr == relplt_addr
+ && shdr.sh_size == relplt_size) {
+ if (elf_read_relocs(lte, scn, &shdr,
+ <e->plt_relocs) < 0) {
+ fprintf(stderr, "Couldn't get .rel*.plt"
+ " data: %s\n", elf_errmsg(-1));
+ exit(EXIT_FAILURE);
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void
+arch_elf_destroy(struct ltelf *lte)
+{
+}
+
+GElf_Addr arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela)
+{
+ return rela->r_offset;
+}
+
+void *sym2addr(struct process *proc, struct library_symbol *sym)
+{
+ void *addr = NULL;
+ long ret;
+
+ switch (sym->plt_type) {
+ case LS_TOPLT_NONE:
+ addr = sym->enter_addr + 3;
+ break;
+
+ case LS_TOPLT_EXEC:
+ ret = ptrace(PTRACE_PEEKTEXT, proc->pid, sym->enter_addr, 0);
+ addr = ret == -1 ? NULL : (void *)(ret + 3);
+ break;
+ }
+ if (sym->arch.resolved_addr == NULL)
+ sym->arch.resolved_addr = addr;
+ return addr;
+}
+
+int
+arch_library_symbol_init(struct library_symbol *libsym)
+{
+ libsym->arch.resolved_addr = NULL;
+ return 0;
+}
+
+void
+arch_library_symbol_destroy(struct library_symbol *libsym)
+{
+}
+
+int
+arch_library_symbol_clone(struct library_symbol *retp,
+ struct library_symbol *libsym)
+{
+ retp->arch = libsym->arch;
+ return 0;
+}
+
+void arch_symbol_ret(struct process *proc, struct library_symbol *libsym)
+{
+ struct breakpoint *bp;
+ arch_addr_t resolved_addr;
+ struct process *leader = proc->leader;
+
+ resolved_addr = sym2addr(proc, libsym);
+
+ if (libsym->arch.resolved_addr == resolved_addr)
+ return;
+
+ /* Delete breakpoint at PLT entry: PLT entry still may be called
+ * if the compiler decided to cache the function address before
+ * it was resolved, but such calls will never be removed from the
+ * ltrace call stack, because both breakpoints (at PLT entry and
+ * at the function itself) are associated with the same struct
+ * library_symbol. */
+
+ delete_breakpoint_at(proc, libsym->arch.resolved_addr);
+ libsym->arch.resolved_addr = resolved_addr;
+
+ if (DICT_HAS_KEY(proc->breakpoints, &resolved_addr)) {
+ return;
+ }
+
+ bp = malloc(sizeof (*bp));
+ if (bp == NULL) {
+ fprintf(stderr, "Failed to allocate bp for %s\n",
+ libsym->name);
+ return;
+ }
+
+ if (breakpoint_init(bp, leader, resolved_addr, libsym) < 0)
+ goto err;
+
+ if (proc_add_breakpoint(leader, bp) < 0) {
+ breakpoint_destroy(bp);
+ goto err;
+ }
+
+ if (breakpoint_turn_on(bp, leader) < 0) {
+ proc_remove_breakpoint(leader, bp);
+ breakpoint_destroy(bp);
+ goto err;
+ }
+ return;
+err:
+ free(bp);
+}
diff --git a/sysdeps/linux-gnu/xtensa/ptrace.h b/sysdeps/linux-gnu/xtensa/ptrace.h
new file mode 100644
index 0000000..6e67fff
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/ptrace.h
@@ -0,0 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/xtensa/regs.c b/sysdeps/linux-gnu/xtensa/regs.c
new file mode 100644
index 0000000..b07d331
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/regs.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+#include "proc.h"
+#include "common.h"
+
+void *get_instruction_pointer(struct process *proc)
+{
+ int retval = ptrace(PTRACE_PEEKUSER, proc->pid, REG_PC, 0);
+ return (void *)retval;
+}
+
+void set_instruction_pointer(struct process *proc, void *addr)
+{
+ ptrace(PTRACE_POKEUSER, proc->pid, REG_PC, addr);
+}
+
+void *get_stack_pointer(struct process *proc)
+{
+ int retval = ptrace(PTRACE_PEEKUSER, proc->pid, (REG_A_BASE + 1), 0);
+ return (void *)retval;
+}
+
+void *get_return_addr(struct process *proc, void *stack_pointer)
+{
+ unsigned int retval = ptrace(PTRACE_PEEKUSER, proc->pid, (REG_A_BASE + 0), 0);
+ /* Assume call8, mask the upper 2 bits. */
+ return (void *)(0x3FFFFFFF & retval);
+}
diff --git a/sysdeps/linux-gnu/xtensa/signalent.h b/sysdeps/linux-gnu/xtensa/signalent.h
new file mode 100644
index 0000000..953534d
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/signalent.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+ "SIG_0", /* 0 */
+ "SIGHUP", /* 1 */
+ "SIGINT", /* 2 */
+ "SIGQUIT", /* 3 */
+ "SIGILL", /* 4 */
+ "SIGTRAP", /* 5 */
+ "SIGABRT", /* 6 */
+ "SIGBUS", /* 7 */
+ "SIGFPE", /* 8 */
+ "SIGKILL", /* 9 */
+ "SIGUSR1", /* 10 */
+ "SIGSEGV", /* 11 */
+ "SIGUSR2", /* 12 */
+ "SIGPIPE", /* 13 */
+ "SIGALRM", /* 14 */
+ "SIGTERM", /* 15 */
+ "SIGSTKFLT", /* 16 */
+ "SIGCHLD", /* 17 */
+ "SIGCONT", /* 18 */
+ "SIGSTOP", /* 19 */
+ "SIGTSTP", /* 20 */
+ "SIGTTIN", /* 21 */
+ "SIGTTOU", /* 22 */
+ "SIGURG", /* 23 */
+ "SIGXCPU", /* 24 */
+ "SIGXFSZ", /* 25 */
+ "SIGVTALRM", /* 26 */
+ "SIGPROF", /* 27 */
+ "SIGWINCH", /* 28 */
+ "SIGIO", /* 29 */
+ "SIGPWR", /* 30 */
+ "SIGSYS", /* 31 */
diff --git a/sysdeps/linux-gnu/xtensa/syscallent.h b/sysdeps/linux-gnu/xtensa/syscallent.h
new file mode 100644
index 0000000..ff19d83
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/syscallent.h
@@ -0,0 +1,357 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+ "spill", /* 0 */
+ "xtensa", /* 1 */
+ "available4", /* 2 */
+ "available5", /* 3 */
+ "available6", /* 4 */
+ "available7", /* 5 */
+ "available8", /* 6 */
+ "available9", /* 7 */
+ "open", /* 8 */
+ "close", /* 9 */
+ "dup", /* 10 */
+ "dup2", /* 11 */
+ "read", /* 12 */
+ "write", /* 13 */
+ "select", /* 14 */
+ "lseek", /* 15 */
+ "poll", /* 16 */
+ "_llseek", /* 17 */
+ "epoll_wait", /* 18 */
+ "epoll_ctl", /* 19 */
+ "epoll_create", /* 20 */
+ "creat", /* 21 */
+ "truncate", /* 22 */
+ "ftruncate", /* 23 */
+ "readv", /* 24 */
+ "writev", /* 25 */
+ "fsync", /* 26 */
+ "fdatasync", /* 27 */
+ "truncate64", /* 28 */
+ "ftruncate64", /* 29 */
+ "pread64", /* 30 */
+ "pwrite64", /* 31 */
+ "link", /* 32 */
+ "rename", /* 33 */
+ "symlink", /* 34 */
+ "readlink", /* 35 */
+ "mknod", /* 36 */
+ "pipe", /* 37 */
+ "unlink", /* 38 */
+ "rmdir", /* 39 */
+ "mkdir", /* 40 */
+ "chdir", /* 41 */
+ "fchdir", /* 42 */
+ "getcwd", /* 43 */
+ "chmod", /* 44 */
+ "chown", /* 45 */
+ "stat", /* 46 */
+ "stat64", /* 47 */
+ "lchown", /* 48 */
+ "lstat", /* 49 */
+ "lstat64", /* 50 */
+ "available51", /* 51 */
+ "fchmod", /* 52 */
+ "fchown", /* 53 */
+ "fstat", /* 54 */
+ "fstat64", /* 55 */
+ "flock", /* 56 */
+ "access", /* 57 */
+ "umask", /* 58 */
+ "getdents", /* 59 */
+ "getdents64", /* 60 */
+ "fcntl64", /* 61 */
+ "available62", /* 62 */
+ "fadvise64_64", /* 63 */
+ "utime", /* 64 */
+ "utimes", /* 65 */
+ "ioctl", /* 66 */
+ "fcntl", /* 67 */
+ "setxattr", /* 68 */
+ "getxattr", /* 69 */
+ "listxattr", /* 70 */
+ "removexattr", /* 71 */
+ "lsetxattr", /* 72 */
+ "lgetxattr", /* 73 */
+ "llistxattr", /* 74 */
+ "lremovexattr", /* 75 */
+ "fsetxattr", /* 76 */
+ "fgetxattr", /* 77 */
+ "flistxattr", /* 78 */
+ "fremovexattr", /* 79 */
+ "mmap2", /* 80 */
+ "munmap", /* 81 */
+ "mprotect", /* 82 */
+ "brk", /* 83 */
+ "mlock", /* 84 */
+ "munlock", /* 85 */
+ "mlockall", /* 86 */
+ "munlockall", /* 87 */
+ "mremap", /* 88 */
+ "msync", /* 89 */
+ "mincore", /* 90 */
+ "madvise", /* 91 */
+ "shmget", /* 92 */
+ "shmat", /* 93 */
+ "shmctl", /* 94 */
+ "shmdt", /* 95 */
+ "socket", /* 96 */
+ "setsockopt", /* 97 */
+ "getsockopt", /* 98 */
+ "shutdown", /* 99 */
+ "bind", /* 100 */
+ "connect", /* 101 */
+ "listen", /* 102 */
+ "accept", /* 103 */
+ "getsockname", /* 104 */
+ "getpeername", /* 105 */
+ "sendmsg", /* 106 */
+ "recvmsg", /* 107 */
+ "send", /* 108 */
+ "recv", /* 109 */
+ "sendto", /* 110 */
+ "recvfrom", /* 111 */
+ "socketpair", /* 112 */
+ "sendfile", /* 113 */
+ "sendfile64", /* 114 */
+ "sendmmsg", /* 115 */
+ "clone", /* 116 */
+ "execve", /* 117 */
+ "exit", /* 118 */
+ "exit_group", /* 119 */
+ "getpid", /* 120 */
+ "wait4", /* 121 */
+ "waitid", /* 122 */
+ "kill", /* 123 */
+ "tkill", /* 124 */
+ "tgkill", /* 125 */
+ "set_tid_address", /* 126 */
+ "gettid", /* 127 */
+ "setsid", /* 128 */
+ "getsid", /* 129 */
+ "prctl", /* 130 */
+ "personality", /* 131 */
+ "getpriority", /* 132 */
+ "setpriority", /* 133 */
+ "setitimer", /* 134 */
+ "getitimer", /* 135 */
+ "setuid", /* 136 */
+ "getuid", /* 137 */
+ "setgid", /* 138 */
+ "getgid", /* 139 */
+ "geteuid", /* 140 */
+ "getegid", /* 141 */
+ "setreuid", /* 142 */
+ "setregid", /* 143 */
+ "setresuid", /* 144 */
+ "getresuid", /* 145 */
+ "setresgid", /* 146 */
+ "getresgid", /* 147 */
+ "setpgid", /* 148 */
+ "getpgid", /* 149 */
+ "getppid", /* 150 */
+ "getpgrp", /* 151 */
+ "reserved152", /* 152 */
+ "reserved153", /* 153 */
+ "times", /* 154 */
+ "acct", /* 155 */
+ "sched_setaffinity", /* 156 */
+ "sched_getaffinity", /* 157 */
+ "capget", /* 158 */
+ "capset", /* 159 */
+ "ptrace", /* 160 */
+ "semtimedop", /* 161 */
+ "semget", /* 162 */
+ "semop", /* 163 */
+ "semctl", /* 164 */
+ "available165", /* 165 */
+ "msgget", /* 166 */
+ "msgsnd", /* 167 */
+ "msgrcv", /* 168 */
+ "msgctl", /* 169 */
+ "available170", /* 170 */
+ "umount2", /* 171 */
+ "mount", /* 172 */
+ "swapon", /* 173 */
+ "chroot", /* 174 */
+ "pivot_root", /* 175 */
+ "umount", /* 176 */
+ "swapoff", /* 177 */
+ "sync", /* 178 */
+ "syncfs", /* 179 */
+ "setfsuid", /* 180 */
+ "setfsgid", /* 181 */
+ "sysfs", /* 182 */
+ "ustat", /* 183 */
+ "statfs", /* 184 */
+ "fstatfs", /* 185 */
+ "statfs64", /* 186 */
+ "fstatfs64", /* 187 */
+ "setrlimit", /* 188 */
+ "getrlimit", /* 189 */
+ "getrusage", /* 190 */
+ "futex", /* 191 */
+ "gettimeofday", /* 192 */
+ "settimeofday", /* 193 */
+ "adjtimex", /* 194 */
+ "nanosleep", /* 195 */
+ "getgroups", /* 196 */
+ "setgroups", /* 197 */
+ "sethostname", /* 198 */
+ "setdomainname", /* 199 */
+ "syslog", /* 200 */
+ "vhangup", /* 201 */
+ "uselib", /* 202 */
+ "reboot", /* 203 */
+ "quotactl", /* 204 */
+ "nfsservctl", /* 205 */
+ "_sysctl", /* 206 */
+ "bdflush", /* 207 */
+ "uname", /* 208 */
+ "sysinfo", /* 209 */
+ "init_module", /* 210 */
+ "delete_module", /* 211 */
+ "sched_setparam", /* 212 */
+ "sched_getparam", /* 213 */
+ "sched_setscheduler", /* 214 */
+ "sched_getscheduler", /* 215 */
+ "sched_get_priority_max", /* 216 */
+ "sched_get_priority_min", /* 217 */
+ "sched_rr_get_interval", /* 218 */
+ "sched_yield", /* 219 */
+ "220", /* 220 */
+ "221", /* 221 */
+ "available222", /* 222 */
+ "restart_syscall", /* 223 */
+ "sigaltstack", /* 224 */
+ "rt_sigreturn", /* 225 */
+ "rt_sigaction", /* 226 */
+ "rt_sigprocmask", /* 227 */
+ "rt_sigpending", /* 228 */
+ "rt_sigtimedwait", /* 229 */
+ "rt_sigqueueinfo", /* 230 */
+ "rt_sigsuspend", /* 231 */
+ "mq_open", /* 232 */
+ "mq_unlink", /* 233 */
+ "mq_timedsend", /* 234 */
+ "mq_timedreceive", /* 235 */
+ "mq_notify", /* 236 */
+ "mq_getsetattr", /* 237 */
+ "available238", /* 238 */
+ "io_setup", /* 239 */
+ "io_destroy", /* 240 */
+ "io_submit", /* 241 */
+ "io_getevents", /* 242 */
+ "io_cancel", /* 243 */
+ "clock_settime", /* 244 */
+ "clock_gettime", /* 245 */
+ "clock_getres", /* 246 */
+ "clock_nanosleep", /* 247 */
+ "timer_create", /* 248 */
+ "timer_delete", /* 249 */
+ "timer_settime", /* 250 */
+ "timer_gettime", /* 251 */
+ "timer_getoverrun", /* 252 */
+ "reserved253", /* 253 */
+ "lookup_dcookie", /* 254 */
+ "available255", /* 255 */
+ "add_key", /* 256 */
+ "request_key", /* 257 */
+ "keyctl", /* 258 */
+ "available259", /* 259 */
+ "readahead", /* 260 */
+ "remap_file_pages", /* 261 */
+ "migrate_pages", /* 262 */
+ "mbind", /* 263 */
+ "get_mempolicy", /* 264 */
+ "set_mempolicy", /* 265 */
+ "unshare", /* 266 */
+ "move_pages", /* 267 */
+ "splice", /* 268 */
+ "tee", /* 269 */
+ "vmsplice", /* 270 */
+ "available271", /* 271 */
+ "pselect6", /* 272 */
+ "ppoll", /* 273 */
+ "epoll_pwait", /* 274 */
+ "epoll_create1", /* 275 */
+ "inotify_init", /* 276 */
+ "inotify_add_watch", /* 277 */
+ "inotify_rm_watch", /* 278 */
+ "inotify_init1", /* 279 */
+ "getcpu", /* 280 */
+ "kexec_load", /* 281 */
+ "ioprio_set", /* 282 */
+ "ioprio_get", /* 283 */
+ "set_robust_list", /* 284 */
+ "get_robust_list", /* 285 */
+ "available286", /* 286 */
+ "available287", /* 287 */
+ "openat", /* 288 */
+ "mkdirat", /* 289 */
+ "mknodat", /* 290 */
+ "unlinkat", /* 291 */
+ "renameat", /* 292 */
+ "linkat", /* 293 */
+ "symlinkat", /* 294 */
+ "readlinkat", /* 295 */
+ "utimensat", /* 296 */
+ "fchownat", /* 297 */
+ "futimesat", /* 298 */
+ "fstatat64", /* 299 */
+ "fchmodat", /* 300 */
+ "faccessat", /* 301 */
+ "available302", /* 302 */
+ "available303", /* 303 */
+ "signalfd", /* 304 */
+ "305", /* 305 */
+ "eventfd", /* 306 */
+ "recvmmsg", /* 307 */
+ "setns", /* 308 */
+ "signalfd4", /* 309 */
+ "dup3", /* 310 */
+ "pipe2", /* 311 */
+ "timerfd_create", /* 312 */
+ "timerfd_settime", /* 313 */
+ "timerfd_gettime", /* 314 */
+ "available315", /* 315 */
+ "eventfd2", /* 316 */
+ "preadv", /* 317 */
+ "pwritev", /* 318 */
+ "available319", /* 319 */
+ "fanotify_init", /* 320 */
+ "fanotify_mark", /* 321 */
+ "process_vm_readv", /* 322 */
+ "process_vm_writev", /* 323 */
+ "name_to_handle_at", /* 324 */
+ "open_by_handle_at", /* 325 */
+ "sync_file_range", /* 326 */
+ "perf_event_open", /* 327 */
+ "rt_tgsigqueueinfo", /* 328 */
+ "clock_adjtime", /* 329 */
+ "prlimit64", /* 330 */
+ "kcmp", /* 331 */
+ "finit_module", /* 332 */
+ "accept4", /* 333 */
+ "sched_setattr", /* 334 */
+ "sched_getattr", /* 335 */
+ "syscall_count", /* 336 */
diff --git a/sysdeps/linux-gnu/xtensa/trace.c b/sysdeps/linux-gnu/xtensa/trace.c
new file mode 100644
index 0000000..0fbcfcb
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/trace.c
@@ -0,0 +1,100 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+#include "common.h"
+#include "proc.h"
+
+void
+get_arch_dep(struct process *proc)
+{
+}
+
+/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */
+int syscall_p(struct process *proc, int status, int *sysnum)
+{
+ if (WIFSTOPPED(status)
+ && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
+ /* get the user's pc */
+ int pc = ptrace(PTRACE_PEEKUSER, proc->pid, REG_PC, 0);
+
+ /* fetch the SWI instruction */
+ int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 3, 0);
+
+ *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, SYSCALL_NR, 0);
+ /* if it is a syscall, return 1 or 2 */
+ if ((insn & XTENSA_SYSCALL_MASK) == XTENSA_SYSCALL_VALUE) {
+ if ((proc->callstack_depth > 0)
+ && proc->callstack[proc->callstack_depth
+ - 1].is_syscall) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+long gimme_arg(enum tof type, struct process *proc, int arg_num)
+{
+ /* Deal with the Xtensa calling conventions. Function calls
+ * and system calls have different ABIs. */
+ /* Assume call8 for function calls. */
+ if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
+ if (arg_num == -1) /* return value */
+ return ptrace(PTRACE_PEEKUSER, proc->pid,
+ (REG_A_BASE + 10), 0);
+ else if (arg_num < 6) {
+ int regnr;
+ regnr = REG_A_BASE + 2 + arg_num;
+ return ptrace(PTRACE_PEEKUSER, proc->pid, regnr, 0);
+ } else
+ return ptrace(PTRACE_PEEKDATA, proc->pid,
+ proc->stack_pointer
+ + 4 * (arg_num - 6), 0);
+ } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
+ if (arg_num == -1) /* return value */
+ return ptrace(PTRACE_PEEKUSER, proc->pid,
+ (REG_A_BASE + 2), 0);
+ if (arg_num < 6) {
+ int regnr;
+ regnr = REG_A_BASE
+ + ((arg_num == 0)
+ ? 6 : arg_num + ((arg_num >= 4) ? 4 : 2));
+ return ptrace(PTRACE_PEEKUSER, proc->pid, regnr, 0);
+ } else
+ return ptrace(PTRACE_PEEKDATA, proc->pid,
+ proc->stack_pointer + 4 * (arg_num - 6),
+ 0);
+ } else {
+ fprintf(stderr, "gimme_arg called with wrong arguments\n");
+ return -1;
+ }
+
+ return 0;
+}
--
1.8.1.4
More information about the Ltrace-devel
mailing list