blob: 4a16afd89166959206f441453ee617aecd004e88 [file] [log] [blame]
sewardj5d616df2013-07-02 08:07:15 +00001
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
sewardj5d7fde12013-08-01 22:16:41 +000091/* Needed to get a definition for pread() from unistd.h */
92#define _XOPEN_SOURCE 500
93
sewardj5d616df2013-07-02 08:07:15 +000094#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");
sewardj518510b2014-02-05 13:20:58 +0000746 printf("(%d) SessionID %llu: open failed for \"%s\"\n",
747 conn_count, conn_state[conn_no].session_id, filename );
sewardj5d616df2013-07-02 08:07:15 +0000748 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) {
sewardjbd7a24a2013-10-20 09:34:13 +0000785 res = mk_Frame_asciiz("FAIL", "READ: invalid session ID");
sewardj5d616df2013-07-02 08:07:15 +0000786 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;
florian2d3aed72014-09-02 12:05:15 +0000813 }
sewardj5d616df2013-07-02 08:07:15 +0000814 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);
florian2d3aed72014-09-02 12:05:15 +0000826 lzo_uint zLen = zLenMax;
sewardj5d616df2013-07-02 08:07:15 +0000827 Int lzo_rc = lzo1x_1_compress(unzBuf, req_len,
florian2d3aed72014-09-02 12:05:15 +0000828 zBuf, &zLen, wrkmem);
sewardj5d616df2013-07-02 08:07:15 +0000829 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. */
florian97b89f72014-09-02 11:58:10 +0000887 free_Frame(req);
888 free_Frame(res);
sewardj5d616df2013-07-02 08:07:15 +0000889 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/*--------------------------------------------------------------------*/