diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f7576ff..8b9803c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -22,7 +22,7 @@ jobs:
./.scripts/install-freemint.sh mintlib
- name: Setup environment
env:
- PROJECT_VERSION: "0.3"
+ PROJECT_VERSION: "0.4"
run: ./.scripts/setup_env.sh
- name: build
run: ./.scripts/build.sh
diff --git a/.gitignore b/.gitignore
index a764971..b29d24f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ src/flags
src/mintbin
src/stack
src/symex
+src/stripex
stamp-*
.deps
*.o
diff --git a/configure b/configure
index 5fc95cd..a4a0a90 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for mintbin 0.3.
+# Generated by GNU Autoconf 2.71 for mintbin 0.4.
#
# Report bugs to .
#
@@ -611,8 +611,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='mintbin'
PACKAGE_TARNAME='mintbin'
-PACKAGE_VERSION='0.3'
-PACKAGE_STRING='mintbin 0.3'
+PACKAGE_VERSION='0.4'
+PACKAGE_STRING='mintbin 0.4'
PACKAGE_BUGREPORT='https://github.com/freemint/mintbin/issues/'
PACKAGE_URL='https://github.com/freemint/mintbin/'
@@ -1344,7 +1344,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures mintbin 0.3 to adapt to many kinds of systems.
+\`configure' configures mintbin 0.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1415,7 +1415,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of mintbin 0.3:";;
+ short | recursive ) echo "Configuration of mintbin 0.4:";;
esac
cat <<\_ACEOF
@@ -1517,7 +1517,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-mintbin configure 0.3
+mintbin configure 0.4
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1835,7 +1835,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by mintbin $as_me 0.3, which was
+It was created by mintbin $as_me 0.4, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -3190,7 +3190,7 @@ fi
# Define the identity of the package.
PACKAGE='mintbin'
- VERSION='0.3'
+ VERSION='0.4'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -7950,7 +7950,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by mintbin $as_me 0.3, which was
+This file was extended by mintbin $as_me 0.4, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -8023,7 +8023,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
-mintbin config.status 0.3
+mintbin config.status 0.4
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
diff --git a/configure.in b/configure.in
index 2c9f45b..da2bd9e 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script.
-AC_INIT(mintbin, 0.3, [https://github.com/freemint/mintbin/issues/],,[https://github.com/freemint/mintbin/])
+AC_INIT(mintbin, 0.4, [https://github.com/freemint/mintbin/issues/],,[https://github.com/freemint/mintbin/])
AC_CONFIG_SRCDIR(src/mintbin.c)
AC_CANONICAL_HOST
AM_CONFIG_HEADER(config.h)
diff --git a/src/Makefile.am b/src/Makefile.am
index 8eed9ea..1d93ced 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,7 +17,7 @@ LIBS = $(INTLLIBS) @LIBS@
noinst_HEADERS = exec.h symbols.h targets.h ar.h
-bin_PROGRAMS = arconv cnm csize cstrip flags mintbin stack symex
+bin_PROGRAMS = arconv cnm csize cstrip flags mintbin stack symex stripex
arconv_SOURCES = arconv.c targets.c version.c
cnm_SOURCES = cnm.c symbols.c targets.c version.c
@@ -27,6 +27,7 @@ flags_SOURCES = flags.c targets.c version.c
mintbin_SOURCES = mintbin.c targets.c version.c
stack_SOURCES = stack.c symbols.c targets.c version.c
symex_SOURCES = symex.c targets.c version.c
+stripex_SOURCES = stripex.c
install-exec-local:
@$(NORMAL_INSTALL)
diff --git a/src/Makefile.in b/src/Makefile.in
index 457c889..a33c1d6 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -93,7 +93,7 @@ build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = arconv$(EXEEXT) cnm$(EXEEXT) csize$(EXEEXT) \
cstrip$(EXEEXT) flags$(EXEEXT) mintbin$(EXEEXT) stack$(EXEEXT) \
- symex$(EXEEXT)
+ symex$(EXEEXT) stripex$(EXEEXT)
subdir = src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
@@ -142,6 +142,10 @@ am_stack_OBJECTS = stack.$(OBJEXT) symbols.$(OBJEXT) targets.$(OBJEXT) \
stack_OBJECTS = $(am_stack_OBJECTS)
stack_LDADD = $(LDADD)
stack_DEPENDENCIES = ../lib/libmb.a
+am_stripex_OBJECTS = stripex.$(OBJEXT)
+stripex_OBJECTS = $(am_stripex_OBJECTS)
+stripex_LDADD = $(LDADD)
+stripex_DEPENDENCIES = ../lib/libmb.a
am_symex_OBJECTS = symex.$(OBJEXT) targets.$(OBJEXT) version.$(OBJEXT)
symex_OBJECTS = $(am_symex_OBJECTS)
symex_LDADD = $(LDADD)
@@ -164,9 +168,10 @@ am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/arconv.Po ./$(DEPDIR)/cnm.Po \
./$(DEPDIR)/csize.Po ./$(DEPDIR)/cstrip.Po \
./$(DEPDIR)/flags.Po ./$(DEPDIR)/mintbin.Po \
- ./$(DEPDIR)/stack.Po ./$(DEPDIR)/symbols.Po \
- ./$(DEPDIR)/symex.Po ./$(DEPDIR)/targets.Po \
- ./$(DEPDIR)/tempname.Po ./$(DEPDIR)/version.Po
+ ./$(DEPDIR)/stack.Po ./$(DEPDIR)/stripex.Po \
+ ./$(DEPDIR)/symbols.Po ./$(DEPDIR)/symex.Po \
+ ./$(DEPDIR)/targets.Po ./$(DEPDIR)/tempname.Po \
+ ./$(DEPDIR)/version.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -182,10 +187,10 @@ am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(arconv_SOURCES) $(cnm_SOURCES) $(csize_SOURCES) \
$(cstrip_SOURCES) $(flags_SOURCES) $(mintbin_SOURCES) \
- $(stack_SOURCES) $(symex_SOURCES)
+ $(stack_SOURCES) $(stripex_SOURCES) $(symex_SOURCES)
DIST_SOURCES = $(arconv_SOURCES) $(cnm_SOURCES) $(csize_SOURCES) \
$(cstrip_SOURCES) $(flags_SOURCES) $(mintbin_SOURCES) \
- $(stack_SOURCES) $(symex_SOURCES)
+ $(stack_SOURCES) $(stripex_SOURCES) $(symex_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -350,6 +355,7 @@ flags_SOURCES = flags.c targets.c version.c
mintbin_SOURCES = mintbin.c targets.c version.c
stack_SOURCES = stack.c symbols.c targets.c version.c
symex_SOURCES = symex.c targets.c version.c
+stripex_SOURCES = stripex.c
all: all-am
.SUFFIXES:
@@ -470,6 +476,10 @@ stack$(EXEEXT): $(stack_OBJECTS) $(stack_DEPENDENCIES) $(EXTRA_stack_DEPENDENCIE
@rm -f stack$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(stack_OBJECTS) $(stack_LDADD) $(LIBS)
+stripex$(EXEEXT): $(stripex_OBJECTS) $(stripex_DEPENDENCIES) $(EXTRA_stripex_DEPENDENCIES)
+ @rm -f stripex$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(stripex_OBJECTS) $(stripex_LDADD) $(LIBS)
+
symex$(EXEEXT): $(symex_OBJECTS) $(symex_DEPENDENCIES) $(EXTRA_symex_DEPENDENCIES)
@rm -f symex$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(symex_OBJECTS) $(symex_LDADD) $(LIBS)
@@ -487,6 +497,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flags.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mintbin.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stripex.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbols.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symex.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/targets.Po@am__quote@ # am--include-marker
@@ -646,6 +657,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/flags.Po
-rm -f ./$(DEPDIR)/mintbin.Po
-rm -f ./$(DEPDIR)/stack.Po
+ -rm -f ./$(DEPDIR)/stripex.Po
-rm -f ./$(DEPDIR)/symbols.Po
-rm -f ./$(DEPDIR)/symex.Po
-rm -f ./$(DEPDIR)/targets.Po
@@ -703,6 +715,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/flags.Po
-rm -f ./$(DEPDIR)/mintbin.Po
-rm -f ./$(DEPDIR)/stack.Po
+ -rm -f ./$(DEPDIR)/stripex.Po
-rm -f ./$(DEPDIR)/symbols.Po
-rm -f ./$(DEPDIR)/symex.Po
-rm -f ./$(DEPDIR)/targets.Po
diff --git a/src/stripex.c b/src/stripex.c
new file mode 100644
index 0000000..8cf2446
--- /dev/null
+++ b/src/stripex.c
@@ -0,0 +1,684 @@
+/*
+ * stripex.c
+ * strip symbol table, GNU binutils aexec header, and ELF headers from TOS executables.
+ * Needed e.g. for SLB shared library files or CPX modules to get the header back
+ * to the start of the text segment.
+ *
+ * BUGS:
+ * - relocation table is not checked for validity. If it is corrupted,
+ * this program might crash and/or create corrupted output files.
+ * Should rarely be a problem, since the kernel does not check the table either.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef O_BINARY
+# ifdef _O_BINARY
+# define O_BINARY _O_BINARY
+# else
+# define O_BINARY 0
+# endif
+#endif
+
+#define NEWBUFSIZ 16384L
+
+static unsigned char mybuf[NEWBUFSIZ];
+static int verbose;
+static int force;
+
+static char tmpname[1024];
+
+#if defined(__atarist__) && defined(__GNUC__)
+long _stksize = 30000;
+#endif
+
+struct aexec
+{
+ short a_magic; /* magic number */
+ unsigned long a_text; /* size of text segment */
+ unsigned long a_data; /* size of initialized data */
+ unsigned long a_bss; /* size of uninitialized data */
+ unsigned long a_syms; /* size of symbol table */
+ unsigned long a_res1; /* see below */
+ unsigned long a_AZero2; /* always zero */
+ unsigned short a_isreloc; /* is reloc info present */
+};
+
+#define CMAGIC 0x601A /* contiguous text */
+
+/*
+ * magic values in a_res1 field
+ */
+#define EXEC_FMT_TOS 0 /* original TOS */
+#define EXEC_FMT_MINT 0x4d694e54UL /* binutils a.out format */
+#define EXEC_FMT_ELF 0x454c4600UL /* new binutils PRG+ELF format */
+
+
+#define SIZEOF_SHORT 2
+#define SIZEOF_LONG 4
+
+/*
+ * sizeof(struct aexec)
+ */
+#define SIZEOF_AEXEC (SIZEOF_SHORT + (6 * SIZEOF_LONG) + SIZEOF_SHORT)
+/*
+ * extra header added by a.out-mintprg format
+ */
+#define SIZEOF_BINUTILS_AEXEC 228
+
+
+static char *f_basename(char *name)
+{
+ char *p1, *p2;
+
+ p1 = strrchr(name, '/');
+ p2 = strrchr(name, '\\');
+ if (p1 == NULL || p2 > p1)
+ p1 = p2;
+ if (p1 == NULL)
+ p1 = name;
+ else
+ p1++;
+ return p1;
+}
+
+
+static unsigned short read_beword(const unsigned char *p)
+{
+ return (p[0] << 8) | p[1];
+}
+
+
+static unsigned long read_belong(const unsigned char *p)
+{
+ return ((unsigned long)read_beword(p) << 16) | read_beword(p + 2);
+}
+
+
+static void write_beword(unsigned char *p, unsigned short v)
+{
+ p[0] = (v >> 8) & 0xff;
+ p[1] = (v ) & 0xff;
+}
+
+
+static void write_belong(unsigned char *p, unsigned long v)
+{
+ p[0] = (unsigned char)((v >> 24) & 0xff);
+ p[1] = (unsigned char)((v >> 16) & 0xff);
+ p[2] = (unsigned char)((v >> 8) & 0xff);
+ p[3] = (unsigned char)((v ) & 0xff);
+}
+
+
+/*
+ * read header -- return -1 on error
+ */
+static int read_head(int fd, struct aexec *a)
+{
+ unsigned char buf[SIZEOF_AEXEC];
+
+ if (read(fd, buf, SIZEOF_AEXEC) != SIZEOF_AEXEC)
+ return -1;
+ a->a_magic = read_beword(buf);
+ a->a_text = read_belong(buf + 2);
+ a->a_data = read_belong(buf + 6);
+ a->a_bss = read_belong(buf + 10);
+ a->a_syms = read_belong(buf + 14);
+ a->a_res1 = read_belong(buf + 18);
+ a->a_AZero2 = read_belong(buf + 22);
+ a->a_isreloc = read_beword(buf + 26);
+
+ return SIZEOF_AEXEC;
+}
+
+
+static int write_head(int fd, const struct aexec *a)
+{
+ unsigned char buf[SIZEOF_AEXEC];
+
+ write_beword(buf, a->a_magic);
+ write_belong(buf + 2, a->a_text);
+ write_belong(buf + 6, a->a_data);
+ write_belong(buf + 10, a->a_bss);
+ write_belong(buf + 14, a->a_syms);
+ write_belong(buf + 18, a->a_res1);
+ write_belong(buf + 22, a->a_AZero2);
+ write_beword(buf + 26, a->a_isreloc);
+
+ if (write(fd, buf, SIZEOF_AEXEC) != SIZEOF_AEXEC)
+ return -1;
+ return SIZEOF_AEXEC;
+}
+
+
+/*
+ * copy from, to in NEWBUFSIZ chunks upto bytes or EOF whichever occurs first
+ * returns # of bytes copied
+ */
+static long copy(int from, int to, long bytes)
+{
+ long todo;
+ long done = 0;
+ long remaining = bytes;
+ long actual;
+
+ while (done != bytes)
+ {
+ todo = (remaining > NEWBUFSIZ) ? NEWBUFSIZ : remaining;
+ if ((actual = read(from, mybuf, todo)) != todo)
+ {
+ if (actual < 0)
+ {
+ fprintf(stderr, "Error Reading\n");
+ return -done;
+ }
+ }
+ if (write(to, mybuf, actual) != actual)
+ {
+ fprintf(stderr, "Error Writing\n");
+ return -done;
+ }
+ done += actual;
+ if (actual != todo) /* eof reached */
+ return done;
+ remaining -= actual;
+ }
+ return done;
+}
+
+
+static int relocate(const char *name, int fd, long reloc_pos, long bytes_to_delete)
+{
+ if (lseek(fd, reloc_pos, SEEK_SET) != reloc_pos)
+ {
+ perror(name);
+ return 0;
+ }
+ if (read(fd, mybuf, SIZEOF_LONG) != SIZEOF_LONG)
+ {
+ perror(name);
+ return 0;
+ }
+ write_belong(mybuf, read_belong(mybuf) - bytes_to_delete);
+ if (lseek(fd, reloc_pos, SEEK_SET) != reloc_pos)
+ {
+ perror(name);
+ return 0;
+ }
+ if (write(fd, mybuf, SIZEOF_LONG) != SIZEOF_LONG)
+ {
+ perror(name);
+ return 0;
+ }
+ return 1;
+}
+
+
+/* copy TOS relocation table from `from` to `to`. Copy bytes until NUL byte or
+ first 4 bytes if == 0.
+ returns length of relocation table or -1 in case of an error */
+
+static long copy_relocs(const char *name, int from, int to, long bytes_to_delete, long image_size)
+{
+ long res = 0;
+ long bytes;
+ long rbytes = 0;
+ long first_relo;
+ long reloc_pos;
+ long limit;
+
+ res = read(from, mybuf, SIZEOF_LONG);
+ if (res != 0 && res != SIZEOF_LONG)
+ {
+ fprintf(stderr, "Error reading\n");
+ return -1;
+ }
+
+ if (res == 0)
+ {
+ /* I think empty relocation tables are allowed,
+ but could cause trouble with certain programs */
+ fprintf(stderr, "Warning: %s: No relocation table\n", name);
+ return 0;
+ }
+ first_relo = read_belong(mybuf);
+ if (first_relo != 0)
+ {
+ /*
+ * The initially designed elf format had some relocations in the header
+ * that we are about to remove.
+ * Supporting that would require to rebuild the relocation table.
+ * The current format does not have such relocations anymore,
+ * but better check for it.
+ */
+ if (first_relo <= bytes_to_delete)
+ {
+ fprintf(stderr, "%s: first relocation at 0x%08lx is in area to be deleted\n", name, first_relo);
+ fprintf(stderr, "update your binutils\n");
+ return -1;
+ }
+ first_relo -= bytes_to_delete;
+ write_belong(mybuf, first_relo);
+ }
+
+ if (write(to, mybuf, res) != res)
+ {
+ fprintf(stderr, "%s: Error writing\n", name);
+ return -1;
+ }
+
+ rbytes = SIZEOF_LONG;
+ if (first_relo == 0)
+ return rbytes; /* This is a clean version of an empty
+ relocation table */
+
+ reloc_pos = SIZEOF_AEXEC + first_relo;
+ if (relocate(name, to, reloc_pos, bytes_to_delete) == 0)
+ return -1;
+ limit = SIZEOF_AEXEC + image_size;
+
+ for (;;)
+ {
+ lseek(to, 0, SEEK_END);
+ if ((bytes = read(from, mybuf, 1)) < 0)
+ {
+ fprintf(stderr, "%s: Error reading\n", name);
+ return -1;
+ }
+ if (bytes == 0)
+ {
+ fprintf(stderr, "Warning: %s: Unterminated relocation table\n", name);
+ return rbytes;
+ }
+ if (write(to, mybuf, bytes) != bytes)
+ {
+ fprintf(stderr, "%s: Error writing\n", name);
+ return -1;
+ }
+ rbytes += bytes;
+ if (mybuf[0] == 0)
+ break;
+ if (mybuf[0] == 1)
+ {
+ reloc_pos += 254;
+ } else
+ {
+ reloc_pos += mybuf[0];
+ /*
+ * check that we don't try to write beyond the new image size.
+ * This too, could happen with early version of new elf binutils
+ */
+ if (reloc_pos >= limit)
+ {
+ fprintf(stderr, "%s: relocation at 0x%08lx is outside image\n", name, reloc_pos);
+ fprintf(stderr, "update your binutils\n");
+ return -1;
+ }
+ if (relocate(name, to, reloc_pos, bytes_to_delete) == 0)
+ return -1;
+ }
+ }
+ return rbytes;
+}
+
+
+static int strip(const char *name)
+{
+ int fd;
+ int tfd;
+ long count, rbytes, sbytes;
+ struct aexec ahead;
+ unsigned char buf[13 * SIZEOF_LONG];
+ unsigned long magic1, magic2;
+ long bytes_to_delete;
+
+ if ((fd = open(name, O_RDONLY | O_BINARY, 0755)) < 0)
+ {
+ perror(name);
+ return 1;
+ }
+ if ((tfd = open(tmpname, O_RDWR | O_BINARY | O_TRUNC | O_CREAT, 0755)) < 0)
+ {
+ perror(tmpname);
+ close(fd);
+ return 1;
+ }
+
+ /*
+ * read g_jump_entry and first 8 longs of exec header
+ */
+ if (read_head(fd, &ahead) < 0 ||
+ (int)read(fd, buf, 8 * SIZEOF_LONG) != 8 * SIZEOF_LONG)
+ {
+ perror(name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ if (ahead.a_magic != CMAGIC)
+ {
+ fprintf(stderr, "%s: Bad Magic number\n", name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ if (ahead.a_res1 == EXEC_FMT_MINT) /* 'MiNT' extended exec header magic */
+ {
+ long e_entry;
+
+ bytes_to_delete = SIZEOF_BINUTILS_AEXEC;
+
+ /*
+ * read trampoline code
+ */
+ magic1 = read_belong(buf);
+ magic2 = read_belong(buf + SIZEOF_LONG);
+ if (!((magic1 == 0x283a001aUL && magic2 == 0x4efb48faUL) || /* Original binutils */
+ (magic1 == 0x203a001aUL && magic2 == 0x4efb08faUL))) /* binutils >= 2.18-mint-20080209 */
+ {
+ fprintf(stderr, "%s: no aexec header\n", name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+#if 0
+ magic1 = read_belong(buf + 2 * SIZEOF_LONG);
+ printf("e_info: %08lx\n", magic1);
+ magic1 = read_belong(buf + 3 * SIZEOF_LONG);
+ printf("e_text: %08lx\n", magic1);
+ magic1 = read_belong(buf + 4 * SIZEOF_LONG);
+ printf("e_data: %08lx\n", magic1);
+ magic1 = read_belong(buf + 5 * SIZEOF_LONG);
+ printf("e_bss: %08lx\n", magic1);
+ magic1 = read_belong(buf + 6 * SIZEOF_LONG);
+ printf("e_syms: %08lx\n", magic1);
+#endif
+ e_entry = read_belong(buf + 7 * SIZEOF_LONG);
+#if 0
+ printf("e_entry: %08lx\n", e_entry);
+#endif
+ if (e_entry != bytes_to_delete)
+ {
+ fprintf(stderr, "%s: warning: entry %08lx not at start of text segment\n", name, e_entry);
+ if (!force)
+ {
+ fprintf(stderr, "use -f to override\n");
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ }
+ } else if ((ahead.a_res1 & 0xffffff00UL) == EXEC_FMT_ELF && (ahead.a_res1 & 0xff) >= 40)
+ {
+ long elf_offset;
+ long e_phoff;
+ long e_entry;
+ long p_offset;
+ unsigned short e_phnum;
+
+ /*
+ * offset of ELF header is determined by last byte of a_res1 (normally 40)
+ */
+ elf_offset = (ahead.a_res1 & 0xff);
+ /*
+ * read trampoline code
+ */
+ magic1 = read_belong(buf);
+ magic2 = read_belong(buf + SIZEOF_LONG);
+ if (magic1 != (0x203a0000UL | (elf_offset + 24 - 30)) || magic2 != 0x4efb08faUL) /* binutils >= 2.41-mintelf */
+ {
+ fprintf(stderr, "%s: no exec header\n", name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+#if 0
+ magic1 = read_belong(buf + 2 * SIZEOF_LONG);
+ printf("_stksize: @%08lx\n", magic1);
+#endif
+ if (lseek(fd, elf_offset, SEEK_SET) < 0 ||
+ (int)read(fd, buf, 13 * SIZEOF_LONG) != 13 * SIZEOF_LONG)
+ {
+ perror(name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ /*
+ * We will find a complete ELF header there,
+ * but only care here about e_magic & e_entry
+ */
+ magic1 = read_belong(buf);
+ e_phnum = read_beword(buf + 44);
+ if (magic1 != 0x7f454c46UL || e_phnum == 0)
+ {
+ fprintf(stderr, "%s: no ELF header\n", name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ e_entry = read_belong(buf + 6 * SIZEOF_LONG);
+ e_phoff = read_belong(buf + 7 * SIZEOF_LONG);
+ /*
+ * read first program header
+ */
+ if (lseek(fd, e_phoff, SEEK_SET) < 0 ||
+ (int)read(fd, buf, 8 * SIZEOF_LONG) != 8 * SIZEOF_LONG)
+ {
+ perror(name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ /*
+ * get start of text segment
+ */
+ p_offset = read_belong(buf + SIZEOF_LONG);
+ bytes_to_delete = e_phoff + e_phnum * 32 - SIZEOF_AEXEC;
+ if (p_offset != SIZEOF_AEXEC || e_entry != bytes_to_delete)
+ {
+ fprintf(stderr, "%s: warning: entry %08lx not at start of text segment %08lx\n", name, e_entry, bytes_to_delete);
+ if (!force)
+ {
+ fprintf(stderr, "use -f to override\n");
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ }
+ } else if (ahead.a_res1 == EXEC_FMT_TOS)
+ {
+ if (ahead.a_syms == 0)
+ {
+ fprintf(stderr, "%s: already stripped\n", name);
+ close(tfd);
+ close(fd);
+ return 0;
+ }
+ bytes_to_delete = 0;
+ } else
+ {
+ fprintf(stderr, "%s: unsupported file format\n", name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+
+ sbytes = ahead.a_syms;
+ if (verbose)
+ {
+ printf("%s: text=0x%lx, data=0x%lx, syms=0x%lx\n", name, ahead.a_text, ahead.a_data, ahead.a_syms);
+ }
+
+ ahead.a_syms = 0;
+ ahead.a_text -= bytes_to_delete;
+ ahead.a_res1 = 0;
+ if (write_head(tfd, &ahead) < 0)
+ {
+ perror(name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ if (lseek(fd, bytes_to_delete + SIZEOF_AEXEC, SEEK_SET) < 0)
+ {
+ perror(name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ if (verbose)
+ {
+ printf("%s: skipped 0x%lx bytes extra header\n", name, bytes_to_delete);
+ }
+
+ count = ahead.a_text + ahead.a_data;
+ if (copy(fd, tfd, count) != count)
+ {
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ if (verbose)
+ {
+ printf("%s: copied 0x%lx bytes text+data\n", name, count);
+ }
+ if (lseek(fd, sbytes, SEEK_CUR) < 0)
+ {
+ perror(name);
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ if (sbytes != 0 && verbose)
+ {
+ printf("%s: skipped 0x%lx bytes symbols\n", name, sbytes);
+ }
+ rbytes = 0;
+ if (ahead.a_isreloc == 0)
+ {
+ if ((rbytes = copy_relocs(name, fd, tfd, bytes_to_delete, count)) < 0)
+ {
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ if (verbose)
+ {
+ printf("%s: copied 0x%lx bytes relocation table\n", name, rbytes);
+ }
+ }
+ if (verbose)
+ {
+ unsigned long pos, size;
+
+ pos = lseek(fd, 0, SEEK_CUR);
+ lseek(fd, 0, SEEK_END);
+ size = lseek(fd, 0, SEEK_CUR);
+ lseek(fd, pos, SEEK_SET);
+ if (size > pos)
+ {
+ /* could be pure-c debug information, after end of relocation table */
+ printf("%s: skipped 0x%lx bytes trailer\n", name, size - pos);
+ }
+ }
+
+ close(tfd);
+ close(fd);
+ if (rename(tmpname, name) == 0)
+ return 0; /* try to rename it */
+ if ((fd = open(name, O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, 0755)) < 0)
+ {
+ perror(name);
+ return 1;
+ }
+ if ((tfd = open(tmpname, O_RDONLY | O_BINARY, 0755)) < 0)
+ {
+ perror(tmpname);
+ close(fd);
+ return 1;
+ }
+
+ count = SIZEOF_AEXEC + ahead.a_text + ahead.a_data + rbytes;
+ if (copy(tfd, fd, count) != count)
+ {
+ close(tfd);
+ close(fd);
+ return 1;
+ }
+ close(tfd);
+ close(fd);
+ return 0;
+}
+
+
+static void usage(const char *s)
+{
+ fprintf(stderr, "%s", s);
+ fprintf(stderr, "Usage: stripex [-f] files ...\n");
+ fprintf(stderr, "strip GNU-binutils aexec/elf header from executables\n");
+}
+
+
+int main(int argc, char **argv)
+{
+ int status = 0;
+
+ verbose = 0;
+
+ /* process arguments */
+ while (argv++, --argc)
+ {
+ if ('-' != **argv)
+ break;
+ (*argv)++;
+ switch (**argv)
+ {
+ case 'v':
+ verbose = 1;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ default:
+ usage("");
+ return 1;
+ }
+ }
+
+ if (argc < 1)
+ {
+ usage("");
+ return 1;
+ }
+
+ do
+ {
+ const char *filename = *argv++;
+ char *base;
+ int fd;
+
+ strcpy(tmpname, filename);
+ base = f_basename(tmpname);
+ strcpy(base, "STXXXXXX");
+ fd = mkstemp(tmpname);
+ if (fd < 0)
+ {
+ perror(tmpname);
+ status |= 1;
+ } else
+ {
+ close(fd);
+ status |= strip(filename);
+ unlink(tmpname);
+ }
+ } while (--argc > 0);
+
+ return status;
+}