1 From 05ee6bd2986c62d611ff9dfe6dbf11d2def0844b Mon Sep 17 00:00:00 2001
2 From: Max Filippov <jcmvbkbc@gmail.com>
3 Date: Sun, 4 Jan 2015 06:57:41 +0300
4 Subject: [PATCH] xtensa: add xtensa support
6 Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
12 sysdeps/linux-gnu/Makefile.am | 2 +-
13 sysdeps/linux-gnu/xtensa/Makefile.am | 36 +++
14 sysdeps/linux-gnu/xtensa/arch.h | 111 ++++++++
15 sysdeps/linux-gnu/xtensa/breakpoint.c | 71 ++++++
16 sysdeps/linux-gnu/xtensa/fetch.c | 188 ++++++++++++++
17 sysdeps/linux-gnu/xtensa/plt.c | 463 ++++++++++++++++++++++++++++++++++
18 sysdeps/linux-gnu/xtensa/ptrace.h | 21 ++
19 sysdeps/linux-gnu/xtensa/regs.c | 83 ++++++
20 sysdeps/linux-gnu/xtensa/signalent.h | 52 ++++
21 sysdeps/linux-gnu/xtensa/syscallent.h | 357 ++++++++++++++++++++++++++
22 sysdeps/linux-gnu/xtensa/trace.c | 61 +++++
23 15 files changed, 1452 insertions(+), 1 deletion(-)
24 create mode 100644 sysdeps/linux-gnu/xtensa/Makefile.am
25 create mode 100644 sysdeps/linux-gnu/xtensa/arch.h
26 create mode 100644 sysdeps/linux-gnu/xtensa/breakpoint.c
27 create mode 100644 sysdeps/linux-gnu/xtensa/fetch.c
28 create mode 100644 sysdeps/linux-gnu/xtensa/plt.c
29 create mode 100644 sysdeps/linux-gnu/xtensa/ptrace.h
30 create mode 100644 sysdeps/linux-gnu/xtensa/regs.c
31 create mode 100644 sysdeps/linux-gnu/xtensa/signalent.h
32 create mode 100644 sysdeps/linux-gnu/xtensa/syscallent.h
33 create mode 100644 sysdeps/linux-gnu/xtensa/trace.c
35 diff --git a/CREDITS b/CREDITS
36 index c85eb76..67f1761 100644
39 @@ -61,6 +61,10 @@ N: Timothy Fesig
44 +E: jcmvbkbc@gmail.com
48 E: Roman.Hodek@informatik.uni-erlangen.de
50 diff --git a/NEWS b/NEWS
51 index 71d3a1f..a8e83f1 100644
55 binaries, as currently there's no 32-bit userspace available for
57 - Imagination Technologies Meta is now supported.
58 + - Cadence Tensilica Xtensa is now supported.
60 - On Linux, tracing of IFUNC symbols is supported. On i386,
61 x86_64, ppc32 with secure PLT and ppc64, IRELATIVE PLT slots are
62 diff --git a/README b/README
63 index a04b767..a38e8dc 100644
66 @@ -37,6 +37,7 @@ to test each release comprehensively on each target.
72 The following systems were supported at some point in past, but
73 current status is unknown:
74 diff --git a/configure.ac b/configure.ac
75 index 4f360c8..55c5c84 100644
78 @@ -47,6 +47,7 @@ case "${host_cpu}" in
79 sun4u|sparc64) HOST_CPU="sparc" ;;
80 s390x) HOST_CPU="s390" ;;
81 i?86|x86_64) HOST_CPU="x86" ;;
82 + xtensa*) HOST_CPU="xtensa" ;;
83 *) HOST_CPU="${host_cpu}" ;;
86 @@ -412,6 +413,7 @@ AC_CONFIG_FILES([
87 sysdeps/linux-gnu/s390/Makefile
88 sysdeps/linux-gnu/sparc/Makefile
89 sysdeps/linux-gnu/x86/Makefile
90 + sysdeps/linux-gnu/xtensa/Makefile
92 testsuite/ltrace.main/Makefile
93 testsuite/ltrace.minor/Makefile
94 diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am
95 index ec26162..857f2da 100644
96 --- a/sysdeps/linux-gnu/Makefile.am
97 +++ b/sysdeps/linux-gnu/Makefile.am
101 DIST_SUBDIRS = aarch64 alpha arm cris ia64 m68k metag mips ppc s390 \
107 diff --git a/sysdeps/linux-gnu/xtensa/Makefile.am b/sysdeps/linux-gnu/xtensa/Makefile.am
109 index 0000000..9ce81e1
111 +++ b/sysdeps/linux-gnu/xtensa/Makefile.am
113 +# This file is part of ltrace.
114 +# Copyright (C) 2014 Cadence Design Systems Inc.
116 +# This program is free software; you can redistribute it and/or
117 +# modify it under the terms of the GNU General Public License as
118 +# published by the Free Software Foundation; either version 2 of the
119 +# License, or (at your option) any later version.
121 +# This program is distributed in the hope that it will be useful, but
122 +# WITHOUT ANY WARRANTY; without even the implied warranty of
123 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
124 +# General Public License for more details.
126 +# You should have received a copy of the GNU General Public License
127 +# along with this program; if not, write to the Free Software
128 +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
131 +noinst_LTLIBRARIES = \
134 +___libcpu_la_SOURCES = \
147 +MAINTAINERCLEANFILES = \
149 diff --git a/sysdeps/linux-gnu/xtensa/arch.h b/sysdeps/linux-gnu/xtensa/arch.h
151 index 0000000..c4d300a
153 +++ b/sysdeps/linux-gnu/xtensa/arch.h
156 + * This file is part of ltrace.
157 + * Copyright (C) 2014 Cadence Design Systems Inc.
159 + * This program is free software; you can redistribute it and/or
160 + * modify it under the terms of the GNU General Public License as
161 + * published by the Free Software Foundation; either version 2 of the
162 + * License, or (at your option) any later version.
164 + * This program is distributed in the hope that it will be useful, but
165 + * WITHOUT ANY WARRANTY; without even the implied warranty of
166 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
167 + * General Public License for more details.
169 + * You should have received a copy of the GNU General Public License
170 + * along with this program; if not, write to the Free Software
171 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
177 +#ifdef __XTENSA_EL__
179 +# define ARCH_ENDIAN_LITTLE
181 +# define BREAKPOINT_VALUE { 0x00, 0x41, 0x00 }
182 +# define DENSITY_BREAKPOINT_VALUE { 0x2d, 0xf1 }
184 +# define XTENSA_OP0_MASK 0xf
185 +# define XTENSA_DENSITY_FIRST 0x8
186 +# define XTENSA_DENSITY_LAST 0xe
187 +# define XTENSA_SYSCALL_MASK 0xffffff
188 +# define XTENSA_SYSCALL_VALUE 0x005000
189 +# define XTENSA_ENTRY_MASK 0xff
190 +# define XTENSA_ENTRY_VALUE 0x36
192 +#elif defined(__XTENSA_EB__)
194 +# define ARCH_ENDIAN_BIG
196 +# define BREAKPOINT_VALUE { 0x00, 0x14, 0x00 }
197 +# define DENSITY_BREAKPOINT_VALUE { 0xd2, 0x1f }
199 +# define XTENSA_OP0_MASK 0xf0
200 +# define XTENSA_DENSITY_FIRST 0x80
201 +# define XTENSA_DENSITY_LAST 0xe0
202 +# define XTENSA_SYSCALL_MASK 0xffffff00
203 +# define XTENSA_SYSCALL_VALUE 0x00050000
204 +# define XTENSA_ENTRY_MASK 0xff000000
205 +# define XTENSA_ENTRY_VALUE 0x63000000
208 +# error __XTENSA_EL__ or __XTENSA_EB__ must be defined
211 +#define BREAKPOINT_LENGTH 3
212 +#define DENSITY_BREAKPOINT_LENGTH 2
214 +#define DECR_PC_AFTER_BREAK 0
216 +#define LT_ELFCLASS ELFCLASS32
217 +#define LT_ELF_MACHINE EM_XTENSA
219 +static inline int is_density(const void *p)
221 + const unsigned char *bytes = p;
222 + return (bytes[0] & XTENSA_OP0_MASK) >= XTENSA_DENSITY_FIRST &&
223 + (bytes[0] & XTENSA_OP0_MASK) < XTENSA_DENSITY_LAST;
226 +#define ARCH_HAVE_LTELF_DATA
227 +struct arch_ltelf_data {
230 +enum xtensa_plt_type {
232 + XTENSA_PLT_UNRESOLVED,
233 + XTENSA_PLT_RESOLVED,
236 +#define ARCH_HAVE_LIBRARY_DATA
237 +struct arch_library_data {
238 + GElf_Addr loadable_sz;
241 +#define ARCH_HAVE_LIBRARY_SYMBOL_DATA
242 +struct arch_library_symbol_data {
243 + enum xtensa_plt_type type;
244 + GElf_Addr resolved_addr;
247 +#define ARCH_HAVE_BREAKPOINT_DATA
248 +struct arch_breakpoint_data {
251 +#define ARCH_HAVE_PROCESS_DATA
252 +struct arch_process_data {
253 + /* Breakpoint that hits when the dynamic linker is about to
254 + * update a .plt slot. NULL before that address is known. */
255 + struct breakpoint *dl_plt_update_bp;
257 + /* PLT update breakpoint looks here for the handler. */
258 + struct process_stopping_handler *handler;
261 +#define ARCH_HAVE_ADD_PLT_ENTRY
262 +#define ARCH_HAVE_DYNLINK_DONE
263 +#define ARCH_HAVE_ENABLE_BREAKPOINT
264 +#define ARCH_HAVE_GET_SYMINFO
265 +#define ARCH_HAVE_FETCH_ARG
266 diff --git a/sysdeps/linux-gnu/xtensa/breakpoint.c b/sysdeps/linux-gnu/xtensa/breakpoint.c
268 index 0000000..256d1dd
270 +++ b/sysdeps/linux-gnu/xtensa/breakpoint.c
273 + * This file is part of ltrace.
274 + * Copyright (C) 2014 Cadence Design Systems Inc.
276 + * This program is free software; you can redistribute it and/or
277 + * modify it under the terms of the GNU General Public License as
278 + * published by the Free Software Foundation; either version 2 of the
279 + * License, or (at your option) any later version.
281 + * This program is distributed in the hope that it will be useful, but
282 + * WITHOUT ANY WARRANTY; without even the implied warranty of
283 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
284 + * General Public License for more details.
286 + * You should have received a copy of the GNU General Public License
287 + * along with this program; if not, write to the Free Software
288 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
294 +#include <sys/ptrace.h>
300 +#include "backend.h"
302 +#include "breakpoint.h"
304 +#include "library.h"
307 +arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
309 + static unsigned char break_insn[] = BREAKPOINT_VALUE;
310 + static unsigned char density_break_insn[] = DENSITY_BREAKPOINT_VALUE;
311 + unsigned char *bytes;
314 + debug(DEBUG_PROCESS,
315 + "arch_enable_breakpoint: pid=%d, addr=%p, symbol=%s",
316 + pid, sbp->addr, breakpoint_name(sbp));
319 + a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr, 0);
320 + if (a == -1 && errno) {
321 + fprintf(stderr, "enable_breakpoint"
322 + " pid=%d, addr=%p, symbol=%s: %s\n",
323 + pid, sbp->addr, breakpoint_name(sbp),
327 + bytes = (unsigned char *)&a;
328 + memcpy(sbp->orig_value, bytes, BREAKPOINT_LENGTH);
329 + if (is_density(bytes)) {
330 + memcpy(bytes, density_break_insn, DENSITY_BREAKPOINT_LENGTH);
332 + memcpy(bytes, break_insn, BREAKPOINT_LENGTH);
334 + a = ptrace(PTRACE_POKETEXT, pid, sbp->addr, a);
336 + fprintf(stderr, "enable_breakpoint"
337 + " pid=%d, addr=%p, symbol=%s: %s\n",
338 + pid, sbp->addr, breakpoint_name(sbp),
343 diff --git a/sysdeps/linux-gnu/xtensa/fetch.c b/sysdeps/linux-gnu/xtensa/fetch.c
345 index 0000000..c211ac5
347 +++ b/sysdeps/linux-gnu/xtensa/fetch.c
350 + * This file is part of ltrace.
351 + * Copyright (C) 2014 Cadence Design Systems Inc.
353 + * This program is free software; you can redistribute it and/or
354 + * modify it under the terms of the GNU General Public License as
355 + * published by the Free Software Foundation; either version 2 of the
356 + * License, or (at your option) any later version.
358 + * This program is distributed in the hope that it will be useful, but
359 + * WITHOUT ANY WARRANTY; without even the implied warranty of
360 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
361 + * General Public License for more details.
363 + * You should have received a copy of the GNU General Public License
364 + * along with this program; if not, write to the Free Software
365 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
369 +#include <sys/ptrace.h>
370 +#include <asm/ptrace.h>
378 +#include <stdbool.h>
380 +#include "backend.h"
382 +#include "library.h"
389 + MAX_REG_ARG_WORDS = 6,
390 + REG_ARG_BASE_REG = 2,
392 + MAX_RETURN_WORDS = 4,
393 + RETURN_BASE_REG = 10,
394 + SYSCALL_RETURN_BASE_REG = 2,
397 +struct fetch_context {
398 + unsigned arg_word_idx;
400 + arch_addr_t ret_struct;
404 +struct fetch_context *
405 +arch_fetch_arg_init(enum tof type, struct process *proc,
406 + struct arg_type_info *ret_info)
408 + struct fetch_context *ctx = malloc(sizeof(*ctx));
409 + size_t ret_sz = type_sizeof(proc, ret_info);
410 + unsigned long sp = ptrace(PTRACE_PEEKUSER, proc->pid,
411 + (REG_A_BASE + 1), 0);
413 + if (ctx == NULL || sp == (size_t)-1) {
418 + ctx->arg_word_idx = 0;
419 + ctx->sp = (arch_addr_t)sp;
420 + ctx->ret_struct = NULL;
422 + if (ret_sz > MAX_RETURN_WORDS * sizeof(long)) {
423 + unsigned long a2 = ptrace(PTRACE_PEEKUSER, proc->pid,
424 + (REG_A_BASE + 2), 0);
425 + ctx->ret_struct = (arch_addr_t)a2;
426 + ++ctx->arg_word_idx;
432 +struct fetch_context *
433 +arch_fetch_arg_clone(struct process *proc,
434 + struct fetch_context *ctx)
436 + struct fetch_context *clone = malloc(sizeof(*ctx));
445 +arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
446 + struct process *proc,
447 + struct arg_type_info *info, struct value *valuep)
449 + size_t sz = type_sizeof(proc, info);
450 + size_t al = type_alignof(proc, info);
451 + size_t words = (sz + sizeof(long) - 1) / sizeof(long);
453 + assert(sz != (size_t)-1);
454 + assert(al != (size_t)-1);
456 + if (al > sizeof(long)) {
457 + al /= sizeof(long);
458 + ctx->arg_word_idx = (ctx->arg_word_idx + al - 1) & ~(al - 1);
461 + if (ctx->arg_word_idx + words <= MAX_REG_ARG_WORDS) {
463 + unsigned char *data = value_reserve(valuep, sz);
468 + for (i = 0; i < words; ++i) {
469 + static const unsigned syscall_reg[] = {
473 + (type == LT_TOF_FUNCTION ?
474 + REG_ARG_BASE_REG + ctx->arg_word_idx + i :
475 + syscall_reg[ctx->arg_word_idx + i]);
476 + unsigned long a = ptrace(PTRACE_PEEKUSER, proc->pid,
477 + (REG_A_BASE + regnr), 0);
478 + size_t copy = sizeof(a) < sz ? sizeof(a) : sz;
480 + memcpy(data, &a, copy);
481 + data += sizeof(long);
484 + ctx->arg_word_idx += words;
486 + } else if (ctx->arg_word_idx < MAX_REG_ARG_WORDS) {
487 + ctx->arg_word_idx = MAX_REG_ARG_WORDS;
490 + value_in_inferior(valuep, ctx->sp + sizeof(long) *
491 + (ctx->arg_word_idx - MAX_REG_ARG_WORDS));
492 + ctx->arg_word_idx += words;
498 +arch_fetch_retval(struct fetch_context *ctx, enum tof type,
499 + struct process *proc, struct arg_type_info *info,
500 + struct value *valuep)
502 + size_t sz = type_sizeof(proc, info);
503 + size_t words = (sz + sizeof(long) - 1) / sizeof(long);
505 + assert(sz != (size_t)-1);
507 + if (words <= MAX_RETURN_WORDS) {
509 + unsigned char *data = value_reserve(valuep, sz);
514 + for (i = 0; i < words; ++i) {
515 + unsigned regnr = i +
516 + (type == LT_TOF_FUNCTIONR ?
517 + RETURN_BASE_REG : SYSCALL_RETURN_BASE_REG);
518 + unsigned long a = ptrace(PTRACE_PEEKUSER, proc->pid,
519 + (REG_A_BASE + regnr), 0);
520 + size_t copy = sizeof(a) < sz ? sizeof(a) : sz;
522 + memcpy(data, &a, copy);
523 + data += sizeof(long);
527 + value_in_inferior(valuep, ctx->ret_struct);
533 +arch_fetch_arg_done(struct fetch_context *context)
537 diff --git a/sysdeps/linux-gnu/xtensa/plt.c b/sysdeps/linux-gnu/xtensa/plt.c
539 index 0000000..dd0a0f1
541 +++ b/sysdeps/linux-gnu/xtensa/plt.c
544 + * This file is part of ltrace.
545 + * Copyright (C) 2014 Cadence Design Systems Inc.
547 + * This program is free software; you can redistribute it and/or
548 + * modify it under the terms of the GNU General Public License as
549 + * published by the Free Software Foundation; either version 2 of the
550 + * License, or (at your option) any later version.
552 + * This program is distributed in the hope that it will be useful, but
553 + * WITHOUT ANY WARRANTY; without even the implied warranty of
554 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
555 + * General Public License for more details.
557 + * You should have received a copy of the GNU General Public License
558 + * along with this program; if not, write to the Free Software
559 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
566 +#include <inttypes.h>
568 +#include <sys/ptrace.h>
573 +#include "library.h"
574 +#include "breakpoint.h"
575 +#include "backend.h"
579 +mark_as_resolved(struct process *proc, struct library_symbol *libsym,
582 + arch_addr_t addr = (arch_addr_t)(intptr_t)libsym->arch.resolved_addr;
583 + struct breakpoint *bp = insert_breakpoint_at(proc, addr, libsym);
586 + enable_breakpoint(proc, bp);
588 + libsym->arch.type = XTENSA_PLT_RESOLVED;
589 + libsym->arch.resolved_addr = value;
593 +read_plt_slot_value(struct process *proc, arch_addr_t addr, GElf_Addr *valp)
595 + long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr);
598 + debug(DEBUG_EVENT, "ptrace .plt slot value @%p: %s",
599 + addr, strerror(errno));
603 + *valp = (GElf_Addr)l;
608 +unresolve_plt_slot(struct process *proc, arch_addr_t addr, GElf_Addr value)
610 + if (ptrace(PTRACE_POKETEXT, proc->pid, addr,
611 + (void *)(intptr_t)value) < 0) {
612 + debug(DEBUG_EVENT, "failed to unresolve .plt slot @%p: %s",
613 + addr, strerror(errno));
620 +arch_elf_init(struct ltelf *lte, struct library *lib)
624 + GElf_Addr relplt_addr;
626 + GElf_Addr low, high;
627 + int has_loadable = 0;
630 + for (i = 0; gelf_getphdr(lte->elf, i, &phdr) != NULL; ++i) {
631 + if (phdr.p_type == PT_LOAD) {
632 + if (has_loadable) {
633 + if (phdr.p_vaddr < low)
634 + low = phdr.p_vaddr;
635 + if (phdr.p_vaddr + phdr.p_memsz > high)
636 + high = phdr.p_vaddr + phdr.p_memsz;
639 + low = phdr.p_vaddr;
640 + high = phdr.p_vaddr + phdr.p_memsz;
644 + lib->arch.loadable_sz = has_loadable ? high - low : 0;
646 + if (elf_load_dynamic_entry(lte, DT_JMPREL, &relplt_addr) < 0 ||
647 + elf_get_section_covering(lte, relplt_addr, &scn, &shdr) < 0 ||
651 + if (elf_read_relocs(lte, scn, &shdr, <e->plt_relocs) < 0) {
652 + fprintf(stderr, "Couldn't get .rel*.plt data: %s\n",
660 +arch_elf_destroy(struct ltelf *lte)
665 +arch_get_sym_info(struct ltelf *lte, const char *filename,
666 + size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
668 + if (gelf_getsym(lte->dynsym, ELF64_R_SYM(rela->r_info), sym) == NULL)
671 + /* .rela.plt entries that reference locally defined functions point
672 + * to their entry points directly, not to PLT entries. Skip such
674 + if (sym->st_shndx != SHN_UNDEF) {
675 + const char *name = lte->dynstr + sym->st_name;
676 + debug(2, "symbol %s does not have plt entry", name);
684 +arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
685 + const char *name, GElf_Rela *rela, size_t ndx,
686 + struct library_symbol **ret)
688 + if (default_elf_add_plt_entry(proc, lte, name, rela, ndx, ret) < 0) {
692 + /* All PLT library symbols are initially marked as delayed. Some of
693 + * them may reference weak symbols that are never loaded, sym2addr for
694 + * such entries will return NULL. All other symbols are activated
695 + * after the dynlink is done. */
696 + (*ret)->delayed = 1;
701 +arch_dynlink_done(struct process *proc)
703 + struct library_symbol *libsym = NULL;
705 + while ((libsym = proc_each_symbol(proc, libsym,
706 + library_symbol_delayed_cb, NULL))) {
707 + assert(libsym->plt_type == LS_TOPLT_EXEC);
709 + if (read_plt_slot_value(proc, libsym->enter_addr,
710 + &libsym->arch.resolved_addr) == 0 &&
711 + libsym->arch.resolved_addr) {
713 + (GElf_Addr)(intptr_t)libsym->lib->base;
714 + GElf_Addr sz = libsym->lib->arch.loadable_sz;
716 + /* Some references may be resolved at this point, they
717 + * will point outside the loadable area of their own
719 + if (libsym->arch.resolved_addr >= base &&
720 + libsym->arch.resolved_addr - base < sz) {
721 + libsym->arch.type = XTENSA_PLT_UNRESOLVED;
722 + proc_activate_delayed_symbol(proc, libsym);
724 + libsym->arch.type = XTENSA_PLT_RESOLVED;
730 +GElf_Addr arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela)
732 + return rela->r_offset;
735 +void *sym2addr(struct process *proc, struct library_symbol *sym)
738 + long ret = ptrace(PTRACE_PEEKTEXT, proc->pid, sym->enter_addr, 0);
740 + switch (sym->plt_type) {
741 + case LS_TOPLT_NONE:
742 + addr = sym->enter_addr;
744 + /* Not every exported function starts with ENTRY instruction,
745 + * e.g. _start does not. Only skip first instruction if it's
746 + * entry, otherwise don't do it: if the first instruction is
747 + * FLIX or density it will break it or the following
749 + if ((ret & XTENSA_ENTRY_MASK) == XTENSA_ENTRY_VALUE) {
754 + case LS_TOPLT_EXEC:
756 + /* OTOH every PLT entry starts with ENTRY. Put initial
757 + * breakpoint after it. After symbol resolution put
758 + * additional breakpoint at the first instruction. */
759 + addr = (ret == -1 || ret == 0) ? NULL : (void *)(ret + 3);
766 +arch_library_symbol_init(struct library_symbol *libsym)
768 + libsym->arch.type = XTENSA_DEFAULT;
773 +arch_library_symbol_destroy(struct library_symbol *libsym)
778 +arch_library_symbol_clone(struct library_symbol *retp,
779 + struct library_symbol *libsym)
781 + retp->arch = libsym->arch;
786 +dl_plt_update_bp_on_hit(struct breakpoint *bp, struct process *proc)
788 + debug(DEBUG_PROCESS, "pid=%d dl_plt_update_bp_on_hit %s(%p)",
789 + proc->pid, breakpoint_name(bp), bp->addr);
790 + struct process_stopping_handler *self = proc->arch.handler;
791 + assert(self != NULL);
793 + struct library_symbol *libsym = self->breakpoint_being_enabled->libsym;
795 + if (read_plt_slot_value(proc, libsym->enter_addr, &value) < 0)
798 + unresolve_plt_slot(proc, libsym->enter_addr,
799 + libsym->arch.resolved_addr);
800 + mark_as_resolved(proc, libsym, value);
802 + /* cb_on_all_stopped looks if HANDLER is set to NULL as a way
803 + * to check that this was run. It's an error if it
805 + proc->arch.handler = NULL;
807 + breakpoint_turn_off(bp, proc);
810 +static enum callback_status
811 +cb_keep_stepping_p(struct process_stopping_handler *self)
813 + struct process *proc = self->task_enabling_breakpoint;
814 + struct library_symbol *libsym = self->breakpoint_being_enabled->libsym;
817 + if (read_plt_slot_value(proc, libsym->enter_addr, &value) < 0)
820 + /* In UNRESOLVED state, the resolved_addr in fact contains
821 + * the PLT entry value. */
822 + if (value == libsym->arch.resolved_addr) {
823 + /* Don't try to single-step over our own breakpoint infinitely.
824 + * This may happen if we fail to detect resolved PLT entry. */
825 + if (address2bpstruct(proc, get_instruction_pointer(proc))) {
831 + debug(DEBUG_PROCESS, "pid=%d PLT got resolved to value %#"PRIx64,
834 + /* The .plt slot got resolved! We can migrate the breakpoint
835 + * to RESOLVED and stop single-stepping. */
836 + if (unresolve_plt_slot(proc, libsym->enter_addr,
837 + libsym->arch.resolved_addr) < 0)
840 + /* Install breakpoint to the address where the change takes
841 + * place. If we fail, then that just means that we'll have to
842 + * singlestep the next time around as well. */
843 + struct process *leader = proc->leader;
844 + if (leader == NULL || leader->arch.dl_plt_update_bp != NULL)
847 + arch_addr_t addr = get_instruction_pointer(proc);
848 + struct breakpoint *dl_plt_update_bp =
849 + insert_breakpoint_at(proc, addr, NULL);
850 + if (dl_plt_update_bp == NULL)
853 + leader->arch.dl_plt_update_bp = dl_plt_update_bp;
855 + static struct bp_callbacks dl_plt_update_cbs = {
856 + .on_hit = dl_plt_update_bp_on_hit,
858 + breakpoint_set_callbacks(dl_plt_update_bp, &dl_plt_update_cbs);
860 + /* Turn it off for now. We will turn it on again when we hit
861 + * the PLT entry that needs this. */
862 + breakpoint_turn_off(dl_plt_update_bp, proc);
865 + mark_as_resolved(proc, libsym, value);
871 +cb_on_all_stopped(struct process_stopping_handler *self)
873 + /* Put that in for dl_plt_update_bp_on_hit to see. */
874 + assert(self->task_enabling_breakpoint->arch.handler == NULL);
875 + self->task_enabling_breakpoint->arch.handler = self;
877 + linux_ptrace_disable_and_continue(self);
881 +xtensa_plt_bp_hit(struct breakpoint *bp, struct process *proc)
883 + struct library_symbol *libsym = bp->libsym;
885 + if (libsym->arch.type == XTENSA_PLT_RESOLVED) {
887 + (arch_addr_t)(intptr_t)libsym->arch.resolved_addr;
889 + set_instruction_pointer(proc, addr);
890 + ptrace(PTRACE_SINGLESTEP, proc->pid, NULL, NULL);
896 +xtensa_plt_bp_continue(struct breakpoint *bp, struct process *proc)
898 + struct process *leader = proc->leader;
899 + void (*on_all_stopped)(struct process_stopping_handler *) = NULL;
900 + enum callback_status (*keep_stepping_p)
901 + (struct process_stopping_handler *) = NULL;
903 + if (bp->libsym->arch.type != XTENSA_PLT_UNRESOLVED) {
904 + continue_process(proc->pid);
908 + if (leader != NULL && leader->arch.dl_plt_update_bp != NULL &&
909 + breakpoint_turn_on(leader->arch.dl_plt_update_bp, proc) >= 0) {
910 + on_all_stopped = cb_on_all_stopped;
912 + keep_stepping_p = cb_keep_stepping_p;
915 + if (process_install_stopping_handler(proc, bp, on_all_stopped,
916 + keep_stepping_p, NULL) < 0) {
917 + fprintf(stderr, "%s: couldn't install event handler\n",
919 + continue_after_breakpoint(proc, bp);
923 +/* For some symbol types, we need to set up custom callbacks.
926 +arch_breakpoint_init(struct process *proc, struct breakpoint *bp)
928 + /* Artificial and entry-point breakpoints are plain. */
929 + if (bp->libsym == NULL || bp->libsym->plt_type != LS_TOPLT_EXEC)
932 + static struct bp_callbacks cbs = {
933 + .on_hit = xtensa_plt_bp_hit,
934 + .on_continue = xtensa_plt_bp_continue,
936 + breakpoint_set_callbacks(bp, &cbs);
942 +arch_breakpoint_destroy(struct breakpoint *bp)
947 +arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
949 + retp->arch = sbp->arch;
954 +arch_process_init(struct process *proc)
956 + proc->arch.dl_plt_update_bp = NULL;
961 +arch_process_destroy(struct process *proc)
966 +arch_process_clone(struct process *retp, struct process *proc)
968 + retp->arch = proc->arch;
970 + if (retp->arch.dl_plt_update_bp != NULL) {
971 + /* Point it to the corresponding breakpoint in RETP.
972 + * It must be there, this part of PROC has already
973 + * been cloned to RETP. */
974 + retp->arch.dl_plt_update_bp
975 + = address2bpstruct(retp,
976 + retp->arch.dl_plt_update_bp->addr);
978 + assert(retp->arch.dl_plt_update_bp != NULL);
985 +arch_process_exec(struct process *proc)
987 + return arch_process_init(proc);
991 +arch_library_init(struct library *lib)
997 +arch_library_destroy(struct library *lib)
1002 +arch_library_clone(struct library *retp, struct library *lib)
1006 diff --git a/sysdeps/linux-gnu/xtensa/ptrace.h b/sysdeps/linux-gnu/xtensa/ptrace.h
1007 new file mode 100644
1008 index 0000000..6e67fff
1010 +++ b/sysdeps/linux-gnu/xtensa/ptrace.h
1013 + * This file is part of ltrace.
1014 + * Copyright (C) 2014 Cadence Design Systems Inc.
1016 + * This program is free software; you can redistribute it and/or
1017 + * modify it under the terms of the GNU General Public License as
1018 + * published by the Free Software Foundation; either version 2 of the
1019 + * License, or (at your option) any later version.
1021 + * This program is distributed in the hope that it will be useful, but
1022 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1023 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1024 + * General Public License for more details.
1026 + * You should have received a copy of the GNU General Public License
1027 + * along with this program; if not, write to the Free Software
1028 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1032 +#include <sys/ptrace.h>
1033 diff --git a/sysdeps/linux-gnu/xtensa/regs.c b/sysdeps/linux-gnu/xtensa/regs.c
1034 new file mode 100644
1035 index 0000000..a5a8c8d
1037 +++ b/sysdeps/linux-gnu/xtensa/regs.c
1040 + * This file is part of ltrace.
1041 + * Copyright (C) 2014 Cadence Design Systems Inc.
1043 + * This program is free software; you can redistribute it and/or
1044 + * modify it under the terms of the GNU General Public License as
1045 + * published by the Free Software Foundation; either version 2 of the
1046 + * License, or (at your option) any later version.
1048 + * This program is distributed in the hope that it will be useful, but
1049 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1050 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1051 + * General Public License for more details.
1053 + * You should have received a copy of the GNU General Public License
1054 + * along with this program; if not, write to the Free Software
1055 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1059 +#include "config.h"
1062 +#include <string.h>
1063 +#include <sys/types.h>
1064 +#include <sys/ptrace.h>
1065 +#include <asm/ptrace.h>
1068 +#include "common.h"
1070 +static int xtensa_peek_user(struct process *proc, unsigned addr,
1071 + unsigned long *res)
1076 + retval = ptrace(PTRACE_PEEKUSER, proc->pid, addr, 0);
1077 + if (retval == -1 && errno) {
1078 + fprintf(stderr, "%s: pid=%d, %s\n",
1079 + __func__, proc->pid, strerror(errno));
1087 +void *get_instruction_pointer(struct process *proc)
1089 + unsigned long res;
1091 + if (xtensa_peek_user(proc, REG_PC, &res))
1092 + return (void *)res;
1097 +void set_instruction_pointer(struct process *proc, void *addr)
1099 + ptrace(PTRACE_POKEUSER, proc->pid, REG_PC, addr);
1102 +void *get_stack_pointer(struct process *proc)
1104 + unsigned long res;
1106 + if (xtensa_peek_user(proc, REG_A_BASE + 1, &res))
1107 + return (void *)res;
1112 +void *get_return_addr(struct process *proc, void *stack_pointer)
1114 + unsigned long res;
1116 + if (xtensa_peek_user(proc, REG_A_BASE, &res))
1117 + /* Assume call8, mask the upper 2 bits. */
1118 + return (void *)(0x3FFFFFFF & res);
1122 diff --git a/sysdeps/linux-gnu/xtensa/signalent.h b/sysdeps/linux-gnu/xtensa/signalent.h
1123 new file mode 100644
1124 index 0000000..953534d
1126 +++ b/sysdeps/linux-gnu/xtensa/signalent.h
1129 + * This file is part of ltrace.
1130 + * Copyright (C) 2014 Cadence Design Systems Inc.
1132 + * This program is free software; you can redistribute it and/or
1133 + * modify it under the terms of the GNU General Public License as
1134 + * published by the Free Software Foundation; either version 2 of the
1135 + * License, or (at your option) any later version.
1137 + * This program is distributed in the hope that it will be useful, but
1138 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1139 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1140 + * General Public License for more details.
1142 + * You should have received a copy of the GNU General Public License
1143 + * along with this program; if not, write to the Free Software
1144 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1151 + "SIGQUIT", /* 3 */
1153 + "SIGTRAP", /* 5 */
1154 + "SIGABRT", /* 6 */
1157 + "SIGKILL", /* 9 */
1158 + "SIGUSR1", /* 10 */
1159 + "SIGSEGV", /* 11 */
1160 + "SIGUSR2", /* 12 */
1161 + "SIGPIPE", /* 13 */
1162 + "SIGALRM", /* 14 */
1163 + "SIGTERM", /* 15 */
1164 + "SIGSTKFLT", /* 16 */
1165 + "SIGCHLD", /* 17 */
1166 + "SIGCONT", /* 18 */
1167 + "SIGSTOP", /* 19 */
1168 + "SIGTSTP", /* 20 */
1169 + "SIGTTIN", /* 21 */
1170 + "SIGTTOU", /* 22 */
1171 + "SIGURG", /* 23 */
1172 + "SIGXCPU", /* 24 */
1173 + "SIGXFSZ", /* 25 */
1174 + "SIGVTALRM", /* 26 */
1175 + "SIGPROF", /* 27 */
1176 + "SIGWINCH", /* 28 */
1178 + "SIGPWR", /* 30 */
1179 + "SIGSYS", /* 31 */
1180 diff --git a/sysdeps/linux-gnu/xtensa/syscallent.h b/sysdeps/linux-gnu/xtensa/syscallent.h
1181 new file mode 100644
1182 index 0000000..ff19d83
1184 +++ b/sysdeps/linux-gnu/xtensa/syscallent.h
1187 + * This file is part of ltrace.
1188 + * Copyright (C) 2014 Cadence Design Systems Inc.
1190 + * This program is free software; you can redistribute it and/or
1191 + * modify it under the terms of the GNU General Public License as
1192 + * published by the Free Software Foundation; either version 2 of the
1193 + * License, or (at your option) any later version.
1195 + * This program is distributed in the hope that it will be useful, but
1196 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1197 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1198 + * General Public License for more details.
1200 + * You should have received a copy of the GNU General Public License
1201 + * along with this program; if not, write to the Free Software
1202 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1208 + "available4", /* 2 */
1209 + "available5", /* 3 */
1210 + "available6", /* 4 */
1211 + "available7", /* 5 */
1212 + "available8", /* 6 */
1213 + "available9", /* 7 */
1220 + "select", /* 14 */
1223 + "_llseek", /* 17 */
1224 + "epoll_wait", /* 18 */
1225 + "epoll_ctl", /* 19 */
1226 + "epoll_create", /* 20 */
1228 + "truncate", /* 22 */
1229 + "ftruncate", /* 23 */
1231 + "writev", /* 25 */
1233 + "fdatasync", /* 27 */
1234 + "truncate64", /* 28 */
1235 + "ftruncate64", /* 29 */
1236 + "pread64", /* 30 */
1237 + "pwrite64", /* 31 */
1239 + "rename", /* 33 */
1240 + "symlink", /* 34 */
1241 + "readlink", /* 35 */
1244 + "unlink", /* 38 */
1248 + "fchdir", /* 42 */
1249 + "getcwd", /* 43 */
1253 + "stat64", /* 47 */
1254 + "lchown", /* 48 */
1256 + "lstat64", /* 50 */
1257 + "available51", /* 51 */
1258 + "fchmod", /* 52 */
1259 + "fchown", /* 53 */
1261 + "fstat64", /* 55 */
1263 + "access", /* 57 */
1265 + "getdents", /* 59 */
1266 + "getdents64", /* 60 */
1267 + "fcntl64", /* 61 */
1268 + "available62", /* 62 */
1269 + "fadvise64_64", /* 63 */
1271 + "utimes", /* 65 */
1274 + "setxattr", /* 68 */
1275 + "getxattr", /* 69 */
1276 + "listxattr", /* 70 */
1277 + "removexattr", /* 71 */
1278 + "lsetxattr", /* 72 */
1279 + "lgetxattr", /* 73 */
1280 + "llistxattr", /* 74 */
1281 + "lremovexattr", /* 75 */
1282 + "fsetxattr", /* 76 */
1283 + "fgetxattr", /* 77 */
1284 + "flistxattr", /* 78 */
1285 + "fremovexattr", /* 79 */
1287 + "munmap", /* 81 */
1288 + "mprotect", /* 82 */
1291 + "munlock", /* 85 */
1292 + "mlockall", /* 86 */
1293 + "munlockall", /* 87 */
1294 + "mremap", /* 88 */
1296 + "mincore", /* 90 */
1297 + "madvise", /* 91 */
1298 + "shmget", /* 92 */
1300 + "shmctl", /* 94 */
1302 + "socket", /* 96 */
1303 + "setsockopt", /* 97 */
1304 + "getsockopt", /* 98 */
1305 + "shutdown", /* 99 */
1307 + "connect", /* 101 */
1308 + "listen", /* 102 */
1309 + "accept", /* 103 */
1310 + "getsockname", /* 104 */
1311 + "getpeername", /* 105 */
1312 + "sendmsg", /* 106 */
1313 + "recvmsg", /* 107 */
1316 + "sendto", /* 110 */
1317 + "recvfrom", /* 111 */
1318 + "socketpair", /* 112 */
1319 + "sendfile", /* 113 */
1320 + "sendfile64", /* 114 */
1321 + "sendmmsg", /* 115 */
1322 + "clone", /* 116 */
1323 + "execve", /* 117 */
1325 + "exit_group", /* 119 */
1326 + "getpid", /* 120 */
1327 + "wait4", /* 121 */
1328 + "waitid", /* 122 */
1330 + "tkill", /* 124 */
1331 + "tgkill", /* 125 */
1332 + "set_tid_address", /* 126 */
1333 + "gettid", /* 127 */
1334 + "setsid", /* 128 */
1335 + "getsid", /* 129 */
1336 + "prctl", /* 130 */
1337 + "personality", /* 131 */
1338 + "getpriority", /* 132 */
1339 + "setpriority", /* 133 */
1340 + "setitimer", /* 134 */
1341 + "getitimer", /* 135 */
1342 + "setuid", /* 136 */
1343 + "getuid", /* 137 */
1344 + "setgid", /* 138 */
1345 + "getgid", /* 139 */
1346 + "geteuid", /* 140 */
1347 + "getegid", /* 141 */
1348 + "setreuid", /* 142 */
1349 + "setregid", /* 143 */
1350 + "setresuid", /* 144 */
1351 + "getresuid", /* 145 */
1352 + "setresgid", /* 146 */
1353 + "getresgid", /* 147 */
1354 + "setpgid", /* 148 */
1355 + "getpgid", /* 149 */
1356 + "getppid", /* 150 */
1357 + "getpgrp", /* 151 */
1358 + "reserved152", /* 152 */
1359 + "reserved153", /* 153 */
1360 + "times", /* 154 */
1362 + "sched_setaffinity", /* 156 */
1363 + "sched_getaffinity", /* 157 */
1364 + "capget", /* 158 */
1365 + "capset", /* 159 */
1366 + "ptrace", /* 160 */
1367 + "semtimedop", /* 161 */
1368 + "semget", /* 162 */
1369 + "semop", /* 163 */
1370 + "semctl", /* 164 */
1371 + "available165", /* 165 */
1372 + "msgget", /* 166 */
1373 + "msgsnd", /* 167 */
1374 + "msgrcv", /* 168 */
1375 + "msgctl", /* 169 */
1376 + "available170", /* 170 */
1377 + "umount2", /* 171 */
1378 + "mount", /* 172 */
1379 + "swapon", /* 173 */
1380 + "chroot", /* 174 */
1381 + "pivot_root", /* 175 */
1382 + "umount", /* 176 */
1383 + "swapoff", /* 177 */
1385 + "syncfs", /* 179 */
1386 + "setfsuid", /* 180 */
1387 + "setfsgid", /* 181 */
1388 + "sysfs", /* 182 */
1389 + "ustat", /* 183 */
1390 + "statfs", /* 184 */
1391 + "fstatfs", /* 185 */
1392 + "statfs64", /* 186 */
1393 + "fstatfs64", /* 187 */
1394 + "setrlimit", /* 188 */
1395 + "getrlimit", /* 189 */
1396 + "getrusage", /* 190 */
1397 + "futex", /* 191 */
1398 + "gettimeofday", /* 192 */
1399 + "settimeofday", /* 193 */
1400 + "adjtimex", /* 194 */
1401 + "nanosleep", /* 195 */
1402 + "getgroups", /* 196 */
1403 + "setgroups", /* 197 */
1404 + "sethostname", /* 198 */
1405 + "setdomainname", /* 199 */
1406 + "syslog", /* 200 */
1407 + "vhangup", /* 201 */
1408 + "uselib", /* 202 */
1409 + "reboot", /* 203 */
1410 + "quotactl", /* 204 */
1411 + "nfsservctl", /* 205 */
1412 + "_sysctl", /* 206 */
1413 + "bdflush", /* 207 */
1414 + "uname", /* 208 */
1415 + "sysinfo", /* 209 */
1416 + "init_module", /* 210 */
1417 + "delete_module", /* 211 */
1418 + "sched_setparam", /* 212 */
1419 + "sched_getparam", /* 213 */
1420 + "sched_setscheduler", /* 214 */
1421 + "sched_getscheduler", /* 215 */
1422 + "sched_get_priority_max", /* 216 */
1423 + "sched_get_priority_min", /* 217 */
1424 + "sched_rr_get_interval", /* 218 */
1425 + "sched_yield", /* 219 */
1428 + "available222", /* 222 */
1429 + "restart_syscall", /* 223 */
1430 + "sigaltstack", /* 224 */
1431 + "rt_sigreturn", /* 225 */
1432 + "rt_sigaction", /* 226 */
1433 + "rt_sigprocmask", /* 227 */
1434 + "rt_sigpending", /* 228 */
1435 + "rt_sigtimedwait", /* 229 */
1436 + "rt_sigqueueinfo", /* 230 */
1437 + "rt_sigsuspend", /* 231 */
1438 + "mq_open", /* 232 */
1439 + "mq_unlink", /* 233 */
1440 + "mq_timedsend", /* 234 */
1441 + "mq_timedreceive", /* 235 */
1442 + "mq_notify", /* 236 */
1443 + "mq_getsetattr", /* 237 */
1444 + "available238", /* 238 */
1445 + "io_setup", /* 239 */
1446 + "io_destroy", /* 240 */
1447 + "io_submit", /* 241 */
1448 + "io_getevents", /* 242 */
1449 + "io_cancel", /* 243 */
1450 + "clock_settime", /* 244 */
1451 + "clock_gettime", /* 245 */
1452 + "clock_getres", /* 246 */
1453 + "clock_nanosleep", /* 247 */
1454 + "timer_create", /* 248 */
1455 + "timer_delete", /* 249 */
1456 + "timer_settime", /* 250 */
1457 + "timer_gettime", /* 251 */
1458 + "timer_getoverrun", /* 252 */
1459 + "reserved253", /* 253 */
1460 + "lookup_dcookie", /* 254 */
1461 + "available255", /* 255 */
1462 + "add_key", /* 256 */
1463 + "request_key", /* 257 */
1464 + "keyctl", /* 258 */
1465 + "available259", /* 259 */
1466 + "readahead", /* 260 */
1467 + "remap_file_pages", /* 261 */
1468 + "migrate_pages", /* 262 */
1469 + "mbind", /* 263 */
1470 + "get_mempolicy", /* 264 */
1471 + "set_mempolicy", /* 265 */
1472 + "unshare", /* 266 */
1473 + "move_pages", /* 267 */
1474 + "splice", /* 268 */
1476 + "vmsplice", /* 270 */
1477 + "available271", /* 271 */
1478 + "pselect6", /* 272 */
1479 + "ppoll", /* 273 */
1480 + "epoll_pwait", /* 274 */
1481 + "epoll_create1", /* 275 */
1482 + "inotify_init", /* 276 */
1483 + "inotify_add_watch", /* 277 */
1484 + "inotify_rm_watch", /* 278 */
1485 + "inotify_init1", /* 279 */
1486 + "getcpu", /* 280 */
1487 + "kexec_load", /* 281 */
1488 + "ioprio_set", /* 282 */
1489 + "ioprio_get", /* 283 */
1490 + "set_robust_list", /* 284 */
1491 + "get_robust_list", /* 285 */
1492 + "available286", /* 286 */
1493 + "available287", /* 287 */
1494 + "openat", /* 288 */
1495 + "mkdirat", /* 289 */
1496 + "mknodat", /* 290 */
1497 + "unlinkat", /* 291 */
1498 + "renameat", /* 292 */
1499 + "linkat", /* 293 */
1500 + "symlinkat", /* 294 */
1501 + "readlinkat", /* 295 */
1502 + "utimensat", /* 296 */
1503 + "fchownat", /* 297 */
1504 + "futimesat", /* 298 */
1505 + "fstatat64", /* 299 */
1506 + "fchmodat", /* 300 */
1507 + "faccessat", /* 301 */
1508 + "available302", /* 302 */
1509 + "available303", /* 303 */
1510 + "signalfd", /* 304 */
1512 + "eventfd", /* 306 */
1513 + "recvmmsg", /* 307 */
1514 + "setns", /* 308 */
1515 + "signalfd4", /* 309 */
1517 + "pipe2", /* 311 */
1518 + "timerfd_create", /* 312 */
1519 + "timerfd_settime", /* 313 */
1520 + "timerfd_gettime", /* 314 */
1521 + "available315", /* 315 */
1522 + "eventfd2", /* 316 */
1523 + "preadv", /* 317 */
1524 + "pwritev", /* 318 */
1525 + "available319", /* 319 */
1526 + "fanotify_init", /* 320 */
1527 + "fanotify_mark", /* 321 */
1528 + "process_vm_readv", /* 322 */
1529 + "process_vm_writev", /* 323 */
1530 + "name_to_handle_at", /* 324 */
1531 + "open_by_handle_at", /* 325 */
1532 + "sync_file_range", /* 326 */
1533 + "perf_event_open", /* 327 */
1534 + "rt_tgsigqueueinfo", /* 328 */
1535 + "clock_adjtime", /* 329 */
1536 + "prlimit64", /* 330 */
1538 + "finit_module", /* 332 */
1539 + "accept4", /* 333 */
1540 + "sched_setattr", /* 334 */
1541 + "sched_getattr", /* 335 */
1542 + "syscall_count", /* 336 */
1543 diff --git a/sysdeps/linux-gnu/xtensa/trace.c b/sysdeps/linux-gnu/xtensa/trace.c
1544 new file mode 100644
1545 index 0000000..c7d3077
1547 +++ b/sysdeps/linux-gnu/xtensa/trace.c
1550 + * This file is part of ltrace.
1551 + * Copyright (C) 2014 Cadence Design Systems Inc.
1553 + * This program is free software; you can redistribute it and/or
1554 + * modify it under the terms of the GNU General Public License as
1555 + * published by the Free Software Foundation; either version 2 of the
1556 + * License, or (at your option) any later version.
1558 + * This program is distributed in the hope that it will be useful, but
1559 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1560 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1561 + * General Public License for more details.
1563 + * You should have received a copy of the GNU General Public License
1564 + * along with this program; if not, write to the Free Software
1565 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1569 +#include "config.h"
1571 +#include <sys/types.h>
1572 +#include <sys/wait.h>
1573 +#include <signal.h>
1574 +#include <sys/ptrace.h>
1575 +#include <asm/ptrace.h>
1577 +#include "common.h"
1581 +get_arch_dep(struct process *proc)
1585 +/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */
1586 +int syscall_p(struct process *proc, int status, int *sysnum)
1588 + if (WIFSTOPPED(status)
1589 + && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
1590 + /* get the user's pc */
1591 + int pc = ptrace(PTRACE_PEEKUSER, proc->pid, REG_PC, 0);
1593 + /* fetch the SWI instruction */
1594 + int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 3, 0);
1596 + *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, SYSCALL_NR, 0);
1597 + /* if it is a syscall, return 1 or 2 */
1598 + if ((insn & XTENSA_SYSCALL_MASK) == XTENSA_SYSCALL_VALUE) {
1599 + if ((proc->callstack_depth > 0)
1600 + && proc->callstack[proc->callstack_depth
1601 + - 1].is_syscall) {