/* * Copyright (c) 2011 Charles Wilson * * 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, see . * * See the COPYING file for full license information. */ #include #include #include #include #include #include #if defined(__CYGWIN__) || defined(__MSYS__) #include #endif #include #include #include #include #include #include #if defined(__MSYS__) /* MSYS has no inttypes.h */ # define PRIx64 "llx" #else # include #endif #include #include #include "rebase-db.h" BOOL load_image_info (); void parse_args (int argc, char *argv[]); void usage (); void help (); void version (); int args_index = 0; BOOL verbose = FALSE; BOOL quiet = FALSE; const char *progname; img_info_hdr_t hdr; img_info_t *img_info_list = NULL; unsigned int img_info_size = 0; unsigned int img_info_rebase_start = 0; unsigned int img_info_max_size = 0; char *db_file = NULL; void gen_progname (const char *arg0) { char *p; p = strrchr (arg0, '/'); if (!p) p = strrchr (arg0, '\\'); progname = p ? p + 1 : arg0; if ((p = strrchr (progname, '.')) && !strcmp (p, ".exe")) *p = 0; } int main (int argc, char *argv[]) { setlocale (LC_ALL, ""); gen_progname (argv[0]); parse_args (argc, argv); if (args_index != argc - 1) { fprintf (stderr, "%s: no database file specified\n", progname); usage (); return 1; } db_file = strdup (argv[args_index]); if (load_image_info () < 0) return 2; /* Nothing to do? */ if (img_info_size == 0) return 0; dump_rebasedb (stdout, &hdr, img_info_list, img_info_size); return 0; } int load_image_info () { int fd; int ret = 0; int i; fd = open (db_file, O_RDONLY | O_BINARY); if (fd < 0) { fprintf (stderr, "%s: failed to open rebase database \"%s\":\n%s\n", progname, db_file, strerror (errno)); return -1; } /* First read the header. */ if (read (fd, &hdr, sizeof hdr) < 0) { fprintf (stderr, "%s: failed to read rebase database \"%s\":\n%s\n", progname, db_file, strerror (errno)); close (fd); return -1; } if (verbose) printf ("== read %u (0x%08x) bytes (database header)\n", sizeof hdr, sizeof hdr); /* Check the header. */ if (memcmp (hdr.magic, IMG_INFO_MAGIC, 4) != 0) { fprintf (stderr, "%s: \"%s\" is not a valid rebase database.\n", progname, db_file); close (fd); return -1; } if (verbose) { dump_rebasedb_header (stdout, &hdr); } if (hdr.machine != IMAGE_FILE_MACHINE_I386 && hdr.machine != IMAGE_FILE_MACHINE_AMD64) { fprintf (stderr, "%s: \"%s\" is a database file for a machine type\n" "I don't know about.", progname, db_file); close (fd); return -1; } if (hdr.version != IMG_INFO_VERSION) { fprintf (stderr, "%s: \"%s\" is a version %u rebase database.\n" "I can only handle versions up to %lu.\n", progname, db_file, hdr.version, IMG_INFO_VERSION); close (fd); return -1; } img_info_size = hdr.count; /* Allocate memory for the image list. */ if (ret == 0) { img_info_max_size = roundup (img_info_size, 100); img_info_list = (img_info_t *) calloc (img_info_max_size, sizeof (img_info_t)); if (!img_info_list) { fprintf (stderr, "%s: Out of memory.\n", progname); ret = -1; } } /* Now read the list. */ if (ret == 0 && read (fd, img_info_list, img_info_size * sizeof (img_info_t)) < 0) { fprintf (stderr, "%s: failed to read rebase database \"%s\":\n%s\n", progname, db_file, strerror (errno)); ret = -1; } if (ret == 0 && verbose) { printf ("== read %u (0x%08x) bytes (database w/o strings)\n", img_info_size * sizeof (img_info_t), img_info_size * sizeof (img_info_t)); } /* Make sure all pointers are NULL (also dump db as read) */ if (ret == 0) { if (verbose) printf ("---- database records without strings ----\n"); for (i = 0; i < img_info_size; ++i) { img_info_list[i].name = NULL; if (verbose) printf ("%03d: base 0x%0*" PRIx64 " size 0x%08lx slot 0x%08lx namesize %4ld %c\n", i, hdr.machine == IMAGE_FILE_MACHINE_I386 ? 8 : 12, img_info_list[i].base, img_info_list[i].size, img_info_list[i].slot_size, img_info_list[i].name_size, img_info_list[i].flag.needs_rebasing ? '*' : ' '); } } /* Eventually read the strings. */ if (ret == 0) { if (verbose) printf ("---- database strings ----\n"); for (i = 0; i < img_info_size; ++i) { img_info_list[i].name = (char *) calloc (img_info_list[i].name_size, sizeof(char)); if (!img_info_list[i].name) { fprintf (stderr, "%s: Out of memory.\n", progname); ret = -1; break; } if (read (fd, (void *)img_info_list[i].name, (size_t) img_info_list[i].name_size) < 0) { fprintf (stderr, "%s: failed to read rebase database \"%s\": " "%s\n", progname, db_file, strerror (errno)); ret = -1; break; } else if (verbose) { printf ("%03d: namesize %4ld (0x%04lx) %s\n", i, img_info_list[i].name_size, img_info_list[i].name_size, img_info_list[i].name); } } } close (fd); /* On failure, free all allocated memory and set list pointer to NULL. */ if (ret < 0) { for (i = 0; i < img_info_size && img_info_list[i].name; ++i) free (img_info_list[i].name); free (img_info_list); img_info_list = NULL; img_info_size = 0; img_info_max_size = 0; } return ret; } static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"usage", no_argument, NULL, 'h'}, {"quiet", no_argument, NULL, 'q'}, {"usage", no_argument, NULL, 'h'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {NULL, no_argument, NULL, 0 } }; static const char *short_options = "hqvV"; void parse_args (int argc, char *argv[]) { int opt = 0; while ((opt = getopt_long (argc, argv, short_options, long_options, NULL)) != -1) { switch (opt) { case 'q': quiet = TRUE; break; case 'v': verbose = TRUE; break; case 'h': help (); exit (1); break; case 'V': version (); exit (1); break; default: usage (); exit (1); break; } } args_index = optind; } void usage () { fprintf (stderr, "usage: %s [-hqvV] dbfile\n" " %s --help or --usage for full help text\n", progname, progname); } void help () { printf ("\ Usage: %s [OPTIONS] [FILE]n\ Dumps the rebase database file in readable format.\n\ -q, --quiet Be quiet about non-critical issues.\n\ -v, --verbose Print some debug output.\n\ -V, --version Print version info and exit.\n\ -h, --help, --usage This help.\n", progname); } void version () { fprintf (stderr, "rebase-dump version %s (imagehelper version %s)\n", VERSION, LIB_VERSION); fprintf (stderr, "Copyright (c) 2011 Charles Wilson\n"); }