From: Max Filippov <jcmvbkbc@gmail.com>
To: buildroot@busybox.net
Subject: [Buildroot] [PATCH] package/ltrace: add support for xtensa
Date: Tue, 17 Mar 2015 23:26:01 +0300 [thread overview]
Message-ID: <1426623961-2817-1-git-send-email-jcmvbkbc@gmail.com> (raw)
Backported from: 05143c95e4609e5592775fae5facbf77b7bfa694
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
.../ltrace/0004-xtensa-add-xtensa-support.patch | 1612 ++++++++++++++++++++
package/ltrace/Config.in | 2 +-
2 files changed, 1613 insertions(+), 1 deletion(-)
create mode 100644 package/ltrace/0004-xtensa-add-xtensa-support.patch
diff --git a/package/ltrace/0004-xtensa-add-xtensa-support.patch b/package/ltrace/0004-xtensa-add-xtensa-support.patch
new file mode 100644
index 0000000..798a230
--- /dev/null
+++ b/package/ltrace/0004-xtensa-add-xtensa-support.patch
@@ -0,0 +1,1612 @@
+From 05ee6bd2986c62d611ff9dfe6dbf11d2def0844b Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Sun, 4 Jan 2015 06:57:41 +0300
+Subject: [PATCH] xtensa: add xtensa support
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+ CREDITS | 4 +
+ NEWS | 1 +
+ README | 1 +
+ configure.ac | 2 +
+ sysdeps/linux-gnu/Makefile.am | 2 +-
+ sysdeps/linux-gnu/xtensa/Makefile.am | 36 +++
+ sysdeps/linux-gnu/xtensa/arch.h | 111 ++++++++
+ sysdeps/linux-gnu/xtensa/breakpoint.c | 71 ++++++
+ sysdeps/linux-gnu/xtensa/fetch.c | 188 ++++++++++++++
+ sysdeps/linux-gnu/xtensa/plt.c | 463 ++++++++++++++++++++++++++++++++++
+ sysdeps/linux-gnu/xtensa/ptrace.h | 21 ++
+ sysdeps/linux-gnu/xtensa/regs.c | 83 ++++++
+ sysdeps/linux-gnu/xtensa/signalent.h | 52 ++++
+ sysdeps/linux-gnu/xtensa/syscallent.h | 357 ++++++++++++++++++++++++++
+ sysdeps/linux-gnu/xtensa/trace.c | 61 +++++
+ 15 files changed, 1452 insertions(+), 1 deletion(-)
+ 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/fetch.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/CREDITS b/CREDITS
+index c85eb76..67f1761 100644
+--- a/CREDITS
++++ b/CREDITS
+@@ -61,6 +61,10 @@ N: Timothy Fesig
+ E: slate at us.ibm.com
+ D: s390 port
+
++N: Max Filippov
++E: jcmvbkbc at gmail.com
++D: xtensa port
++
+ N: Roman Hodek
+ E: Roman.Hodek at informatik.uni-erlangen.de
+ D: m68k port
+diff --git a/NEWS b/NEWS
+index 71d3a1f..a8e83f1 100644
+--- a/NEWS
++++ b/NEWS
+@@ -38,6 +38,7 @@
+ binaries, as currently there's no 32-bit userspace available for
+ ARM64 processors.
+ - Imagination Technologies Meta is now supported.
++ - Cadence Tensilica Xtensa is now supported.
+
+ - On Linux, tracing of IFUNC symbols is supported. On i386,
+ x86_64, ppc32 with secure PLT and ppc64, IRELATIVE PLT slots are
+diff --git a/README b/README
+index a04b767..a38e8dc 100644
+--- a/README
++++ b/README
+@@ -37,6 +37,7 @@ to test each release comprehensively on each target.
+ s390-*-linux-gnu
+ s390x-*-linux-gnu
+ x86_64-*-linux-gnu
++ xtensa-*-linux-gnu
+
+ The following systems were supported at some point in past, but
+ current status is unknown:
+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/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..9ce81e1
+--- /dev/null
++++ b/sysdeps/linux-gnu/xtensa/Makefile.am
+@@ -0,0 +1,36 @@
++# 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 \
++ fetch.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..c4d300a
+--- /dev/null
++++ b/sysdeps/linux-gnu/xtensa/arch.h
+@@ -0,0 +1,111 @@
++/*
++ * 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 <gelf.h>
++
++#ifdef __XTENSA_EL__
++
++# define ARCH_ENDIAN_LITTLE
++
++# define BREAKPOINT_VALUE { 0x00, 0x41, 0x00 }
++# define DENSITY_BREAKPOINT_VALUE { 0x2d, 0xf1 }
++
++# define XTENSA_OP0_MASK 0xf
++# define XTENSA_DENSITY_FIRST 0x8
++# define XTENSA_DENSITY_LAST 0xe
++# define XTENSA_SYSCALL_MASK 0xffffff
++# define XTENSA_SYSCALL_VALUE 0x005000
++# define XTENSA_ENTRY_MASK 0xff
++# define XTENSA_ENTRY_VALUE 0x36
++
++#elif defined(__XTENSA_EB__)
++
++# define ARCH_ENDIAN_BIG
++
++# define BREAKPOINT_VALUE { 0x00, 0x14, 0x00 }
++# define DENSITY_BREAKPOINT_VALUE { 0xd2, 0x1f }
++
++# define XTENSA_OP0_MASK 0xf0
++# define XTENSA_DENSITY_FIRST 0x80
++# define XTENSA_DENSITY_LAST 0xe0
++# define XTENSA_SYSCALL_MASK 0xffffff00
++# define XTENSA_SYSCALL_VALUE 0x00050000
++# define XTENSA_ENTRY_MASK 0xff000000
++# define XTENSA_ENTRY_VALUE 0x63000000
++
++#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
++
++static inline int is_density(const void *p)
++{
++ const unsigned char *bytes = p;
++ return (bytes[0] & XTENSA_OP0_MASK) >= XTENSA_DENSITY_FIRST &&
++ (bytes[0] & XTENSA_OP0_MASK) < XTENSA_DENSITY_LAST;
++}
++
++#define ARCH_HAVE_LTELF_DATA
++struct arch_ltelf_data {
++};
++
++enum xtensa_plt_type {
++ XTENSA_DEFAULT,
++ XTENSA_PLT_UNRESOLVED,
++ XTENSA_PLT_RESOLVED,
++};
++
++#define ARCH_HAVE_LIBRARY_DATA
++struct arch_library_data {
++ GElf_Addr loadable_sz;
++};
++
++#define ARCH_HAVE_LIBRARY_SYMBOL_DATA
++struct arch_library_symbol_data {
++ enum xtensa_plt_type type;
++ GElf_Addr resolved_addr;
++};
++
++#define ARCH_HAVE_BREAKPOINT_DATA
++struct arch_breakpoint_data {
++};
++
++#define ARCH_HAVE_PROCESS_DATA
++struct arch_process_data {
++ /* Breakpoint that hits when the dynamic linker is about to
++ * update a .plt slot. NULL before that address is known. */
++ struct breakpoint *dl_plt_update_bp;
++
++ /* PLT update breakpoint looks here for the handler. */
++ struct process_stopping_handler *handler;
++};
++
++#define ARCH_HAVE_ADD_PLT_ENTRY
++#define ARCH_HAVE_DYNLINK_DONE
++#define ARCH_HAVE_ENABLE_BREAKPOINT
++#define ARCH_HAVE_GET_SYMINFO
++#define ARCH_HAVE_FETCH_ARG
+diff --git a/sysdeps/linux-gnu/xtensa/breakpoint.c b/sysdeps/linux-gnu/xtensa/breakpoint.c
+new file mode 100644
+index 0000000..256d1dd
+--- /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));
++
++ errno = 0;
++ 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 (is_density(bytes)) {
++ 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/fetch.c b/sysdeps/linux-gnu/xtensa/fetch.c
+new file mode 100644
+index 0000000..c211ac5
+--- /dev/null
++++ b/sysdeps/linux-gnu/xtensa/fetch.c
+@@ -0,0 +1,188 @@
++/*
++ * 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>
++#include <asm/ptrace.h>
++#include <assert.h>
++#include <elf.h>
++#include <libelf.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <stdbool.h>
++
++#include "backend.h"
++#include "fetch.h"
++#include "library.h"
++#include "proc.h"
++#include "ptrace.h"
++#include "type.h"
++#include "value.h"
++
++enum {
++ MAX_REG_ARG_WORDS = 6,
++ REG_ARG_BASE_REG = 2,
++
++ MAX_RETURN_WORDS = 4,
++ RETURN_BASE_REG = 10,
++ SYSCALL_RETURN_BASE_REG = 2,
++};
++
++struct fetch_context {
++ unsigned arg_word_idx;
++ arch_addr_t sp;
++ arch_addr_t ret_struct;
++
++};
++
++struct fetch_context *
++arch_fetch_arg_init(enum tof type, struct process *proc,
++ struct arg_type_info *ret_info)
++{
++ struct fetch_context *ctx = malloc(sizeof(*ctx));
++ size_t ret_sz = type_sizeof(proc, ret_info);
++ unsigned long sp = ptrace(PTRACE_PEEKUSER, proc->pid,
++ (REG_A_BASE + 1), 0);
++
++ if (ctx == NULL || sp == (size_t)-1) {
++ free(ctx);
++ return NULL;
++ }
++
++ ctx->arg_word_idx = 0;
++ ctx->sp = (arch_addr_t)sp;
++ ctx->ret_struct = NULL;
++
++ if (ret_sz > MAX_RETURN_WORDS * sizeof(long)) {
++ unsigned long a2 = ptrace(PTRACE_PEEKUSER, proc->pid,
++ (REG_A_BASE + 2), 0);
++ ctx->ret_struct = (arch_addr_t)a2;
++ ++ctx->arg_word_idx;
++ }
++
++ return ctx;
++}
++
++struct fetch_context *
++arch_fetch_arg_clone(struct process *proc,
++ struct fetch_context *ctx)
++{
++ struct fetch_context *clone = malloc(sizeof(*ctx));
++
++ if (clone == NULL)
++ return NULL;
++ *clone = *ctx;
++ return clone;
++}
++
++int
++arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
++ struct process *proc,
++ struct arg_type_info *info, struct value *valuep)
++{
++ size_t sz = type_sizeof(proc, info);
++ size_t al = type_alignof(proc, info);
++ size_t words = (sz + sizeof(long) - 1) / sizeof(long);
++
++ assert(sz != (size_t)-1);
++ assert(al != (size_t)-1);
++
++ if (al > sizeof(long)) {
++ al /= sizeof(long);
++ ctx->arg_word_idx = (ctx->arg_word_idx + al - 1) & ~(al - 1);
++ }
++
++ if (ctx->arg_word_idx + words <= MAX_REG_ARG_WORDS) {
++ size_t i;
++ unsigned char *data = value_reserve(valuep, sz);
++
++ if (data == NULL)
++ return -1;
++
++ for (i = 0; i < words; ++i) {
++ static const unsigned syscall_reg[] = {
++ 6, 3, 4, 5, 8, 9
++ };
++ unsigned regnr =
++ (type == LT_TOF_FUNCTION ?
++ REG_ARG_BASE_REG + ctx->arg_word_idx + i :
++ syscall_reg[ctx->arg_word_idx + i]);
++ unsigned long a = ptrace(PTRACE_PEEKUSER, proc->pid,
++ (REG_A_BASE + regnr), 0);
++ size_t copy = sizeof(a) < sz ? sizeof(a) : sz;
++
++ memcpy(data, &a, copy);
++ data += sizeof(long);
++ sz -= copy;
++ }
++ ctx->arg_word_idx += words;
++ return 0;
++ } else if (ctx->arg_word_idx < MAX_REG_ARG_WORDS) {
++ ctx->arg_word_idx = MAX_REG_ARG_WORDS;
++ }
++
++ value_in_inferior(valuep, ctx->sp + sizeof(long) *
++ (ctx->arg_word_idx - MAX_REG_ARG_WORDS));
++ ctx->arg_word_idx += words;
++
++ return 0;
++}
++
++int
++arch_fetch_retval(struct fetch_context *ctx, enum tof type,
++ struct process *proc, struct arg_type_info *info,
++ struct value *valuep)
++{
++ size_t sz = type_sizeof(proc, info);
++ size_t words = (sz + sizeof(long) - 1) / sizeof(long);
++
++ assert(sz != (size_t)-1);
++
++ if (words <= MAX_RETURN_WORDS) {
++ size_t i;
++ unsigned char *data = value_reserve(valuep, sz);
++
++ if (data == NULL)
++ return -1;
++
++ for (i = 0; i < words; ++i) {
++ unsigned regnr = i +
++ (type == LT_TOF_FUNCTIONR ?
++ RETURN_BASE_REG : SYSCALL_RETURN_BASE_REG);
++ unsigned long a = ptrace(PTRACE_PEEKUSER, proc->pid,
++ (REG_A_BASE + regnr), 0);
++ size_t copy = sizeof(a) < sz ? sizeof(a) : sz;
++
++ memcpy(data, &a, copy);
++ data += sizeof(long);
++ sz -= copy;
++ }
++ } else {
++ value_in_inferior(valuep, ctx->ret_struct);
++ }
++ return 0;
++}
++
++void
++arch_fetch_arg_done(struct fetch_context *context)
++{
++ free(context);
++}
+diff --git a/sysdeps/linux-gnu/xtensa/plt.c b/sysdeps/linux-gnu/xtensa/plt.c
+new file mode 100644
+index 0000000..dd0a0f1
+--- /dev/null
++++ b/sysdeps/linux-gnu/xtensa/plt.c
+@@ -0,0 +1,463 @@
++/*
++ * 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 <inttypes.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"
++#include "trace.h"
++
++static void
++mark_as_resolved(struct process *proc, struct library_symbol *libsym,
++ GElf_Addr value)
++{
++ arch_addr_t addr = (arch_addr_t)(intptr_t)libsym->arch.resolved_addr;
++ struct breakpoint *bp = insert_breakpoint_at(proc, addr, libsym);
++
++ if (bp != NULL) {
++ enable_breakpoint(proc, bp);
++ }
++ libsym->arch.type = XTENSA_PLT_RESOLVED;
++ libsym->arch.resolved_addr = value;
++}
++
++static int
++read_plt_slot_value(struct process *proc, arch_addr_t addr, GElf_Addr *valp)
++{
++ long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr);
++
++ if (l < 0) {
++ debug(DEBUG_EVENT, "ptrace .plt slot value @%p: %s",
++ addr, strerror(errno));
++ return -1;
++ }
++
++ *valp = (GElf_Addr)l;
++ return 0;
++}
++
++static int
++unresolve_plt_slot(struct process *proc, arch_addr_t addr, GElf_Addr value)
++{
++ if (ptrace(PTRACE_POKETEXT, proc->pid, addr,
++ (void *)(intptr_t)value) < 0) {
++ debug(DEBUG_EVENT, "failed to unresolve .plt slot @%p: %s",
++ addr, strerror(errno));
++ return -1;
++ }
++ return 0;
++}
++
++int
++arch_elf_init(struct ltelf *lte, struct library *lib)
++{
++ Elf_Scn *scn;
++ GElf_Shdr shdr;
++ GElf_Addr relplt_addr;
++ GElf_Phdr phdr;
++ GElf_Addr low, high;
++ int has_loadable = 0;
++ size_t i;
++
++ for (i = 0; gelf_getphdr(lte->elf, i, &phdr) != NULL; ++i) {
++ if (phdr.p_type == PT_LOAD) {
++ if (has_loadable) {
++ if (phdr.p_vaddr < low)
++ low = phdr.p_vaddr;
++ if (phdr.p_vaddr + phdr.p_memsz > high)
++ high = phdr.p_vaddr + phdr.p_memsz;
++ } else {
++ has_loadable = 1;
++ low = phdr.p_vaddr;
++ high = phdr.p_vaddr + phdr.p_memsz;
++ }
++ }
++ }
++ lib->arch.loadable_sz = has_loadable ? high - low : 0;
++
++ if (elf_load_dynamic_entry(lte, DT_JMPREL, &relplt_addr) < 0 ||
++ elf_get_section_covering(lte, relplt_addr, &scn, &shdr) < 0 ||
++ scn == NULL)
++ return 0;
++
++ if (elf_read_relocs(lte, scn, &shdr, <e->plt_relocs) < 0) {
++ fprintf(stderr, "Couldn't get .rel*.plt data: %s\n",
++ elf_errmsg(-1));
++ return -1;
++ }
++ return 0;
++}
++
++void
++arch_elf_destroy(struct ltelf *lte)
++{
++}
++
++int
++arch_get_sym_info(struct ltelf *lte, const char *filename,
++ size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
++{
++ if (gelf_getsym(lte->dynsym, ELF64_R_SYM(rela->r_info), sym) == NULL)
++ return -1;
++
++ /* .rela.plt entries that reference locally defined functions point
++ * to their entry points directly, not to PLT entries. Skip such
++ * symbols. */
++ if (sym->st_shndx != SHN_UNDEF) {
++ const char *name = lte->dynstr + sym->st_name;
++ debug(2, "symbol %s does not have plt entry", name);
++ return 1;
++ }
++
++ return 0;
++}
++
++enum plt_status
++arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
++ const char *name, GElf_Rela *rela, size_t ndx,
++ struct library_symbol **ret)
++{
++ if (default_elf_add_plt_entry(proc, lte, name, rela, ndx, ret) < 0) {
++ return PLT_FAIL;
++ }
++
++ /* All PLT library symbols are initially marked as delayed. Some of
++ * them may reference weak symbols that are never loaded, sym2addr for
++ * such entries will return NULL. All other symbols are activated
++ * after the dynlink is done. */
++ (*ret)->delayed = 1;
++ return PLT_OK;
++}
++
++void
++arch_dynlink_done(struct process *proc)
++{
++ struct library_symbol *libsym = NULL;
++
++ while ((libsym = proc_each_symbol(proc, libsym,
++ library_symbol_delayed_cb, NULL))) {
++ assert(libsym->plt_type == LS_TOPLT_EXEC);
++
++ if (read_plt_slot_value(proc, libsym->enter_addr,
++ &libsym->arch.resolved_addr) == 0 &&
++ libsym->arch.resolved_addr) {
++ GElf_Addr base =
++ (GElf_Addr)(intptr_t)libsym->lib->base;
++ GElf_Addr sz = libsym->lib->arch.loadable_sz;
++
++ /* Some references may be resolved at this point, they
++ * will point outside the loadable area of their own
++ * library. */
++ if (libsym->arch.resolved_addr >= base &&
++ libsym->arch.resolved_addr - base < sz) {
++ libsym->arch.type = XTENSA_PLT_UNRESOLVED;
++ proc_activate_delayed_symbol(proc, libsym);
++ } else {
++ libsym->arch.type = XTENSA_PLT_RESOLVED;
++ }
++ }
++ }
++}
++
++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 = ptrace(PTRACE_PEEKTEXT, proc->pid, sym->enter_addr, 0);
++
++ switch (sym->plt_type) {
++ case LS_TOPLT_NONE:
++ addr = sym->enter_addr;
++
++ /* Not every exported function starts with ENTRY instruction,
++ * e.g. _start does not. Only skip first instruction if it's
++ * entry, otherwise don't do it: if the first instruction is
++ * FLIX or density it will break it or the following
++ * instruction. */
++ if ((ret & XTENSA_ENTRY_MASK) == XTENSA_ENTRY_VALUE) {
++ addr += 3;
++ }
++ break;
++
++ case LS_TOPLT_EXEC:
++
++ /* OTOH every PLT entry starts with ENTRY. Put initial
++ * breakpoint after it. After symbol resolution put
++ * additional breakpoint at the first instruction. */
++ addr = (ret == -1 || ret == 0) ? NULL : (void *)(ret + 3);
++ break;
++ }
++ return addr;
++}
++
++int
++arch_library_symbol_init(struct library_symbol *libsym)
++{
++ libsym->arch.type = XTENSA_DEFAULT;
++ 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;
++}
++
++static void
++dl_plt_update_bp_on_hit(struct breakpoint *bp, struct process *proc)
++{
++ debug(DEBUG_PROCESS, "pid=%d dl_plt_update_bp_on_hit %s(%p)",
++ proc->pid, breakpoint_name(bp), bp->addr);
++ struct process_stopping_handler *self = proc->arch.handler;
++ assert(self != NULL);
++
++ struct library_symbol *libsym = self->breakpoint_being_enabled->libsym;
++ GElf_Addr value;
++ if (read_plt_slot_value(proc, libsym->enter_addr, &value) < 0)
++ return;
++
++ unresolve_plt_slot(proc, libsym->enter_addr,
++ libsym->arch.resolved_addr);
++ mark_as_resolved(proc, libsym, value);
++
++ /* cb_on_all_stopped looks if HANDLER is set to NULL as a way
++ * to check that this was run. It's an error if it
++ * wasn't. */
++ proc->arch.handler = NULL;
++
++ breakpoint_turn_off(bp, proc);
++}
++
++static enum callback_status
++cb_keep_stepping_p(struct process_stopping_handler *self)
++{
++ struct process *proc = self->task_enabling_breakpoint;
++ struct library_symbol *libsym = self->breakpoint_being_enabled->libsym;
++
++ GElf_Addr value;
++ if (read_plt_slot_value(proc, libsym->enter_addr, &value) < 0)
++ return CBS_FAIL;
++
++ /* In UNRESOLVED state, the resolved_addr in fact contains
++ * the PLT entry value. */
++ if (value == libsym->arch.resolved_addr) {
++ /* Don't try to single-step over our own breakpoint infinitely.
++ * This may happen if we fail to detect resolved PLT entry. */
++ if (address2bpstruct(proc, get_instruction_pointer(proc))) {
++ return CBS_FAIL;
++ }
++ return CBS_CONT;
++ }
++
++ debug(DEBUG_PROCESS, "pid=%d PLT got resolved to value %#"PRIx64,
++ proc->pid, value);
++
++ /* The .plt slot got resolved! We can migrate the breakpoint
++ * to RESOLVED and stop single-stepping. */
++ if (unresolve_plt_slot(proc, libsym->enter_addr,
++ libsym->arch.resolved_addr) < 0)
++ return CBS_FAIL;
++
++ /* Install breakpoint to the address where the change takes
++ * place. If we fail, then that just means that we'll have to
++ * singlestep the next time around as well. */
++ struct process *leader = proc->leader;
++ if (leader == NULL || leader->arch.dl_plt_update_bp != NULL)
++ goto done;
++
++ arch_addr_t addr = get_instruction_pointer(proc);
++ struct breakpoint *dl_plt_update_bp =
++ insert_breakpoint_at(proc, addr, NULL);
++ if (dl_plt_update_bp == NULL)
++ goto done;
++
++ leader->arch.dl_plt_update_bp = dl_plt_update_bp;
++
++ static struct bp_callbacks dl_plt_update_cbs = {
++ .on_hit = dl_plt_update_bp_on_hit,
++ };
++ breakpoint_set_callbacks(dl_plt_update_bp, &dl_plt_update_cbs);
++
++ /* Turn it off for now. We will turn it on again when we hit
++ * the PLT entry that needs this. */
++ breakpoint_turn_off(dl_plt_update_bp, proc);
++
++done:
++ mark_as_resolved(proc, libsym, value);
++
++ return CBS_STOP;
++}
++
++static void
++cb_on_all_stopped(struct process_stopping_handler *self)
++{
++ /* Put that in for dl_plt_update_bp_on_hit to see. */
++ assert(self->task_enabling_breakpoint->arch.handler == NULL);
++ self->task_enabling_breakpoint->arch.handler = self;
++
++ linux_ptrace_disable_and_continue(self);
++}
++
++static void
++xtensa_plt_bp_hit(struct breakpoint *bp, struct process *proc)
++{
++ struct library_symbol *libsym = bp->libsym;
++
++ if (libsym->arch.type == XTENSA_PLT_RESOLVED) {
++ arch_addr_t addr =
++ (arch_addr_t)(intptr_t)libsym->arch.resolved_addr;
++
++ set_instruction_pointer(proc, addr);
++ ptrace(PTRACE_SINGLESTEP, proc->pid, NULL, NULL);
++ return;
++ }
++}
++
++static void
++xtensa_plt_bp_continue(struct breakpoint *bp, struct process *proc)
++{
++ struct process *leader = proc->leader;
++ void (*on_all_stopped)(struct process_stopping_handler *) = NULL;
++ enum callback_status (*keep_stepping_p)
++ (struct process_stopping_handler *) = NULL;
++
++ if (bp->libsym->arch.type != XTENSA_PLT_UNRESOLVED) {
++ continue_process(proc->pid);
++ return;
++ }
++
++ if (leader != NULL && leader->arch.dl_plt_update_bp != NULL &&
++ breakpoint_turn_on(leader->arch.dl_plt_update_bp, proc) >= 0) {
++ on_all_stopped = cb_on_all_stopped;
++ } else {
++ keep_stepping_p = cb_keep_stepping_p;
++ }
++
++ if (process_install_stopping_handler(proc, bp, on_all_stopped,
++ keep_stepping_p, NULL) < 0) {
++ fprintf(stderr, "%s: couldn't install event handler\n",
++ __func__);
++ continue_after_breakpoint(proc, bp);
++ }
++}
++
++/* For some symbol types, we need to set up custom callbacks.
++ */
++int
++arch_breakpoint_init(struct process *proc, struct breakpoint *bp)
++{
++ /* Artificial and entry-point breakpoints are plain. */
++ if (bp->libsym == NULL || bp->libsym->plt_type != LS_TOPLT_EXEC)
++ return 0;
++
++ static struct bp_callbacks cbs = {
++ .on_hit = xtensa_plt_bp_hit,
++ .on_continue = xtensa_plt_bp_continue,
++ };
++ breakpoint_set_callbacks(bp, &cbs);
++
++ return 0;
++}
++
++void
++arch_breakpoint_destroy(struct breakpoint *bp)
++{
++}
++
++int
++arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
++{
++ retp->arch = sbp->arch;
++ return 0;
++}
++
++int
++arch_process_init(struct process *proc)
++{
++ proc->arch.dl_plt_update_bp = NULL;
++ return 0;
++}
++
++void
++arch_process_destroy(struct process *proc)
++{
++}
++
++int
++arch_process_clone(struct process *retp, struct process *proc)
++{
++ retp->arch = proc->arch;
++
++ if (retp->arch.dl_plt_update_bp != NULL) {
++ /* Point it to the corresponding breakpoint in RETP.
++ * It must be there, this part of PROC has already
++ * been cloned to RETP. */
++ retp->arch.dl_plt_update_bp
++ = address2bpstruct(retp,
++ retp->arch.dl_plt_update_bp->addr);
++
++ assert(retp->arch.dl_plt_update_bp != NULL);
++ }
++
++ return 0;
++}
++
++int
++arch_process_exec(struct process *proc)
++{
++ return arch_process_init(proc);
++}
++
++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)
++{
++ return 0;
++}
+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..a5a8c8d
+--- /dev/null
++++ b/sysdeps/linux-gnu/xtensa/regs.c
+@@ -0,0 +1,83 @@
++/*
++ * 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 <errno.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/ptrace.h>
++#include <asm/ptrace.h>
++
++#include "proc.h"
++#include "common.h"
++
++static int xtensa_peek_user(struct process *proc, unsigned addr,
++ unsigned long *res)
++{
++ long retval;
++
++ errno = 0;
++ retval = ptrace(PTRACE_PEEKUSER, proc->pid, addr, 0);
++ if (retval == -1 && errno) {
++ fprintf(stderr, "%s: pid=%d, %s\n",
++ __func__, proc->pid, strerror(errno));
++ *res = 0;
++ return 0;
++ }
++ *res = retval;
++ return 1;
++}
++
++void *get_instruction_pointer(struct process *proc)
++{
++ unsigned long res;
++
++ if (xtensa_peek_user(proc, REG_PC, &res))
++ return (void *)res;
++ else
++ return NULL;
++}
++
++void set_instruction_pointer(struct process *proc, void *addr)
++{
++ ptrace(PTRACE_POKEUSER, proc->pid, REG_PC, addr);
++}
++
++void *get_stack_pointer(struct process *proc)
++{
++ unsigned long res;
++
++ if (xtensa_peek_user(proc, REG_A_BASE + 1, &res))
++ return (void *)res;
++ else
++ return NULL;
++}
++
++void *get_return_addr(struct process *proc, void *stack_pointer)
++{
++ unsigned long res;
++
++ if (xtensa_peek_user(proc, REG_A_BASE, &res))
++ /* Assume call8, mask the upper 2 bits. */
++ return (void *)(0x3FFFFFFF & res);
++ else
++ return NULL;
++}
+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..c7d3077
+--- /dev/null
++++ b/sysdeps/linux-gnu/xtensa/trace.c
+@@ -0,0 +1,61 @@
++/*
++ * 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;
++}
+--
+1.8.1.4
+
diff --git a/package/ltrace/Config.in b/package/ltrace/Config.in
index 56e4402..e7237da 100644
--- a/package/ltrace/Config.in
+++ b/package/ltrace/Config.in
@@ -5,7 +5,7 @@ config BR2_PACKAGE_LTRACE
# 'relplt_count'). Issue reported upstream at
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=756764.
depends on (BR2_i386 || BR2_arm \
- || BR2_powerpc || BR2_sparc || BR2_x86_64)
+ || BR2_powerpc || BR2_sparc || BR2_x86_64 || BR2_xtensa)
select BR2_PACKAGE_ELFUTILS
depends on BR2_LARGEFILE # elfutils
depends on BR2_USE_WCHAR # elfutils
--
1.8.1.4
next reply other threads:[~2015-03-17 20:26 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-17 20:26 Max Filippov [this message]
2015-03-17 20:34 ` [Buildroot] [PATCH] package/ltrace: add support for xtensa Thomas Petazzoni
2015-03-17 20:43 ` Max Filippov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1426623961-2817-1-git-send-email-jcmvbkbc@gmail.com \
--to=jcmvbkbc@gmail.com \
--cc=buildroot@busybox.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.