diff options
author | Petr Machata <pmachata@redhat.com> | 2013-10-23 00:39:23 +0200 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2013-10-23 00:39:23 +0200 |
commit | 82f748d1bc2b95d594327ad15f3a6908070dd5c3 (patch) | |
tree | bca73acc5b6bfd5390e800d678a3868993f489ed | |
parent | 71025328700158770edf84cbce64d977298b6e88 (diff) | |
download | ltrace-82f748d1bc2b95d594327ad15f3a6908070dd5c3.tar.gz |
System calls are now part of dedicated symbol library
- This symbol library is still special in that symbols are created on
demand and never actually added. It just serves as a link to
protolibrary with system call prototypes, and has a name (SYS).
- Prototypes for system calls were moved to a dedicated prototype
library called syscalls.conf.
- Because it's undesirable to look up syscall prototypes in anything
but the dedicated syscall protolib, prototype.c/.h now understand
that some lookups shouldn't be done recursively (and so we never
pick the definition from -F file that just happens to have the same
name as a system call). The good thing is that now libraries can
actually use symbols named SYS_something without clashing with
system call prototypes.
- One test case needed to be updated, because we now display system
calls as something@SYS instead of SYS_something.
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | etc/ltrace.conf | 111 | ||||
-rw-r--r-- | etc/syscalls.conf | 115 | ||||
-rw-r--r-- | handle_event.c | 38 | ||||
-rw-r--r-- | library.h | 1 | ||||
-rw-r--r-- | output.c | 3 | ||||
-rw-r--r-- | prototype.c | 19 | ||||
-rw-r--r-- | prototype.h | 18 | ||||
-rw-r--r-- | read_config_file.c | 4 | ||||
-rw-r--r-- | testsuite/ltrace.main/Makefile.am | 4 | ||||
-rw-r--r-- | testsuite/ltrace.main/system_call_params.exp | 49 | ||||
-rw-r--r-- | testsuite/ltrace.main/system_calls.exp | 34 |
12 files changed, 245 insertions, 154 deletions
diff --git a/Makefile.am b/Makefile.am index cef453b..edb8442 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,8 +64,7 @@ dist_man5_MANS = ltrace.conf.5 dist_doc_DATA = COPYING CREDITS INSTALL README TODO -dist_sysconf_DATA = \ - etc/ltrace.conf +dist_pkgdata_DATA = etc/syscalls.conf etc/ltrace.conf EXTRA_DIST = \ debian/changelog \ diff --git a/etc/ltrace.conf b/etc/ltrace.conf index b82df19..0dc573d 100644 --- a/etc/ltrace.conf +++ b/etc/ltrace.conf @@ -477,114 +477,3 @@ mntent *getmntent(addr); mntent *getmntent_r(file, +mntent*, string, int); mntent *__getmntent_r(file, +mntent*, string, int); string hasmntopt(mntent*, string); - -; SYSCALLS -addr SYS_brk(addr); -int SYS_close(int); -int SYS_execve(string,addr,addr); -void SYS_exit(int); -void SYS_exit_group(int); -int SYS_fork(); -int SYS_getcwd(+string2,ulong); -int SYS_getpid(); -;addr SYS_mmap(addr,ulong,int,int,int,long); -int SYS_munmap(addr,ulong); -int SYS_open(string,int,octal); -int SYS_personality(uint); -long SYS_read(int,+string0,ulong); -int SYS_stat(string,addr); -octal SYS_umask(octal); -int SYS_uname(addr); -long SYS_write(int,string3,ulong); -int SYS_sync(); -int SYS_setxattr(string,string,addr,uint,int); -int SYS_lsetxattr(string,string,addr,uint,int); -int SYS_fsetxattr(int,string,addr,uint,int); -int SYS_getxattr(string,string,addr,uint); -int SYS_lgetxattr(string,string,addr,uint); -int SYS_fgetxattr(int,string,addr,uint); -int SYS_listxattr(string,addr,uint); -int SYS_llistxattr(string,addr,uint); -int SYS_flistxattr(int,addr,uint); -int SYS_removexattr(string,string); -int SYS_lremovexattr(string,string); -int SYS_fremovexattr(int,string); -int SYS_chdir(string); -int SYS_fchdir(int); -int SYS_chmod(string,octal); -int SYS_fchmod(int,octal); -int SYS_chown(string,int,int); -int SYS_fchown(int,int,int); -int SYS_lchown(string,int,int); -int SYS_chroot(string); -int SYS_dup(int); -int SYS_dup2(int,int); -int SYS_fdatasync(int); -int SYS_fsync(int); -int SYS_getpriority(int,int); -int SYS_setpriority(int,int,int); -int SYS_getrlimit(int,addr); -int SYS_setrlimit(int,addr); -int SYS_gettimeofday(addr,addr); -int SYS_settimeofday(addr,addr); -int SYS_setfsgid(int); -int SYS_setfsuid(int); -int SYS_getuid(); -int SYS_setuid(int); -int SYS_getgid(); -int SYS_setgid(int); -int SYS_getsid(int); -int SYS_setsid(int); -int SYS_setreuid(int,int); -int SYS_setregid(int,int); -int SYS_geteuid(); -int SYS_getegid(); -int SYS_setpgid(int,int); -int SYS_getresuid(addr,addr,addr); -int SYS_setresuid(int,int,int); -int SYS_getresgid(addr,addr,addr); -int SYS_setresgid(int,int,int); -int SYS_kill(int,int); -int SYS_link(string,string); -int SYS_madvise(addr,ulong,int); -int SYS_mkdir(string,octal); -int SYS_mknod(string,octal,int); -int SYS_msync(addr,ulong,int); -int SYS_nice(int); -int SYS_poll(addr,uint,int); -int SYS_readdir(uint,addr,uint); -int SYS_readlink(string,string,ulong); -int SYS_reboot(int,int,int,addr); -int SYS_rename(string,string); -int SYS_rmdir(string); -int SYS_sigaltstack(addr,addr); -int SYS_statfs(string,addr); -int SYS_fstatfs(int,addr); -int SYS_fstat(int,addr); -int SYS_lstat(string,addr); -int SYS_stime(addr); -int SYS_symlink(string, string); -int SYS_sysinfo(addr); -int SYS_syslog(int,string,int); -int SYS_truncate(string,long); -int SYS_ftruncate(int,long); -int SYS_mount(string,string,string,ulong,addr); -int SYS_umount(string); -int SYS_umount2(string,int); -int SYS_unlink(string); -int SYS_utime(string,addr); -long SYS_lseek(int,long,int); -addr SYS_signal(int,addr); -int SYS_sigaction(int,addr,addr); -int SYS_pause(); -int SYS_sigpending(addr); -int SYS_sigprocmask(int,addr,addr); -int SYS_sigqueue(int,int,addr); -int SYS_sigsuspend(addr); -int SYS_wait(addr); -int SYS_waitpid(int,addr,int); -ulong SYS_readv(int,addr,int); -ulong SYS_writev(int,addr,int); -int SYS_mprotect(addr,int,int); -int SYS_access(string,octal); -int SYS_getdents(uint, void *, uint); diff --git a/etc/syscalls.conf b/etc/syscalls.conf new file mode 100644 index 0000000..562f4e7 --- /dev/null +++ b/etc/syscalls.conf @@ -0,0 +1,115 @@ +# syscall.conf -- system call prototypes +# See ltrace.conf(5) for description of syntax of this file. + +addr brk(addr); +int close(int); +int execve(string,addr,addr); +void exit(int); +void exit_group(int); +int fork(); +int getcwd(+string2,ulong); +int getpid(); + +# XXX the last argument should be off_t +addr mmap(addr,ulong,int,int,int,long); + +int munmap(addr,ulong); +int open(string,int,octal); +int personality(uint); +long read(int,+string0,ulong); +int stat(string,addr); +octal umask(octal); +int uname(addr); +long write(int,string3,ulong); +int sync(); +int setxattr(string,string,addr,uint,int); +int lsetxattr(string,string,addr,uint,int); +int fsetxattr(int,string,addr,uint,int); +int getxattr(string,string,addr,uint); +int lgetxattr(string,string,addr,uint); +int fgetxattr(int,string,addr,uint); +int listxattr(string,addr,uint); +int llistxattr(string,addr,uint); +int flistxattr(int,addr,uint); +int removexattr(string,string); +int lremovexattr(string,string); +int fremovexattr(int,string); +int chdir(string); +int fchdir(int); +int chmod(string,octal); +int fchmod(int,octal); +int chown(string,int,int); +int fchown(int,int,int); +int lchown(string,int,int); +int chroot(string); +int dup(int); +int dup2(int,int); +int fdatasync(int); +int fsync(int); +int getpriority(int,int); +int setpriority(int,int,int); +int getrlimit(int,addr); +int setrlimit(int,addr); +int gettimeofday(addr,addr); +int settimeofday(addr,addr); +int setfsgid(int); +int setfsuid(int); +int getuid(); +int setuid(int); +int getgid(); +int setgid(int); +int getsid(int); +int setsid(int); +int setreuid(int,int); +int setregid(int,int); +int geteuid(); +int getegid(); +int setpgid(int,int); +int getresuid(addr,addr,addr); +int setresuid(int,int,int); +int getresgid(addr,addr,addr); +int setresgid(int,int,int); +int kill(int,int); +int link(string,string); +int madvise(addr,ulong,int); +int mkdir(string,octal); +int mknod(string,octal,int); +int msync(addr,ulong,int); +int nice(int); +int poll(addr,uint,int); +int readdir(uint,addr,uint); +int readlink(string,string,ulong); +int reboot(int,int,int,addr); +int rename(string,string); +int rmdir(string); +int sigaltstack(addr,addr); +int statfs(string,addr); +int fstatfs(int,addr); +int fstat(int,addr); +int lstat(string,addr); +int stime(addr); +int symlink(string, string); +int sysinfo(addr); +int syslog(int,string,int); +int truncate(string,long); +int ftruncate(int,long); +int mount(string,string,string,ulong,addr); +int umount(string); +int umount2(string,int); +int unlink(string); +int utime(string,addr); +long lseek(int,long,int); +addr signal(int,addr); +int sigaction(int,addr,addr); +int pause(); +int sigpending(addr); +int sigprocmask(int,addr,addr); +int sigqueue(int,int,addr); +int sigsuspend(addr); +int wait(addr); +int waitpid(int,addr,int); +ulong readv(int,addr,int); +ulong writev(int,addr,int); +int mprotect(addr,int,int); +int access(string,octal); +int getdents(uint, void *, uint); diff --git a/handle_event.c b/handle_event.c index b7a755c..ae61ade 100644 --- a/handle_event.c +++ b/handle_event.c @@ -33,6 +33,7 @@ #include <stdlib.h> #include <string.h> #include <sys/time.h> +#include <stdbool.h> #include "backend.h" #include "breakpoint.h" @@ -41,6 +42,7 @@ #include "library.h" #include "proc.h" #include "value_dict.h" +#include "prototype.h" static void handle_signal(Event *event); static void handle_exit(Event *event); @@ -379,9 +381,7 @@ sysname(struct process *proc, int sysnum) sprintf(result, "SYS_%d", sysnum); return result; } else { - sprintf(result, "SYS_%s", - syscallents[proc->personality][sysnum]); - return result; + return syscallents[proc->personality][sysnum]; } } @@ -445,8 +445,40 @@ output_syscall(struct process *proc, const char *name, enum tof tof, void (*output)(enum tof, struct process *, struct library_symbol *)) { + static struct library syscall_lib; + if (syscall_lib.protolib == NULL) { + struct protolib *protolib + = protolib_cache_search(&g_protocache, "syscalls", 0, 1); + if (protolib == NULL) { + fprintf(stderr, "Couldn't load system call prototypes:" + " %s.\n", strerror(errno)); + + /* Instead, get a fake one just so we can + * carry on, limping. */ + protolib = malloc(sizeof *protolib); + if (protolib == NULL) { + fprintf(stderr, "Couldn't even allocate a fake " + "prototype library: %s.\n", + strerror(errno)); + abort(); + } + protolib_init(protolib); + } + + assert(protolib != NULL); + if (library_init(&syscall_lib, LT_LIBTYPE_SYSCALL) < 0) { + fprintf(stderr, "Couldn't initialize system call " + "library: %s.\n", strerror(errno)); + abort(); + } + + library_set_soname(&syscall_lib, "SYS", 0); + syscall_lib.protolib = protolib; + } + struct library_symbol syscall; if (library_symbol_init(&syscall, 0, name, 0, LS_TOPLT_NONE) >= 0) { + syscall.lib = &syscall_lib; (*output)(tof, proc, &syscall); library_symbol_destroy(&syscall); } @@ -115,6 +115,7 @@ enum callback_status library_symbol_delayed_cb(struct library_symbol *libsym, enum library_type { LT_LIBTYPE_MAIN, LT_LIBTYPE_DSO, + LT_LIBTYPE_SYSCALL, }; /* XXX we might consider sharing libraries across processes. Things @@ -191,7 +191,8 @@ library_get_prototype(struct library *lib, const char *name) if (lib->protolib == NULL) return NULL; - return protolib_lookup_prototype(lib->protolib, name); + return protolib_lookup_prototype(lib->protolib, name, + lib->type != LT_LIBTYPE_SYSCALL); } struct find_proto_data { diff --git a/prototype.c b/prototype.c index 24e2625..fa9b6cc 100644 --- a/prototype.c +++ b/prototype.c @@ -244,8 +244,9 @@ protolib_add_named_type(struct protolib *plib, const char *name, int own_name, struct lookup { const char *name; - void *result; struct dict *(*getter)(struct protolib *plib); + bool imports; + void *result; }; static struct dict * @@ -274,7 +275,8 @@ protolib_lookup_rec(struct protolib **plibp, void *data) if (lookup->result != NULL) return CBS_STOP; - if (each_import(*plibp, NULL, &protolib_lookup_rec, lookup) != NULL) { + if (lookup->imports && each_import(*plibp, NULL, &protolib_lookup_rec, + lookup) != NULL) { assert(lookup->result != NULL); return CBS_STOP; } @@ -284,10 +286,11 @@ protolib_lookup_rec(struct protolib **plibp, void *data) static void * protolib_lookup(struct protolib *plib, const char *name, - struct dict *(*getter)(struct protolib *)) + struct dict *(*getter)(struct protolib *), + bool imports) { assert(plib != NULL); - struct lookup lookup = { name, NULL, getter }; + struct lookup lookup = { name, getter, imports, NULL }; if (protolib_lookup_rec(&plib, &lookup) == CBS_STOP) assert(lookup.result != NULL); else @@ -296,17 +299,17 @@ protolib_lookup(struct protolib *plib, const char *name, } struct prototype * -protolib_lookup_prototype(struct protolib *plib, const char *name) +protolib_lookup_prototype(struct protolib *plib, const char *name, bool imports) { assert(plib != NULL); - return protolib_lookup(plib, name, &get_prototypes); + return protolib_lookup(plib, name, &get_prototypes, imports); } struct named_type * -protolib_lookup_type(struct protolib *plib, const char *name) +protolib_lookup_type(struct protolib *plib, const char *name, bool imports) { assert(plib != NULL); - return protolib_lookup(plib, name, &get_named_types); + return protolib_lookup(plib, name, &get_named_types, imports); } static void diff --git a/prototype.h b/prototype.h index e6a4c21..26c3098 100644 --- a/prototype.h +++ b/prototype.h @@ -21,6 +21,8 @@ #ifndef _PROTOTYPE_H_ #define _PROTOTYPE_H_ +#include <stdbool.h> + #include "forward.h" #include "dict.h" #include "vect.h" @@ -122,21 +124,21 @@ int protolib_add_named_type(struct protolib *plib, const char *name, int own_name, struct named_type *named); -/* Lookup prototype named NAME in PLIB. If none is found, look - * recursively in each of the imports. Returns the corresponding - * prototype, or NULL if none was found. */ +/* Lookup prototype named NAME in PLIB. If none is found and IMPORTS + * is true, look recursively in each of the imports. Returns the + * corresponding prototype, or NULL if none was found. */ struct prototype *protolib_lookup_prototype(struct protolib *plib, - const char *name); + const char *name, bool imports); /* Add a named type NAMED to PLIB. Returns 0 on success or a negative * value on failure. */ int protolib_add_type(struct protolib *plib, struct named_type *named); -/* Lookup type named NAME in PLIB. If none is found, look recursively - * in each of the imports. Returns the corresponding type, or NULL if - * none was found. */ +/* Lookup type named NAME in PLIB. If none is found and IMPORTS is + * true, look recursively in each of the imports. Returns the + * corresponding type, or NULL if none was found. */ struct named_type *protolib_lookup_type(struct protolib *plib, - const char *name); + const char *name, bool imports); /* A cache of prototype libraries. Can load prototype libraries on * demand. diff --git a/read_config_file.c b/read_config_file.c index 49aeb9c..980b89b 100644 --- a/read_config_file.c +++ b/read_config_file.c @@ -406,7 +406,7 @@ parse_typedef_name(struct protolib *plib, char **str) *str += len; buf[len] = 0; - struct named_type *nt = protolib_lookup_type(plib, buf); + struct named_type *nt = protolib_lookup_type(plib, buf, true); if (nt == NULL) return NULL; return nt->info; @@ -422,7 +422,7 @@ parse_typedef(struct protolib *plib, struct locus *loc, char **str) /* Look through the typedef list whether we already have a * forward of this type. If we do, it must be forward * structure. */ - struct named_type *forward = protolib_lookup_type(plib, name); + struct named_type *forward = protolib_lookup_type(plib, name, true); if (forward != NULL && (forward->info->type != ARGTYPE_STRUCT || !forward->forward)) { diff --git a/testsuite/ltrace.main/Makefile.am b/testsuite/ltrace.main/Makefile.am index 925988d..12bbb9b 100644 --- a/testsuite/ltrace.main/Makefile.am +++ b/testsuite/ltrace.main/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 1992 - 2001, 2012 Free Software Foundation, Inc. +# Copyright (C) 1992 - 2001, 2012, 2013 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ EXTRA_DIST = branch_func.c branch_func.exp filters.exp hello-vfork.c \ main-threaded.c main-threaded.exp main-vfork.c main-vfork.exp \ parameters.c parameters.conf parameters.exp parameters-lib.c \ parameters2.exp parameters3.exp signals.c signals.exp \ - system_calls.c system_calls.exp + system_calls.c system_calls.exp system_call_params.exp CLEANFILES = *.o *.so *.log *.sum *.ltrace setval.tmp \ main main-internal parameters signals system_calls diff --git a/testsuite/ltrace.main/system_call_params.exp b/testsuite/ltrace.main/system_call_params.exp new file mode 100644 index 0000000..e5bffce --- /dev/null +++ b/testsuite/ltrace.main/system_call_params.exp @@ -0,0 +1,49 @@ +# This file is part of ltrace. +# Copyright (C) 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 +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# 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 + +set bin [ltraceCompile {} [ltraceSource c { + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + int main(void) { + open("/some/path", O_RDONLY); + } +}]] + +set dir [ltraceDir] +set conf [ltraceNamedSource "$dir/syscalls.conf" { + int open(string, int); +}] + +# When given the file directly via -F, ltrace should not use it for +# formatting system calls. The reason is that libraries are generally +# allowed to have functions with the same names as system calls +# (there's no interference between those two). In particular, +# readdir@SYS has a different prototype from readdir@libc. If a -F +# somelib.conf is passed, and syscalls.conf is not available, or +# doesn't list readdir, that would be taken from somelib.conf with a +# wrong prototype. + +ltraceMatch1 [ltraceRun -L -S -F $conf -- $bin] {open@SYS\("/some/path"} == 0 + +# On the other hand, if -F somedir/ is given, we want to accept +# syscalls.conf found there. + +ltraceMatch1 [ltraceRun -L -S -F $dir -- $bin] {open@SYS\("/some/path"} == 1 + +ltraceDone diff --git a/testsuite/ltrace.main/system_calls.exp b/testsuite/ltrace.main/system_calls.exp index 259ae25..3200d40 100644 --- a/testsuite/ltrace.main/system_calls.exp +++ b/testsuite/ltrace.main/system_calls.exp @@ -29,39 +29,39 @@ if [regexp {ELF from incompatible architecture} $exec_output] { } -set pattern "SYS_munmap" +set pattern "munmap@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 2 -set pattern "SYS_write" +set pattern "write@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_unlink" +set pattern "unlink@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_brk" +set pattern "brk@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_open" +set pattern "open@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_(new)?fstat" +set pattern "(new)?fstat@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 egrep -set pattern "SYS_(old_)?mmap" +set pattern "(old_)?mmap@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 egrep -set pattern "SYS_close" +set pattern "close@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_getcwd" +set pattern "getcwd@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_chdir" +set pattern "chdir@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_symlink" +set pattern "symlink@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_unlink" +set pattern "unlink@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_(new)?stat" +set pattern "(new)?stat@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 egrep -set pattern "SYS_access" +set pattern "access@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_rename" +set pattern "rename@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_mkdir" +set pattern "mkdir@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 -set pattern "SYS_rmdir" +set pattern "rmdir@SYS" ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1 |