From: Nicholas Nethercote Date: Sat, 4 Jun 2005 20:03:55 +0000 (+0000) Subject: Modularised file and socket libc stuff in m_libcfile. X-Git-Tag: svn/VALGRIND_3_0_0~474 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=face101a47b330776f7ba81118b901ceff76e6ec;p=thirdparty%2Fvalgrind.git Modularised file and socket libc stuff in m_libcfile. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3844 --- diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c index a7bfd6b2d0..5c7fd8bfae 100644 --- a/cachegrind/cg_main.c +++ b/cachegrind/cg_main.c @@ -34,6 +34,7 @@ #include "pub_tool_hashtable.h" #include "pub_tool_libcbase.h" #include "pub_tool_libcassert.h" +#include "pub_tool_libcfile.h" #include "pub_tool_libcprint.h" #include "pub_tool_mallocfree.h" #include "pub_tool_options.h" diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 1068b7dec6..7e11f44b4c 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -48,6 +48,7 @@ noinst_HEADERS = \ pub_core_hashtable.h \ pub_core_libcbase.h \ pub_core_libcassert.h \ + pub_core_libcfile.h \ pub_core_libcprint.h \ pub_core_main.h \ pub_core_mallocfree.h \ @@ -92,6 +93,7 @@ stage2_SOURCES = \ m_hashtable.c \ m_libcbase.c \ m_libcassert.c \ + m_libcfile.c \ m_libcprint.c \ m_main.c \ m_mallocfree.c \ diff --git a/coregrind/core.h b/coregrind/core.h index 97ccf8bbb6..a371342dfb 100644 --- a/coregrind/core.h +++ b/coregrind/core.h @@ -112,14 +112,6 @@ extern Int VG_(mprotect) ( void *start, SizeT length, UInt prot ); extern Int VG_(mprotect_native)( void *start, SizeT length, UInt prot ); -/* Move an fd into the Valgrind-safe range */ -Int VG_(safe_fd)(Int oldfd); - -extern Int VG_(write_socket)( Int sd, void *msg, Int count ); - -/* --- Connecting over the network --- */ -extern Int VG_(connect_via_socket)( UChar* str ); - /* Environment manipulations */ extern Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val ); diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c index ab18b87407..a33032e30b 100644 --- a/coregrind/m_aspacemgr/aspacemgr.c +++ b/coregrind/m_aspacemgr/aspacemgr.c @@ -34,6 +34,7 @@ #include "pub_core_aspacemgr.h" #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" // For VG_(fstat)() #include "pub_core_libcprint.h" #include "pub_core_options.h" #include "pub_core_syscalls.h" diff --git a/coregrind/m_aspacemgr/read_procselfmaps.c b/coregrind/m_aspacemgr/read_procselfmaps.c index 1797171023..0e6381db29 100644 --- a/coregrind/m_aspacemgr/read_procselfmaps.c +++ b/coregrind/m_aspacemgr/read_procselfmaps.c @@ -34,6 +34,7 @@ #include "pub_core_aspacemgr.h" #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" #include "pub_core_libcprint.h" /* Size of a smallish table used to read /proc/self/map entries. */ diff --git a/coregrind/m_debuginfo/symtab.c b/coregrind/m_debuginfo/symtab.c index 43f0f4c5d2..c0787ae65d 100644 --- a/coregrind/m_debuginfo/symtab.c +++ b/coregrind/m_debuginfo/symtab.c @@ -34,6 +34,7 @@ #include "pub_core_demangle.h" #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" #include "pub_core_libcprint.h" #include "pub_core_options.h" #include "pub_core_profile.h" diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c index 71ae7ceb2b..9f14f23e47 100644 --- a/coregrind/m_errormgr.c +++ b/coregrind/m_errormgr.c @@ -34,6 +34,7 @@ #include "pub_core_execontext.h" #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" #include "pub_core_libcprint.h" #include "pub_core_main.h" // for VG_(start_debugger)() #include "pub_core_options.h" @@ -1107,5 +1108,5 @@ static Supp* is_suppressible_error ( Error* err ) } /*--------------------------------------------------------------------*/ -/*--- end m_errormgr.c ---*/ +/*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c new file mode 100644 index 0000000000..974dcdbdb7 --- /dev/null +++ b/coregrind/m_libcfile.c @@ -0,0 +1,446 @@ + +/*--------------------------------------------------------------------*/ +/*--- File- and socket-related libc stuff. m_libcfile.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#include "core.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" +#include "pub_core_options.h" +#include "pub_core_syscalls.h" // For VG_(is_kerror)() +#include "vki_unistd.h" + +/* --------------------------------------------------------------------- + File stuff + ------------------------------------------------------------------ */ + +static inline Bool fd_exists(Int fd) +{ + struct vki_stat st; + + return VG_(fstat)(fd, &st) == 0; +} + +/* Move an fd into the Valgrind-safe range */ +Int VG_(safe_fd)(Int oldfd) +{ + Int newfd; + + vg_assert(VG_(fd_hard_limit) != -1); + + newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit)); + if (newfd != -1) + VG_(close)(oldfd); + + VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC); + + vg_assert(newfd >= VG_(fd_hard_limit)); + return newfd; +} + +/* Returns -1 on failure. */ +Int VG_(open) ( const Char* pathname, Int flags, Int mode ) +{ + Int fd = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode); + return fd; +} + +void VG_(close) ( Int fd ) +{ + VG_(do_syscall1)(__NR_close, fd); +} + +Int VG_(read) ( Int fd, void* buf, Int count) +{ + Int res; + res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); + return res; +} + +Int VG_(write) ( Int fd, const void* buf, Int count) +{ + Int res; + res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count); + return res; +} + +Int VG_(pipe) ( Int fd[2] ) +{ + Int ret = VG_(do_syscall1)(__NR_pipe, (UWord)fd); + return VG_(is_kerror)(ret) ? -1 : 0; +} + +OffT VG_(lseek) ( Int fd, OffT offset, Int whence) +{ + Int res; + res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence); + if (VG_(is_kerror)(res)) res = -1; + return res; +} + +Int VG_(stat) ( Char* file_name, struct vki_stat* buf ) +{ + Int res; + res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf); + return res; /* return -ve error */ +} + +Int VG_(fstat) ( Int fd, struct vki_stat* buf ) +{ + Int res; + res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf); + return VG_(is_kerror)(res) ? (-1) : 0; +} + +Int VG_(dup2) ( Int oldfd, Int newfd ) +{ + Int res; + res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd); + return VG_(is_kerror)(res) ? (-1) : res; +} + +Int VG_(rename) ( Char* old_name, Char* new_name ) +{ + Int res; + res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name); + return VG_(is_kerror)(res) ? (-1) : 0; +} + +Int VG_(unlink) ( Char* file_name ) +{ + Int res; + res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name); + return VG_(is_kerror)(res) ? (-1) : 0; +} + +/* Nb: we do not allow the Linux extension which malloc()s memory for the + buffer if buf==NULL, because we don't want Linux calling malloc() */ +Char* VG_(getcwd) ( Char* buf, SizeT size ) +{ + Word res; + vg_assert(buf != NULL); + res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size); + return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res; +} + +/* Alternative version that does allocate the memory. Easier to use. */ +Bool VG_(getcwd_alloc) ( Char** out ) +{ + SizeT size = 4; + + *out = NULL; + while (True) { + *out = VG_(malloc)(size); + if (NULL == VG_(getcwd)(*out, size)) { + VG_(free)(*out); + if (size > 65535) + return False; + size *= 2; + } else { + return True; + } + } +} + +Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz) +{ + Int res; + /* res = readlink( path, buf, bufsiz ); */ + res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); + if (VG_(is_kerror)(res)) res = -1; + return res; +} + +Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count) +{ + Int res; + /* res = getdents( fd, dirp, count ); */ + res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); + if (VG_(is_kerror)(res)) res = -1; + return res; +} + +/* --------------------------------------------------------------------- + Socket-related stuff. This is very Linux-kernel specific. + ------------------------------------------------------------------ */ + +static +Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ); + +static +Int my_socket ( Int domain, Int type, Int protocol ); + +static +Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, + Int addrlen ); + +static +UInt my_htonl ( UInt x ) +{ + return + (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) + | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); +} + +static +UShort my_htons ( UShort x ) +{ + return + (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8); +} + + +/* The main function. + + Supplied string contains either an ip address "192.168.0.1" or + an ip address and port pair, "192.168.0.1:1500". Parse these, + and return: + -1 if there is a parse error + -2 if no parse error, but specified host:port cannot be opened + the relevant file (socket) descriptor, otherwise. + is used. +*/ +Int VG_(connect_via_socket)( UChar* str ) +{ + Int sd, res; + struct vki_sockaddr_in servAddr; + UInt ip = 0; + UShort port = VG_CLO_DEFAULT_LOGPORT; + Bool ok = parse_inet_addr_and_port(str, &ip, &port); + if (!ok) + return -1; + + //if (0) + // VG_(printf)("ip = %d.%d.%d.%d, port %d\n", + // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, + // (ip >> 8) & 0xFF, ip & 0xFF, + // (UInt)port ); + + servAddr.sin_family = VKI_AF_INET; + servAddr.sin_addr.s_addr = my_htonl(ip); + servAddr.sin_port = my_htons(port); + + /* create socket */ + sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */); + if (sd < 0) { + /* this shouldn't happen ... nevertheless */ + return -2; + } + + /* connect to server */ + res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr, + sizeof(servAddr)); + if (res < 0) { + /* connection failed */ + return -2; + } + + return sd; +} + + +/* Let d = one or more digits. Accept either: + d.d.d.d or d.d.d.d:d +*/ +Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ) +{ +# define GET_CH ((*str) ? (*str++) : 0) + UInt ipa, i, j, c, any; + ipa = 0; + for (i = 0; i < 4; i++) { + j = 0; + any = 0; + while (1) { + c = GET_CH; + if (c < '0' || c > '9') break; + j = 10 * j + (int)(c - '0'); + any = 1; + } + if (any == 0 || j > 255) goto syntaxerr; + ipa = (ipa << 8) + j; + if (i <= 2 && c != '.') goto syntaxerr; + } + if (c == 0 || c == ':') + *ip_addr = ipa; + if (c == 0) goto ok; + if (c != ':') goto syntaxerr; + j = 0; + any = 0; + while (1) { + c = GET_CH; + if (c < '0' || c > '9') break; + j = j * 10 + (int)(c - '0'); + any = 1; + if (j > 65535) goto syntaxerr; + } + if (any == 0 || c != 0) goto syntaxerr; + if (j < 1024) goto syntaxerr; + *port = (UShort)j; + ok: + return 1; + syntaxerr: + return 0; +# undef GET_CH +} + + +static +Int my_socket ( Int domain, Int type, Int protocol ) +{ +// AMD64/Linux doesn't define __NR_socketcall... see comment above +// VG_(sigpending)() for more details. +#ifdef __amd64__ + I_die_here; +#else + Int res; + UWord args[3]; + args[0] = domain; + args[1] = type; + args[2] = protocol; + res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args); + if (VG_(is_kerror)(res)) + res = -1; + return res; +#endif +} + +static +Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, + Int addrlen ) +{ +// AMD64/Linux doesn't define __NR_socketcall... see comment above +// VG_(sigpending)() for more details. +#ifdef __amd64__ + I_die_here; +#else + Int res; + UWord args[3]; + args[0] = sockfd; + args[1] = (UWord)serv_addr; + args[2] = addrlen; + res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args); + if (VG_(is_kerror)(res)) + res = -1; + return res; +#endif +} + +Int VG_(write_socket)( Int sd, void *msg, Int count ) +{ +// AMD64/Linux doesn't define __NR_socketcall... see comment above +// VG_(sigpending)() for more details. +#ifdef __amd64__ + I_die_here; +#else + /* This is actually send(). */ + + /* Requests not to send SIGPIPE on errors on stream oriented + sockets when the other end breaks the connection. The EPIPE + error is still returned. */ + Int flags = VKI_MSG_NOSIGNAL; + + Int res; + UWord args[4]; + args[0] = sd; + args[1] = (UWord)msg; + args[2] = count; + args[3] = flags; + res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args); + if (VG_(is_kerror)(res)) + res = -1; + return res; +#endif +} + +Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) +{ +// AMD64/Linux doesn't define __NR_socketcall... see comment above +// VG_(sigpending)() for more details. +#ifdef __amd64__ + I_die_here; +#else + Int res; + UWord args[3]; + args[0] = sd; + args[1] = (UWord)name; + args[2] = (UWord)namelen; + res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args); + if(VG_(is_kerror)(res)) + res = -1; + return res; +#endif +} + +Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) +{ +// AMD64/Linux doesn't define __NR_socketcall... see comment above +// VG_(sigpending)() for more details. +#ifdef __amd64__ + I_die_here; +#else + Int res; + UWord args[3]; + args[0] = sd; + args[1] = (UWord)name; + args[2] = (UWord)namelen; + res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args); + if(VG_(is_kerror)(res)) + res = -1; + return res; +#endif +} + +Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, + Int *optlen) +{ +// AMD64/Linux doesn't define __NR_socketcall... see comment above +// VG_(sigpending)() for more details. +#ifdef __amd64__ + I_die_here; +#else + Int res; + UWord args[5]; + args[0] = sd; + args[1] = level; + args[2] = optname; + args[3] = (UWord)optval; + args[4] = (UWord)optlen; + res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args); + if(VG_(is_kerror)(res)) + res = -1; + return res; +#endif +} + + + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ + diff --git a/coregrind/m_libcprint.c b/coregrind/m_libcprint.c index f782c48841..f4ca698d23 100644 --- a/coregrind/m_libcprint.c +++ b/coregrind/m_libcprint.c @@ -32,6 +32,7 @@ #include "pub_core_debuglog.h" #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" #include "pub_core_libcprint.h" #include "pub_core_options.h" #include "valgrind.h" // for RUNNING_ON_VALGRIND diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 7a2e424ff1..7c1d0c7ece 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -38,6 +38,7 @@ #include "pub_core_execontext.h" #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" #include "pub_core_libcprint.h" #include "pub_core_main.h" #include "pub_core_options.h" diff --git a/coregrind/m_scheduler/sema.c b/coregrind/m_scheduler/sema.c index 5db9e58791..dd1ba1b191 100644 --- a/coregrind/m_scheduler/sema.c +++ b/coregrind/m_scheduler/sema.c @@ -30,6 +30,7 @@ #include "core.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" #include "priv_sema.h" /* diff --git a/coregrind/m_syscalls/syscalls-linux.c b/coregrind/m_syscalls/syscalls-linux.c index 00f5238e88..2d801a1a9e 100644 --- a/coregrind/m_syscalls/syscalls-linux.c +++ b/coregrind/m_syscalls/syscalls-linux.c @@ -31,6 +31,7 @@ #include "core.h" #include "pub_core_aspacemgr.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" #include "pub_core_libcprint.h" #include "pub_core_tooliface.h" #include "priv_syscalls.h" diff --git a/coregrind/m_syscalls/syscalls.c b/coregrind/m_syscalls/syscalls.c index 0a7cbee744..faa6514a05 100644 --- a/coregrind/m_syscalls/syscalls.c +++ b/coregrind/m_syscalls/syscalls.c @@ -33,6 +33,7 @@ #include "pub_core_aspacemgr.h" #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" #include "pub_core_libcprint.h" #include "pub_core_main.h" #include "pub_core_profile.h" diff --git a/coregrind/pub_core_libcfile.h b/coregrind/pub_core_libcfile.h new file mode 100644 index 0000000000..59386ade9b --- /dev/null +++ b/coregrind/pub_core_libcfile.h @@ -0,0 +1,55 @@ + +/*--------------------------------------------------------------------*/ +/*--- File/socket-related libc stuff. pub_core_libcfile.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PUB_CORE_LIBCFILE_H +#define __PUB_CORE_LIBCFILE_H + +//-------------------------------------------------------------------- +// PURPOSE: This module contains all the libc code that relates to +// files and sockets: opening, reading, writing, etc. +//-------------------------------------------------------------------- + +#include "pub_tool_libcfile.h" + +/* Move an fd into the Valgrind-safe range */ +extern Int VG_(safe_fd)(Int oldfd); + +extern Int VG_(write_socket)( Int sd, void *msg, Int count ); +extern Int VG_(connect_via_socket)( UChar* str ); +extern Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen ); +extern Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen ); +extern Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, + Int *optlen ); + +#endif // __PUB_CORE_LIBCFILE_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index bc00797ad0..03effb9c51 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -438,142 +438,6 @@ Char* VG_(strdup) ( const Char* s ) return VG_(arena_strdup) ( VG_AR_TOOL, s ); } -/* --------------------------------------------------------------------- - Primitive support for reading files. - ------------------------------------------------------------------ */ - -static inline Bool fd_exists(Int fd) -{ - struct vki_stat st; - - return VG_(fstat)(fd, &st) == 0; -} - -/* Move an fd into the Valgrind-safe range */ -Int VG_(safe_fd)(Int oldfd) -{ - Int newfd; - - vg_assert(VG_(fd_hard_limit) != -1); - - newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit)); - if (newfd != -1) - VG_(close)(oldfd); - - VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC); - - vg_assert(newfd >= VG_(fd_hard_limit)); - return newfd; -} - - - -/* Returns -1 on failure. */ -Int VG_(open) ( const Char* pathname, Int flags, Int mode ) -{ - Int fd = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode); - return fd; -} - -Int VG_(pipe) ( Int fd[2] ) -{ - Int ret = VG_(do_syscall1)(__NR_pipe, (UWord)fd); - return VG_(is_kerror)(ret) ? -1 : 0; -} - -void VG_(close) ( Int fd ) -{ - VG_(do_syscall1)(__NR_close, fd); -} - - -Int VG_(read) ( Int fd, void* buf, Int count) -{ - Int res; - res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); - return res; -} - -Int VG_(write) ( Int fd, const void* buf, Int count) -{ - Int res; - res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count); - return res; -} - -OffT VG_(lseek) ( Int fd, OffT offset, Int whence) -{ - Int res; - res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence); - if (VG_(is_kerror)(res)) res = -1; - return res; -} - -Int VG_(stat) ( Char* file_name, struct vki_stat* buf ) -{ - Int res; - res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf); - return res; /* return -ve error */ -} - -Int VG_(fstat) ( Int fd, struct vki_stat* buf ) -{ - Int res; - res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf); - return VG_(is_kerror)(res) ? (-1) : 0; -} - -Int VG_(dup2) ( Int oldfd, Int newfd ) -{ - Int res; - res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd); - return VG_(is_kerror)(res) ? (-1) : res; -} - -Int VG_(rename) ( Char* old_name, Char* new_name ) -{ - Int res; - res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name); - return VG_(is_kerror)(res) ? (-1) : 0; -} - -Int VG_(unlink) ( Char* file_name ) -{ - Int res; - res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name); - return VG_(is_kerror)(res) ? (-1) : 0; -} - -/* Nb: we do not allow the Linux extension which malloc()s memory for the - buffer if buf==NULL, because we don't want Linux calling malloc() */ -Char* VG_(getcwd) ( Char* buf, SizeT size ) -{ - Word res; - vg_assert(buf != NULL); - res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size); - return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res; -} - -/* Alternative version that does allocate the memory. Easier to use. */ -Bool VG_(getcwd_alloc) ( Char** out ) -{ - SizeT size = 4; - - *out = NULL; - while (True) { - *out = VG_(malloc)(size); - if (NULL == VG_(getcwd)(*out, size)) { - VG_(free)(*out); - if (size > 65535) - return False; - size *= 2; - } else { - return True; - } - } -} - - /* --------------------------------------------------------------------- Misc functions looking for a proper home. ------------------------------------------------------------------ */ @@ -702,26 +566,6 @@ Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim) } -/* Support for getdents. */ -Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count) -{ - Int res; - /* res = getdents( fd, dirp, count ); */ - res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); - if (VG_(is_kerror)(res)) res = -1; - return res; -} - -/* Support for a readlink. */ -Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz) -{ - Int res; - /* res = readlink( path, buf, bufsiz ); */ - res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); - if (VG_(is_kerror)(res)) res = -1; - return res; -} - /* You'd be amazed how many places need to know the current pid. */ Int VG_(getpid) ( void ) { @@ -951,259 +795,6 @@ void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who ) VG_(exit)(1); } -/* --------------------------------------------------------------------- - Gruesome hackery for connecting to a logging server over the network. - This is all very Linux-kernel specific. - ------------------------------------------------------------------ */ - -static -Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ); - -static -Int my_socket ( Int domain, Int type, Int protocol ); - -static -Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, - Int addrlen ); - -static -UInt my_htonl ( UInt x ) -{ - return - (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) - | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); -} - -static -UShort my_htons ( UShort x ) -{ - return - (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8); -} - - -/* The main function. - - Supplied string contains either an ip address "192.168.0.1" or - an ip address and port pair, "192.168.0.1:1500". Parse these, - and return: - -1 if there is a parse error - -2 if no parse error, but specified host:port cannot be opened - the relevant file (socket) descriptor, otherwise. - is used. -*/ -Int VG_(connect_via_socket)( UChar* str ) -{ - Int sd, res; - struct vki_sockaddr_in servAddr; - UInt ip = 0; - UShort port = VG_CLO_DEFAULT_LOGPORT; - Bool ok = parse_inet_addr_and_port(str, &ip, &port); - if (!ok) - return -1; - - if (0) - VG_(printf)("ip = %d.%d.%d.%d, port %d\n", - (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, - (ip >> 8) & 0xFF, ip & 0xFF, - (UInt)port ); - - servAddr.sin_family = VKI_AF_INET; - servAddr.sin_addr.s_addr = my_htonl(ip); - servAddr.sin_port = my_htons(port); - - /* create socket */ - sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */); - if (sd < 0) { - /* this shouldn't happen ... nevertheless */ - return -2; - } - - /* connect to server */ - res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr, - sizeof(servAddr)); - if (res < 0) { - /* connection failed */ - return -2; - } - - return sd; -} - - -/* Let d = one or more digits. Accept either: - d.d.d.d or d.d.d.d:d -*/ -Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ) -{ -# define GET_CH ((*str) ? (*str++) : 0) - UInt ipa, i, j, c, any; - ipa = 0; - for (i = 0; i < 4; i++) { - j = 0; - any = 0; - while (1) { - c = GET_CH; - if (c < '0' || c > '9') break; - j = 10 * j + (int)(c - '0'); - any = 1; - } - if (any == 0 || j > 255) goto syntaxerr; - ipa = (ipa << 8) + j; - if (i <= 2 && c != '.') goto syntaxerr; - } - if (c == 0 || c == ':') - *ip_addr = ipa; - if (c == 0) goto ok; - if (c != ':') goto syntaxerr; - j = 0; - any = 0; - while (1) { - c = GET_CH; - if (c < '0' || c > '9') break; - j = j * 10 + (int)(c - '0'); - any = 1; - if (j > 65535) goto syntaxerr; - } - if (any == 0 || c != 0) goto syntaxerr; - if (j < 1024) goto syntaxerr; - *port = (UShort)j; - ok: - return 1; - syntaxerr: - return 0; -# undef GET_CH -} - - -static -Int my_socket ( Int domain, Int type, Int protocol ) -{ -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[3]; - args[0] = domain; - args[1] = type; - args[2] = protocol; - res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args); - if (VG_(is_kerror)(res)) - res = -1; - return res; -#endif -} - -static -Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, - Int addrlen ) -{ -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[3]; - args[0] = sockfd; - args[1] = (UWord)serv_addr; - args[2] = addrlen; - res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args); - if (VG_(is_kerror)(res)) - res = -1; - return res; -#endif -} - -Int VG_(write_socket)( Int sd, void *msg, Int count ) -{ -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - /* This is actually send(). */ - - /* Requests not to send SIGPIPE on errors on stream oriented - sockets when the other end breaks the connection. The EPIPE - error is still returned. */ - Int flags = VKI_MSG_NOSIGNAL; - - Int res; - UWord args[4]; - args[0] = sd; - args[1] = (UWord)msg; - args[2] = count; - args[3] = flags; - res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args); - if (VG_(is_kerror)(res)) - res = -1; - return res; -#endif -} - -Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) -{ -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[3]; - args[0] = sd; - args[1] = (UWord)name; - args[2] = (UWord)namelen; - res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args); - if(VG_(is_kerror)(res)) - res = -1; - return res; -#endif -} - -Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) -{ -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[3]; - args[0] = sd; - args[1] = (UWord)name; - args[2] = (UWord)namelen; - res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args); - if(VG_(is_kerror)(res)) - res = -1; - return res; -#endif -} - -Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, - Int *optlen) -{ -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[5]; - args[0] = sd; - args[1] = level; - args[2] = optname; - args[3] = (UWord)optval; - args[4] = (UWord)optlen; - res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args); - if(VG_(is_kerror)(res)) - res = -1; - return res; -#endif -} - /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/include/Makefile.am b/include/Makefile.am index b087a30c36..a38b33d9cc 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -10,6 +10,7 @@ incinc_HEADERS = \ pub_tool_hashtable.h \ pub_tool_libcbase.h \ pub_tool_libcassert.h \ + pub_tool_libcfile.h \ pub_tool_libcprint.h \ pub_tool_mallocfree.h \ pub_tool_options.h \ diff --git a/include/pub_tool_libcfile.h b/include/pub_tool_libcfile.h new file mode 100644 index 0000000000..0a1b01cc42 --- /dev/null +++ b/include/pub_tool_libcfile.h @@ -0,0 +1,65 @@ + +/*--------------------------------------------------------------------*/ +/*--- File/socket-related libc stuff. pub_tool_libcfile.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PUB_TOOL_LIBCFILE_H +#define __PUB_TOOL_LIBCFILE_H + +/* --------------------------------------------------------------------- + File-related functions. + ------------------------------------------------------------------ */ + +extern Int VG_(open) ( const Char* pathname, Int flags, Int mode ); +extern void VG_(close) ( Int fd ); +extern Int VG_(read) ( Int fd, void* buf, Int count); +extern Int VG_(write) ( Int fd, const void* buf, Int count); +extern Int VG_(pipe) ( Int fd[2] ); +extern OffT VG_(lseek) ( Int fd, OffT offset, Int whence); + +extern Int VG_(stat) ( Char* file_name, struct vki_stat* buf ); +extern Int VG_(fstat) ( Int fd, struct vki_stat* buf ); +extern Int VG_(dup2) ( Int oldfd, Int newfd ); +extern Int VG_(rename) ( Char* old_name, Char* new_name ); +extern Int VG_(unlink) ( Char* file_name ); + +extern Char* VG_(getcwd) ( Char* buf, SizeT size ); + +/* Easier to use than VG_(getcwd)() -- does the buffer fiddling itself. + String put into 'cwd' is VG_(malloc)'d, and should be VG_(free)'d. + Returns False if it fails. Will fail if the pathname is > 65535 bytes. */ +extern Bool VG_(getcwd_alloc) ( Char** cwd ); + +extern Int VG_(readlink)( Char* path, Char* buf, UInt bufsize ); +extern Int VG_(getdents)( UInt fd, struct vki_dirent *dirp, UInt count ); + +#endif // __PUB_TOOL_LIBCFILE_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/include/tool.h b/include/tool.h index 795a129d85..ecaf3ba19e 100644 --- a/include/tool.h +++ b/include/tool.h @@ -111,11 +111,6 @@ extern Addr VG_(get_IP) ( ThreadId tid ); # define NULL ((void*)0) #endif -/* ------------------------------------------------------------------ */ -/* stdio.h */ - -extern Int VG_(rename) ( Char* old_name, Char* new_name ); - /* ------------------------------------------------------------------ */ /* stdlib.h */ @@ -142,35 +137,12 @@ extern Int VG_(system) ( Char* cmd ); /* ------------------------------------------------------------------ */ /* unistd.h, fcntl.h, sys/stat.h */ -extern Int VG_(getdents)( UInt fd, struct vki_dirent *dirp, UInt count ); -extern Int VG_(readlink)( Char* path, Char* buf, UInt bufsize ); extern Int VG_(getpid) ( void ); extern Int VG_(getppid) ( void ); extern Int VG_(getpgrp) ( void ); extern Int VG_(gettid) ( void ); extern Int VG_(setpgid) ( Int pid, Int pgrp ); -extern Int VG_(open) ( const Char* pathname, Int flags, Int mode ); -extern Int VG_(read) ( Int fd, void* buf, Int count); -extern Int VG_(write) ( Int fd, const void* buf, Int count); -extern OffT VG_(lseek) ( Int fd, OffT offset, Int whence); -extern void VG_(close) ( Int fd ); - -extern Int VG_(pipe) ( Int fd[2] ); - -/* Nb: VG_(rename)() declared in stdio.h section above */ -extern Int VG_(unlink) ( Char* file_name ); -extern Int VG_(stat) ( Char* file_name, struct vki_stat* buf ); -extern Int VG_(fstat) ( Int fd, struct vki_stat* buf ); -extern Int VG_(dup2) ( Int oldfd, Int newfd ); - -extern Char* VG_(getcwd) ( Char* buf, SizeT size ); - -/* Easier to use than VG_(getcwd)() -- does the buffer fiddling itself. - String put into 'cwd' is VG_(malloc)'d, and should be VG_(free)'d. - Returns False if it fails. Will fail if the pathname is > 65535 bytes. */ -extern Bool VG_(getcwd_alloc) ( Char** cwd ); - /* ------------------------------------------------------------------ */ /* Get memory by anonymous mmap. */ extern void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who ); @@ -247,14 +219,6 @@ extern Int VG_(sigpending) ( vki_sigset_t* set ); extern Int VG_(waitpid) ( Int pid, Int *status, Int options ); -/* ------------------------------------------------------------------ */ -/* socket.h. */ - -extern Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen); -extern Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen); -extern Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, - Int *optlen); - /* ------------------------------------------------------------------ */ /* other, randomly useful functions */ extern UInt VG_(read_millisecond_timer) ( void ); diff --git a/massif/ms_main.c b/massif/ms_main.c index aebc27d962..0e37aa7f22 100644 --- a/massif/ms_main.c +++ b/massif/ms_main.c @@ -39,6 +39,7 @@ #include "pub_tool_hashtable.h" #include "pub_tool_libcbase.h" #include "pub_tool_libcassert.h" +#include "pub_tool_libcfile.h" #include "pub_tool_libcprint.h" #include "pub_tool_mallocfree.h" #include "pub_tool_options.h"