1
2/*--------------------------------------------------------------------*/
3/*--- A simple debuginfo server for Valgrind.                      ---*/
4/*---                                         valgrind-di-server.c ---*/
5/*--------------------------------------------------------------------*/
6
7/* To build for an x86_64-linux host:
8      gcc -g -Wall -O -o valgrind-di-server \
9         auxprogs/valgrind-di-server.c -Icoregrind -Iinclude \
10         -IVEX/pub -DVGO_linux -DVGA_amd64
11
12   To build for an x86 (32-bit) host
13      The same, except change -DVGA_amd64 to -DVGA_x86
14*/
15
16/*
17   This file is part of Valgrind, a dynamic binary instrumentation
18   framework.
19
20   Copyright (C) 2013-2013 Mozilla Foundation
21
22   This program is free software; you can redistribute it and/or
23   modify it under the terms of the GNU General Public License as
24   published by the Free Software Foundation; either version 2 of the
25   License, or (at your option) any later version.
26
27   This program is distributed in the hope that it will be useful, but
28   WITHOUT ANY WARRANTY; without even the implied warranty of
29   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
30   General Public License for more details.
31
32   You should have received a copy of the GNU General Public License
33   along with this program; if not, write to the Free Software
34   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
35   02111-1307, USA.
36
37   The GNU General Public License is contained in the file COPYING.
38*/
39
40/* Contributed by Julian Seward <jseward@acm.org> */
41
42/* This code works (just), but it's a mess.  Cleanups (also for
43   coregrind/m_debuginfo/image.c):
44
45   * Build this file for the host arch, not the target.  But how?
46     Even Tromey had difficulty figuring out how to do that.
47
48   * Change the use of pread w/ fd to FILE*, for the file we're
49     serving.  Or, at least, put a loop around the pread uses
50     so that it works correctly in the case where pread reads more
51     than zero but less than we asked for.
52
53   * CRC3 request/response: pass session-IDs back and forth and
54     check them
55
56   * Check that all error cases result in a FAIL frame being returned.
57
58   * image.c: don't assert in cases where a FAIL frame is returned;
59     instead cause the debuginfo reading to fail gracefully.  (Not
60     sure how to do this)
61
62   * Improve diagnostic printing
63
64   * image.c: do we need to do VG_(write_socket) ?  Will it work
65     just to use ordinary VG_(write) ?
66
67   * Both files: document the reason for setting TCP_NODELAY
68
69   * Add a command line argument saying where the served-from
70     directory is -- changes clo_serverpath.
71
72   * Fix up (common up) massive code duplication between client and
73     server.
74
75   * Tidy up the LZO source files; integrate properly in the build
76     system.
77*/
78
79/*---------------------------------------------------------------*/
80
81/* Include valgrind headers before system headers to avoid problems
82   with the system headers #defining things which are used as names
83   of structure members in vki headers. */
84
85#include "pub_core_basics.h"
86#include "pub_core_libcassert.h"    // For VG_BUGS_TO
87#include "pub_core_vki.h"           // Avoids warnings from
88                                    // pub_core_libcfile.h
89#include "pub_core_libcfile.h"      // For VG_CLO_DEFAULT_LOGPORT
90
91/* Needed to get a definition for pread() from unistd.h */
92#define _XOPEN_SOURCE 500
93
94#include <stdio.h>
95#include <unistd.h>
96#include <string.h>
97#include <time.h>
98#include <fcntl.h>
99#include <stdlib.h>
100#include <signal.h>
101#include <sys/poll.h>
102#include <sys/types.h>
103#include <sys/socket.h>
104#include <netinet/in.h>
105#include <sys/stat.h>
106#include <netinet/tcp.h>
107
108#include "../coregrind/m_debuginfo/minilzo.h"
109
110/*---------------------------------------------------------------*/
111
112/* The maximum allowable number concurrent connections. */
113#define M_CONNECTIONS 50
114
115static const char* clo_serverpath = ".";
116
117
118/*---------------------------------------------------------------*/
119
120__attribute__ ((noreturn))
121static void panic ( const char* str )
122{
123   fprintf(stderr,
124           "\nvalgrind-di-server: the "
125           "'impossible' happened:\n   %s\n", str);
126   fprintf(stderr,
127           "Please report this bug at: %s\n\n", VG_BUGS_TO);
128   exit(1);
129}
130
131__attribute__ ((noreturn))
132static void my_assert_fail ( const char* expr, const char* file, int line, const char* fn )
133{
134   fprintf(stderr,
135           "\nvalgrind-di-server: %s:%d (%s): Assertion '%s' failed.\n",
136           file, line, fn, expr );
137   fprintf(stderr,
138           "Please report this bug at: %s\n\n", VG_BUGS_TO);
139   exit(1);
140}
141
142#undef assert
143
144#define assert(expr)                                             \
145  ((void) ((expr) ? 0 :					         \
146	   (my_assert_fail (VG_STRINGIFY(expr),	                 \
147                            __FILE__, __LINE__,                  \
148                            __PRETTY_FUNCTION__), 0)))
149
150
151/*---------------------------------------------------------------*/
152
153/* Holds the state that we need to track, for each connection. */
154typedef
155   struct {
156      // is this entry in use?
157      Bool in_use;
158      // socket descriptor to communicate with client.  Initialised as
159      // soon as this entry is created.
160      int  conn_sd;
161      // fd for the file that we are connected to.  Zero if not
162      // currently connected to any file.
163      int   file_fd;
164      ULong file_size;
165      // Session ID
166      ULong session_id;
167      // How many bytes and chunks sent?
168      ULong stats_n_rdok_frames;
169      ULong stats_n_read_unz_bytes; // bytes via READ (uncompressed)
170      ULong stats_n_read_z_bytes;   // bytes via READ (compressed)
171   }
172   ConnState;
173
174/* The state itself. */
175static int       conn_count = 0;
176static ConnState conn_state[M_CONNECTIONS];
177
178/* Issues unique session ID values. */
179static ULong next_session_id = 1;
180
181
182/*---------------------------------------------------------------*/
183
184// Code that is duplicated with the client :-(
185
186/* The following Adler-32 checksum code is taken from zlib-1.2.3, which
187   has the following copyright notice. */
188/*
189Copyright notice:
190
191 (C) 1995-2004 Jean-loup Gailly and Mark Adler
192
193  This software is provided 'as-is', without any express or implied
194  warranty.  In no event will the authors be held liable for any damages
195  arising from the use of this software.
196
197  Permission is granted to anyone to use this software for any purpose,
198  including commercial applications, and to alter it and redistribute it
199  freely, subject to the following restrictions:
200
201  1. The origin of this software must not be misrepresented; you must not
202     claim that you wrote the original software. If you use this software
203     in a product, an acknowledgment in the product documentation would be
204     appreciated but is not required.
205  2. Altered source versions must be plainly marked as such, and must not be
206     misrepresented as being the original software.
207  3. This notice may not be removed or altered from any source distribution.
208
209  Jean-loup Gailly        Mark Adler
210  jloup@gzip.org          madler@alumni.caltech.edu
211
212If you use the zlib library in a product, we would appreciate *not*
213receiving lengthy legal documents to sign. The sources are provided
214for free but without warranty of any kind.  The library has been
215entirely written by Jean-loup Gailly and Mark Adler; it does not
216include third-party code.
217
218If you redistribute modified sources, we would appreciate that you include
219in the file ChangeLog history information documenting your changes. Please
220read the FAQ for more information on the distribution of modified source
221versions.
222*/
223
224/* Update a running Adler-32 checksum with the bytes buf[0..len-1] and
225   return the updated checksum. If buf is NULL, this function returns
226   the required initial value for the checksum. An Adler-32 checksum is
227   almost as reliable as a CRC32 but can be computed much faster. */
228static
229UInt adler32( UInt adler, const UChar* buf, UInt len )
230{
231#  define BASE 65521UL    /* largest prime smaller than 65536 */
232#  define NMAX 5552
233   /* NMAX is the largest n such that
234      255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
235
236#  define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
237#  define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
238#  define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
239#  define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
240#  define DO16(buf)   DO8(buf,0); DO8(buf,8);
241
242   /* The zlib sources recommend this definition of MOD if the
243      processor cannot do integer division in hardware. */
244#  define MOD(a) \
245      do { \
246          if (a >= (BASE << 16)) a -= (BASE << 16); \
247          if (a >= (BASE << 15)) a -= (BASE << 15); \
248          if (a >= (BASE << 14)) a -= (BASE << 14); \
249          if (a >= (BASE << 13)) a -= (BASE << 13); \
250          if (a >= (BASE << 12)) a -= (BASE << 12); \
251          if (a >= (BASE << 11)) a -= (BASE << 11); \
252          if (a >= (BASE << 10)) a -= (BASE << 10); \
253          if (a >= (BASE << 9)) a -= (BASE << 9); \
254          if (a >= (BASE << 8)) a -= (BASE << 8); \
255          if (a >= (BASE << 7)) a -= (BASE << 7); \
256          if (a >= (BASE << 6)) a -= (BASE << 6); \
257          if (a >= (BASE << 5)) a -= (BASE << 5); \
258          if (a >= (BASE << 4)) a -= (BASE << 4); \
259          if (a >= (BASE << 3)) a -= (BASE << 3); \
260          if (a >= (BASE << 2)) a -= (BASE << 2); \
261          if (a >= (BASE << 1)) a -= (BASE << 1); \
262          if (a >= BASE) a -= BASE; \
263      } while (0)
264#  define MOD4(a) \
265      do { \
266          if (a >= (BASE << 4)) a -= (BASE << 4); \
267          if (a >= (BASE << 3)) a -= (BASE << 3); \
268          if (a >= (BASE << 2)) a -= (BASE << 2); \
269          if (a >= (BASE << 1)) a -= (BASE << 1); \
270          if (a >= BASE) a -= BASE; \
271      } while (0)
272
273    UInt sum2;
274    UInt n;
275
276    /* split Adler-32 into component sums */
277    sum2 = (adler >> 16) & 0xffff;
278    adler &= 0xffff;
279
280    /* in case user likes doing a byte at a time, keep it fast */
281    if (len == 1) {
282        adler += buf[0];
283        if (adler >= BASE)
284            adler -= BASE;
285        sum2 += adler;
286        if (sum2 >= BASE)
287            sum2 -= BASE;
288        return adler | (sum2 << 16);
289    }
290
291    /* initial Adler-32 value (deferred check for len == 1 speed) */
292    if (buf == NULL)
293        return 1L;
294
295    /* in case short lengths are provided, keep it somewhat fast */
296    if (len < 16) {
297        while (len--) {
298            adler += *buf++;
299            sum2 += adler;
300        }
301        if (adler >= BASE)
302            adler -= BASE;
303        MOD4(sum2);             /* only added so many BASE's */
304        return adler | (sum2 << 16);
305    }
306
307    /* do length NMAX blocks -- requires just one modulo operation */
308    while (len >= NMAX) {
309        len -= NMAX;
310        n = NMAX / 16;          /* NMAX is divisible by 16 */
311        do {
312            DO16(buf);          /* 16 sums unrolled */
313            buf += 16;
314        } while (--n);
315        MOD(adler);
316        MOD(sum2);
317    }
318
319    /* do remaining bytes (less than NMAX, still just one modulo) */
320    if (len) {                  /* avoid modulos if none remaining */
321        while (len >= 16) {
322            len -= 16;
323            DO16(buf);
324            buf += 16;
325        }
326        while (len--) {
327            adler += *buf++;
328            sum2 += adler;
329        }
330        MOD(adler);
331        MOD(sum2);
332    }
333
334    /* return recombined sums */
335    return adler | (sum2 << 16);
336
337#  undef MOD4
338#  undef MOD
339#  undef DO16
340#  undef DO8
341#  undef DO4
342#  undef DO2
343#  undef DO1
344#  undef NMAX
345#  undef BASE
346}
347
348
349/* A frame.  The first 4 bytes of |data| give the kind of the frame,
350   and the rest of it is kind-specific data. */
351typedef  struct { UChar* data; SizeT n_data; }  Frame;
352
353
354static void write_UInt_le ( /*OUT*/UChar* dst, UInt n )
355{
356   Int i;
357   for (i = 0; i <= 3; i++) {
358      dst[i] = (UChar)(n & 0xFF);
359      n >>= 8;
360   }
361}
362
363static UInt read_UInt_le ( UChar* src )
364{
365   UInt r = 0;
366   Int i;
367   for (i = 3; i >= 0; i--) {
368      r <<= 8;
369      r += (UInt)src[i];
370   }
371   return r;
372}
373
374static void write_ULong_le ( /*OUT*/UChar* dst, ULong n )
375{
376   Int i;
377   for (i = 0; i <= 7; i++) {
378      dst[i] = (UChar)(n & 0xFF);
379      n >>= 8;
380   }
381}
382
383static ULong read_ULong_le ( UChar* src )
384{
385   ULong r = 0;
386   Int i;
387   for (i = 7; i >= 0; i--) {
388      r <<= 8;
389      r += (ULong)src[i];
390   }
391   return r;
392}
393
394static Frame* mk_Frame_asciiz ( const char* tag, const char* str )
395{
396   assert(strlen(tag) == 4);
397   Frame* f = calloc(sizeof(Frame), 1);
398   size_t n_str = strlen(str);
399   f->n_data = 4 + n_str + 1;
400   f->data = calloc(f->n_data, 1);
401   memcpy(&f->data[0], tag, 4);
402   memcpy(&f->data[4], str, n_str);
403   assert(f->data[4 + n_str] == 0);
404   return f;
405}
406
407static Bool parse_Frame_noargs ( Frame* fr, const HChar* tag )
408{
409   assert(strlen(tag) == 4);
410   if (!fr || !fr->data) return False;
411   if (fr->n_data < 4) return False;
412   if (memcmp(&fr->data[0], tag, 4) != 0) return False;
413   if (fr->n_data != 4) return False;
414   return True;
415}
416
417static Bool parse_Frame_asciiz ( Frame* fr, const HChar* tag,
418                                 /*OUT*/UChar** str )
419{
420   assert(strlen(tag) == 4);
421   if (!fr || !fr->data) return False;
422   if (fr->n_data < 4) return False;
423   if (memcmp(&fr->data[0], tag, 4) != 0) return False;
424   if (fr->n_data < 5) return False; // else there isn't even enough
425                                     // space for the terminating zero
426   /* Find the terminating zero and ensure it's right at the end
427      of the data.  If not, the frame is malformed. */
428   SizeT i = 4;
429   while (True) {
430      if (i >= fr->n_data) break;
431      if (fr->data[i] == 0) break;
432      i++;
433   }
434   assert(i <= fr->n_data);
435   if (i == fr->n_data-1 && fr->data[i] == 0) {
436      *str = &fr->data[4];
437      return True;
438   } else {
439      return False;
440   }
441}
442
443static Frame* mk_Frame_le64 ( const HChar* tag, ULong n1 )
444{
445   assert(strlen(tag) == 4);
446   Frame* f = calloc(sizeof(Frame), 1);
447   f->n_data = 4 + 1*8;
448   f->data = calloc(f->n_data, 1);
449   memcpy(&f->data[0], tag, 4);
450   write_ULong_le(&f->data[4 + 0*8], n1);
451   return f;
452}
453
454static Frame* mk_Frame_le64_le64 ( const HChar* tag, ULong n1, ULong n2 )
455{
456   assert(strlen(tag) == 4);
457   Frame* f = calloc(sizeof(Frame), 1);
458   f->n_data = 4 + 2*8;
459   f->data = calloc(f->n_data, 1);
460   memcpy(&f->data[0], tag, 4);
461   write_ULong_le(&f->data[4 + 0*8], n1);
462   write_ULong_le(&f->data[4 + 1*8], n2);
463   return f;
464}
465
466static Bool parse_Frame_le64_le64_le64 ( Frame* fr, const HChar* tag,
467                                         /*OUT*/ULong* n1, /*OUT*/ULong* n2,
468                                         /*OUT*/ULong* n3 )
469{
470   assert(strlen(tag) == 4);
471   if (!fr || !fr->data) return False;
472   if (fr->n_data < 4) return False;
473   if (memcmp(&fr->data[0], tag, 4) != 0) return False;
474   if (fr->n_data != 4 + 3*8) return False;
475   *n1 = read_ULong_le(&fr->data[4 + 0*8]);
476   *n2 = read_ULong_le(&fr->data[4 + 1*8]);
477   *n3 = read_ULong_le(&fr->data[4 + 2*8]);
478   return True;
479}
480
481static Frame* mk_Frame_le64_le64_le64_bytes (
482                 const HChar* tag,
483                 ULong n1, ULong n2, ULong n3, ULong n_data,
484                 /*OUT*/UChar** data )
485{
486   assert(strlen(tag) == 4);
487   Frame* f = calloc(sizeof(Frame), 1);
488   f->n_data = 4 + 3*8 + n_data;
489   f->data = calloc(f->n_data, 1);
490   memcpy(&f->data[0], tag, 4);
491   write_ULong_le(&f->data[4 + 0*8], n1);
492   write_ULong_le(&f->data[4 + 1*8], n2);
493   write_ULong_le(&f->data[4 + 2*8], n3);
494   *data = &f->data[4 + 3*8];
495   return f;
496}
497
498static void free_Frame ( Frame* fr )
499{
500   assert(fr && fr->data);
501   free(fr->data);
502   free(fr);
503}
504
505
506static void set_blocking ( int sd )
507{
508   int res;
509   res = fcntl(sd, F_GETFL);
510   res = fcntl(sd, F_SETFL, res & ~O_NONBLOCK);
511   if (res != 0) {
512      perror("fcntl failed");
513      panic("set_blocking");
514   }
515}
516
517
518#if 0
519static void set_nonblocking ( int sd )
520{
521   int res;
522   res = fcntl(sd, F_GETFL);
523   res = fcntl(sd, F_SETFL, res | O_NONBLOCK);
524   if (res != 0) {
525      perror("fcntl failed");
526      panic("set_nonblocking");
527   }
528}
529#endif
530
531
532/* Tries to read 'len' bytes from fd, blocking if necessary.  Assumes
533   fd has been set in blocking mode.  If it returns with the number of
534   bytes read < len, it means that either fd was closed, or there was
535   an error on it. */
536static SizeT my_read ( Int fd, UChar* buf, SizeT len )
537{
538  //set_blocking(fd);
539   SizeT nRead = 0;
540   while (1) {
541      if (nRead == len) return nRead;
542      assert(nRead < len);
543      SizeT nNeeded = len - nRead;
544      assert(nNeeded > 0);
545      SSizeT n = read(fd, &buf[nRead], nNeeded);
546      if (n <= 0) return nRead; /* error or EOF */
547      nRead += n;
548   }
549}
550
551/* Tries to write 'len' bytes to fd, blocking if necessary.  Assumes
552   fd has been set in blocking mode.  If it returns with the number of
553   bytes written < len, it means that either fd was closed, or there was
554   an error on it. */
555static SizeT my_write ( Int fd, UChar* buf, SizeT len )
556{
557  //set_nonblocking(fd);
558   SizeT nWritten = 0;
559   while (1) {
560      if (nWritten == len) return nWritten;
561      assert(nWritten < len);
562      SizeT nStillToDo = len - nWritten;
563      assert(nStillToDo > 0);
564      SSizeT n = write(fd, &buf[nWritten], nStillToDo);
565      if (n < 0) return nWritten; /* error or EOF */
566      nWritten += n;
567   }
568}
569
570
571static UInt calc_gnu_debuglink_crc32(/*OUT*/Bool* ok, int fd, ULong size)
572{
573  static const UInt crc32_table[256] =
574    {
575      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
576      0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
577      0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
578      0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
579      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
580      0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
581      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
582      0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
583      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
584      0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
585      0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
586      0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
587      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
588      0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
589      0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
590      0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
591      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
592      0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
593      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
594      0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
595      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
596      0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
597      0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
598      0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
599      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
600      0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
601      0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
602      0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
603      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
604      0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
605      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
606      0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
607      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
608      0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
609      0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
610      0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
611      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
612      0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
613      0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
614      0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
615      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
616      0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
617      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
618      0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
619      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
620      0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
621      0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
622      0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
623      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
624      0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
625      0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
626      0x2d02ef8d
627    };
628
629      /* Work through the image in 1 KB chunks. */
630      UInt  crc      = 0xFFFFFFFF;
631      ULong img_szB  = size;
632      ULong curr_off = 0;
633      while (1) {
634         assert(curr_off >= 0 && curr_off <= img_szB);
635         if (curr_off == img_szB) break;
636         ULong avail = img_szB - curr_off;
637         assert(avail > 0 && avail <= img_szB);
638         if (avail > 65536) avail = 65536;
639         UChar buf[65536];
640         Int nRead = pread(fd, buf, avail, curr_off);
641         if (nRead <= 0) { /* EOF or error on the file; neither should happen */
642            *ok = False;
643            return 0;
644         }
645         /* this is a kludge .. we should loop around pread and deal
646            with short reads, for whatever reason */
647         assert(nRead == avail);
648         UInt i;
649         for (i = 0; i < (UInt)nRead; i++)
650            crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
651         curr_off += nRead;
652      }
653      *ok = True;
654      return ~crc & 0xFFFFFFFF;
655   }
656
657
658/*---------------------------------------------------------------*/
659
660/* Handle a transaction for conn_state[conn_no].  There is incoming
661   data available; read it and send back an appropriate response.
662   Returns a boolean indicating whether the connection has been
663   closed; in which case this function does all necessary cleanup and
664   leaves conn_state[conn_no] in a not-in-use state. */
665
666static Bool handle_transaction ( int conn_no )
667{
668   Frame* req = NULL; /* the request frame that we receive */
669   Frame* res = NULL; /* the response frame that we send back */
670
671   assert(conn_no >= 0 && conn_no < M_CONNECTIONS);
672   assert(conn_state[conn_no].in_use);
673
674   //printf("SERVER: handle_transaction(%d)\n", conn_no); fflush(stdout);
675
676   Int sd = conn_state[conn_no].conn_sd;
677
678   /* Get a frame out of the channel. */
679   UChar rd_first8[8];  // adler32; length32
680   { Int r = my_read(sd, &rd_first8[0], 8);
681     if (r == 0) goto client_closed_conn;
682     if (r != 8) goto fail;
683   }
684   UInt rd_adler = read_UInt_le(&rd_first8[0]);
685   UInt rd_len   = read_UInt_le(&rd_first8[4]);
686   /* Allocate a Frame to hold the result data, and read into it. */
687   // Reject obviously-insane length fields.
688   if (rd_len > 4*1024*1024) goto fail;
689   assert(req == NULL);
690   req = calloc(sizeof(Frame), 1);
691   req->n_data = rd_len;
692   req->data = calloc(rd_len, 1);
693   if (rd_len > 0) {
694      Int r = my_read(sd, req->data, req->n_data);
695      if (r != rd_len) goto fail;
696   }
697//printf("SERVER: recv %c%c%c%c\n", req->data[0], req->data[1], req->data[2], req->data[3]); fflush(stdout);
698
699   /* Compute the checksum for the received data, and check it. */
700   UInt adler = adler32(0, NULL, 0); // initial value
701   adler = adler32(adler, &rd_first8[4], 4);
702   if (req->n_data > 0)
703      adler = adler32(adler, req->data, req->n_data);
704
705   if (adler/*computed*/ != rd_adler/*expected*/) goto fail;
706
707   /* Now we have a request frame.  Cook up a response. */
708   assert(res == NULL);
709
710   UChar* filename = NULL;
711   ULong req_session_id = 0, req_offset = 0, req_len = 0;
712
713   if (parse_Frame_noargs(req, "VERS")) {
714      res = mk_Frame_asciiz("VEOK", "Valgrind Debuginfo Server, Version 1");
715   }
716   else
717   if (parse_Frame_noargs(req, "CRC3")) {
718      /* FIXME: add a session ID to this request, and check it */
719      if (conn_state[conn_no].file_fd == 0) {
720         res = mk_Frame_asciiz("CRC3", "FAIL: not connected to file");
721      } else {
722         Bool ok    = False;
723         UInt crc32 = calc_gnu_debuglink_crc32(&ok,
724                                               conn_state[conn_no].file_fd,
725                                               conn_state[conn_no].file_size);
726         if (ok) {
727            res = mk_Frame_le64("CROK", (ULong)crc32);
728         } else {
729            res = mk_Frame_asciiz("FAIL", "CRC3: I/O error reading file");
730         }
731      }
732   }
733   else
734   if (parse_Frame_asciiz(req, "OPEN", &filename)) {
735      Bool ok = True;
736      int  fd = 0;
737      if (conn_state[conn_no].file_fd != 0) {
738         res = mk_Frame_asciiz("FAIL", "OPEN: already connected to file");
739         ok = False;
740      }
741      if (ok) {
742         assert(clo_serverpath);
743         fd = open((char*)filename, O_RDONLY);
744         if (fd == -1) {
745            res = mk_Frame_asciiz("FAIL", "OPEN: cannot open file");
746            printf("(%d) SessionID %llu: open failed for \"%s\"\n",
747                   conn_count, conn_state[conn_no].session_id, filename );
748            ok = False;
749         } else {
750            assert(fd > 2);
751         }
752      }
753      if (ok) {
754         struct stat stat_buf;
755         int r = fstat(fd, &stat_buf);
756         if (r != 0) {
757            res = mk_Frame_asciiz("FAIL", "OPEN: cannot stat file");
758            ok = False;
759         }
760         if (ok && stat_buf.st_size == 0) {
761            res = mk_Frame_asciiz("FAIL", "OPEN: file has zero size");
762            ok = False;
763         }
764         if (ok) {
765            conn_state[conn_no].file_fd   = fd;
766            conn_state[conn_no].file_size = stat_buf.st_size;
767            assert(res == NULL);
768            res = mk_Frame_le64_le64("OPOK", conn_state[conn_no].session_id,
769                                             conn_state[conn_no].file_size);
770            printf("(%d) SessionID %llu: open successful for \"%s\"\n",
771                   conn_count, conn_state[conn_no].session_id, filename );
772            fflush(stdout);
773         }
774      }
775   }
776   else
777   if (parse_Frame_le64_le64_le64(req, "READ", &req_session_id,
778                                  &req_offset, &req_len)) {
779      /* Because each new connection is associated with its own socket
780         descriptor and hence with a particular conn_no, the requested
781         session-ID is redundant -- it must be the one associated with
782         this slot.  But check anyway. */
783      Bool ok = True;
784      if (req_session_id != conn_state[conn_no].session_id) {
785         res = mk_Frame_asciiz("FAIL", "READ: invalid session ID");
786         ok = False;
787      }
788      /* Check we're connected to a file, and if so range-check the
789         request. */
790      if (ok && conn_state[conn_no].file_fd == 0) {
791         res = mk_Frame_asciiz("FAIL", "READ: no associated file");
792         ok = False;
793      }
794      if (ok && (req_len == 0 || req_len > 4*1024*1024)) {
795         res = mk_Frame_asciiz("FAIL", "READ: invalid request size");
796         ok = False;
797      }
798      if (ok && req_len + req_offset > conn_state[conn_no].file_size) {
799         res = mk_Frame_asciiz("FAIL", "READ: request exceeds file size");
800         ok = False;
801      }
802      /* Try to read the file. */
803      if (ok) {
804         /* First, allocate a temp buf and read from the file into it. */
805         /* FIXME: what if pread reads short and we have to redo it? */
806         UChar* unzBuf = malloc(req_len);
807         size_t nRead = pread(conn_state[conn_no].file_fd,
808                              unzBuf, req_len, req_offset);
809         if (nRead != req_len) {
810            free_Frame(res);
811            res = mk_Frame_asciiz("FAIL", "READ: I/O error reading file");
812            ok = False;
813         }         UInt zLen = 0;
814         if (ok) {
815            // Now compress it with LZO.  LZO appears to recommend
816            // the worst-case output size as (in_len + in_len / 16 + 67).
817            // Be more conservative here.
818#           define STACK_ALLOC(var,size) \
819               lzo_align_t __LZO_MMODEL \
820                  var [ ((size) \
821                        + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
822            STACK_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS);
823#           undef STACK_ALLOC
824            UInt zLenMax = req_len + req_len / 4 + 1024;
825            UChar* zBuf = malloc(zLenMax);
826            zLen = zLenMax;
827            Int lzo_rc = lzo1x_1_compress(unzBuf, req_len,
828                                          zBuf, (lzo_uint*)&zLen, wrkmem);
829            if (lzo_rc == LZO_E_OK) {
830              //printf("XXXXX req_len %u  zLen %u\n", (UInt)req_len, (UInt)zLen);
831               assert(zLen <= zLenMax);
832               /* Make a frame to put the results in.  Bytes 24 and
833                  onwards need to be filled from the compressed data,
834                  and 'buf' is set to point to the right bit. */
835               UChar* buf = NULL;
836               res = mk_Frame_le64_le64_le64_bytes
837                 ("RDOK", req_session_id, req_offset, req_len, zLen, &buf);
838               assert(res);
839               assert(buf);
840               memcpy(buf, zBuf, zLen);
841               // Update stats
842               conn_state[conn_no].stats_n_rdok_frames++;
843               conn_state[conn_no].stats_n_read_unz_bytes += req_len;
844               conn_state[conn_no].stats_n_read_z_bytes   += zLen;
845            } else {
846               ok = False;
847               free_Frame(res);
848               res = mk_Frame_asciiz("FAIL", "READ: LZO failed");
849            }
850            free(zBuf);
851         }
852         free(unzBuf);
853      }
854   }
855   else {
856      res = mk_Frame_asciiz("FAIL", "Invalid request frame type");
857   }
858
859   /* All paths through the above should result in an assignment to |res|. */
860   assert(res != NULL);
861
862   /* And send the response frame back to the client. */
863   /* What goes on the wire is:
864         adler(le32) n_data(le32) data[0 .. n_data-1]
865      where the checksum covers n_data as well as data[].
866   */
867   /* The initial Adler-32 value */
868   adler = adler32(0, NULL, 0);
869
870   /* Fold in the length field, encoded as le32. */
871   UChar wr_first8[8];
872   write_UInt_le(&wr_first8[4], res->n_data);
873   adler = adler32(adler, &wr_first8[4], 4);
874   /* Fold in the data values */
875   adler = adler32(adler, res->data, res->n_data);
876   write_UInt_le(&wr_first8[0], adler);
877
878   Int r = my_write(sd, &wr_first8[0], 8);
879   if (r != 8) goto fail;
880   assert(res->n_data >= 4); // else ill formed -- no KIND field
881   r = my_write(sd, res->data, res->n_data);
882   if (r != res->n_data) goto fail;
883
884//printf("SERVER: send %c%c%c%c\n", res->data[0], res->data[1], res->data[2], res->data[3]); fflush(stdout);
885
886   /* So, success. */
887   if (req) free_Frame(req);
888   if (res) free_Frame(res);
889   return False;  /* "connection still in use" */
890
891   // Is there any difference between these?
892  client_closed_conn:
893  fail:
894   if (conn_state[conn_no].conn_sd > 0)
895      close(conn_state[conn_no].conn_sd);
896   if (conn_state[conn_no].file_fd > 0)
897      close(conn_state[conn_no].file_fd);
898
899   if (conn_state[conn_no].stats_n_rdok_frames > 0) {
900      printf("(%d) SessionID %llu:   sent %llu frames, "
901             "%llu MB (unz), %llu MB (z), ratio %4.2f:1\n",
902             conn_count, conn_state[conn_no].session_id,
903             conn_state[conn_no].stats_n_rdok_frames,
904             conn_state[conn_no].stats_n_read_unz_bytes / 1000000,
905             conn_state[conn_no].stats_n_read_z_bytes / 1000000,
906             (double)conn_state[conn_no].stats_n_read_unz_bytes
907               / (double)conn_state[conn_no].stats_n_read_z_bytes);
908      printf("(%d) SessionID %llu: closed\n",
909             conn_count, conn_state[conn_no].session_id);
910
911      fflush(stdout);
912   }
913
914   memset(&conn_state[conn_no], 0, sizeof(conn_state[conn_no]));
915   if (req) free_Frame(req);
916   if (res) free_Frame(res);
917   return True; /* "connection has been closed" */
918}
919
920
921/*---------------------------------------------------------------*/
922
923
924
925#if 0
926static void copyout ( char* buf, int nbuf )
927{
928   int i;
929   for (i = 0; i < nbuf; i++) {
930      if (buf[i] == '\n') {
931         fprintf(stdout, "\n(%d) ", conn_count);
932      } else {
933         __attribute__((unused)) size_t ignored
934            = fwrite(&buf[i], 1, 1, stdout);
935      }
936   }
937   fflush(stdout);
938}
939
940static int read_from_sd ( int sd )
941{
942   char buf[100];
943   int n;
944
945   set_blocking(sd);
946   n = read(sd, buf, 99);
947   if (n <= 0) return 0; /* closed */
948   copyout(buf, n);
949
950   set_nonblocking(sd);
951   while (1) {
952      n = read(sd, buf, 100);
953      if (n <= 0) return 1; /* not closed */
954      copyout(buf, n);
955   }
956}
957#endif
958
959static void snooze ( void )
960{
961   struct timespec req;
962   req.tv_sec = 0;
963   req.tv_nsec = 200 * 1000 * 1000;
964   nanosleep(&req,NULL);
965}
966
967
968/* returns 0 if invalid, else port # */
969static int atoi_portno ( const char* str )
970{
971   int n = 0;
972   while (1) {
973      if (*str == 0)
974         break;
975      if (*str < '0' || *str > '9')
976         return 0;
977      n = 10*n + (int)(*str - '0');
978      str++;
979      if (n >= 65536)
980         return 0;
981   }
982   if (n < 1024)
983      return 0;
984   return n;
985}
986
987
988static void usage ( void )
989{
990   fprintf(stderr,
991      "\n"
992      "usage is:\n"
993      "\n"
994      "   valgrind-di-server [--exit-at-zero|-e] [port-number]\n"
995      "\n"
996      "   where   --exit-at-zero or -e causes the listener to exit\n"
997      "           when the number of connections falls back to zero\n"
998      "           (the default is to keep listening forever)\n"
999      "\n"
1000      "           port-number is the default port on which to listen for\n"
1001      "           connections.  It must be between 1024 and 65535.\n"
1002      "           Current default is %d.\n"
1003      "\n"
1004      ,
1005      VG_CLO_DEFAULT_LOGPORT
1006   );
1007   exit(1);
1008}
1009
1010
1011static void banner ( const char* str )
1012{
1013   time_t t;
1014   t = time(NULL);
1015   printf("valgrind-di-server %s at %s", str, ctime(&t));
1016   fflush(stdout);
1017}
1018
1019
1020static void exit_routine ( void )
1021{
1022   banner("exited");
1023   exit(0);
1024}
1025
1026
1027static void sigint_handler ( int signo )
1028{
1029   exit_routine();
1030}
1031
1032
1033int main (int argc, char** argv)
1034{
1035   int    i, j, res, one;
1036   int    main_sd, new_sd;
1037   socklen_t client_len;
1038   struct sockaddr_in client_addr, server_addr;
1039
1040   char /*bool*/ exit_when_zero = 0;
1041   int           port = VG_CLO_DEFAULT_LOGPORT;
1042
1043   for (i = 1; i < argc; i++) {
1044      if (0==strcmp(argv[i], "--exit-at-zero")
1045          || 0==strcmp(argv[i], "-e")) {
1046         exit_when_zero = 1;
1047      }
1048      else
1049      if (atoi_portno(argv[i]) > 0) {
1050         port = atoi_portno(argv[i]);
1051      }
1052      else
1053      usage();
1054   }
1055
1056   banner("started");
1057   signal(SIGINT, sigint_handler);
1058
1059   conn_count = 0;
1060   memset(&conn_state, 0, sizeof(conn_state));
1061
1062   /* create socket */
1063   main_sd = socket(AF_INET, SOCK_STREAM, 0);
1064   if (main_sd < 0) {
1065      perror("cannot open socket ");
1066      panic("main -- create socket");
1067   }
1068
1069   /* allow address reuse to avoid "address already in use" errors */
1070
1071   one = 1;
1072   if (setsockopt(main_sd, SOL_SOCKET, SO_REUSEADDR,
1073		  &one, sizeof(one)) < 0) {
1074      perror("cannot enable address reuse ");
1075      panic("main -- enable address reuse");
1076   }
1077
1078   /* bind server port */
1079   server_addr.sin_family      = AF_INET;
1080   server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1081   server_addr.sin_port        = htons(port);
1082
1083   if (bind(main_sd, (struct sockaddr *) &server_addr,
1084                     sizeof(server_addr) ) < 0) {
1085      perror("cannot bind port ");
1086      panic("main -- bind port");
1087   }
1088
1089   res = listen(main_sd, M_CONNECTIONS);
1090   if (res != 0) {
1091      perror("listen failed ");
1092      panic("main -- listen");
1093   }
1094
1095   Bool do_snooze = False;
1096   while (1) {
1097
1098      if (0 && do_snooze)
1099         snooze();
1100
1101      /* Snooze after this iteration, unless something happened. */
1102      do_snooze = True;
1103
1104      /* enquire, using poll, whether there is any activity available on
1105         the main socket descriptor.  If so, someone is trying to
1106         connect; get the fd and add it to our table thereof. */
1107      { struct pollfd ufd;
1108        while (1) {
1109           ufd.fd      = main_sd;
1110           ufd.events  = POLLIN;
1111           ufd.revents = 0;
1112           res = poll(&ufd, 1, 0/*ms*/ /* 0=return immediately. */);
1113           if (res == 0) break;
1114
1115           /* ok, we have someone waiting to connect.  Get the sd. */
1116           client_len = sizeof(client_addr);
1117           new_sd = accept(main_sd, (struct sockaddr *)&client_addr,
1118                                                       &client_len);
1119           if (new_sd < 0) {
1120              perror("cannot accept connection ");
1121              panic("main -- accept connection");
1122           }
1123
1124           /* find a place to put it. */
1125	   assert(new_sd > 0);
1126           for (i = 0; i < M_CONNECTIONS; i++)
1127              if (!conn_state[i].in_use)
1128                 break;
1129
1130           if (i >= M_CONNECTIONS) {
1131              fprintf(stderr, "Too many concurrent connections.  "
1132                              "Increase M_CONNECTIONS and recompile.\n");
1133              panic("main -- too many concurrent connections");
1134           }
1135
1136assert(one == 1);
1137int ret = setsockopt( new_sd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
1138assert(ret != -1);
1139
1140           memset(&conn_state[i], 0, sizeof(conn_state[i]));
1141           conn_state[i].in_use     = True;
1142           conn_state[i].conn_sd    = new_sd;
1143           conn_state[i].file_fd    = 0; /* not known yet */
1144           conn_state[i].session_id = next_session_id++;
1145           set_blocking(new_sd);
1146           conn_count++;
1147           do_snooze = False;
1148        } /* while (1) */
1149      }
1150
1151      /* We've processed all new connect requests.  Listen for changes
1152         to the current set of fds.  This requires gathering up all
1153         the known conn_sd values and doing poll() on them. */
1154      struct pollfd tmp_pollfd[M_CONNECTIONS];
1155      /* And a parallel array which maps entries in tmp_pollfd back to
1156         entries in conn_state. */
1157      int tmp_pollfd_to_conn_state[M_CONNECTIONS];
1158      j = 0;
1159      for (i = 0; i < M_CONNECTIONS; i++) {
1160         if (!conn_state[i].in_use)
1161            continue;
1162         assert(conn_state[i].conn_sd > 2);
1163         tmp_pollfd[j].fd      = conn_state[i].conn_sd;
1164         tmp_pollfd[j].events  = POLLIN /* | POLLHUP | POLLNVAL */;
1165         tmp_pollfd[j].revents = 0;
1166         tmp_pollfd_to_conn_state[j] = i;
1167         j++;
1168      }
1169
1170      res = poll(tmp_pollfd, j, 20/*ms*/ /* 0=return immediately. */ );
1171      if (res < 0) {
1172         perror("poll(main) failed");
1173         panic("poll(main) failed");
1174      }
1175
1176      /* nothing happened. go round again. */
1177      if (res == 0) {
1178         continue;
1179      }
1180
1181      /* inspect the fds. */
1182      for (i = 0; i < j; i++) {
1183
1184         if (tmp_pollfd[i].revents & POLLIN) {
1185            /* We have some activity on tmp_pollfd[i].  We need to
1186               figure out which conn_state[] entry that corresponds
1187               to, which is what tmp_pollfd_to_conn_state is for. */
1188            Int  conn_no  = tmp_pollfd_to_conn_state[i];
1189            Bool finished = handle_transaction(conn_no);
1190            if (finished) {
1191               /* this connection has been closed or otherwise gone
1192                  bad; forget about it. */
1193               conn_count--;
1194               fflush(stdout);
1195               if (conn_count == 0 && exit_when_zero) {
1196                  if (0) printf("\n");
1197                  fflush(stdout);
1198                  exit_routine();
1199	       }
1200            } else {
1201               // maybe show stats
1202               if (conn_state[i].stats_n_rdok_frames > 0
1203                   && (conn_state[i].stats_n_rdok_frames % 1000) == 0) {
1204                  printf("(%d) SessionID %llu:   sent %llu frames, "
1205                         "%llu MB (unz), %llu MB (z)\n",
1206                         conn_count, conn_state[conn_no].session_id,
1207                         conn_state[conn_no].stats_n_rdok_frames,
1208                         conn_state[conn_no].stats_n_read_unz_bytes / 1000000,
1209                         conn_state[conn_no].stats_n_read_z_bytes / 1000000);
1210                  fflush(stdout);
1211               }
1212            }
1213         }
1214
1215      } /* for (i = 0; i < j; i++) */
1216
1217      do_snooze = False;
1218
1219   } /* while (1) */
1220
1221   /* NOTREACHED */
1222}
1223
1224////////////////////////////////////////////////////
1225#include "../coregrind/m_debuginfo/minilzo-inl.c"
1226
1227/*--------------------------------------------------------------------*/
1228/*--- end                                     valgrind-di-server.c ---*/
1229/*--------------------------------------------------------------------*/
1230