Add git ignore file to avoid accidentially including build products in repository
[binmatch.git] / binmatch.c
1 /*
2    Find occurances of one binary file within another
3    Copyright (C) 2010 TJ
4    Author: TJ <linux@tjworld.net>
5
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, version 3 of the License.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <sys/mman.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <string.h>
28
29 void
30 usage(const char *name) {
31  printf("Usage: %s:  [-d] -n <needle> -h <haystack>\n", name);
32  printf("Copyright 2010 TJ <linux@tjworld.net>\n"
33         "Licensed under the terms of the GNU GPL v3\n\n"
34         "\t-d\tprint matching addresses in decimal not hexadecimal\n"
35         "\t-n\tpath to the file containing the needle\n"
36         "\t-h\tpath to the file containing the haystack\n\n"
37
38         "\tInformation messages are written to stderr and only matches are written to stdout.\n"
39         "\tThis allows the output to be piped through other filters.\n"
40  );
41 }
42
43 int
44 main(int argc, char *argv[], char *env[]) {
45  int ret = 0;
46  int c, use_decimal, needle_fd, haystack_fd;
47  char *needle_name, *haystack_name;
48  void *needle_mmap, *haystack_mmap;
49  struct stat needle_stat, haystack_stat;
50
51  needle_name = haystack_name = needle_mmap = haystack_mmap = NULL;
52  use_decimal = 0;
53
54  if (argc > 1) { // must have some parameters
55   opterr = 0;
56
57   while ((c = getopt(argc, argv, "n:h:d")) != -1 ) { // iterate the options
58    switch(c) {
59     case 'n':
60      needle_name = optarg;
61      break;
62     case 'h':
63      haystack_name = optarg;
64      break;
65     case 'd':
66      use_decimal = 1;
67      break;
68     default:
69      abort();
70    }
71   }
72
73   if ((needle_fd = open(needle_name, O_RDONLY)) == -1) {
74    perror("Unable to open needle");
75    ret |= 1;
76   }
77
78   if ((haystack_fd = open(haystack_name, O_RDONLY)) == -1) {
79    perror("Unable to open haystack");
80    ret |= 2;
81   }
82   
83   if (!ret) {
84    fstat(needle_fd, &needle_stat);
85    fstat(haystack_fd, &haystack_stat);
86    fprintf(stderr, "Base:\t%s\n", use_decimal == 1 ? "decimal" : "hexadecimal");
87    fprintf(stderr, "Needle:\t\t%12ld\t%s\n", needle_stat.st_size, needle_name);
88    fprintf(stderr, "HayStack:\t%12ld\t%s\n", haystack_stat.st_size, haystack_name);
89
90    if(MAP_FAILED == (needle_mmap = mmap(needle_mmap, needle_stat.st_size, PROT_READ, MAP_SHARED, needle_fd, 0))) {
91     perror("Unable to memory-map needle");
92     exit(4);
93    }
94    if(MAP_FAILED == (haystack_mmap = mmap(haystack_mmap, haystack_stat.st_size, PROT_READ, MAP_SHARED, haystack_fd, 0))) {
95     perror("Unable to memory-map haystack");
96     exit(8);
97    }
98    {
99     void *n = needle_mmap; // convenient short names
100     void *h = haystack_mmap;
101     unsigned long end = haystack_stat.st_size - needle_stat.st_size;
102     unsigned long offset;
103
104     fprintf(stderr, "Searching...\n");
105     for (offset = 0; offset <= end; offset++) {
106      if (memcmp(n, h+offset, needle_stat.st_size) == 0) { // match ?
107       if (use_decimal) printf("%10ld matches\n", offset);
108       else printf("0x%08lX matches\n", offset);
109      }
110     }
111     fprintf(stderr, "Done.\n");
112    }
113   }
114  }
115  else
116   usage(argv[0]);
117
118  if (needle_mmap > 0) munmap(needle_mmap, needle_stat.st_size);
119  if (haystack_mmap > 0) munmap(haystack_mmap, haystack_stat.st_size);
120  if (needle_fd > 0) close(needle_fd);
121  if (haystack_fd > 0) close(haystack_fd);
122
123  return ret;
124 }