summaryrefslogtreecommitdiff
path: root/sys/arch/amiga/stand/binpatch
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/amiga/stand/binpatch
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/amiga/stand/binpatch')
-rw-r--r--sys/arch/amiga/stand/binpatch/Makefile9
-rw-r--r--sys/arch/amiga/stand/binpatch/binpatch.896
-rw-r--r--sys/arch/amiga/stand/binpatch/binpatch.c419
3 files changed, 524 insertions, 0 deletions
diff --git a/sys/arch/amiga/stand/binpatch/Makefile b/sys/arch/amiga/stand/binpatch/Makefile
new file mode 100644
index 00000000000..68515d25505
--- /dev/null
+++ b/sys/arch/amiga/stand/binpatch/Makefile
@@ -0,0 +1,9 @@
+# $NetBSD: Makefile,v 1.4 1994/12/22 10:47:08 cgd Exp $
+
+PROG=binpatch
+MAN=binpatch.8
+
+BINDIR=/sbin
+LDFLAGS+=-static
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/amiga/stand/binpatch/binpatch.8 b/sys/arch/amiga/stand/binpatch/binpatch.8
new file mode 100644
index 00000000000..935f010b7c6
--- /dev/null
+++ b/sys/arch/amiga/stand/binpatch/binpatch.8
@@ -0,0 +1,96 @@
+.\" $NetBSD: binpatch.8,v 1.3 1994/10/26 02:06:54 cgd Exp $
+.\"
+.\" Copyright (c) 1994 Christian E. Hopps
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Christian E. Hopps.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd February 2, 1994
+.Dt BINPATCH 8 amiga
+.Os
+.Sh NAME
+.Nm binpatch
+.Nd examine and or modify initialized data in a binary file.
+.Sh SYNOPSIS
+.Nm binpatch
+.Op Fl b | Fl w | Fl l
+.Op Fl o Ar offset
+.Fl s Ar symname
+.Op Fl r Ar value
+.Ar binfile
+.Nm binpatch
+.Op Fl b | Fl w | Fl l
+.Op Fl o Ar offset
+.Fl a Ar addr
+.Op Fl r Ar value
+.Ar binfile
+.Sh DESCRIPTION
+.Nm binpatch
+is used to modify or examine the data associated with a symbol in a binary
+file
+.Ar binfile .
+The flags
+.Fl b ,
+.Fl w
+and
+.Fl l
+specify the size of the data to be modified or examined
+(byte, word and long respectively.) The
+.Ar binfile
+is scanned in search of the symbol
+.Ar symname
+(specified with the
+.Fl s
+flag)
+If the symbol is found the current data and address are printed. Next if the
+.Fl r
+flag has been given, the current data is replaced with that of
+.Ar value .
+.Pp
+If the second form is used the address
+.Ar addr
+specified with the
+.Fl a
+flag is used as a direct address into the data section of the binary and
+no symbol search is performed.
+.Pp
+The
+.Fl o
+flag specifies an offset in byte, word or long (
+.Fl b
+,
+.Fl w
+,
+or
+.Fl l
+) units from the given locator (
+.Fl s
+or
+.Fl a
+) for
+.Nm binpatch
+to perform it's described actions.
+
diff --git a/sys/arch/amiga/stand/binpatch/binpatch.c b/sys/arch/amiga/stand/binpatch/binpatch.c
new file mode 100644
index 00000000000..300bdfe3bef
--- /dev/null
+++ b/sys/arch/amiga/stand/binpatch/binpatch.c
@@ -0,0 +1,419 @@
+/* $NetBSD: binpatch.c,v 1.6 1995/08/18 15:28:28 chopps Exp $ */
+
+/* Author: Markus Wild mw@eunet.ch ??? */
+/* Modified: Rob Leland leland@mitre.org */
+
+#include <sys/types.h>
+#include <a.out.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __NetBSD__
+/*
+ * assume NMAGIC files are linked at 0 (for kernel)
+ */
+#undef N_TXTADDR
+#define N_TXTADDR(ex) \
+ ((N_GETMAGIC2(ex) == (ZMAGIC|0x10000) || N_GETMAGIC2(ex) == NMAGIC) ? \
+ 0 : __LDPGSZ)
+#endif
+
+
+static char synusage[] = "
+NAME
+\t%s - Allows the patching of BSD binaries
+SYNOPSIS
+\t%s [-HELP]
+\t%s [-b|-w|-l] -s symbol[[[index]][=value]] binary
+\t%s [-b|-w|-l] [-o offset] -s symbol [-r value] binary
+\t%s [-b|-w|-l] [-o offset] -a address [-r value] binary
+";
+static char desusage[] = "DESCRIPTION
+\tAllows the patching of BSD binaries, for example,a distributed
+\tkernel. Recient additions allows the user to index into an array
+\tand assign a value. Binpatch has internal variables to allow
+\tyou to test it on itself under NetBSD.
+OPTIONS
+\t-a patch variable by specifying address in hex
+\t-b symbol or address to be patched is 1 byte
+\t-l symbol or address to be patched is 4 bytes (default)
+\t-o offset to begin patching value relative to symbol or address
+\t-r replace value, and print out previous value to stdout
+\t-s patch variable by specifying symbol name. Use '[]'
+\t to specify the 'index'. If '-b, -w or -l' not specified
+\t then index value is used like an offset. Also can use '='
+\t to assign value
+\t-w symbol or address to be patched is 2 bytes
+EXAMPLES
+\tThis should print 100 (this is a nice reality check...)
+\t\tbinpatch -l -s _hz netbsd
+\tNow it gets more advanced, replace the value:
+\t\tbinpatch -l -s _sbic_debug -r 1 netbsd
+\tNow patch a variable at a given 'index' not offset,
+\tunder NetBSD you must use '', under AmigaDos CLI '' is optional.:
+\t\tbinpatch -w -s '_vieww[4]' -r 0 a.out
+\tsame as
+\t\tbinpatch -w -o 8 -s _vieww -r 0 a.out
+\tAnother example of using []
+\t\tbinpatch -s '_viewl[4]' -r 0 a.out
+\tsame as
+\t\tbinpatch -o 4 -s _viewl -r 0 a.out
+\tOne last example using '=' and []
+\t\tbinpatch -w -s '_vieww[4]=2' a.out
+\tSo if the kernel is not finding your drives, you could enable
+\tall available debugging options, helping to shed light on that problem.
+\t\tbinpatch -l -s _sbic_debug -r 1 netbsd scsi-level
+\t\tbinpatch -l -s _sddebug -r 1 netbsd sd-level (disk-driver)
+\t\tbinpatch -l -s _acdebug -r 1 netbsd autoconfig-level
+SEE ALSO
+\tbinpatch.c binpatch(1)
+";
+
+extern char *optarg;
+extern int optind;
+
+volatile void error (char *);
+static void Synopsis(char *program_name);
+static void Usage(char *program_name);
+static u_long FindAssign(char *symbol,u_long *rvalue);
+static void FindOffset(char *symbol,u_long *index);
+
+/* The following variables are so binpatch can be tested on itself */
+int test = 1;
+int testbss;
+char foo = 23;
+char viewb[10] = {0,0,1,0,1,1,0,1,1,1};
+short vieww[10] = {0,0,1,0,1,1,0,1,1,1};
+long viewl[10] = {0,0,1,0,1,1,0,1,1,1};
+/* End of test binpatch variables */
+int
+main(int argc, char *argv[])
+{
+ struct exec e;
+ int c;
+ u_long addr = 0, offset = 0;
+ u_long index = 0;/* Related to offset */
+ u_long replace = 0, do_replace = 0;
+ char *symbol = 0;
+ char size = 4; /* default to long */
+ char size_opt = 0; /* Flag to say size option was set, used with index */
+ char *fname;
+ char *pgname = argv[0]; /* Program name */
+ int fd;
+ int type, off;
+ u_long lval;
+ u_short sval;
+ u_char cval;
+
+
+ while ((c = getopt (argc, argv, "H:a:bwlr:s:o:")) != EOF)
+ switch (c)
+ {
+ case 'H':
+ Usage(argv[0]);
+ break;
+ case 'a':
+ if (addr || symbol)
+ error ("only one address/symbol allowed");
+ if (! strncmp (optarg, "0x", 2))
+ sscanf (optarg, "%x", &addr);
+ else
+ addr = atoi (optarg);
+ if (! addr)
+ error ("invalid address");
+ break;
+
+ case 'b':
+ size = 1;
+ size_opt = 1;
+ break;
+
+ case 'w':
+ size = 2;
+ size_opt = 1;
+ break;
+
+ case 'l':
+ size = 4;
+ size_opt = 1;
+ break;
+
+ case 'r':
+ do_replace = 1;
+ if (! strncmp (optarg, "0x", 2))
+ sscanf (optarg, "%x", &replace);
+ else
+ replace = atoi (optarg);
+ break;
+
+ case 's':
+ if (addr || symbol)
+ error ("only one address/symbol allowed");
+ symbol = optarg;
+ break;
+
+ case 'o':
+ if (offset)
+ error ("only one offset allowed");
+ if (! strncmp (optarg, "0x", 2))
+ sscanf (optarg, "%x", &offset);
+ else
+ offset = atoi (optarg);
+ break;
+ }/* while switch() */
+
+ if (argc > 1)
+ {
+ if (addr || symbol)
+ {
+ argv += optind;
+ argc -= optind;
+
+ if (argc < 1)
+ error ("No file to patch.");
+
+ fname = argv[0];
+ if ((fd = open (fname, 0)) < 0)
+ error ("Can't open file");
+
+ if (read (fd, &e, sizeof (e)) != sizeof (e)
+ || N_BADMAG (e))
+ error ("Not a valid executable.");
+
+ /* fake mid, so the N_ macros work on the amiga.. */
+ e.a_midmag |= 127 << 16;
+
+ if (symbol)
+ {
+ struct nlist nl[2];
+ if (offset == 0)
+ {
+ u_long new_do_replace = 0;
+ new_do_replace = FindAssign(symbol,&replace);
+ if (new_do_replace && do_replace)
+ error("Cannot use both '=' and '-r' option!");
+ FindOffset(symbol,&index);
+ if (size_opt)
+ offset = index*size; /* Treat like an index */
+ else
+ offset = index; /* Treat index like an offset */
+ if (new_do_replace)
+ do_replace = new_do_replace;
+ }
+ nl[0].n_un.n_name = symbol;
+ nl[1].n_un.n_name = 0;
+ if (nlist (fname, nl) != 0)
+ {
+ fprintf(stderr,"Symbol is %s ",symbol);
+ error ("Symbol not found.");
+ }
+ addr = nl[0].n_value;
+ type = nl[0].n_type & N_TYPE;
+ }
+ else
+ {
+ type = N_UNDF;
+ if (addr >= N_TXTADDR(e) && addr < N_DATADDR(e))
+ type = N_TEXT;
+ else if (addr >= N_DATADDR(e) && addr < N_DATADDR(e) + e.a_data)
+ type = N_DATA;
+ }
+ addr += offset;
+
+ /* if replace-mode, have to reopen the file for writing.
+ Can't do that from the beginning, or nlist() will not
+ work (at least not under AmigaDOS) */
+ if (do_replace)
+ {
+ close (fd);
+ if ((fd = open (fname, 2)) == -1)
+ error ("Can't reopen file for writing.");
+ }
+
+ if (type != N_TEXT && type != N_DATA)
+ error ("address/symbol is not in text or data section.");
+
+ if (type == N_TEXT)
+ off = addr - N_TXTADDR(e) + N_TXTOFF(e);
+ else
+ off = addr - N_DATADDR(e) + N_DATOFF(e);
+
+ if (lseek (fd, off, 0) == -1)
+ error ("lseek");
+
+ /* not beautiful, but works on big and little endian machines */
+ switch (size)
+ {
+ case 1:
+ if (read (fd, &cval, 1) != 1)
+ error ("cread");
+ lval = cval;
+ break;
+
+ case 2:
+ if (read (fd, &sval, 2) != 2)
+ error ("sread");
+ lval = sval;
+ break;
+
+ case 4:
+ if (read (fd, &lval, 4) != 4)
+ error ("lread");
+ break;
+ }/* switch size */
+
+
+ if (symbol)
+ printf ("%s(0x%x): %d (0x%x)\n", symbol, addr, lval, lval);
+ else
+ printf ("0x%x: %d (0x%x)\n", addr, lval, lval);
+
+ if (do_replace)
+ {
+ if (lseek (fd, off, 0) == -1)
+ error ("write-lseek");
+ switch (size)
+ {
+ case 1:
+ cval = replace;
+ if (cval != replace)
+ error ("byte-value overflow.");
+ if (write (fd, &cval, 1) != 1)
+ error ("cwrite");
+ break;
+
+ case 2:
+ sval = replace;
+ if (sval != replace)
+ error ("word-value overflow.");
+ if (write (fd, &sval, 2) != 2)
+ error ("swrite");
+ break;
+
+ case 4:
+ if (write (fd, &replace, 4) != 4)
+ error ("lwrite");
+ break;
+ }/* switch(size) */
+ }/* if (do_replace) */
+
+ close (fd);
+ }/* if(addr || symbol ) */
+ else
+ {
+ error("Must specify either address or symbol.");
+ }
+ }/* if argc < 1 */
+ else
+ {
+ Synopsis(pgname);
+ }
+ return(0);
+}/* main () */
+
+
+
+volatile void error (char *str)
+{
+ fprintf (stderr, "%s\n", str);
+ exit (1);
+}
+
+/* Give user very short help to avoid scrolling screen much */
+static void Synopsis(char *pgname)
+{
+ fprintf(stdout,synusage,pgname,pgname,pgname,pgname,pgname);
+}
+
+
+static void Usage(char *pgname)
+{
+ Synopsis(pgname);
+ fprintf(stdout,desusage);
+ exit(0);
+}
+
+
+/* FindOffset() - Determine if there is an offset, -or- index
+ embedded in the symbol.
+ If there is, return it, and truncate symbol to
+ exclude the [...].
+ Example: If view is declared as short view[10],
+ and we want to index the 3rd. element.
+ which is offset = (3 -1)*sizeof(short) =4.
+ we would use view[4], which becomes view,4.
+ The was the code is implemented the [value] is
+ treated as a index if-and-only-if a '-b -w -l' option
+ was given. Otherwise it is treated like an offset.
+ See above documentation in for of help!
+*/
+static void FindOffset(char *symbol,u_long *index)
+{
+ char *sb=strchr(symbol,'['); /* Start of '[', now line must
+ contain matching']' */
+ char *eb=strchr(symbol,']'); /* End of ']' */
+ short sz=strlen(symbol); /* symbol size */
+ if (sb)
+ {
+ if (eb && (eb > sb))
+ {
+ if ((eb - symbol) == (sz - 1))
+ {
+ char *sindex; /* Start of index */
+ u_long newindex = 0;
+ /* In the future we could get fancy and parse the
+ sindex string for mathmatical expressions like:
+ (3 - 1)*2 = 4 from above example,
+ ugh forget I mentioned ot :-) !
+ */
+ sindex = sb + 1;
+ *eb = '\0';
+ newindex = (u_long)atoi(sindex);
+ if (*index == 0)
+ {
+ *index = newindex;
+ *sb = '\0'; /* Make _view[3] look like _view */
+ }
+ else
+ fprintf(stderr,"Error index can only be specified once!\n");
+ }
+ else
+ {
+ fprintf(stderr,"Error: Garbage trailing ']'\n");
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Error ']' in symbol before '[' !\n");
+ }
+ }/* if sb != 0 */
+}/* FindOffset */
+
+/* FindAssign : Scans symbol name for an '=number' strips it off
+ of the symbol and proceeds.
+*/
+static u_long FindAssign(char *symbol,u_long *rvalue)
+{
+ char *ce = rindex(symbol,'='); /* Assign symbol some number */
+ char *cn = ce + 1; /* This should point at some number, no spaces allowed */
+ u_long dr = 0; /* flag for do_replace */
+ if (ce)
+ {
+ int nscan; /* number of variaables scanned in */
+ /* get the number to assign to symbol and strip off = */
+ for (cn=ce + 1;((*cn==' ')&&(*cn!='\0'));cn++)
+ ;
+ if (! strncmp (cn, "0x", 2))
+ nscan = sscanf (cn, "%x",rvalue);
+ else
+ nscan = sscanf(cn,"%d",rvalue);
+ if (nscan != 1)
+ error("Invalid value following '='");
+ dr = 1;
+ *ce = '\0';/* Now were left with just symbol */
+ }/* if (ce) */
+ return(dr);
+}/* FindAssign */