The cirros image was rebuilt against the 3.13.0-83 kernel, drivers e1000e, igbvf...
[packages/trusty/cirros-testvm.git] / cirros-testvm / src-cirros / buildroot-2015.05 / package / ltrace / 0004-xtensa-add-xtensa-support.patch
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
5
6 Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
7 ---
8  CREDITS                               |   4 +
9  NEWS                                  |   1 +
10  README                                |   1 +
11  configure.ac                          |   2 +
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
34
35 diff --git a/CREDITS b/CREDITS
36 index c85eb76..67f1761 100644
37 --- a/CREDITS
38 +++ b/CREDITS
39 @@ -61,6 +61,10 @@ N: Timothy Fesig
40  E: slate@us.ibm.com
41  D: s390 port
42  
43 +N: Max Filippov
44 +E: jcmvbkbc@gmail.com
45 +D: xtensa port
46 +
47  N: Roman Hodek
48  E: Roman.Hodek@informatik.uni-erlangen.de
49  D: m68k port
50 diff --git a/NEWS b/NEWS
51 index 71d3a1f..a8e83f1 100644
52 --- a/NEWS
53 +++ b/NEWS
54 @@ -38,6 +38,7 @@
55       binaries, as currently there's no 32-bit userspace available for
56       ARM64 processors.
57     - Imagination Technologies Meta is now supported.
58 +   - Cadence Tensilica Xtensa is now supported.
59  
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
64 --- a/README
65 +++ b/README
66 @@ -37,6 +37,7 @@ to test each release comprehensively on each target.
67         s390-*-linux-gnu
68         s390x-*-linux-gnu
69         x86_64-*-linux-gnu
70 +       xtensa-*-linux-gnu
71  
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
76 --- a/configure.ac
77 +++ b/configure.ac
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}" ;;
84  esac
85  AC_SUBST(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
91         testsuite/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
98 @@ -18,7 +18,7 @@
99  # 02110-1301 USA
100  
101  DIST_SUBDIRS = aarch64 alpha arm cris ia64 m68k metag mips ppc s390    \
102 -              sparc x86
103 +              sparc x86 xtensa
104  
105  SUBDIRS = \
106         $(HOST_CPU)
107 diff --git a/sysdeps/linux-gnu/xtensa/Makefile.am b/sysdeps/linux-gnu/xtensa/Makefile.am
108 new file mode 100644
109 index 0000000..9ce81e1
110 --- /dev/null
111 +++ b/sysdeps/linux-gnu/xtensa/Makefile.am
112 @@ -0,0 +1,36 @@
113 +# This file is part of ltrace.
114 +# Copyright (C) 2014 Cadence Design Systems Inc.
115 +#
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.
120 +#
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.
125 +#
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
129 +# 02110-1301 USA
130 +
131 +noinst_LTLIBRARIES = \
132 +       ../libcpu.la
133 +
134 +___libcpu_la_SOURCES = \
135 +       breakpoint.c \
136 +       fetch.c \
137 +       plt.c \
138 +       regs.c \
139 +       trace.c
140 +
141 +noinst_HEADERS = \
142 +       arch.h \
143 +       ptrace.h \
144 +       signalent.h \
145 +       syscallent.h
146 +
147 +MAINTAINERCLEANFILES = \
148 +       Makefile.in
149 diff --git a/sysdeps/linux-gnu/xtensa/arch.h b/sysdeps/linux-gnu/xtensa/arch.h
150 new file mode 100644
151 index 0000000..c4d300a
152 --- /dev/null
153 +++ b/sysdeps/linux-gnu/xtensa/arch.h
154 @@ -0,0 +1,111 @@
155 +/*
156 + * This file is part of ltrace.
157 + * Copyright (C) 2014 Cadence Design Systems Inc.
158 + *
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.
163 + *
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.
168 + *
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
172 + * 02110-1301 USA
173 + */
174 +
175 +#include <gelf.h>
176 +
177 +#ifdef __XTENSA_EL__
178 +
179 +# define ARCH_ENDIAN_LITTLE
180 +
181 +# define BREAKPOINT_VALUE { 0x00, 0x41, 0x00 }
182 +# define DENSITY_BREAKPOINT_VALUE { 0x2d, 0xf1 }
183 +
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
191 +
192 +#elif defined(__XTENSA_EB__)
193 +
194 +# define ARCH_ENDIAN_BIG
195 +
196 +# define BREAKPOINT_VALUE { 0x00, 0x14, 0x00 }
197 +# define DENSITY_BREAKPOINT_VALUE { 0xd2, 0x1f }
198 +
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
206 +
207 +#else
208 +# error __XTENSA_EL__ or __XTENSA_EB__ must be defined
209 +#endif
210 +
211 +#define BREAKPOINT_LENGTH 3
212 +#define DENSITY_BREAKPOINT_LENGTH 2
213 +
214 +#define DECR_PC_AFTER_BREAK 0
215 +
216 +#define LT_ELFCLASS    ELFCLASS32
217 +#define LT_ELF_MACHINE EM_XTENSA
218 +
219 +static inline int is_density(const void *p)
220 +{
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;
224 +}
225 +
226 +#define ARCH_HAVE_LTELF_DATA
227 +struct arch_ltelf_data {
228 +};
229 +
230 +enum xtensa_plt_type {
231 +       XTENSA_DEFAULT,
232 +       XTENSA_PLT_UNRESOLVED,
233 +       XTENSA_PLT_RESOLVED,
234 +};
235 +
236 +#define ARCH_HAVE_LIBRARY_DATA
237 +struct arch_library_data {
238 +       GElf_Addr loadable_sz;
239 +};
240 +
241 +#define ARCH_HAVE_LIBRARY_SYMBOL_DATA
242 +struct arch_library_symbol_data {
243 +       enum xtensa_plt_type type;
244 +       GElf_Addr resolved_addr;
245 +};
246 +
247 +#define ARCH_HAVE_BREAKPOINT_DATA
248 +struct arch_breakpoint_data {
249 +};
250 +
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;
256 +
257 +       /* PLT update breakpoint looks here for the handler.  */
258 +       struct process_stopping_handler *handler;
259 +};
260 +
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
267 new file mode 100644
268 index 0000000..256d1dd
269 --- /dev/null
270 +++ b/sysdeps/linux-gnu/xtensa/breakpoint.c
271 @@ -0,0 +1,71 @@
272 +/*
273 + * This file is part of ltrace.
274 + * Copyright (C) 2014 Cadence Design Systems Inc.
275 + *
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.
280 + *
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.
285 + *
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
289 + * 02110-1301 USA
290 + */
291 +
292 +#include "config.h"
293 +
294 +#include <sys/ptrace.h>
295 +#include <errno.h>
296 +#include <string.h>
297 +#include <stdio.h>
298 +
299 +#include "common.h"
300 +#include "backend.h"
301 +#include "sysdep.h"
302 +#include "breakpoint.h"
303 +#include "proc.h"
304 +#include "library.h"
305 +
306 +void
307 +arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
308 +{
309 +       static unsigned char break_insn[] = BREAKPOINT_VALUE;
310 +       static unsigned char density_break_insn[] = DENSITY_BREAKPOINT_VALUE;
311 +       unsigned char *bytes;
312 +       long a;
313 +
314 +       debug(DEBUG_PROCESS,
315 +             "arch_enable_breakpoint: pid=%d, addr=%p, symbol=%s",
316 +             pid, sbp->addr, breakpoint_name(sbp));
317 +
318 +       errno = 0;
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),
324 +                       strerror(errno));
325 +               return;
326 +       }
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);
331 +       } else {
332 +               memcpy(bytes, break_insn, BREAKPOINT_LENGTH);
333 +       }
334 +       a = ptrace(PTRACE_POKETEXT, pid, sbp->addr, a);
335 +       if (a == -1) {
336 +               fprintf(stderr, "enable_breakpoint"
337 +                       " pid=%d, addr=%p, symbol=%s: %s\n",
338 +                       pid, sbp->addr, breakpoint_name(sbp),
339 +                       strerror(errno));
340 +               return;
341 +       }
342 +}
343 diff --git a/sysdeps/linux-gnu/xtensa/fetch.c b/sysdeps/linux-gnu/xtensa/fetch.c
344 new file mode 100644
345 index 0000000..c211ac5
346 --- /dev/null
347 +++ b/sysdeps/linux-gnu/xtensa/fetch.c
348 @@ -0,0 +1,188 @@
349 +/*
350 + * This file is part of ltrace.
351 + * Copyright (C) 2014 Cadence Design Systems Inc.
352 + *
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.
357 + *
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.
362 + *
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
366 + * 02110-1301 USA
367 + */
368 +
369 +#include <sys/ptrace.h>
370 +#include <asm/ptrace.h>
371 +#include <assert.h>
372 +#include <elf.h>
373 +#include <libelf.h>
374 +#include <stdint.h>
375 +#include <stdio.h>
376 +#include <stdlib.h>
377 +#include <string.h>
378 +#include <stdbool.h>
379 +
380 +#include "backend.h"
381 +#include "fetch.h"
382 +#include "library.h"
383 +#include "proc.h"
384 +#include "ptrace.h"
385 +#include "type.h"
386 +#include "value.h"
387 +
388 +enum {
389 +       MAX_REG_ARG_WORDS = 6,
390 +       REG_ARG_BASE_REG = 2,
391 +
392 +       MAX_RETURN_WORDS = 4,
393 +       RETURN_BASE_REG = 10,
394 +       SYSCALL_RETURN_BASE_REG = 2,
395 +};
396 +
397 +struct fetch_context {
398 +       unsigned arg_word_idx;
399 +       arch_addr_t sp;
400 +       arch_addr_t ret_struct;
401 +
402 +};
403 +
404 +struct fetch_context *
405 +arch_fetch_arg_init(enum tof type, struct process *proc,
406 +                   struct arg_type_info *ret_info)
407 +{
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);
412 +
413 +       if (ctx == NULL || sp == (size_t)-1) {
414 +               free(ctx);
415 +               return NULL;
416 +       }
417 +
418 +       ctx->arg_word_idx = 0;
419 +       ctx->sp = (arch_addr_t)sp;
420 +       ctx->ret_struct = NULL;
421 +
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;
427 +       }
428 +
429 +       return ctx;
430 +}
431 +
432 +struct fetch_context *
433 +arch_fetch_arg_clone(struct process *proc,
434 +                    struct fetch_context *ctx)
435 +{
436 +       struct fetch_context *clone = malloc(sizeof(*ctx));
437 +
438 +       if (clone == NULL)
439 +               return NULL;
440 +       *clone = *ctx;
441 +       return clone;
442 +}
443 +
444 +int
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)
448 +{
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);
452 +
453 +       assert(sz != (size_t)-1);
454 +       assert(al != (size_t)-1);
455 +
456 +       if (al > sizeof(long)) {
457 +               al /= sizeof(long);
458 +               ctx->arg_word_idx = (ctx->arg_word_idx + al - 1) & ~(al - 1);
459 +       }
460 +
461 +       if (ctx->arg_word_idx + words <= MAX_REG_ARG_WORDS) {
462 +               size_t i;
463 +               unsigned char *data = value_reserve(valuep, sz);
464 +
465 +               if (data == NULL)
466 +                       return -1;
467 +
468 +               for (i = 0; i < words; ++i) {
469 +                       static const unsigned syscall_reg[] = {
470 +                               6, 3, 4, 5, 8, 9
471 +                       };
472 +                       unsigned regnr =
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;
479 +
480 +                       memcpy(data, &a, copy);
481 +                       data += sizeof(long);
482 +                       sz -= copy;
483 +               }
484 +               ctx->arg_word_idx += words;
485 +               return 0;
486 +       } else if (ctx->arg_word_idx < MAX_REG_ARG_WORDS) {
487 +               ctx->arg_word_idx = MAX_REG_ARG_WORDS;
488 +       }
489 +
490 +       value_in_inferior(valuep, ctx->sp + sizeof(long) *
491 +                         (ctx->arg_word_idx - MAX_REG_ARG_WORDS));
492 +       ctx->arg_word_idx += words;
493 +
494 +       return 0;
495 +}
496 +
497 +int
498 +arch_fetch_retval(struct fetch_context *ctx, enum tof type,
499 +                 struct process *proc, struct arg_type_info *info,
500 +                 struct value *valuep)
501 +{
502 +       size_t sz = type_sizeof(proc, info);
503 +       size_t words = (sz + sizeof(long) - 1) / sizeof(long);
504 +
505 +       assert(sz != (size_t)-1);
506 +
507 +       if (words <= MAX_RETURN_WORDS) {
508 +               size_t i;
509 +               unsigned char *data = value_reserve(valuep, sz);
510 +
511 +               if (data == NULL)
512 +                       return -1;
513 +
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;
521 +
522 +                       memcpy(data, &a, copy);
523 +                       data += sizeof(long);
524 +                       sz -= copy;
525 +               }
526 +       } else {
527 +               value_in_inferior(valuep, ctx->ret_struct);
528 +       }
529 +       return 0;
530 +}
531 +
532 +void
533 +arch_fetch_arg_done(struct fetch_context *context)
534 +{
535 +       free(context);
536 +}
537 diff --git a/sysdeps/linux-gnu/xtensa/plt.c b/sysdeps/linux-gnu/xtensa/plt.c
538 new file mode 100644
539 index 0000000..dd0a0f1
540 --- /dev/null
541 +++ b/sysdeps/linux-gnu/xtensa/plt.c
542 @@ -0,0 +1,463 @@
543 +/*
544 + * This file is part of ltrace.
545 + * Copyright (C) 2014 Cadence Design Systems Inc.
546 + *
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.
551 + *
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.
556 + *
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
560 + * 02110-1301 USA
561 + */
562 +
563 +#include <errno.h>
564 +#include <error.h>
565 +#include <gelf.h>
566 +#include <inttypes.h>
567 +#include <string.h>
568 +#include <sys/ptrace.h>
569 +
570 +#include "common.h"
571 +#include "debug.h"
572 +#include "proc.h"
573 +#include "library.h"
574 +#include "breakpoint.h"
575 +#include "backend.h"
576 +#include "trace.h"
577 +
578 +static void
579 +mark_as_resolved(struct process *proc, struct library_symbol *libsym,
580 +                GElf_Addr value)
581 +{
582 +       arch_addr_t addr = (arch_addr_t)(intptr_t)libsym->arch.resolved_addr;
583 +       struct breakpoint *bp = insert_breakpoint_at(proc, addr, libsym);
584 +
585 +       if (bp != NULL) {
586 +               enable_breakpoint(proc, bp);
587 +       }
588 +       libsym->arch.type = XTENSA_PLT_RESOLVED;
589 +       libsym->arch.resolved_addr = value;
590 +}
591 +
592 +static int
593 +read_plt_slot_value(struct process *proc, arch_addr_t addr, GElf_Addr *valp)
594 +{
595 +       long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr);
596 +
597 +       if (l < 0) {
598 +               debug(DEBUG_EVENT, "ptrace .plt slot value @%p: %s",
599 +                     addr, strerror(errno));
600 +               return -1;
601 +       }
602 +
603 +       *valp = (GElf_Addr)l;
604 +       return 0;
605 +}
606 +
607 +static int
608 +unresolve_plt_slot(struct process *proc, arch_addr_t addr, GElf_Addr value)
609 +{
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));
614 +               return -1;
615 +       }
616 +       return 0;
617 +}
618 +
619 +int
620 +arch_elf_init(struct ltelf *lte, struct library *lib)
621 +{
622 +       Elf_Scn *scn;
623 +       GElf_Shdr shdr;
624 +       GElf_Addr relplt_addr;
625 +       GElf_Phdr phdr;
626 +       GElf_Addr low, high;
627 +       int has_loadable = 0;
628 +       size_t i;
629 +
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;
637 +                       } else {
638 +                               has_loadable = 1;
639 +                               low = phdr.p_vaddr;
640 +                               high = phdr.p_vaddr + phdr.p_memsz;
641 +                       }
642 +               }
643 +       }
644 +       lib->arch.loadable_sz = has_loadable ? high - low : 0;
645 +
646 +       if (elf_load_dynamic_entry(lte, DT_JMPREL, &relplt_addr) < 0 ||
647 +           elf_get_section_covering(lte, relplt_addr, &scn, &shdr) < 0 ||
648 +           scn == NULL)
649 +               return 0;
650 +
651 +       if (elf_read_relocs(lte, scn, &shdr, &lte->plt_relocs) < 0) {
652 +               fprintf(stderr, "Couldn't get .rel*.plt data: %s\n",
653 +                       elf_errmsg(-1));
654 +               return -1;
655 +       }
656 +       return 0;
657 +}
658 +
659 +void
660 +arch_elf_destroy(struct ltelf *lte)
661 +{
662 +}
663 +
664 +int
665 +arch_get_sym_info(struct ltelf *lte, const char *filename,
666 +                 size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
667 +{
668 +       if (gelf_getsym(lte->dynsym, ELF64_R_SYM(rela->r_info), sym) == NULL)
669 +               return -1;
670 +
671 +       /* .rela.plt entries that reference locally defined functions point
672 +        * to their entry points directly, not to PLT entries.  Skip such
673 +        * symbols.  */
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);
677 +               return 1;
678 +       }
679 +
680 +       return 0;
681 +}
682 +
683 +enum plt_status
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)
687 +{
688 +       if (default_elf_add_plt_entry(proc, lte, name, rela, ndx, ret) < 0) {
689 +               return PLT_FAIL;
690 +       }
691 +
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;
697 +       return PLT_OK;
698 +}
699 +
700 +void
701 +arch_dynlink_done(struct process *proc)
702 +{
703 +       struct library_symbol *libsym = NULL;
704 +
705 +       while ((libsym = proc_each_symbol(proc, libsym,
706 +                                         library_symbol_delayed_cb, NULL))) {
707 +               assert(libsym->plt_type == LS_TOPLT_EXEC);
708 +
709 +               if (read_plt_slot_value(proc, libsym->enter_addr,
710 +                                       &libsym->arch.resolved_addr) == 0 &&
711 +                   libsym->arch.resolved_addr) {
712 +                       GElf_Addr base =
713 +                               (GElf_Addr)(intptr_t)libsym->lib->base;
714 +                       GElf_Addr sz = libsym->lib->arch.loadable_sz;
715 +
716 +                       /* Some references may be resolved at this point, they
717 +                        * will point outside the loadable area of their own
718 +                        * library.  */
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);
723 +                       } else {
724 +                               libsym->arch.type = XTENSA_PLT_RESOLVED;
725 +                       }
726 +               }
727 +       }
728 +}
729 +
730 +GElf_Addr arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela)
731 +{
732 +       return rela->r_offset;
733 +}
734 +
735 +void *sym2addr(struct process *proc, struct library_symbol *sym)
736 +{
737 +       void *addr = NULL;
738 +       long ret = ptrace(PTRACE_PEEKTEXT, proc->pid, sym->enter_addr, 0);
739 +
740 +       switch (sym->plt_type) {
741 +       case LS_TOPLT_NONE:
742 +               addr = sym->enter_addr;
743 +
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
748 +                * instruction.  */
749 +               if ((ret & XTENSA_ENTRY_MASK) == XTENSA_ENTRY_VALUE) {
750 +                       addr += 3;
751 +               }
752 +               break;
753 +
754 +       case LS_TOPLT_EXEC:
755 +
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);
760 +               break;
761 +       }
762 +       return addr;
763 +}
764 +
765 +int
766 +arch_library_symbol_init(struct library_symbol *libsym)
767 +{
768 +       libsym->arch.type = XTENSA_DEFAULT;
769 +       return 0;
770 +}
771 +
772 +void
773 +arch_library_symbol_destroy(struct library_symbol *libsym)
774 +{
775 +}
776 +
777 +int
778 +arch_library_symbol_clone(struct library_symbol *retp,
779 +                         struct library_symbol *libsym)
780 +{
781 +       retp->arch = libsym->arch;
782 +       return 0;
783 +}
784 +
785 +static void
786 +dl_plt_update_bp_on_hit(struct breakpoint *bp, struct process *proc)
787 +{
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);
792 +
793 +       struct library_symbol *libsym = self->breakpoint_being_enabled->libsym;
794 +       GElf_Addr value;
795 +       if (read_plt_slot_value(proc, libsym->enter_addr, &value) < 0)
796 +               return;
797 +
798 +       unresolve_plt_slot(proc, libsym->enter_addr,
799 +                          libsym->arch.resolved_addr);
800 +       mark_as_resolved(proc, libsym, value);
801 +
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
804 +        * wasn't.  */
805 +       proc->arch.handler = NULL;
806 +
807 +       breakpoint_turn_off(bp, proc);
808 +}
809 +
810 +static enum callback_status
811 +cb_keep_stepping_p(struct process_stopping_handler *self)
812 +{
813 +       struct process *proc = self->task_enabling_breakpoint;
814 +       struct library_symbol *libsym = self->breakpoint_being_enabled->libsym;
815 +
816 +       GElf_Addr value;
817 +       if (read_plt_slot_value(proc, libsym->enter_addr, &value) < 0)
818 +               return CBS_FAIL;
819 +
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))) {
826 +                       return CBS_FAIL;
827 +               }
828 +               return CBS_CONT;
829 +       }
830 +
831 +       debug(DEBUG_PROCESS, "pid=%d PLT got resolved to value %#"PRIx64,
832 +             proc->pid, value);
833 +
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)
838 +               return CBS_FAIL;
839 +
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)
845 +               goto done;
846 +
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)
851 +               goto done;
852 +
853 +       leader->arch.dl_plt_update_bp = dl_plt_update_bp;
854 +
855 +       static struct bp_callbacks dl_plt_update_cbs = {
856 +               .on_hit = dl_plt_update_bp_on_hit,
857 +       };
858 +       breakpoint_set_callbacks(dl_plt_update_bp, &dl_plt_update_cbs);
859 +
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);
863 +
864 +done:
865 +       mark_as_resolved(proc, libsym, value);
866 +
867 +       return CBS_STOP;
868 +}
869 +
870 +static void
871 +cb_on_all_stopped(struct process_stopping_handler *self)
872 +{
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;
876 +
877 +       linux_ptrace_disable_and_continue(self);
878 +}
879 +
880 +static void
881 +xtensa_plt_bp_hit(struct breakpoint *bp, struct process *proc)
882 +{
883 +       struct library_symbol *libsym = bp->libsym;
884 +
885 +       if (libsym->arch.type == XTENSA_PLT_RESOLVED) {
886 +               arch_addr_t addr =
887 +                       (arch_addr_t)(intptr_t)libsym->arch.resolved_addr;
888 +
889 +               set_instruction_pointer(proc, addr);
890 +               ptrace(PTRACE_SINGLESTEP, proc->pid, NULL, NULL);
891 +               return;
892 +       }
893 +}
894 +
895 +static void
896 +xtensa_plt_bp_continue(struct breakpoint *bp, struct process *proc)
897 +{
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;
902 +
903 +       if (bp->libsym->arch.type != XTENSA_PLT_UNRESOLVED) {
904 +               continue_process(proc->pid);
905 +               return;
906 +       }
907 +
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;
911 +       } else {
912 +               keep_stepping_p = cb_keep_stepping_p;
913 +       }
914 +
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",
918 +                       __func__);
919 +               continue_after_breakpoint(proc, bp);
920 +       }
921 +}
922 +
923 +/* For some symbol types, we need to set up custom callbacks.
924 + */
925 +int
926 +arch_breakpoint_init(struct process *proc, struct breakpoint *bp)
927 +{
928 +       /* Artificial and entry-point breakpoints are plain.  */
929 +       if (bp->libsym == NULL || bp->libsym->plt_type != LS_TOPLT_EXEC)
930 +               return 0;
931 +
932 +       static struct bp_callbacks cbs = {
933 +               .on_hit = xtensa_plt_bp_hit,
934 +               .on_continue = xtensa_plt_bp_continue,
935 +       };
936 +       breakpoint_set_callbacks(bp, &cbs);
937 +
938 +       return 0;
939 +}
940 +
941 +void
942 +arch_breakpoint_destroy(struct breakpoint *bp)
943 +{
944 +}
945 +
946 +int
947 +arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
948 +{
949 +       retp->arch = sbp->arch;
950 +       return 0;
951 +}
952 +
953 +int
954 +arch_process_init(struct process *proc)
955 +{
956 +       proc->arch.dl_plt_update_bp = NULL;
957 +       return 0;
958 +}
959 +
960 +void
961 +arch_process_destroy(struct process *proc)
962 +{
963 +}
964 +
965 +int
966 +arch_process_clone(struct process *retp, struct process *proc)
967 +{
968 +       retp->arch = proc->arch;
969 +
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);
977 +
978 +               assert(retp->arch.dl_plt_update_bp != NULL);
979 +       }
980 +
981 +       return 0;
982 +}
983 +
984 +int
985 +arch_process_exec(struct process *proc)
986 +{
987 +       return arch_process_init(proc);
988 +}
989 +
990 +int
991 +arch_library_init(struct library *lib)
992 +{
993 +       return 0;
994 +}
995 +
996 +void
997 +arch_library_destroy(struct library *lib)
998 +{
999 +}
1000 +
1001 +int
1002 +arch_library_clone(struct library *retp, struct library *lib)
1003 +{
1004 +       return 0;
1005 +}
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
1009 --- /dev/null
1010 +++ b/sysdeps/linux-gnu/xtensa/ptrace.h
1011 @@ -0,0 +1,21 @@
1012 +/*
1013 + * This file is part of ltrace.
1014 + * Copyright (C) 2014 Cadence Design Systems Inc.
1015 + *
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.
1020 + *
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.
1025 + *
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
1029 + * 02110-1301 USA
1030 + */
1031 +
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
1036 --- /dev/null
1037 +++ b/sysdeps/linux-gnu/xtensa/regs.c
1038 @@ -0,0 +1,83 @@
1039 +/*
1040 + * This file is part of ltrace.
1041 + * Copyright (C) 2014 Cadence Design Systems Inc.
1042 + *
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.
1047 + *
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.
1052 + *
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
1056 + * 02110-1301 USA
1057 + */
1058 +
1059 +#include "config.h"
1060 +
1061 +#include <errno.h>
1062 +#include <string.h>
1063 +#include <sys/types.h>
1064 +#include <sys/ptrace.h>
1065 +#include <asm/ptrace.h>
1066 +
1067 +#include "proc.h"
1068 +#include "common.h"
1069 +
1070 +static int xtensa_peek_user(struct process *proc, unsigned addr,
1071 +                           unsigned long *res)
1072 +{
1073 +       long retval;
1074 +
1075 +       errno = 0;
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));
1080 +               *res = 0;
1081 +               return 0;
1082 +       }
1083 +       *res = retval;
1084 +       return 1;
1085 +}
1086 +
1087 +void *get_instruction_pointer(struct process *proc)
1088 +{
1089 +       unsigned long res;
1090 +
1091 +       if (xtensa_peek_user(proc, REG_PC, &res))
1092 +               return (void *)res;
1093 +       else
1094 +               return NULL;
1095 +}
1096 +
1097 +void set_instruction_pointer(struct process *proc, void *addr)
1098 +{
1099 +       ptrace(PTRACE_POKEUSER, proc->pid, REG_PC, addr);
1100 +}
1101 +
1102 +void *get_stack_pointer(struct process *proc)
1103 +{
1104 +       unsigned long res;
1105 +
1106 +       if (xtensa_peek_user(proc, REG_A_BASE + 1, &res))
1107 +               return (void *)res;
1108 +       else
1109 +               return NULL;
1110 +}
1111 +
1112 +void *get_return_addr(struct process *proc, void *stack_pointer)
1113 +{
1114 +       unsigned long res;
1115 +
1116 +       if (xtensa_peek_user(proc, REG_A_BASE, &res))
1117 +               /* Assume call8, mask the upper 2 bits. */
1118 +               return (void *)(0x3FFFFFFF & res);
1119 +       else
1120 +               return NULL;
1121 +}
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
1125 --- /dev/null
1126 +++ b/sysdeps/linux-gnu/xtensa/signalent.h
1127 @@ -0,0 +1,52 @@
1128 +/*
1129 + * This file is part of ltrace.
1130 + * Copyright (C) 2014 Cadence Design Systems Inc.
1131 + *
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.
1136 + *
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.
1141 + *
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
1145 + * 02110-1301 USA
1146 + */
1147 +
1148 +       "SIG_0",           /* 0 */
1149 +       "SIGHUP",          /* 1 */
1150 +       "SIGINT",          /* 2 */
1151 +       "SIGQUIT",         /* 3 */
1152 +       "SIGILL",          /* 4 */
1153 +       "SIGTRAP",         /* 5 */
1154 +       "SIGABRT",         /* 6 */
1155 +       "SIGBUS",          /* 7 */
1156 +       "SIGFPE",          /* 8 */
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 */
1177 +       "SIGIO",           /* 29 */
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
1183 --- /dev/null
1184 +++ b/sysdeps/linux-gnu/xtensa/syscallent.h
1185 @@ -0,0 +1,357 @@
1186 +/*
1187 + * This file is part of ltrace.
1188 + * Copyright (C) 2014 Cadence Design Systems Inc.
1189 + *
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.
1194 + *
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.
1199 + *
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
1203 + * 02110-1301 USA
1204 + */
1205 +
1206 +       "spill",                           /* 0 */
1207 +       "xtensa",                          /* 1 */
1208 +       "available4",                      /* 2 */
1209 +       "available5",                      /* 3 */
1210 +       "available6",                      /* 4 */
1211 +       "available7",                      /* 5 */
1212 +       "available8",                      /* 6 */
1213 +       "available9",                      /* 7 */
1214 +       "open",                            /* 8 */
1215 +       "close",                           /* 9 */
1216 +       "dup",                             /* 10 */
1217 +       "dup2",                            /* 11 */
1218 +       "read",                            /* 12 */
1219 +       "write",                           /* 13 */
1220 +       "select",                          /* 14 */
1221 +       "lseek",                           /* 15 */
1222 +       "poll",                            /* 16 */
1223 +       "_llseek",                         /* 17 */
1224 +       "epoll_wait",                      /* 18 */
1225 +       "epoll_ctl",                       /* 19 */
1226 +       "epoll_create",                    /* 20 */
1227 +       "creat",                           /* 21 */
1228 +       "truncate",                        /* 22 */
1229 +       "ftruncate",                       /* 23 */
1230 +       "readv",                           /* 24 */
1231 +       "writev",                          /* 25 */
1232 +       "fsync",                           /* 26 */
1233 +       "fdatasync",                       /* 27 */
1234 +       "truncate64",                      /* 28 */
1235 +       "ftruncate64",                     /* 29 */
1236 +       "pread64",                         /* 30 */
1237 +       "pwrite64",                        /* 31 */
1238 +       "link",                            /* 32 */
1239 +       "rename",                          /* 33 */
1240 +       "symlink",                         /* 34 */
1241 +       "readlink",                        /* 35 */
1242 +       "mknod",                           /* 36 */
1243 +       "pipe",                            /* 37 */
1244 +       "unlink",                          /* 38 */
1245 +       "rmdir",                           /* 39 */
1246 +       "mkdir",                           /* 40 */
1247 +       "chdir",                           /* 41 */
1248 +       "fchdir",                          /* 42 */
1249 +       "getcwd",                          /* 43 */
1250 +       "chmod",                           /* 44 */
1251 +       "chown",                           /* 45 */
1252 +       "stat",                            /* 46 */
1253 +       "stat64",                          /* 47 */
1254 +       "lchown",                          /* 48 */
1255 +       "lstat",                           /* 49 */
1256 +       "lstat64",                         /* 50 */
1257 +       "available51",                     /* 51 */
1258 +       "fchmod",                          /* 52 */
1259 +       "fchown",                          /* 53 */
1260 +       "fstat",                           /* 54 */
1261 +       "fstat64",                         /* 55 */
1262 +       "flock",                           /* 56 */
1263 +       "access",                          /* 57 */
1264 +       "umask",                           /* 58 */
1265 +       "getdents",                        /* 59 */
1266 +       "getdents64",                      /* 60 */
1267 +       "fcntl64",                         /* 61 */
1268 +       "available62",                     /* 62 */
1269 +       "fadvise64_64",                    /* 63 */
1270 +       "utime",                           /* 64 */
1271 +       "utimes",                          /* 65 */
1272 +       "ioctl",                           /* 66 */
1273 +       "fcntl",                           /* 67 */
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 */
1286 +       "mmap2",                           /* 80 */
1287 +       "munmap",                          /* 81 */
1288 +       "mprotect",                        /* 82 */
1289 +       "brk",                             /* 83 */
1290 +       "mlock",                           /* 84 */
1291 +       "munlock",                         /* 85 */
1292 +       "mlockall",                        /* 86 */
1293 +       "munlockall",                      /* 87 */
1294 +       "mremap",                          /* 88 */
1295 +       "msync",                           /* 89 */
1296 +       "mincore",                         /* 90 */
1297 +       "madvise",                         /* 91 */
1298 +       "shmget",                          /* 92 */
1299 +       "shmat",                           /* 93 */
1300 +       "shmctl",                          /* 94 */
1301 +       "shmdt",                           /* 95 */
1302 +       "socket",                          /* 96 */
1303 +       "setsockopt",                      /* 97 */
1304 +       "getsockopt",                      /* 98 */
1305 +       "shutdown",                        /* 99 */
1306 +       "bind",                            /* 100 */
1307 +       "connect",                         /* 101 */
1308 +       "listen",                          /* 102 */
1309 +       "accept",                          /* 103 */
1310 +       "getsockname",                     /* 104 */
1311 +       "getpeername",                     /* 105 */
1312 +       "sendmsg",                         /* 106 */
1313 +       "recvmsg",                         /* 107 */
1314 +       "send",                            /* 108 */
1315 +       "recv",                            /* 109 */
1316 +       "sendto",                          /* 110 */
1317 +       "recvfrom",                        /* 111 */
1318 +       "socketpair",                      /* 112 */
1319 +       "sendfile",                        /* 113 */
1320 +       "sendfile64",                      /* 114 */
1321 +       "sendmmsg",                        /* 115 */
1322 +       "clone",                           /* 116 */
1323 +       "execve",                          /* 117 */
1324 +       "exit",                            /* 118 */
1325 +       "exit_group",                      /* 119 */
1326 +       "getpid",                          /* 120 */
1327 +       "wait4",                           /* 121 */
1328 +       "waitid",                          /* 122 */
1329 +       "kill",                            /* 123 */
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 */
1361 +       "acct",                            /* 155 */
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 */
1384 +       "sync",                            /* 178 */
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 */
1426 +       "220",                             /* 220 */
1427 +       "221",                             /* 221 */
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 */
1475 +       "tee",                             /* 269 */
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 */
1511 +       "305",                             /* 305 */
1512 +       "eventfd",                         /* 306 */
1513 +       "recvmmsg",                        /* 307 */
1514 +       "setns",                           /* 308 */
1515 +       "signalfd4",                       /* 309 */
1516 +       "dup3",                            /* 310 */
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 */
1537 +       "kcmp",                            /* 331 */
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
1546 --- /dev/null
1547 +++ b/sysdeps/linux-gnu/xtensa/trace.c
1548 @@ -0,0 +1,61 @@
1549 +/*
1550 + * This file is part of ltrace.
1551 + * Copyright (C) 2014 Cadence Design Systems Inc.
1552 + *
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.
1557 + *
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.
1562 + *
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
1566 + * 02110-1301 USA
1567 + */
1568 +
1569 +#include "config.h"
1570 +
1571 +#include <sys/types.h>
1572 +#include <sys/wait.h>
1573 +#include <signal.h>
1574 +#include <sys/ptrace.h>
1575 +#include <asm/ptrace.h>
1576 +
1577 +#include "common.h"
1578 +#include "proc.h"
1579 +
1580 +void
1581 +get_arch_dep(struct process *proc)
1582 +{
1583 +}
1584 +
1585 +/* Returns 1 if syscall, 2 if sysret, 0 otherwise.  */
1586 +int syscall_p(struct process *proc, int status, int *sysnum)
1587 +{
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);
1592 +
1593 +               /* fetch the SWI instruction */
1594 +               int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 3, 0);
1595 +
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) {
1602 +                               return 2;
1603 +                       } else {
1604 +                               return 1;
1605 +                       }
1606 +               }
1607 +       }
1608 +       return 0;
1609 +}
1610 -- 
1611 1.8.1.4
1612