Rewrite system_calls.exp
[platform/upstream/ltrace.git] / backend.h
index 89c05c3..e25daa0 100644 (file)
--- a/backend.h
+++ b/backend.h
@@ -1,6 +1,6 @@
 /*
  * This file is part of ltrace.
- * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
 #include <gelf.h>
 
 enum process_status {
-       ps_invalid,     /* Failure.  */
-       ps_stop,        /* Job-control stop.  */
-       ps_tracing_stop,
-       ps_sleeping,
-       ps_zombie,
-       ps_other,       /* Necessary other states can be added as needed.  */
+       PS_INVALID,     /* Failure.  */
+       PS_STOP,        /* Job-control stop.  */
+       PS_TRACING_STOP,
+       PS_SLEEPING,
+       PS_ZOMBIE,
+       PS_OTHER,       /* Necessary other states can be added as needed.  */
 };
 
 /*
@@ -70,7 +70,7 @@ int wait_for_proc(pid_t pid);
 int task_kill(pid_t pid, int sig);
 
 /* Called after PID is attached, but before it is continued.  */
-void trace_set_options(struct Process *proc);
+void trace_set_options(struct process *proc);
 
 /* Called after ltrace forks.  Should attach the newly created child,
  * in whose context this function is called.  */
@@ -86,7 +86,7 @@ void untrace_pid(pid_t pid);
 /* The back end may need to store arbitrary data to a process.  This
  * is a place where it can initialize PROC->arch_dep.  XXX this should
  * be dropped in favor of arhc_process_init on pmachata/libs.  */
-void get_arch_dep(struct Process *proc);
+void get_arch_dep(struct process *proc);
 
 /* Return current instruction pointer of PROC.
  *
@@ -95,34 +95,30 @@ void get_arch_dep(struct Process *proc);
  * that would otherwise support this.  Above we have a definition of
  * arch_addr_t.  This should be converted to an integral type and
  * used for target addresses throughout.  */
-void *get_instruction_pointer(struct Process *proc);
+void *get_instruction_pointer(struct process *proc);
 
 /* Set instruction pointer of PROC to ADDR.  XXX see above.  */
-void set_instruction_pointer(struct Process *proc, void *addr);
+void set_instruction_pointer(struct process *proc, void *addr);
 
 /* Return current stack pointer of PROC.  XXX see above.  */
-void *get_stack_pointer(struct Process *proc);
+void *get_stack_pointer(struct process *proc);
 
 /* Find and return caller address, i.e. the address where the current
  * function returns.  */
-void *get_return_addr(struct Process *proc, void *stack_pointer);
-
-/* Adjust PROC so that when the current function returns, it returns
- * to ADDR.  */
-void set_return_addr(struct Process *proc, void *addr);
+void *get_return_addr(struct process *proc, void *stack_pointer);
 
 /* Enable breakpoint SBP in process PROC.  */
-void enable_breakpoint(struct Process *proc, struct breakpoint *sbp);
+void enable_breakpoint(struct process *proc, struct breakpoint *sbp);
 
 /* Disable breakpoint SBP in process PROC.  */
-void disable_breakpoint(struct Process *proc, struct breakpoint *sbp);
+void disable_breakpoint(struct process *proc, struct breakpoint *sbp);
 
 /* Determine whether the event that we have just seen (and that is
  * recorded in STATUS) was a syscall.  If it was, return 1.  If it was
  * a return from syscall, return 2.  In both cases, set *SYSNUM to the
  * number of said syscall.  If it wasn't a syscall, return 0.  If
  * there was an error, return -1.  */
-int syscall_p(struct Process *proc, int status, int *sysnum);
+int syscall_p(struct process *proc, int status, int *sysnum);
 
 /* Continue execution of the process with given PID.  */
 void continue_process(pid_t pid);
@@ -136,17 +132,21 @@ void continue_after_signal(pid_t pid, int signum);
  * is system call, otherwise it's return from a system call.  The
  * callback should do whatever book-keeping is necessary and continue
  * the process if necessary.  */
-void continue_after_syscall(struct Process *proc, int sysnum, int ret_p);
+void continue_after_syscall(struct process *proc, int sysnum, int ret_p);
 
 /* Called after we hit a breakpoint SBP.  Should do whatever
  * book-keeping is necessary and then continue the process.  */
-void continue_after_breakpoint(struct Process *proc, struct breakpoint *sbp);
+void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp);
 
 /* Called after we received a vfork.  Should do whatever book-keeping
  * is necessary and continue the process if necessary.  N.B. right
  * now, with Linux/GNU the only back end, this is not necessary.  I
  * imagine other systems may be different.  */
-void continue_after_vfork(struct Process *proc);
+void continue_after_vfork(struct process *proc);
+
+/* Called after the process exec's.  Should do whatever book-keeping
+ * is necessary and then continue the process.  */
+void continue_after_exec(struct process *proc);
 
 /* Called when trace_me or primary trace_pid fail.  This may plug in
  * any platform-specific knowledge of why it could be so.  */
@@ -171,14 +171,15 @@ void os_ltrace_exiting(void);
 
 /* Should copy COUNT bytes from address ADDR of process PROC to local
  * buffer BUF.  */
-size_t umovebytes (struct Process *proc, void *addr, void *buf, size_t count);
+size_t umovebytes(struct process *proc, arch_addr_t addr,
+                 void *buf, size_t count);
 
 /* Find out an address of symbol SYM in process PROC, and return.
  * Returning NULL delays breakpoint insertion and enables heaps of
  * arch-specific black magic that we should clean up some day.
  *
  * XXX the same points as for get_instruction_pointer apply. */
-void *sym2addr(struct Process *proc, struct library_symbol *sym);
+void *sym2addr(struct process *proc, struct library_symbol *sym);
 
 /* Obtain address of PLT entry corresponding to relocation RELA in
  * file LTE.  This is NDX-th PLT entry in the file.
@@ -189,7 +190,7 @@ GElf_Addr arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela);
 /* Called at some point after we have attached to PROC.  This callback
  * should insert an introspection breakpoint for handling dynamic
  * linker library loads.  */
-int linkmap_init(struct Process *proc, arch_addr_t dyn_addr);
+int linkmap_init(struct process *proc, arch_addr_t dyn_addr);
 
 /* This should produce and return the next event of one of the traced
  * processes.  The returned pointer will not be freed by the core and
@@ -198,14 +199,14 @@ int linkmap_init(struct Process *proc, arch_addr_t dyn_addr);
 struct Event *next_event(void);
 
 /* Called when process PROC was removed.  */
-void process_removed(struct Process *proc);
+void process_removed(struct process *proc);
 
 /* This should extract entry point address and interpreter (dynamic
  * linker) bias if possible.  Returns 0 if there were no errors, -1
  * otherwise.  Sets *ENTRYP and *INTERP_BIASP to non-zero values if
  * the corresponding value is known, or zero otherwise; this is not
  * done for pointers that are NULL.  */
-int process_get_entry(struct Process *proc,
+int process_get_entry(struct process *proc,
                      arch_addr_t *entryp,
                      arch_addr_t *interp_biasp);
 
@@ -227,21 +228,49 @@ int process_get_entry(struct Process *proc,
 int arch_elf_init(struct ltelf *lte, struct library *lib);
 void arch_elf_destroy(struct ltelf *lte);
 
+/* The following callbacks have to be implemented in OS backend if
+ * os.h defines OS_HAVE_BREAKPOINT_DATA.  Those are used to init,
+ * destroy, and clone SBP->os.  os_breakpoint_init and
+ * os_breakpoint_clone return 0 on success or a negative value on
+ * failure.  */
+int os_breakpoint_init(struct process *proc, struct breakpoint *sbp);
+void os_breakpoint_destroy(struct breakpoint *sbp);
+int os_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp);
+
 /* The following callbacks have to be implemented in backend if arch.h
  * defines ARCH_HAVE_BREAKPOINT_DATA.  Those are used to init,
  * destroy, and clone SBP->arch.  arch_breakpoint_init and
  * arch_breakpoint_clone return 0 on success or a negative value on
  * failure.  */
-int arch_breakpoint_init(struct Process *proc, struct breakpoint *sbp);
+int arch_breakpoint_init(struct process *proc, struct breakpoint *sbp);
 void arch_breakpoint_destroy(struct breakpoint *sbp);
 int arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp);
 
+/* The following callbacks have to be implemented in OS backend if
+ * os.h defines OS_HAVE_LIBRARY_DATA.  Those are used to init, destroy
+ * and clone LIB->os.  os_library_init and os_library_clone return 0
+ * on success or a negative value on failure.  */
+int os_library_init(struct library *lib);
+void os_library_destroy(struct library *lib);
+int os_library_clone(struct library *retp, struct library *lib);
+
 /* The following callbacks have to be implemented in backend if arch.h
  * defines ARCH_HAVE_LIBRARY_DATA.  Those are used to init, destroy
- * and clone LIB->arch.  */
-void arch_library_init(struct library *lib);
+ * and clone LIB->arch.  arch_library_init and arch_library_clone
+ * return 0 on success or a negative value on failure.  */
+int arch_library_init(struct library *lib);
 void arch_library_destroy(struct library *lib);
-void arch_library_clone(struct library *retp, struct library *lib);
+int arch_library_clone(struct library *retp, struct library *lib);
+
+/* The following callbacks have to be implemented in OS backend if
+ * os.h defines OS_HAVE_LIBRARY_SYMBOL_DATA.  Those are used to init,
+ * destroy and clone LIBSYM->os.  os_library_symbol_init and
+ * os_library_symbol_clone return 0 on success or a negative value on
+ * failure.  */
+int os_library_symbol_init(struct library_symbol *libsym);
+void os_library_symbol_destroy(struct library_symbol *libsym);
+int os_library_symbol_clone(struct library_symbol *retp,
+                           struct library_symbol *libsym);
 
 /* The following callbacks have to be implemented in backend if arch.h
  * defines ARCH_HAVE_LIBRARY_SYMBOL_DATA.  Those are used to init,
@@ -253,71 +282,100 @@ void arch_library_symbol_destroy(struct library_symbol *libsym);
 int arch_library_symbol_clone(struct library_symbol *retp,
                              struct library_symbol *libsym);
 
+/* The following callbacks have to be implemented in OS backend if
+ * os.h defines OS_HAVE_PROCESS_DATA.  The protocol is same as for,
+ * respectively, arch_process_init, arch_process_destroy,
+ * arch_process_clone and arch_process_exec.  */
+int os_process_init(struct process *proc);
+void os_process_destroy(struct process *proc);
+int os_process_clone(struct process *retp, struct process *proc);
+int os_process_exec(struct process *proc);
+
 /* The following callbacks have to be implemented in backend if arch.h
  * defines ARCH_HAVE_PROCESS_DATA.  Those are used to init, destroy
  * and clone PROC->arch.  arch_process_exec is called to update
  * PROC->arch in case that PROC underwent an exec.  See notes at
  * process_init, process_destroy, process_clone and process_exec in
  * proc.h.  */
-int arch_process_init(struct Process *proc);
-void arch_process_destroy(struct Process *proc);
-int arch_process_clone(struct Process *retp, struct Process *proc);
-int arch_process_exec(struct Process *proc);
-
-/* The following callbacks have to be implemented in OS backend if
- * os.h defines OS_HAVE_PROCESS_DATA.  The protocol is same as for,
- * respectively, arch_process_init, arch_process_destroy,
- * arch_process_clone and arch_process_exec.  */
-int os_process_init(struct Process *proc);
-void os_process_destroy(struct Process *proc);
-int os_process_clone(struct Process *retp, struct Process *proc);
-int os_process_exec(struct Process *proc);
+int arch_process_init(struct process *proc);
+void arch_process_destroy(struct process *proc);
+int arch_process_clone(struct process *retp, struct process *proc);
+int arch_process_exec(struct process *proc);
 
 /* The following callback has to be implemented in backend if arch.h
  * defines ARCH_HAVE_GET_SYM_INFO.
  *
- * This is called for every PLT relocation R in ELF file LTE, that
- * ltrace is about to add to it's internal representation of the
- * program under trace.
- * The corresponding PLT entry is for SYM_INDEX-th relocation in the file.
- *
- * The callback is responsible for initializing RELA and SYM.
- *
- * Return 0 if OK.
- * Return a negative value if this symbol (SYM_INDEX) should be ignored.  */
-int arch_get_sym_info(struct ltelf *lte, const char *filename,
-                     size_t sym_index, GElf_Rela *rela, GElf_Sym *sym);
+ * This is called for every PLT relocation RELA in ELF file LTE (which
+ * is named FILENAME), that ltrace is about to add.  The corresponding
+ * PLT entry is for SYM_INDEX-th relocation in the file.  This call is
+ * supposed to initialize SYM and RELA.  It returns 0 if there were no
+ * errors and given symbol should be used, 1 if the symbol should not
+ * be used, or a negative value if there were errors.  */
+int arch_get_sym_info(struct ltelf *lte, const char *filename, size_t sym_index,
+                     GElf_Rela *rela, GElf_Sym *sym);
 
 enum plt_status {
-       plt_fail,
-       plt_ok,
-       plt_default,
+       PLT_FAIL,
+       PLT_OK,
+       PLT_DEFAULT,
 };
 
-/* The following callback has to be implemented in backend if arch.h
- * defines ARCH_HAVE_ADD_PLT_ENTRY.
+/* The following callback has to be implemented in OS backend if os.h
+ * defines OS_HAVE_ADD_PLT_ENTRY.
  *
  * This is called for every PLT relocation R in ELF file LTE, that
  * ltrace is about to add to a library constructed in process PROC.
  * The corresponding PLT entry is for symbol called NAME, and it's
  * I-th relocation in the file.
  *
- * If this function returns plt_default, PLT address is obtained by
- * calling arch_plt_sym_val, and symbol is allocated.  If plt_ok or
- * plt_default are returned, the chain of symbols passed back in RET
+ * If this function returns PLT_DEFAULT, PLT address is obtained by
+ * calling arch_plt_sym_val, and symbol is allocated.  If PLT_OK or
+ * PLT_DEFAULT are returned, the chain of symbols passed back in RET
  * is added to library under construction.  */
-enum plt_status arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
+enum plt_status os_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
+                                    const char *name, GElf_Rela *rela,
+                                    size_t i, struct library_symbol **ret);
+
+/* Like os_elf_add_plt_entry, but tied to ARCH_HAVE_ADD_PLT_ENTRY in
+ * arch.h.  The arch callback is called first.  If it returns
+ * PLT_DEFAULT, the os callback is called next.  */
+enum plt_status arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
                                       const char *name, GElf_Rela *rela,
                                       size_t i, struct library_symbol **ret);
 
+/* The following callback has to be implemented in OS backend if os.h
+ * defines OS_HAVE_ADD_FUNC_ENTRY.
+ *
+ * This is called for every symbol in ltrace is about to add to the
+ * library constructed for LTE in process PROC.
+ *
+ * If this function returns PLT_DEFAULT, then if there is a
+ * pre-existing symbol, its name may be updated if the newly-found
+ * name is shorter.  Otherwise a new symbol is created.
+ *
+ * If PLT_OK or PLT_DEFAULT are returned, the chain of symbols passed
+ * back in RET is added to library under construction.  */
+enum plt_status os_elf_add_func_entry(struct process *proc, struct ltelf *lte,
+                                     const GElf_Sym *sym,
+                                     arch_addr_t addr, const char *name,
+                                     struct library_symbol **ret);
+
+/* Like os_elf_add_func_entry, but tied to ARCH_HAVE_ADD_FUNC_ENTRY in
+ * arch.h.  The arch callback is called first.  If it returns
+ * PLT_DEFAULT, the os callback is called next.  */
+enum plt_status arch_elf_add_func_entry(struct process *proc, struct ltelf *lte,
+                                       const GElf_Sym *sym,
+                                       arch_addr_t addr, const char *name,
+                                       struct library_symbol **ret);
+
 /* This callback needs to be implemented if arch.h defines
  * ARCH_HAVE_DYNLINK_DONE.  It is called after the dynamic linker is
- * done with the process startup.  */
-void arch_dynlink_done(struct Process *proc);
+ * done with the process start-up.  */
+void arch_dynlink_done(struct process *proc);
 
 /* This callback needs to be implemented if arch.h defines
  * ARCH_HAVE_SYMBOL_RET.  It is called after a traced call returns.  */
-void arch_symbol_ret(struct Process *proc, struct library_symbol *libsym);
+void arch_symbol_ret(struct process *proc, struct library_symbol *libsym);
 
 
 /* This callback needs to be implemented if arch.h defines
@@ -327,9 +385,36 @@ void arch_symbol_ret(struct Process *proc, struct library_symbol *libsym);
  * DYN_ADDR holds the address of the dynamic section.
  * If the debug area is found, return 0 and fill in the address in *RET.
  * If the debug area is not found, return a negative value.  */
-int arch_find_dl_debug(struct Process *proc, arch_addr_t dyn_addr,
+int arch_find_dl_debug(struct process *proc, arch_addr_t dyn_addr,
                       arch_addr_t *ret);
 
+/* This is called to obtain a list of directories to search when
+ * loading config files.  The callback sets *RETP to a pointer to the
+ * first element of a NULL-terminated array of directory names.  It's
+ * legitimate to set *RETP to NULL to indicate there are no
+ * directories.  The function returns 0 on success or a negative value
+ * on a failure.
+ *
+ * If PRIVATE is set, the list in *RETP should contain only user's own
+ * directories (presumably under HOME if there's any such thing on the
+ * given OS).  Otherwise only system directories should be reported.
+ *
+ * The directories don't have to exist.  Directories passed in -F are
+ * handled separately by the caller and this callback shouldn't
+ * concern itself with it.  */
+int os_get_config_dirs(int private, const char ***retp);
+
+/* This is called to obtain list of legacy config files to import, if
+ * any.  A reference to initialized vector of char* is passed in.
+ *
+ * This returns 0 on success, in which case strings from *RETP (if
+ * any) are interpreted as files names.  These files belong to the
+ * caller and will eventually be freed.
+ *
+ * Returns a negative value for failure, in which case *RETP contents
+ * are not consulted in any way.  */
+int os_get_ltrace_conf_filenames(struct vect *retp);
+
 /* If arch.h defines ARCH_HAVE_FETCH_ARG, the following callbacks have
  * to be implemented: arch_fetch_arg_init, arch_fetch_arg_clone,
  * arch_fetch_arg_done, arch_fetch_arg_next and arch_fetch_retval.
@@ -340,4 +425,34 @@ int arch_find_dl_debug(struct Process *proc, arch_addr_t dyn_addr,
  * implemented: arch_fetch_param_pack_start,
  * arch_fetch_param_pack_end.  See fetch.h for details.  */
 
+enum sw_singlestep_status {
+       SWS_FAIL,
+       SWS_OK,
+       SWS_HW,
+};
+struct sw_singlestep_data;
+
+/* The following callback has to be implemented in backend if arch.h
+ * defines ARCH_HAVE_SW_SINGLESTEP.
+ *
+ * This is called before the OS backend requests hardware singlestep.
+ * arch_sw_singlestep should consider whether a singlestep needs to be
+ * done in software.  If not, it returns SWS_HW.  Otherwise it needs
+ * to add one or several breakpoints by calling ADD_CB.  When it is
+ * done, it continues the process as appropriate, and answers either
+ * SWS_OK, or SWS_FAIL, depending on how it went.
+ *
+ * PROC is the process that should perform the singlestep, BP the
+ * breakpoint that we are singlestepping over.  ADD_CB is a callback
+ * to request adding breakpoints that should trap the process after
+ * it's continued.  The arguments to ADD_CB are the address where the
+ * breakpoint should be added, and DATA.  ADD_CB returns 0 on success
+ * or a negative value on failure.  It is expected that
+ * arch_sw_singlestep returns SWS_FAIL if ADD_CB returns error.  */
+enum sw_singlestep_status arch_sw_singlestep(struct process *proc,
+                                            struct breakpoint *bp,
+                                            int (*add_cb)(arch_addr_t addr,
+                                                  struct sw_singlestep_data *),
+                                            struct sw_singlestep_data *data);
+
 #endif /* BACKEND_H */