Package: ltrace
Version: 0.5-3
Severity: important
Tags: patch
User: [EMAIL PROTECTED]
Code compiled with thumb code (-mthumb option in gcc) currently
segfaults on ltrace. This patch fixes this issue.
Changelog:
2008-01-25 Anderson Lizardo <[EMAIL PROTECTED]>
* sysdeps/linux-gnu/arm/arch.h, sysdeps/linux-gnu/arm/regs.c,
sysdeps/linux-gnu/arm/breakpoint.c, sysdeps/linux-gnu/arm/Makefile,
debian/copyright: add ARM Thumb mode support.
--
Anderson Lizardo
Instituto Nokia de Tecnologia
Manaus - Brazil
Code compiled with thumb code (-mthumb option in gcc) currently segfaults on
ltrace. This patch fixes this issue.
Signed-off-by: Anderson Lizardo <[EMAIL PROTECTED]>
Signed-off-by: Bruna Moreira <[EMAIL PROTECTED]>
Index: ltrace-indt/sysdeps/linux-gnu/arm/arch.h
===================================================================
--- ltrace-indt.orig/sysdeps/linux-gnu/arm/arch.h 2007-12-18 21:10:24.000000000 -0400
+++ ltrace-indt/sysdeps/linux-gnu/arm/arch.h 2007-12-18 21:10:25.000000000 -0400
@@ -1,5 +1,10 @@
+#define ARCH_HAVE_ENABLE_BREAKPOINT 1
+#define ARCH_HAVE_DISABLE_BREAKPOINT 1
+
#define BREAKPOINT_VALUE { 0xf0, 0x01, 0xf0, 0xe7 }
#define BREAKPOINT_LENGTH 4
+#define THUMB_BREAKPOINT_VALUE { 0x01, 0xde }
+#define THUMB_BREAKPOINT_LENGTH 2
#define DECR_PC_AFTER_BREAK 0
#define LT_ELFCLASS ELFCLASS32
Index: ltrace-indt/sysdeps/linux-gnu/arm/breakpoint.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ ltrace-indt/sysdeps/linux-gnu/arm/breakpoint.c 2007-12-18 21:10:25.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ * This file is part of ltrace.
+ *
+ * Copyright (C) 2007 by Instituto Nokia de Tecnologia (INdT)
+ *
+ * Author: Anderson Lizardo <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * Modified from sysdeps/linux-gnu/breakpoint.c and added ARM Thumb support.
+*/
+
+#include <sys/ptrace.h>
+#include "config.h"
+#include "arch.h"
+#include "options.h"
+#include "output.h"
+#include "debug.h"
+
+void arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
+{
+ unsigned int i, j;
+ const unsigned char break_insn[] = BREAKPOINT_VALUE;
+ const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE;
+
+ debug(1, "arch_enable_breakpoint(%d,%p)", pid, sbp->addr);
+
+ for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
+ long a =
+ ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
+ 0);
+ unsigned char *bytes = (unsigned char *)&a;
+
+ debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode);
+ for (j = 0;
+ j < sizeof(long)
+ && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
+
+ sbp->orig_value[i * sizeof(long) + j] = bytes[j];
+ if (!sbp->thumb_mode) {
+ bytes[j] = break_insn[i * sizeof(long) + j];
+ }
+ else if (j < THUMB_BREAKPOINT_LENGTH) {
+ bytes[j] = thumb_break_insn[i * sizeof(long) + j];
+ }
+ }
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
+ }
+}
+
+void arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
+{
+ unsigned int i, j;
+ const unsigned char break_insn[] = BREAKPOINT_VALUE;
+ const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE;
+
+ debug(1, "arch_disable_breakpoint(%d,%p)", pid, sbp->addr);
+
+ for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
+ long a =
+ ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
+ 0);
+ unsigned char *bytes = (unsigned char *)&a;
+
+ debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode);
+ for (j = 0;
+ j < sizeof(long)
+ && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
+
+ bytes[j] = sbp->orig_value[i * sizeof(long) + j];
+ }
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
+ }
+}
Index: ltrace-indt/sysdeps/linux-gnu/arm/Makefile
===================================================================
--- ltrace-indt.orig/sysdeps/linux-gnu/arm/Makefile 2007-12-18 21:10:24.000000000 -0400
+++ ltrace-indt/sysdeps/linux-gnu/arm/Makefile 2007-12-18 21:10:25.000000000 -0400
@@ -1,4 +1,4 @@
-OBJ = trace.o regs.o plt.o
+OBJ = trace.o regs.o plt.o breakpoint.o
all: arch.o
Index: ltrace-indt/breakpoints.c
===================================================================
--- ltrace-indt.orig/breakpoints.c 2007-12-18 21:10:24.000000000 -0400
+++ ltrace-indt/breakpoints.c 2007-12-18 21:10:25.000000000 -0400
@@ -48,6 +48,10 @@ insert_breakpoint(struct process *proc,
if (libsym)
libsym->brkpnt = sbp;
}
+#ifdef __arm__
+ sbp->thumb_mode = proc->thumb_mode;
+ proc->thumb_mode = 0;
+#endif
sbp->enabled++;
if (sbp->enabled == 1 && proc->pid)
enable_breakpoint(proc->pid, sbp);
Index: ltrace-indt/ltrace.h
===================================================================
--- ltrace-indt.orig/ltrace.h 2007-12-18 21:10:24.000000000 -0400
+++ ltrace-indt/ltrace.h 2007-12-18 21:10:25.000000000 -0400
@@ -26,6 +26,9 @@ struct breakpoint {
unsigned char orig_value[BREAKPOINT_LENGTH];
int enabled;
struct library_symbol *libsym;
+#ifdef __arm__
+ int thumb_mode;
+#endif
};
enum arg_type {
@@ -170,6 +173,9 @@ struct process {
void *arch_ptr;
short e_machine;
short need_to_reinitialize_breakpoints;
+#ifdef __arm__
+ int thumb_mode; /* ARM execution mode: 0: ARM mode, 1: Thumb mode */
+#endif
/* output: */
enum tof type_being_displayed;
Index: ltrace-indt/sysdeps/linux-gnu/arm/regs.c
===================================================================
--- ltrace-indt.orig/sysdeps/linux-gnu/arm/regs.c 2007-12-18 21:10:24.000000000 -0400
+++ ltrace-indt/sysdeps/linux-gnu/arm/regs.c 2007-12-18 21:10:25.000000000 -0400
@@ -39,5 +39,10 @@ void *get_stack_pointer(struct process *
* a CISC architecture; in our case, we don't need that */
void *get_return_addr(struct process *proc, void *stack_pointer)
{
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0);
+ long addr = ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0);
+
+ proc->thumb_mode = addr & 1;
+ if (proc->thumb_mode)
+ addr &= ~1;
+ return (void *)addr;
}