[Ltrace-devel] PATCH -- mipsel port for 0.4

Vaitl, Eric Eric.Vaitl at sciatl.com
Wed Dec 20 21:41:27 CET 2006


Sorry, our firewall only allows me http/https access, so I can't work
this into the tree myself. 

The below patch is for mipsel against version 0.4. 

The mips is a bit unusual in that it doesn't use a .plt. The .got is
used for function relocation as well as for data. This means that we
can't get the address for the breakpoints until after the program has
been started. Also, because of lazy relocation the address for a library
function can change after the first call to the function. 

For those of you doing cross builds (like myself), there are a couple of
steps you will have to go through to use the below patch:

1) Grab elfutils and cross build it. All you need is libelf.a, so the
elfutils build can break after that. 

2) Either change the name of ltrace/elf.h, put the elf.h from elfutils
in a system header directory or add an "#include_next <elf.h>" to the
"ltrace/elf.h" file . 

3) Locally, I did my own little makefiles. The ltrace autoconf stuff
seemed to balk at doing a cross build and I didn't want to fight with
them.


The patch is for linux-2.4-30. If you have a 2.6 system, you may want to
update syscallent.h.

I've only tried this on mipsel. If your system is big-endian, you may
need to make two one-line changes in trace.c. 

The patch has been approved by Cisco Inc. for release as part of a GPL
v2 project. 

=========================== break
==========================================
diff -Naur ltrace-0.4/breakpoints.c lt-mips/breakpoints.c
--- ltrace-0.4/breakpoints.c	2006-02-20 16:48:07.000000000 -0500
+++ lt-mips/breakpoints.c	2006-12-12 07:24:22.000000000 -0500
@@ -105,6 +105,35 @@
 			dict_apply_to_all(proc->breakpoints,
enable_bp_cb,
 					  proc);
 		}
+#ifdef __mips__
+      {
+          // I'm sure there is a nicer way to do this. We need to
+          // insert breakpoints __after___ the
+          // child has been started. 
+          struct library_symbol *sym;
+          struct library_symbol *new_sym;
+          sym=proc->list_of_symbols;
+          while(sym){
+              void *addr= plt2addr(proc,sym->enter_addr);
+              if(!addr){
+                  sym=sym->next;
+                  continue;
+              }
+              if(dict_find_entry(proc->breakpoints,addr)){
+                  sym=sym->next;
+                  continue;
+              }
+              debug(2,"inserting bp %p %s",addr,sym->name);
+              new_sym=malloc(sizeof(*new_sym));
+              memcpy(new_sym,sym,sizeof(*new_sym));
+              new_sym->next=proc->list_of_symbols;
+              proc->list_of_symbols=new_sym;
+              new_sym->brkpnt=0;
+              insert_breakpoint(proc, addr, new_sym);
+              sym=sym->next;
+          }
+      }
+#endif
 	}
 	proc->breakpoints_enabled = 1;
 }
diff -Naur ltrace-0.4/debug.h lt-mips/debug.h
--- ltrace-0.4/debug.h	2006-02-20 16:48:07.000000000 -0500
+++ lt-mips/debug.h	2006-12-12 07:24:22.000000000 -0500
@@ -1,7 +1,7 @@
 #include <features.h>
 
 void debug_(int level, const char *file, int line, const char *func,
-	    const char *fmt, ...);
+            const char *fmt, ...) __attribute__((format(printf,5,6)));
 
 int xwrite(const char *, size_t);
 int xwrites(const char *);
diff -Naur ltrace-0.4/elf.c lt-mips/elf.c
--- ltrace-0.4/elf.c	2006-02-20 16:48:07.000000000 -0500
+++ lt-mips/elf.c	2006-12-12 07:24:22.000000000 -0500
@@ -361,7 +361,30 @@
 	proc->e_machine = lte->ehdr.e_machine;
 	for (i = 0; i < library_num; ++i)
 		do_init_elf(&lte[i + 1], library[i]);
-
+#ifdef __mips__
+   // MIPS doesn't use the PLT and the GOT entries get changed
+   // on startup. 
+   proc->need_to_reinitialize_breakpoints = 1;
+   for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){
+       GElf_Sym sym;
+       const char *name;
+       GElf_Addr addr = arch_plt_sym_val(lte, i, 0);
+       if (gelf_getsym(lte->dynsym, i, &sym) == NULL){
+           error(EXIT_FAILURE, 0,
+                 "Couldn't get relocation from \"%s\"",
+                 proc->filename);       
+       }
+       name=lte->dynstr+sym.st_name;
+       if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){
+           debug(2,"sym %s not a function",name);
+           continue;
+       }
+       add_library_symbol(addr, name, &library_symbols, 0,
+                          ELF64_ST_BIND(sym.st_info) != 0);
+       if (!lib_tail)
+           lib_tail = &(library_symbols->next);
+   }
+#else
 	for (i = 0; i < lte->relplt_count; ++i) {
 		GElf_Rel rel;
 		GElf_Rela rela;
@@ -398,7 +421,7 @@
 				lib_tail = &(library_symbols->next);
 		}
 	}
-
+#endif
 	if (proc->need_to_reinitialize_breakpoints) {
 		/* Add "PLTs_initialized_by_here" to opt_x list, if not
already there. */
 		main_cheat = (struct opt_e_t *)malloc(sizeof(struct
opt_e_t));
diff -Naur ltrace-0.4/elf.h lt-mips/elf.h
--- ltrace-0.4/elf.h	2006-02-20 16:48:07.000000000 -0500
+++ lt-mips/elf.h	2006-12-12 07:24:22.000000000 -0500
@@ -25,6 +25,12 @@
 	size_t opd_size;
 	Elf32_Word *hash;
 	int hash_malloced;
+
+#ifdef __mips__
+    size_t pltgot_addr;
+    size_t mips_local_gotno;
+    size_t mips_gotsym;
+#endif // __mips__
 };
 
 extern int library_num;
diff -Naur ltrace-0.4/process_event.c lt-mips/process_event.c
--- ltrace-0.4/process_event.c	2006-02-20 16:48:07.000000000 -0500
+++ lt-mips/process_event.c	2006-12-12 07:24:22.000000000 -0500
@@ -306,6 +306,23 @@
 					insert_breakpoint(event->proc,
addr,
 							  libsym);
 			}
+#elif defined(__mips__)
+       void *addr;
+       void *old_addr;
+       struct library_symbol *sym=
event->proc->callstack[i].c_un.libfunc;
+       assert(sym && sym->brkpnt);
+       old_addr=sym->brkpnt->addr;
+       addr=plt2addr(event->proc,sym->enter_addr);
+       assert(old_addr !=0 && addr !=0);
+       if(addr != old_addr){
+           struct library_symbol *new_sym;
+           new_sym=malloc(sizeof(*new_sym));
+           memcpy(new_sym,sym,sizeof(*new_sym));
+           new_sym->next=event->proc->list_of_symbols;
+           event->proc->list_of_symbols=new_sym;
+           new_sym->brkpnt=0;
+           insert_breakpoint(event->proc, addr, new_sym);
+       }       
 #endif
 			for (j = event->proc->callstack_depth - 1; j >
i; j--) {
 				callstack_pop(event->proc);
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/arch.h
lt-mips/sysdeps/linux-gnu/mipsel/arch.h
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/arch.h	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/arch.h	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1,10 @@
+//#define BREAKPOINT_VALUE { 0x01, 0x00, 0x9f, 0xef }
+#define BREAKPOINT_VALUE { 0x0d, 0x00, 0x00, 0x00 }
+#define BREAKPOINT_LENGTH 4
+#define DECR_PC_AFTER_BREAK 0
+
+#define LT_ELFCLASS	ELFCLASS32
+#define LT_ELF_MACHINE	EM_MIPS
+
+#define PLTs_INIT_BY_HERE "_start"
+#define E_ENTRY_NAME    "_start"
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/Makefile
lt-mips/sysdeps/linux-gnu/mipsel/Makefile
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/Makefile	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/Makefile	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1,24 @@
+TOPDIR=$(shell cd ../../..; pwd)
+include $(TOPDIR)/config.mak
+
+.PHONY: all deps clean docs
+
+OBJ	=	trace.o regs.o plt.o
+SRC=$(OBJ:.o=.c)
+
+all:		arch.o
+
+deps:
+	$(CC) $(CFLAGS) $(CPPFLAGS) -M  $(SRC) > .depends
+
+arch.o:		$(OBJ) arch.h
+		$(CC) -nostdlib -r -o arch.o $(OBJ)
+
+clean:
+		-rm -f $(OBJ) arch.o
+
+docs:
+	doxygen
+
+
+-include .depends
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/mipsel.h
lt-mips/sysdeps/linux-gnu/mipsel/mipsel.h
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/mipsel.h	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/mipsel.h	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1,11 @@
+#ifndef MIPSEL_h
+#define  MIPSEL_h
+
+#define off_v0 2
+#define off_pc 64
+#define off_a0 4
+#define off_a3 7
+#define off_lr 31
+#define off_sp 29
+
+#endif //  MIPSEL_h
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/plt.c
lt-mips/sysdeps/linux-gnu/mipsel/plt.c
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/plt.c	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/plt.c	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1,77 @@
+#include <debug.h>
+#include <gelf.h>
+#include <sys/ptrace.h>
+#include "ltrace.h"
+#include "ltrace_elf.h"
+
+/**
+   \addtogroup mipsel
+   @{
+ */
+
+/**
+   \param lte Structure containing link table entry information
+   \param ndx Index into .dynsym
+   \param rela Not used.
+   \return Address of GOT table entry
+
+   MIPS ABI Supplement:
+
+   DT_PLTGOT This member holds the address of the .got section. 
+
+   DT_MIPS_SYMTABNO This member holds the number of entries in the
+   .dynsym section.
+
+   DT_MIPS_LOCAL_GOTNO This member holds the number of local global
+   offset table entries.
+
+   DT_MIPS_GOTSYM This member holds the index of the first dyamic
+   symbol table entry that corresponds to an entry in the gobal offset
+   table.
+
+   Called by read_elf when building the symbol table. 
+
+ */
+GElf_Addr arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *
rela)
+{
+    debug(1,"plt_addr %x ndx %#x",lte->pltgot_addr, ndx);
+    return 
+        lte->pltgot_addr + 
+        sizeof(void *) * (lte->mips_local_gotno + (ndx -
lte->mips_gotsym));
+}
+/**
+   \param proc The process to work on. 
+   \param plt The got table address from arc_plt_sym_val()
+   \return What is at the got table address
+
+   The return value should be the address to put the breakpoint at. 
+
+   On the mips the library_symbol.enter_addr is the .got addr for the
+   symbol and the breakpoint.addr is the actual breakpoint address. 
+
+   Other processors use a plt, the mips is "special" in that is uses
+   the .got for both function and data relocations. Prior to program
+   startup, return 0. 
+
+   \warning MIPS relocations are lazy. This means that the breakpoint
+   may move after the first call. Ltrace dictionary routines don't
+   have a delete and symbol is one to one with breakpoint, so if the
+   breakpoint changes I just add a new breakpoint for the new address. 
+   
+ */
+void *plt2addr(struct process *proc, void **plt)
+{
+    long ret;
+    debug(1,"plt %p pid %d",plt,proc->pid);
+    if(!proc->pid){
+        return 0;
+    }
+    ret=ptrace(PTRACE_PEEKTEXT, proc->pid, plt, 0);
+    if(ret==-1){
+        ret =0;
+    }
+    debug(1,"addr %#lx",ret);
+    return (void *)ret;;
+}
+
+/**@}*/
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/ptrace.h
lt-mips/sysdeps/linux-gnu/mipsel/ptrace.h
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/ptrace.h	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/ptrace.h	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1 @@
+#include <sys/ptrace.h>
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/regs.c
lt-mips/sysdeps/linux-gnu/mipsel/regs.c
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/regs.c	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/regs.c	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1,73 @@
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+#include <linux/user.h>
+
+#include "ltrace.h"
+#include "mipsel.h"
+
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# define PTRACE_POKEUSER PTRACE_POKEUSR
+#endif
+
+/**
+   \addtogroup mipsel
+   @{
+ */
+
+
+/**
+   \param proc The process to work on.
+   \return The current instruction pointer.
+ */
+void *get_instruction_pointer(struct process *proc)
+{
+	return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0);
+}
+
+/**
+   \param proc The process to work on.
+   \param addr The address to set to.
+
+   Called by \c continue_after_breakpoint(). 
+
+   \todo Our mips kernel ptrace doesn't support PTRACE_SINGLESTEP, so
+   we \c continue_process() after a breakpoint. Check if this is OK.
+ */
+void set_instruction_pointer(struct process *proc, void *addr)
+{
+	ptrace(PTRACE_POKEUSER, proc->pid, off_pc, addr);
+}
+
+/**
+   \param proc The process to work on.
+   \return The current stack pointer.
+ */
+void *get_stack_pointer(struct process *proc)
+{
+	return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_sp, 0);
+}
+
+/**
+   \param proc The process to work on.
+   \param stack_pointer The current stack pointer for proc
+   \return The current return address. 
+
+   Called by \c process_breakpoint(). 
+
+   Mips uses r31 for the return address, so the stack_pointer is
+   unused.
+ */
+void *get_return_addr(struct process *proc, void *stack_pointer)
+{
+	return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0);
+}
+/**@}*/
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/signalent.h
lt-mips/sysdeps/linux-gnu/mipsel/signalent.h
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/signalent.h	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/signalent.h	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1,32 @@
+"SIG_0",			/* 0 */
+    "SIGHUP",	//	    1	/* Hangup (POSIX).  */
+    "SIGINT", //		 2	/* Interrupt (ANSI).  */
+    "SIGQUIT", //		 3	/* Quit (POSIX).  */
+    "SIGILL", //		 4	/* Illegal instruction (ANSI).
*/
+    "SIGTRAP", //		 5	/* Trace trap (POSIX).  */
+    "SIGIOT", //		 6	/* IOT trap (4.2 BSD).  */
+    "SIGEMT", //		 7
+    "SIGFPE", //		 8	/* Floating-point exception
(ANSI).  */
+    "SIGKILL", //		 9	/* Kill, unblockable (POSIX).
*/
+    "SIGBUS", //		10	/* BUS error (4.2 BSD).  */
+    "SIGSEGV", //		11	/* Segmentation violation
(ANSI).  */
+    "SIGSYS", //		12
+    "SIGPIPE", //		13	/* Broken pipe (POSIX).  */
+    "SIGALRM", //		14	/* Alarm clock (POSIX).  */
+    "SIGTERM", //		15	/* Termination (ANSI).  */
+    "SIGUSR1", //		16	/* User-defined signal 1
(POSIX).  */
+    "SIGUSR2", //		17	/* User-defined signal 2
(POSIX).  */
+    "SIGCHLD", //		18	/* Child status has changed
(POSIX).  */
+    "SIGPWR", //		19	/* Power failure restart (System
V).  */
+    "SIGWINCH", //	20	/* Window size change (4.3 BSD, Sun).
*/
+    "SIGURG", //		21	/* Urgent condition on socket
(4.2 BSD).  */
+    "SIGIO", //		22	/* I/O now possible (4.2 BSD).
*/
+    "SIGSTOP", //		23	/* Stop, unblockable (POSIX).
*/
+    "SIGTSTP", //		24	/* Keyboard stop (POSIX).  */
+    "SIGCONT", //		25	/* Continue (POSIX).  */
+    "SIGTTIN", //		26	/* Background read from tty
(POSIX).  */
+    "SIGTTOU", //		27	/* Background write to tty
(POSIX).  */
+    "SIGVTALRM", //	28	/* Virtual alarm clock (4.2 BSD).  */
+    "SIGPROF", //		29	/* Profiling alarm clock (4.2
BSD).  */
+    "SIGXCPU", //		30	/* CPU limit exceeded (4.2 BSD).
*/
+    "SIGXFSZ", //		31	/* File size limit exceeded (4.2
BSD).  */
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/syscallent.h
lt-mips/sysdeps/linux-gnu/mipsel/syscallent.h
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/syscallent.h	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/syscallent.h	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1,241 @@
+    "0",			/*Linux +   0*/
+    "exit",			/*Linux +   1*/
+    "fork",			/*Linux +   2*/
+    "read",			/*Linux +   3*/
+    "write",			/*Linux +   4*/
+    "open",			/*Linux +   5*/
+    "close",			/*Linux +   6*/
+    "waitpid",			/*Linux +   7*/
+    "creat",			/*Linux +   8*/
+    "link",			/*Linux +   9*/
+    "unlink",			/*Linux +  10*/
+    "execve",			/*Linux +  11*/
+    "chdir",			/*Linux +  12*/
+    "time",			/*Linux +  13*/
+    "mknod",			/*Linux +  14*/
+    "chmod",			/*Linux +  15*/
+    "lchown",			/*Linux +  16*/
+    "break",			/*Linux +  17*/
+    "unused18",			/*Linux +  18*/
+    "lseek",			/*Linux +  19*/
+    "getpid",			/*Linux +  20*/
+    "mount",			/*Linux +  21*/
+    "umount",			/*Linux +  22*/
+    "setuid",			/*Linux +  23*/
+    "getuid",			/*Linux +  24*/
+    "stime",			/*Linux +  25*/
+    "ptrace",			/*Linux +  26*/
+    "alarm",			/*Linux +  27*/
+    "unused28",			/*Linux +  28*/
+    "pause",			/*Linux +  29*/
+    "utime",			/*Linux +  30*/
+    "stty",			/*Linux +  31*/
+    "gtty",			/*Linux +  32*/
+    "access",			/*Linux +  33*/
+    "nice",			/*Linux +  34*/
+    "ftime",			/*Linux +  35*/
+    "sync",			/*Linux +  36*/
+    "kill",			/*Linux +  37*/
+    "rename",			/*Linux +  38*/
+    "mkdir",			/*Linux +  39*/
+    "rmdir",			/*Linux +  40*/
+    "dup",			/*Linux +  41*/
+    "pipe",			/*Linux +  42*/
+    "times",			/*Linux +  43*/
+    "prof",			/*Linux +  44*/
+    "brk",			/*Linux +  45*/
+    "setgid",			/*Linux +  46*/
+    "getgid",			/*Linux +  47*/
+    "signal",			/*Linux +  48*/
+    "geteuid",			/*Linux +  49*/
+    "getegid",			/*Linux +  50*/
+    "acct",			/*Linux +  51*/
+    "umount2",			/*Linux +  52*/
+    "lock",			/*Linux +  53*/
+    "ioctl",			/*Linux +  54*/
+    "fcntl",			/*Linux +  55*/
+    "mpx",			/*Linux +  56*/
+    "setpgid",			/*Linux +  57*/
+    "ulimit",			/*Linux +  58*/
+    "unused59",			/*Linux +  59*/
+    "umask",			/*Linux +  60*/
+    "chroot",			/*Linux +  61*/
+    "ustat",			/*Linux +  62*/
+    "dup2",			/*Linux +  63*/
+    "getppid",			/*Linux +  64*/
+    "getpgrp",			/*Linux +  65*/
+    "setsid",			/*Linux +  66*/
+    "sigaction",			/*Linux +  67*/
+    "sgetmask",			/*Linux +  68*/
+    "ssetmask",			/*Linux +  69*/
+    "setreuid",			/*Linux +  70*/
+    "setregid",			/*Linux +  71*/
+    "sigsuspend",			/*Linux +  72*/
+    "sigpending",			/*Linux +  73*/
+    "sethostname",		/*Linux +  74*/
+    "setrlimit",			/*Linux +  75*/
+    "getrlimit",			/*Linux +  76*/
+    "getrusage",			/*Linux +  77*/
+    "gettimeofday",		/*Linux +  78*/
+    "settimeofday",		/*Linux +  79*/
+    "getgroups",			/*Linux +  80*/
+    "setgroups",			/*Linux +  81*/
+    "reserved82",			/*Linux +  82*/
+    "symlink",			/*Linux +  83*/
+    "unused84",			/*Linux +  84*/
+    "readlink",			/*Linux +  85*/
+    "uselib",			/*Linux +  86*/
+    "swapon",			/*Linux +  87*/
+    "reboot",			/*Linux +  88*/
+    "readdir",			/*Linux +  89*/
+    "mmap",			/*Linux +  90*/
+    "munmap",			/*Linux +  91*/
+    "truncate",			/*Linux +  92*/
+    "ftruncate",			/*Linux +  93*/
+    "fchmod",			/*Linux +  94*/
+    "fchown",			/*Linux +  95*/
+    "getpriority",		/*Linux +  96*/
+    "setpriority",		/*Linux +  97*/
+    "profil",			/*Linux +  98*/
+    "statfs",			/*Linux +  99*/
+    "fstatfs",			/*Linux + 100*/
+    "ioperm",			/*Linux + 101*/
+    "socketcall",			/*Linux + 102*/
+    "syslog",			/*Linux + 103*/
+    "setitimer",			/*Linux + 104*/
+    "getitimer",			/*Linux + 105*/
+    "stat",			/*Linux + 106*/
+    "lstat",			/*Linux + 107*/
+    "fstat",			/*Linux + 108*/
+    "unused109",			/*Linux + 109*/
+    "iopl",			/*Linux + 110*/
+    "vhangup",			/*Linux + 111*/
+    "idle",			/*Linux + 112*/
+    "vm86",			/*Linux + 113*/
+    "wait4",			/*Linux + 114*/
+    "swapoff",			/*Linux + 115*/
+    "sysinfo",			/*Linux + 116*/
+    "ipc",			/*Linux + 117*/
+    "fsync",			/*Linux + 118*/
+    "sigreturn",			/*Linux + 119*/
+    "clone",			/*Linux + 120*/
+    "setdomainname",		/*Linux + 121*/
+    "uname",			/*Linux + 122*/
+    "modify_ldt",			/*Linux + 123*/
+    "adjtimex",			/*Linux + 124*/
+    "mprotect",			/*Linux + 125*/
+    "sigprocmask",		/*Linux + 126*/
+    "create_module",		/*Linux + 127*/
+    "init_module",		/*Linux + 128*/
+    "delete_module",		/*Linux + 129*/
+    "get_kernel_syms",		/*Linux + 130*/
+    "quotactl",			/*Linux + 131*/
+    "getpgid",			/*Linux + 132*/
+    "fchdir",			/*Linux + 133*/
+    "bdflush",			/*Linux + 134*/
+    "sysfs",			/*Linux + 135*/
+    "personality",		/*Linux + 136*/
+    "afs_syscall",		/*Linux + 137*/ /* Syscall for Andrew
File System */
+    "setfsuid",			/*Linux + 138*/
+    "setfsgid",			/*Linux + 139*/
+    "_llseek",			/*Linux + 140*/
+    "getdents",			/*Linux + 141*/
+    "_newselect",			/*Linux + 142*/
+    "flock",			/*Linux + 143*/
+    "msync",			/*Linux + 144*/
+    "readv",			/*Linux + 145*/
+    "writev",			/*Linux + 146*/
+    "cacheflush",			/*Linux + 147*/
+    "cachectl",			/*Linux + 148*/
+    "sysmips",			/*Linux + 149*/
+    "unused150",			/*Linux + 150*/
+    "getsid",			/*Linux + 151*/
+    "fdatasync",			/*Linux + 152*/
+    "_sysctl",			/*Linux + 153*/
+    "mlock",			/*Linux + 154*/
+    "munlock",			/*Linux + 155*/
+    "mlockall",			/*Linux + 156*/
+    "munlockall",			/*Linux + 157*/
+    "sched_setparam",		/*Linux + 158*/
+    "sched_getparam",		/*Linux + 159*/
+    "sched_setscheduler",		/*Linux + 160*/
+    "sched_getscheduler",		/*Linux + 161*/
+    "sched_yield",		/*Linux + 162*/
+    "sched_get_priority_max",	/*Linux + 163*/
+    "sched_get_priority_min",	/*Linux + 164*/
+    "sched_rr_get_interval",	/*Linux + 165*/
+    "nanosleep",			/*Linux + 166*/
+    "mremap",			/*Linux + 167*/
+    "accept",			/*Linux + 168*/
+    "bind",			/*Linux + 169*/
+    "connect",			/*Linux + 170*/
+    "getpeername",		/*Linux + 171*/
+    "getsockname",		/*Linux + 172*/
+    "getsockopt",			/*Linux + 173*/
+    "listen",			/*Linux + 174*/
+    "recv",			/*Linux + 175*/
+    "recvfrom",			/*Linux + 176*/
+    "recvmsg",			/*Linux + 177*/
+    "send",			/*Linux + 178*/
+    "sendmsg",			/*Linux + 179*/
+    "sendto",			/*Linux + 180*/
+    "setsockopt",			/*Linux + 181*/
+    "shutdown",			/*Linux + 182*/
+    "socket",			/*Linux + 183*/
+    "socketpair",			/*Linux + 184*/
+    "setresuid",			/*Linux + 185*/
+    "getresuid",			/*Linux + 186*/
+    "query_module",		/*Linux + 187*/
+    "poll",			/*Linux + 188*/
+    "nfsservctl",			/*Linux + 189*/
+    "setresgid",			/*Linux + 190*/
+    "getresgid",			/*Linux + 191*/
+    "prctl",			/*Linux + 192*/
+    "rt_sigreturn",		/*Linux + 193*/
+    "rt_sigaction",		/*Linux + 194*/
+    "rt_sigprocmask",		/*Linux + 195*/
+    "rt_sigpending",		/*Linux + 196*/
+    "rt_sigtimedwait",		/*Linux + 197*/
+    "rt_sigqueueinfo",		/*Linux + 198*/
+    "rt_sigsuspend",		/*Linux + 199*/
+    "pread",			/*Linux + 200*/
+    "pwrite",			/*Linux + 201*/
+    "chown",			/*Linux + 202*/
+    "getcwd",			/*Linux + 203*/
+    "capget",			/*Linux + 204*/
+    "capset",			/*Linux + 205*/
+    "sigaltstack",		/*Linux + 206*/
+    "sendfile",			/*Linux + 207*/
+    "getpmsg",			/*Linux + 208*/
+    "putpmsg",			/*Linux + 209*/
+    "mmap2",			/*Linux + 210*/
+    "truncate64",			/*Linux + 211*/
+    "ftruncate64",		/*Linux + 212*/
+    "stat64",			/*Linux + 213*/
+    "lstat64",			/*Linux + 214*/
+    "fstat64",			/*Linux + 215*/
+    "pivot_root",			/*Linux + 216*/
+    "mincore",			/*Linux + 217*/
+    "madvise",			/*Linux + 218*/
+    "getdents64",			/*Linux + 219*/
+    "fcntl64",			/*Linux + 220*/
+    "security",			/*Linux + 221*/
+    "gettid",			/*Linux + 222*/
+    "readahead",			/*Linux + 223*/
+    "setxattr",			/*Linux + 224*/
+    "lsetxattr",			/*Linux + 225*/
+    "fsetxattr",			/*Linux + 226*/
+    "getxattr",			/*Linux + 227*/
+    "lgetxattr",			/*Linux + 228*/
+    "fgetxattr",			/*Linux + 229*/
+    "listxattr",			/*Linux + 230*/
+    "llistxattr",			/*Linux + 231*/
+    "flistxattr",			/*Linux + 232*/
+    "removexattr",		/*Linux + 233*/
+    "lremovexattr",		/*Linux + 234*/
+    "fremovexattr",		/*Linux + 235*/
+    "tkill",			/*Linux + 236*/
+    "sendfile64",			/*Linux + 237*/
+    "futex",			/*Linux + 238*/
+    "sched_setaffinity",		/*Linux + 239*/
+    "sched_getaffinity",		/*Linux + 240*/
diff -Naur ltrace-0.4/sysdeps/linux-gnu/mipsel/trace.c
lt-mips/sysdeps/linux-gnu/mipsel/trace.c
--- ltrace-0.4/sysdeps/linux-gnu/mipsel/trace.c	1969-12-31
19:00:00.000000000 -0500
+++ lt-mips/sysdeps/linux-gnu/mipsel/trace.c	2006-12-12
07:24:22.000000000 -0500
@@ -0,0 +1,169 @@
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+#include "debug.h"
+#include "ltrace.h"
+#include "mipsel.h"
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# define PTRACE_POKEUSER PTRACE_POKEUSR
+#endif
+
+
+/**
+   \addtogroup mipsel Mipsel specific functions.
+
+   These are the functions that it looks like I need to implement in
+   order to get ltrace to work on our target. 
+
+   @{
+ */
+
+/**
+   \param proc The process that had an event. 
+
+   Called by \c wait_for_something() right after the return from wait.
+
+   Most targets just return here. A couple use proc->arch_ptr for a
+   private data area.
+ */
+void get_arch_dep(struct process *proc)
+{
+
+}
+
+/**
+   \param proc Process that had event. 
+   \param status From \c wait()
+   \param sysnum 0-based syscall number. 
+   \return 1 if syscall, 2 if sysret, 0 otherwise.
+
+   Called by \c wait_for_something() after the call to get_arch_dep()
+
+   It seems that the ptrace call trips twice on a system call, once
+   just before the system call and once when it returns. Both times,
+   the pc points at the instruction just after the mipsel "syscall"
+   instruction.
+
+   There are several possiblities for system call sets, each is offset
+   by a base from the others. On our system, it looks like the base
+   for the system calls is 4000.
+ */
+int syscall_p(struct process *proc, int status, int *sysnum)
+{
+	if (WIFSTOPPED(status)
+	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
+       /* get the user's pc (plus 8) */
+       long pc = (long)get_instruction_pointer(proc);
+       /* fetch the SWI instruction */
+       int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
+       int num = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 8, 0);
+       
+/*
+  On a mipsel,  syscall looks like:
+  24040fa1    li v0, 0x0fa1   # 4001 --> _exit syscall
+  0000000c    syscall
+ */
+      if(insn!=0x0000000c){
+          return 0;
+      }
+
+      *sysnum = (num & 0xFFFF) - 4000;
+      /* if it is a syscall, return 1 or 2 */
+      if (proc->callstack_depth > 0 &&
+          proc->callstack[proc->callstack_depth - 1].is_syscall) {
+          return 2;
+      }
+      
+      if (*sysnum >= 0) {
+          return 1;
+      }
+   }
+	return 0;
+}
+/**
+   \param type Function/syscall call or return.
+   \param proc The process that had an event.
+   \param arg_num -1 for return value, 
+   \return The argument to fetch. 
+
+   A couple of assumptions. 
+
+-  Type is LT_TOF_FUNCTIONR or LT_TOF_SYSCALLR if arg_num==-1. These
+   types are only used in calls for output_right(), which only uses -1
+   for arg_num.
+-  Type is LT_TOF_FUNCTION or LT_TOF_SYSCALL for args 0...4. 
+-   I'm only displaying the first 4 args (Registers a0..a3). Good
+   enough for now.
+
+  Mipsel conventions seem to be:
+- syscall parameters: r4...r9
+- syscall return: if(!a3){ return v0;} else{ errno=v0;return -1;}
+- function call: r4..r7. Not sure how to get arg number 5. 
+- function return: v0
+
+The argument registers are wiped by a call, so it is a mistake to ask
+for arguments on a return. If ltrace does this, we will need to cache
+arguments somewhere on the call.
+
+I'm not doing any floating point support here. 
+
+*/
+long gimme_arg(enum tof type, struct process *proc, int arg_num)
+{
+    long ret;
+    debug(2,"type %d arg %d",type,arg_num);
+    if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL){
+        if(arg_num <4){
+            ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_a0+arg_num,0);
+            debug(2,"ret = %#lx",ret);
+            return ret;
+        } else {
+            // If we need this, I think we can look at [sp+16] for
arg_num==4.
+            CP;
+            return 0;
+        }
+    } 
+    if(arg_num>=0){
+       fprintf(stderr,"args on return?");
+    }
+    if(type == LT_TOF_FUNCTIONR) {
+        return  ptrace(PTRACE_PEEKUSER,proc->pid,off_v0,0);
+    }
+    if (type == LT_TOF_SYSCALLR) {
+        unsigned a3=ptrace(PTRACE_PEEKUSER, proc->pid,off_a3,0);
+        unsigned v0=ptrace(PTRACE_PEEKUSER, proc->pid,off_v0,0);
+        if(!a3){
+            return v0;
+        }
+        return -1;
+    }
+    fprintf(stderr, "gimme_arg called with wrong arguments\n");
+	return 0;
+}
+
+/**
+   \param type Type of call/return
+   \param proc Process to work with. 
+   
+   Called by \c output_left(), which is called on a syscall or
+   function.
+   
+   The other architectures stub this out, but seems to be the place to
+   stash off the arguments on a call so we have them on the return.
+   
+*/
+void save_register_args(enum tof type, struct process *proc)
+{
+}
+
+/**@}*/



     - - - - - Appended by Scientific Atlanta, a Cisco company - - - - -         
This e-mail and any attachments may contain information which is confidential, 
proprietary, privileged or otherwise protected by law. The information is solely 
intended for the named addressee (or a person responsible for delivering it to 
the addressee). If you are not the intended recipient of this message, you are 
not authorized to read, print, retain, copy or disseminate this message or any 
part of it. If you have received this e-mail in error, please notify the sender 
immediately by return e-mail and delete it from your computer.




More information about the Ltrace-devel mailing list