| 1 | /* Program to stuff files into a specially prepared space in kdb. |
| 2 | Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc. |
| 3 | |
| 4 | This file is part of GDB. |
| 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; either version 2 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | This program is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License |
| 17 | along with this program; if not, write to the Free Software |
| 18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
| 19 | |
| 20 | /* Written 13-Mar-86 by David Bridgham. */ |
| 21 | |
| 22 | #include <stdio.h> |
| 23 | #include <a.out.h> |
| 24 | #include <sys/types.h> |
| 25 | #include <sys/stat.h> |
| 26 | #include <sys/file.h> |
| 27 | #include <varargs.h> |
| 28 | |
| 29 | main (argc, argv) |
| 30 | int argc; |
| 31 | char *argv[]; |
| 32 | { |
| 33 | register char *cp; |
| 34 | char *outfile; |
| 35 | register int i; |
| 36 | int offset; |
| 37 | int out_fd, in_fd; |
| 38 | struct stat stat_buf; |
| 39 | int size, pad; |
| 40 | char buf[1024]; |
| 41 | static char zeros[4] = {0}; |
| 42 | |
| 43 | if (argc < 4) |
| 44 | err("Not enough arguments\nUsage: %s -o kdb file1 file2 ...\n", |
| 45 | argv[0]); |
| 46 | |
| 47 | outfile = 0; |
| 48 | for (i = 1; i < argc; i++) |
| 49 | { |
| 50 | if (STREQ (argv[i], "-o")) |
| 51 | outfile = argv[++i]; |
| 52 | } |
| 53 | if (outfile == 0) |
| 54 | err("Output file not specified\n"); |
| 55 | |
| 56 | offset = get_offset (outfile, "_heap"); |
| 57 | |
| 58 | out_fd = open (outfile, O_WRONLY); |
| 59 | if (out_fd < 0) |
| 60 | err ("Error opening %s for write: %s\n", outfile, strerror (errno)); |
| 61 | if (lseek (out_fd, offset, 0) < 0) |
| 62 | err ("Error seeking to heap in %s: %s\n", outfile, strerror (errno)); |
| 63 | |
| 64 | /* For each file listed on the command line, write it into the |
| 65 | * 'heap' of the output file. Make sure to skip the arguments |
| 66 | * that name the output file. */ |
| 67 | for (i = 1; i < argc; i++) |
| 68 | { |
| 69 | if (STREQ (argv[i], "-o")) |
| 70 | continue; |
| 71 | if ((in_fd = open (argv[i], O_RDONLY)) < 0) |
| 72 | err ("Error opening %s for read: %s\n", argv[i], |
| 73 | strerror (errno)); |
| 74 | if (fstat (in_fd, &stat_buf) < 0) |
| 75 | err ("Error stat'ing %s: %s\n", argv[i], strerror (errno)); |
| 76 | size = strlen (argv[i]); |
| 77 | pad = 4 - (size & 3); |
| 78 | size += pad + stat_buf.st_size + sizeof (int); |
| 79 | write (out_fd, &size, sizeof (int)); |
| 80 | write (out_fd, argv[i], strlen (argv[i])); |
| 81 | write (out_fd, zeros, pad); |
| 82 | while ((size = read (in_fd, buf, sizeof (buf))) > 0) |
| 83 | write (out_fd, buf, size); |
| 84 | close (in_fd); |
| 85 | } |
| 86 | size = 0; |
| 87 | write (out_fd, &size, sizeof (int)); |
| 88 | close (out_fd); |
| 89 | return (0); |
| 90 | } |
| 91 | |
| 92 | /* Read symbol table from file and returns the offset into the file |
| 93 | * where symbol sym_name is located. If error, print message and |
| 94 | * exit. */ |
| 95 | get_offset (file, sym_name) |
| 96 | char *file; |
| 97 | char *sym_name; |
| 98 | { |
| 99 | int f; |
| 100 | struct exec file_hdr; |
| 101 | struct nlist *symbol_table; |
| 102 | int size; |
| 103 | char *strings; |
| 104 | |
| 105 | f = open (file, O_RDONLY); |
| 106 | if (f < 0) |
| 107 | err ("Error opening %s: %s\n", file, strerror (errno)); |
| 108 | if (read (f, &file_hdr, sizeof (file_hdr)) < 0) |
| 109 | err ("Error reading exec structure: %s\n", strerror (errno)); |
| 110 | if (N_BADMAG (file_hdr)) |
| 111 | err ("File %s not an a.out file\n", file); |
| 112 | |
| 113 | /* read in symbol table */ |
| 114 | if ((symbol_table = (struct nlist *)malloc (file_hdr.a_syms)) == 0) |
| 115 | err ("Couldn't allocate space for symbol table\n"); |
| 116 | if (lseek (f, N_SYMOFF (file_hdr), 0) == -1) |
| 117 | err ("lseek error: %s\n", strerror (errno)); |
| 118 | if (read (f, symbol_table, file_hdr.a_syms) == -1) |
| 119 | err ("Error reading symbol table from %s: %s\n", file, |
| 120 | strerror (errno)); |
| 121 | |
| 122 | /* read in string table */ |
| 123 | if (read (f, &size, 4) == -1) |
| 124 | err ("reading string table size: %s\n", strerror (errno)); |
| 125 | if ((strings = (char *)malloc (size)) == 0) |
| 126 | err ("Couldn't allocate memory for string table\n"); |
| 127 | if (read (f, strings, size - 4) == -1) |
| 128 | err ("reading string table: %s\n", strerror (errno)); |
| 129 | |
| 130 | /* Find the core address at which the first byte of kdb text segment |
| 131 | should be loaded into core when kdb is run. */ |
| 132 | origin = find_symbol ("_etext", symbol_table, file_hdr.a_syms, strings) |
| 133 | - file_hdr.a_text; |
| 134 | /* Find the core address at which the heap will appear. */ |
| 135 | coreaddr = find_symbol (sym_name, symbol_table, file_hdr.a_syms, strings); |
| 136 | /* Return address in file of the heap data space. */ |
| 137 | return (N_TXTOFF (file_hdr) + core_addr - origin); |
| 138 | } |
| 139 | |
| 140 | find_symbol (sym_name, symbol_table, length, strings) |
| 141 | char *sym_name; |
| 142 | struct nlist *symbol_table; |
| 143 | int length; |
| 144 | char *strings; |
| 145 | { |
| 146 | register struct nlist *sym; |
| 147 | |
| 148 | /* Find symbol in question */ |
| 149 | for (sym = symbol_table; |
| 150 | sym != (struct nlist *)((char *)symbol_table + length); |
| 151 | sym++) |
| 152 | { |
| 153 | if ((sym->n_type & N_TYPE) != N_DATA) continue; |
| 154 | if (sym->n_un.n_strx == 0) continue; |
| 155 | if (STREQ (sym_name, strings + sym->n_un.n_strx - 4)) |
| 156 | return sym->n_value; |
| 157 | } |
| 158 | err ("Data symbol %s not found in %s\n", sym_name, file); |
| 159 | } |
| 160 | |
| 161 | /* VARARGS */ |
| 162 | void |
| 163 | err (va_alist) |
| 164 | va_dcl |
| 165 | { |
| 166 | va_list args; |
| 167 | char *string; |
| 168 | |
| 169 | va_start (args); |
| 170 | string = va_arg (args, char *); |
| 171 | vfprintf (gdb_stderr, string, args); |
| 172 | va_end (args); |
| 173 | exit (-1); |
| 174 | } |