pkgsrc-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[pkgsrc/trunk]: pkgsrc/pkgtools/binpatch A small package to arbitrary tiny pa...



details:   https://anonhg.NetBSD.org/pkgsrc/rev/d466a07b0ac1
branches:  trunk
changeset: 478389:d466a07b0ac1
user:      atatat <atatat%pkgsrc.org@localhost>
date:      Fri Jul 23 03:37:26 2004 +0000

description:
A small package to arbitrary tiny patches to binaries (where the
source cannot otherwise be patched).

diffstat:

 pkgtools/binpatch/DESCR            |    2 +
 pkgtools/binpatch/Makefile         |   31 ++++++
 pkgtools/binpatch/PLIST            |    3 +
 pkgtools/binpatch/files/binpatch.1 |  116 ++++++++++++++++++++++++
 pkgtools/binpatch/files/binpatch.c |  174 +++++++++++++++++++++++++++++++++++++
 5 files changed, 326 insertions(+), 0 deletions(-)

diffs (truncated from 346 to 300 lines):

diff -r 86eb9c6f0ba3 -r d466a07b0ac1 pkgtools/binpatch/DESCR
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/pkgtools/binpatch/DESCR   Fri Jul 23 03:37:26 2004 +0000
@@ -0,0 +1,2 @@
+Apply small, arbitrary binary patches using an arcane command line
+syntax.
diff -r 86eb9c6f0ba3 -r d466a07b0ac1 pkgtools/binpatch/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/pkgtools/binpatch/Makefile        Fri Jul 23 03:37:26 2004 +0000
@@ -0,0 +1,31 @@
+# $NetBSD: Makefile,v 1.1.1.1 2004/07/23 03:37:26 atatat Exp $
+#
+
+DISTNAME=      binpatch-1.0
+CATEGORIES=    pkgtools
+MASTER_SITES=  # empty
+DISTFILES=     # empty
+
+MAINTAINER=    atatat%NetBSD.org@localhost
+HOMEPAGE=      ftp://ftp.NetBSD.org/pub/NetBSD/packages/pkgsrc/Packages.txt
+COMMENT=       Trivial binary patch applicator
+
+USE_BUILDLINK3=        yes
+
+NO_CHECKSUM=   # defined
+
+.include "../../mk/bsd.prefs.mk"
+
+do-extract:
+       @${CP} -Rp ${FILESDIR} ${WRKSRC}
+
+do-build:
+       @(cd ${WRKSRC}; \
+         ${ECHO} "${CC} -o binpatch binpatch.c"; \
+         ${CC} -o binpatch binpatch.c )
+
+do-install:
+       ${INSTALL_PROGRAM} ${WRKSRC}/binpatch ${PREFIX}/bin/binpatch
+       ${INSTALL_MAN} ${WRKSRC}/binpatch.1 ${PREFIX}/man/man1
+
+.include "../../mk/bsd.pkg.mk"
diff -r 86eb9c6f0ba3 -r d466a07b0ac1 pkgtools/binpatch/PLIST
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/pkgtools/binpatch/PLIST   Fri Jul 23 03:37:26 2004 +0000
@@ -0,0 +1,3 @@
+@comment $NetBSD: PLIST,v 1.1.1.1 2004/07/23 03:37:26 atatat Exp $
+bin/binpatch
+man/man1/binpatch.1
diff -r 86eb9c6f0ba3 -r d466a07b0ac1 pkgtools/binpatch/files/binpatch.1
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/pkgtools/binpatch/files/binpatch.1        Fri Jul 23 03:37:26 2004 +0000
@@ -0,0 +1,116 @@
+.\"    $NetBSD: binpatch.1,v 1.1.1.1 2004/07/23 03:37:26 atatat Exp $
+.\"
+.\" Copyright (c) 2004 by Andrew Brown <atatat%netbsd.org@localhost>
+.\" Absolutely no warranty.
+.\"
+.Dd July 20, 2004
+.Dt BINPATCH 1
+.Sh NAME
+.Nm binpatch
+.Nd trivial binary patch applicator
+.Sh SYNOPSIS
+.Nm
+.Pa file=...
+.Pa size=...
+.Pa offset=...
+.Pa compare=...
+.Pa skip=...
+.Pa replace=...
+.Sh DESCRIPTION
+The
+.Nm
+utility can read and replace a small section of a given file.
+It is designed for use in those instances where a problem exists with
+a given binary that cannot be reconstructed from source code, but the
+required change can be implemented by replacing a few bytes in the
+existing binary.
+All arguments must be given.
+.Sh EXAMPLES
+Given a binary called
+.Dq a.out
+of 10713 bytes in size with the following text segment:
+.Bd -literal -offset indent
+% objdump -h a.out
+.sp
+a.out:     file format elf32-i386
+.sp
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+[...]
+  9 .text         00000be4  08048968  08048968  00000968  2**2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+[...]
+% objdump -d -j .text a.out
+[...]
+ 8048b0f:       83 ef 04                sub    $0x4,%edi
+ 8048b12:       ff d0                   call   *%eax
+ 8048b14:       83 fe ff                cmp    $0xffffffff,%esi
+[...]
+.sp
+.Ed
+where we wish to elide the call through
+.Ar %eax
+by replacing it with a series of
+.Ar nop
+(or
+.Dq no operation )
+instructions (the machine code for this on the i386 platform is 0x90),
+we first calculate the offset into the file of the previous
+.Ar sub
+instruction.  To do this, we take the address of the
+.Ar sub
+instruction as given by the dissassembly output, subtract the
+.Dq LMA
+and add the
+.Dq File off
+values from the objdump output (note that
+.Xr bc 1
+expects hexadecimal values to be given using upper case):
+.Bd -literal -offset indent
+% bc
+ibase=16
+8048B0F-08048968+00000968
+2831
+.sp
+.Ed
+The region of the binary we want to compare to before applying the
+patch is the concatenation of the relevant machine codes from the
+dissassembly dump (\c
+.Ar 83ef04ffd083feff )
+and the replacement is simply two
+.Ar nop
+instructions (\c
+.Ar 9090 ) ,
+that will replace the
+.Ar ffd0
+of the original call.
+The offset of the replacement is 3, since that is the number of bytes
+in the
+.Ar sub
+instruction.
+From this we have our patch:
+.Bd -literal -offset indent
+% binpatch file=a.out size=10713 offset=2831 \\
+  compare=83ef04ffd083feff skip=3 replace=9090
+% objdump -d -j .text a.out
+[...]
+ 8048b0f:       83 ef 04                sub    $0x4,%edi
+ 8048b12:       90                      nop    
+ 8048b13:       90                      nop    
+ 8048b14:       83 fe ff                cmp    $0xffffffff,%esi
+[...]
+.sp
+.Ed
+And thus the call is removed.
+.Sh DIAGNOSTICS
+The diagnostics are terse and almost unhelpful, but are more verbose
+than users of
+.Xr ed 1
+might be used to.
+They typically mention the command line argument that was in error.
+.Sh SEE ALSO
+.Xr bc 1 ,
+.Xr objdump 1 ,
+.Xr patch 1
+.Sh AUTHORS
+.An Andrew Brown Aq atatat%netbsd.org@localhost
diff -r 86eb9c6f0ba3 -r d466a07b0ac1 pkgtools/binpatch/files/binpatch.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/pkgtools/binpatch/files/binpatch.c        Fri Jul 23 03:37:26 2004 +0000
@@ -0,0 +1,174 @@
+/*      $NetBSD: binpatch.c,v 1.1.1.1 2004/07/23 03:37:26 atatat Exp $ */
+
+/*
+ * ------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Andrew Brown <atatat%NetBSD.org@localhost> wrote this file.  As long as you
+ * retain this notice you can do whatever you want with this stuff.
+ * If we meet some day, and you think this stuff is worth it, you can
+ * buy me a beer in return.
+ * ------------------------------------------------------------------------
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int
+die(int rc, const char *msg)
+{
+       if (rc)
+               perror(msg);
+       else
+               fprintf(stderr, "%s\n", msg);
+       exit(1);
+}
+
+static void
+cvt(const char *s, const char *i, unsigned char *o, size_t l)
+{
+       int t, x;
+
+       for (t = 0; t < l; t++) {
+               x = i[2 * t];
+               if (x >= '0' && x <= '9')
+                       x -= '0';
+               else if (x >= 'a' && x <= 'f')
+                       x -= 'a' - 10;
+               else if (x >= 'A' && x <= 'F')
+                       x -= 'A' - 10;
+               else
+                       die(0, s);
+               o[t] = x * 16;
+
+               x = i[2 * t + 1];
+               if (x >= '0' && x <= '9')
+                       x -= '0';
+               else if (x >= 'a' && x <= 'f')
+                       x -= 'a' - 10;
+               else if (x >= 'A' && x <= 'F')
+                       x -= 'A' - 10;
+               else
+                       die(0, s);
+               o[t] += x;
+       }
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct stat st;
+       char *key, *value;
+       int f, i;
+       unsigned char *buf, *get, *put;
+       size_t lget, lput;
+       off_t sz, cmp_off, skip_off;
+
+       f = -1;
+       get = put = NULL;
+       lget = lput = 0;
+       sz = cmp_off = skip_off = -1;
+
+       while (--argc > 0) {
+               key = *++argv;
+               if ((value = strchr(key, '=')) == NULL)
+                       die(0, "value required");
+               else
+                       *value++ = '\0';
+
+               if (strcmp(key, "file") == 0) {
+                       f = open(value, O_RDWR);
+                       if (f == -1)
+                               die(1, "file");
+               }
+               else if (strcmp(key, "size") == 0) {
+                       char *t;
+                       errno = 0;
+                       sz = strtol(value, &t, 0);
+                       if (errno != 0)
+                               die(1, "size");
+               }
+               else if (strcmp(key, "offset") == 0) {
+                       char *t;
+                       errno = 0;
+                       cmp_off = strtol(value, &t, 0);
+                       if (errno != 0)
+                               die(1, "offset");
+               }
+               else if (strcmp(key, "compare") == 0) {
+                       lget = strlen(value);
+                       if (lget % 2 != 0)
+                               die(0, "compare");
+                       lget /= 2;
+                       get = malloc(lget);
+                       buf = malloc(lget);
+                       cvt("compare", value, get, lget);
+               }
+               else if (strcmp(key, "skip") == 0) {
+                       char *t;
+                       errno = 0;
+                       skip_off = strtol(value, &t, 0);
+                       if (errno != 0)
+                               die(1, "offset");
+               }
+               else if (strcmp(key, "replace") == 0) {
+                       lput = strlen(value);
+                       if (lput % 2 != 0)
+                               die(0, "replace");
+                       lput /= 2;
+                       put = malloc(lput);
+                       cvt("replace", value, put, lput);
+               }
+       }
+



Home | Main Index | Thread Index | Old Index