]> granicus.if.org Git - strace/commitdiff
Add mpers support
authorElvira Khabirova <lineprinter0@gmail.com>
Mon, 3 Aug 2015 22:47:02 +0000 (01:47 +0300)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 28 Aug 2015 08:46:23 +0000 (08:46 +0000)
Add a subsystem for semi-automatical definition of how parsers should
work with personality-dependent (mpers) types of tracee's data.  Create
auxiliary libraries containing mpers syscall parsers and printer
functions, one library for each possible nonnative target personality.

Currently some parsers do not handle differences in definitions of data
types between personalities, namely LP64 and ILP32.  When
this is the case, long integers, pointers, and all compound
types containing long and pointer members may be printed incorrectly,
because of differences in sizes, offsets and alignments.

Since in most cases these are the only differences in desired behaviour
of parsers and printers for different personalities, a correct way
would be to compile one source code into multiple parsers, differing
only in definitions of mpers types.

To get a definition of a given type for nonnative personality
a very basic .c file containing a declaration of a variable of this type
is being compiled for this personality (using -m32 or -mx32 compiler
flag).  Information about the type is then being extracted from
this binary's DWARF debug info with an awk script and put
into a corresponding header file.  Resulting headers are being used to
compile mpers variations of syscall parsers and printer functions.

In addition to syscall parsers, there can occur a need to create mpers
printing functions, which then can be called from many places
in the code (for example, printsiginfo_at).  Such functions (printers)
are marked in a special manner.

For each possible nonnative target personality a library is being
created, containing mpers variations of syscall parsers and printers.
Only syscall parsers from files marked in a special manner and specially
marked functions from such files are being recompiled and included
in these libraries.

generate_mpers_am.sh is called by bootstrap to find the files
from strace_SOURCES which include MPERS_DEFS.  During compilation,
these files are being inspected for inclusions of DEF_MPERS_TYPE,
and nonnative variations of each included type are being generated
by an awk script.

Mpers parser names are being modified during inclusions of syscallent
headers for nonnative personalities.  Pointers to printers are
being stored in structs struct_printers, and a master
pointer printers is being updated on every set_personality.

* README-mpers: New README explaining how to use mpers support.
* empty.h: New empty file.
* generate_mpers_am.sh: New file.
* mpers.awk: Likewise.
* mpers.sh: Likewise.
* mpers_test.sh: Likewise.
* mpers_type.h: Likewise.
* Makefile.am (strace_SOURCES): Add empty.h and mpers_type.h.
(strace_CPPFLAGS, strace_LDFLAGS, strace_LDADD): Move to the beginning
of the file.
(strace_LDADD, noinst_LIBRARIES): Add libmpers-%.a.
(EXTRA_DIST): Add mpers.awk, mpers.sh, mpers_test.sh.
(BUILT_SOURCES, CLEANFILES): Add new generated files:
native_printer_decls.h, native_printer_defs.h, printers.h,
[HAVE_M32_MPERS] $(mpers_m32_targets), and [HAVE_MX32_MPERS]
$(mpers_mx32_targets).
(mpers_NAME, mpers_PREFIX, mpers_DEFS, mpers_INCLUDES, mpers_CPPFLAGS,
mpers_sh_opts, libmpers_CPPFLAGS, libmpers_m[x]32_a_SOURCES,
libmpers_m[x]32_a_CPPFLAGS, mpers_m[x]32_targets): New variables.
(mpers-m[x]32.stamp, m[x]32_defs.h, m[x]32_funcs.h, printers.h,
%_printer_decls.h, %_printer_defs.h, clean-local,
native_printer_decls.h, native_printer_defs.h, $mpers_m[x]32_targets):
New targets.
* bootstrap: Add generate_mpers_am.sh.
* configure.ac: Add AC_PROG_RANLIB.
* m4/mpers.m4: Add HAVE_MPERS variable.  Add $st_cv_mpers checks.
* defs.h: Include mpers_type.h.
Include printers.h, native_printer_decls.h, define MPERS_PRINTER_NAME.
Redefine SYS_FUNC_NAME.  Define MPERS_PRINTER_DECL.
[HAVE_M32_MPERS]: define PERSONALITY1_INCLUDE_FUNCS,
PERSONALITY1_INCLUDE_PRINTERS_DECLS, PERSONALITY1_INCLUDE_PRINTERS_DEFS
for X86_64, X32.
[HAVE_MX32_MPERS]: define PERSONALITY2_INCLUDE_FUNCS,
PERSONALITY2_INCLUDE_PRINTERS_DECLS, PERSONALITY2_INCLUDE_PRINTERS_DEFS
for X86_64.
Add fallback definitions of
PERSONALITY1_INCLUDE_FUNCS, PERSONALITY2_INCLUDE_FUNCS,
PERSONALITY0_INCLUDE_PRINTERS_DECLS, PERSONALITY0_INCLUDE_PRINTERS_DEFS,
PERSONALITY1_INCLUDE_PRINTERS_DECLS, PERSONALITY1_INCLUDE_PRINTERS_DEFS,
PERSONALITY2_INCLUDE_PRINTERS_DECLS, PERSONALITY2_INCLUDE_PRINTERS_DEFS.
* syscall.c: Include PERSONALITY1_INCLUDE_FUNCS,
PERSONALITY2_INCLUDE_FUNCS,
PERSONALITY0_INCLUDE_PRINTERS_DECLS, PERSONALITY0_INCLUDE_PRINTERS_DEFS,
PERSONALITY1_INCLUDE_PRINTERS_DECLS, PERSONALITY1_INCLUDE_PRINTERS_DEFS,
PERSONALITY2_INCLUDE_PRINTERS_DECLS, PERSONALITY2_INCLUDE_PRINTERS_DEFS.
(printers): New struct.  Update it when needed.
* .gitignore: Add libmpers-m32.a, libmpers-mx32.a, m32_defs.h,
m32_funcs.h, m32_printer_decls.h, m32_printer_defs.h, mpers-m32,
mpers-m32.stamp, mpers-mx32, mpers-mx32.stamp, mpers.am, mx32_defs.h,
mx32_funcs.h, mx32_printer_decls.h, mx32_printer_defs.h,
native_printer_decls.h, native_printer_defs.h, and printers.h.

14 files changed:
.gitignore
Makefile.am
README-mpers [new file with mode: 0644]
bootstrap
configure.ac
defs.h
empty.h [new file with mode: 0644]
generate_mpers_am.sh [new file with mode: 0755]
m4/mpers.m4
mpers.awk [new file with mode: 0644]
mpers.sh [new file with mode: 0755]
mpers_test.sh [new file with mode: 0755]
mpers_type.h [new file with mode: 0644]
syscall.c

index fb7c57646fa24b7251b69d419ffedc3ea91fbd51..edcb641a7658f376deaa33a8110ee14059b14493 100644 (file)
@@ -45,3 +45,22 @@ Makefile.in
 
 /tests-m32
 /tests-mx32
+
+/libmpers-m32.a
+/libmpers-mx32.a
+/m32_defs.h
+/m32_funcs.h
+/m32_printer_decls.h
+/m32_printer_defs.h
+/mpers-m32
+/mpers-m32.stamp
+/mpers-mx32
+/mpers-mx32.stamp
+/mpers.am
+/mx32_defs.h
+/mx32_funcs.h
+/mx32_printer_decls.h
+/mx32_printer_defs.h
+/native_printer_decls.h
+/native_printer_defs.h
+/printers.h
index 9800a3a4093820a5cec9a051227b499b95eb70d0..b0d91562f494077642a0be1147ca8c6700595e19 100644 (file)
@@ -27,6 +27,11 @@ AM_CPPFLAGS = -I$(builddir)/$(OS)/$(ARCH) \
 
 include xlat/Makemodule.am
 
+strace_CPPFLAGS = $(AM_CPPFLAGS)
+strace_LDFLAGS =
+strace_LDADD =
+noinst_LIBRARIES =
+
 strace_SOURCES =       \
        access.c        \
        affinity.c      \
@@ -44,6 +49,7 @@ strace_SOURCES =      \
        count.c         \
        desc.c          \
        dirent.c        \
+       empty.h         \
        epoll.c         \
        evdev.c         \
        eventfd.c       \
@@ -80,6 +86,7 @@ strace_SOURCES =      \
        memfd_create.c  \
        mknod.c         \
        mount.c         \
+       mpers_type.h    \
        mq.c    \
        mtd.c           \
        net.c           \
@@ -146,15 +153,14 @@ strace_SOURCES =  \
        vsprintf.c      \
        wait.c          \
        xattr.c         \
-       xmalloc.c
+       xmalloc.c       \
+       # end of strace_SOURCES
 
 if USE_LIBUNWIND
 strace_SOURCES += unwind.c
-strace_CPPFLAGS = $(AM_CPPFLAGS) $(libunwind_CPPFLAGS)
-strace_LDFLAGS = $(libunwind_LDFLAGS)
-strace_LDADD = $(libunwind_LIBS)
-else
-strace_CPPFLAGS = $(AM_CPPFLAGS)
+strace_CPPFLAGS += $(libunwind_CPPFLAGS)
+strace_LDFLAGS += $(libunwind_LDFLAGS)
+strace_LDADD += $(libunwind_LIBS)
 endif
 
 noinst_HEADERS = defs.h
@@ -575,6 +581,9 @@ EXTRA_DIST =                                \
        maint/ioctls_hex.sh             \
        maint/ioctls_sym.sh             \
        maint/print_ioctlent.c          \
+       mpers.awk                       \
+       mpers.sh                        \
+       mpers_test.sh                   \
        signalent.sh                    \
        strace-graph                    \
        strace-log-merge                \
@@ -589,8 +598,6 @@ EXTRA_DIST =                                \
 srpm: dist-xz
        rpmbuild --define '%_srcrpmdir .' -ts $(distdir).tar.xz
 
-BUILT_SOURCES = .version sys_func.h sen.h
-
 $(srcdir)/.version:
        $(AM_V_GEN)echo $(VERSION) > $@-t && mv $@-t $@
 
@@ -635,8 +642,6 @@ ioctlsort_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD)
 
 ioctls_inc_h = $(wildcard $(srcdir)/$(OS)/$(ARCH)/ioctls_inc*.h)
 ioctlent_h = $(patsubst $(srcdir)/$(OS)/$(ARCH)/ioctls_inc%,ioctlent%,$(ioctls_inc_h))
-BUILT_SOURCES += $(ioctlent_h)
-CLEANFILES = sys_func.h sen.h $(ioctlent_h)
 
 ioctlent%.h: ioctlsort%
        ./$< > $@
@@ -650,6 +655,104 @@ ioctlsort%.o: ioctls_all%.h $(srcdir)/ioctlsort.c
 ioctls_all%.h: $(srcdir)/$(OS)/$(ARCH)/ioctls_inc%.h $(srcdir)/$(OS)/$(ARCH)/ioctls_arch%.h
        cat $^ > $@
 
+BUILT_SOURCES = $(ioctlent_h) native_printer_decls.h native_printer_defs.h printers.h sen.h sys_func.h .version
+CLEANFILES    = $(ioctlent_h) native_printer_decls.h native_printer_defs.h printers.h sen.h sys_func.h
+
+# defines mpers_source_files
+include mpers.am
+srcdir_mpers_source_files = $(patsubst %,$(srcdir)/%,$(mpers_source_files))
+
+mpers_NAME =
+mpers_PREFIX = $(mpers_NAME)_
+mpers_DEFS = $(DEFS)
+mpers_INCLUDES = $(DEFAULT_INCLUDES) $(INCLUDES)
+mpers_CPPFLAGS = $(strace_CPPFLAGS) $(CPPFLAGS)
+mpers_sh_opts = $(mpers_DEFS) $(mpers_INCLUDES) $(mpers_CPPFLAGS)
+libmpers_CPPFLAGS = $(AM_CPPFLAGS) -DIN_MPERS
+
+# mpers targets
+
+mpers-m%.stamp: $(srcdir_mpers_source_files)
+       for f in $^; do \
+               CC="$(CC)" CFLAGS="$(mpers_sh_opts)" \
+               CPP="$(CPP)" CPPFLAGS="$(mpers_CPPFLAGS) $(mpers_INCLUDES) -DIN_MPERS -DMPERS_IS_$(mpers_NAME)" \
+               $(srcdir)/mpers.sh -$(mpers_NAME) $$f || exit; \
+       done
+       > $@
+
+m%_defs.h: $(srcdir_mpers_source_files)
+       for f in $^; do \
+               sed -n 's/^#include DEF_MPERS_TYPE(\([^)]\+\))/#ifdef MPERS_$(mpers_PREFIX)\1\n# define \1 MPERS_$(mpers_PREFIX)\1\n#endif/p' $$f || exit; \
+       done > $@-t
+       mv $@-t $@
+
+m%_funcs.h: $(srcdir_mpers_source_files)
+       for f in $^; do \
+               sed -n 's/^SYS_FUNC(\([^)]\+\))/#undef sys_\1\n#define sys_\1 $(mpers_PREFIX)sys_\1/p' $$f || exit; \
+       done > $@-t && \
+       echo '#include "sys_func.h"' >> $@-t
+       mv $@-t $@
+
+# printers
+
+printers.h: $(srcdir_mpers_source_files)
+       echo '/* Generated by Makefile from $^; do not edit. */' > $@-t
+       echo 'typedef struct {' >> $@-t
+       for f in $^; do \
+               sed -n 's/^MPERS_PRINTER_DECL(\([^,]\+\),[[:space:]]*\([^)]\+\))\(.*\)/ \1 (*\2) \3;/p' $$f || exit; \
+       done >> $@-t
+       echo '} struct_printers;' >> $@-t
+       mv $@-t $@
+
+%_printer_decls.h: $(srcdir_mpers_source_files)
+       echo '/* Generated by Makefile from $^; do not edit. */' > $@-t
+       for f in $^; do \
+               sed -n 's/^MPERS_PRINTER_DECL(\([^,]\+\),[[:space:]]*\([^)]\+\))\(.*\)/extern \1 $(mpers_PREFIX)\2\3;/p' $$f || exit; \
+       done >> $@-t
+       mv $@-t $@
+
+%_printer_defs.h: $(srcdir_mpers_source_files)
+       echo '/* Generated by Makefile from $^; do not edit. */' > $@-t
+       for f in $^; do \
+               sed -n 's/^MPERS_PRINTER_DECL(\([^,]\+\),[[:space:]]*\([^)]\+\))\(.*\)/\.\2 = $(mpers_PREFIX)\2,/p' $$f || exit; \
+       done >> $@-t
+       mv $@-t $@
+
+native_printer_decls.h native_printer_defs.h: mpers_PREFIX =
+
+if HAVE_M32_MPERS
+
+strace_LDADD += libmpers-m32.a
+noinst_LIBRARIES += libmpers-m32.a
+libmpers_m32_a_SOURCES = $(mpers_source_files)
+libmpers_m32_a_CPPFLAGS = $(libmpers_CPPFLAGS) -DMPERS_IS_m32 -I$(builddir)/mpers-m32
+mpers_m32_targets = mpers-m32.stamp m32_defs.h m32_funcs.h m32_printer_decls.h m32_printer_defs.h
+
+BUILT_SOURCES += $(mpers_m32_targets)
+CLEANFILES    += $(mpers_m32_targets)
+
+$(mpers_m32_targets): mpers_NAME = m32
+
+endif # HAVE_M32_MPERS
+
+if HAVE_MX32_MPERS
+
+strace_LDADD += libmpers-mx32.a
+noinst_LIBRARIES += libmpers-mx32.a
+libmpers_mx32_a_SOURCES = $(mpers_source_files)
+libmpers_mx32_a_CPPFLAGS = $(libmpers_CPPFLAGS) -DMPERS_IS_mx32 -I$(builddir)/mpers-mx32
+mpers_mx32_targets = mpers-mx32.stamp mx32_defs.h mx32_funcs.h mx32_printer_decls.h mx32_printer_defs.h
+
+BUILT_SOURCES += $(mpers_mx32_targets)
+CLEANFILES    += $(mpers_mx32_targets)
+
+$(mpers_mx32_targets): mpers_NAME = mx32
+
+endif # HAVE_MX32_MPERS
+
+clean-local:
+       -rm -rf mpers-m32 mpers-mx32
+
 if MAINTAINER_MODE
 
 gen_changelog_start_date = 2009-07-08 20:00
diff --git a/README-mpers b/README-mpers
new file mode 100644 (file)
index 0000000..725a2b6
--- /dev/null
@@ -0,0 +1,12 @@
+To use mpers functionality, one should:
+* typedef all of the target types which are compound and not typedefed
+already;
+* for each target type, include DEF_MPERS_TYPE(target_type_t), these can
+be included conditionally;
+* include MPERS_DEFS once;
+* before inclusion of MPERS_DEFS include all important headers
+(containing definitions of these types or other behaviour-affecting
+defines);
+* printers should be defined
+as MPERS_PRINTER_DECL(return type, function name)(args) and called
+as MPERS_PRINTER_NAME(function name)(args).
index 118d945004e00c8eaab9c931d61c83b86c7efeeb..59d2480d1b832dd25ffe7840005b4f849b0d4a91 100755 (executable)
--- a/bootstrap
+++ b/bootstrap
@@ -15,5 +15,6 @@ for m in -m32 -mx32; do
 done
 
 ./xlat/gen.sh
+./generate_mpers_am.sh
 
 exec autoreconf -f -i "$@"
index eeb618e7ba10bf6e653761cdb5c72249df5b73d5..6131ef1e5eb8c08c2d5669d8c6053a0e44035e39 100644 (file)
@@ -13,6 +13,7 @@ AC_CANONICAL_HOST
 AC_PROG_CC
 AX_PROG_CC_FOR_BUILD
 AC_USE_SYSTEM_EXTENSIONS
+AC_PROG_RANLIB
 
 AC_MSG_CHECKING([for supported architecture])
 case "$host_cpu" in
diff --git a/defs.h b/defs.h
index 7f9c3a3e0b0110bcf80226715729fa60e7896234..9479b9ae82d8b846eae4eb8f48db7264914d4e95 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -54,6 +54,8 @@
 #include <sys/time.h>
 #include <sys/syscall.h>
 
+#include "mpers_type.h"
+
 #ifndef HAVE_STRERROR
 const char *strerror(int);
 #endif
@@ -200,12 +202,27 @@ extern char *stpcpy(char *dst, const char *src);
 # define PERSONALITY0_WORDSIZE 8
 # define PERSONALITY1_WORDSIZE 4
 # define PERSONALITY2_WORDSIZE 4
+# ifdef HAVE_M32_MPERS
+#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
+# endif
+# ifdef HAVE_MX32_MPERS
+#  define PERSONALITY2_INCLUDE_FUNCS "mx32_funcs.h"
+#  define PERSONALITY2_INCLUDE_PRINTERS_DECLS "mx32_printer_decls.h"
+#  define PERSONALITY2_INCLUDE_PRINTERS_DEFS "mx32_printer_defs.h"
+# endif
 #endif
 
 #ifdef X32
 # define SUPPORTED_PERSONALITIES 2
 # define PERSONALITY0_WORDSIZE 4
 # define PERSONALITY1_WORDSIZE 4
+# ifdef HAVE_M32_MPERS
+#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
+# endif
 #endif
 
 #ifdef ARM
@@ -245,6 +262,34 @@ extern char *stpcpy(char *dst, const char *src);
 # define PERSONALITY0_WORDSIZE SIZEOF_LONG
 #endif
 
+#ifndef PERSONALITY0_INCLUDE_PRINTERS_DECLS
+# define PERSONALITY0_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
+#endif
+#ifndef PERSONALITY0_INCLUDE_PRINTERS_DEFS
+# define PERSONALITY0_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
+#endif
+
+#ifndef PERSONALITY1_INCLUDE_PRINTERS_DECLS
+# define PERSONALITY1_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
+#endif
+#ifndef PERSONALITY1_INCLUDE_PRINTERS_DEFS
+# define PERSONALITY1_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
+#endif
+
+#ifndef PERSONALITY2_INCLUDE_PRINTERS_DECLS
+# define PERSONALITY2_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
+#endif
+#ifndef PERSONALITY2_INCLUDE_PRINTERS_DEFS
+# define PERSONALITY2_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
+#endif
+
+#ifndef PERSONALITY1_INCLUDE_FUNCS
+# define PERSONALITY1_INCLUDE_FUNCS "empty.h"
+#endif
+#ifndef PERSONALITY2_INCLUDE_FUNCS
+# define PERSONALITY2_INCLUDE_FUNCS "empty.h"
+#endif
+
 typedef struct sysent {
        unsigned nargs;
        int     sys_flags;
@@ -694,6 +739,7 @@ extern const char *const signalent0[];
 extern const struct_ioctlent ioctlent0[];
 extern qualbits_t *qual_vec[SUPPORTED_PERSONALITIES];
 #define qual_flags (qual_vec[current_personality])
+
 #if SUPPORTED_PERSONALITIES > 1
 extern const struct_sysent *sysent;
 extern const char *const *errnoent;
@@ -705,12 +751,22 @@ extern const struct_ioctlent *ioctlent;
 # define signalent  signalent0
 # define ioctlent   ioctlent0
 #endif
+
 extern unsigned nsyscalls;
 extern unsigned nerrnos;
 extern unsigned nsignals;
 extern unsigned nioctlents;
 extern unsigned num_quals;
 
+#if SUPPORTED_PERSONALITIES > 1
+# include "printers.h"
+extern const struct_printers *printers;
+# define MPERS_PRINTER_NAME(printer_name) printers->printer_name
+#else
+# include "native_printer_decls.h"
+# define MPERS_PRINTER_NAME(printer_name) printer_name
+#endif
+
 /*
  * If you need non-NULL sysent[scno].sys_func and sysent[scno].sys_name
  */
@@ -721,8 +777,12 @@ extern unsigned num_quals;
 #define SCNO_IN_RANGE(scno) \
        ((unsigned long)(scno) < nsyscalls)
 
-#ifndef SYS_FUNC_NAME
-# define SYS_FUNC_NAME(syscall_name) sys_ ## syscall_name
-#endif
+#define MPERS_FUNC_NAME__(prefix, name) prefix ## name
+#define MPERS_FUNC_NAME_(prefix, name) MPERS_FUNC_NAME__(prefix, name)
+#define MPERS_FUNC_NAME(name) MPERS_FUNC_NAME_(MPERS_PREFIX, name)
+
+#define SYS_FUNC_NAME(syscall_name) MPERS_FUNC_NAME(sys_ ## syscall_name)
 
 #define SYS_FUNC(syscall_name) int SYS_FUNC_NAME(syscall_name)(struct tcb *tcp)
+
+#define MPERS_PRINTER_DECL(type, name) type MPERS_FUNC_NAME(name)
diff --git a/empty.h b/empty.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/generate_mpers_am.sh b/generate_mpers_am.sh
new file mode 100755 (executable)
index 0000000..382ef53
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh -e
+
+exec > mpers.am
+
+echo "# Generated by $0; do not edit."
+echo -n 'mpers_source_files = '
+
+sed -n '/^strace_SOURCES[[:space:]]*=/,/^[[:space:]]*# end of strace_SOURCES/ s/^[[:space:]]*\([[:alnum:]][^.]*\.c\)[[:space:]]*\\$/\1/p' Makefile.am |
+       xargs -r grep -lx '#[[:space:]]*include[[:space:]]\+MPERS_DEFS' |
+       tr '\n' ' '
+echo
index 6cb01de47fc4e6101d355ad1e040921fe345c8ef..3d173005e3f65b720f8c7cfa54d17e49029734c8 100644 (file)
@@ -1,10 +1,12 @@
 AC_DEFUN([st_MPERS],[
 
 pushdef([MPERS_NAME], translit([$1], [a-z], [A-Z]))
+pushdef([HAVE_MPERS], [HAVE_]MPERS_NAME[_MPERS])
 pushdef([HAVE_RUNTIME], [HAVE_]MPERS_NAME[_RUNTIME])
 pushdef([CFLAG], [-$1])
 pushdef([st_cv_cc], [st_cv_$1_cc])
 pushdef([st_cv_runtime], [st_cv_$1_runtime])
+pushdef([st_cv_mpers], [st_cv_$1_mpers])
 
 case "$arch" in
        [$2])
@@ -22,21 +24,36 @@ case "$arch" in
                                       [st_cv_runtime=yes],
                                       [st_cv_runtime=no],
                                       [st_cv_runtime=no])])
+               AC_CACHE_CHECK([whether mpers.sh CFLAG works], [st_cv_mpers],
+                       [if CC="$CC" CPP="$CPP" CPPFLAGS="$CPPFLAGS" \
+                           $srcdir/mpers_test.sh [$1]; then
+                               st_cv_mpers=yes
+                        else
+                               st_cv_mpers=no
+                        fi])
+               if test $st_cv_mpers = yes; then
+                       AC_DEFINE(HAVE_MPERS, [1],
+                                 [Define to 1 if you have CFLAG mpers support])
+               fi
        fi
        CFLAGS="$saved_CFLAGS"
        ;;
 
        *)
        st_cv_runtime=no
+       st_cv_mpers=no
        ;;
 esac
 
 AM_CONDITIONAL(HAVE_RUNTIME, [test "$st_cv_runtime" = yes])
+AM_CONDITIONAL(HAVE_MPERS, [test "$st_cv_mpers" = yes])
 
+popdef([st_cv_mpers])
 popdef([st_cv_runtime])
 popdef([st_cv_cc])
 popdef([CFLAG])
 popdef([HAVE_RUNTIME])
+popdef([HAVE_MPERS])
 popdef([MPERS_NAME])
 
 ])
diff --git a/mpers.awk b/mpers.awk
new file mode 100644 (file)
index 0000000..2a2de59
--- /dev/null
+++ b/mpers.awk
@@ -0,0 +1,135 @@
+function compare_indices(i1, v1, i2, v2) {
+       c1 = strtonum(sprintf("%s", i1))
+       c2 = strtonum(sprintf("%s", i2))
+       if (c1 < c2)
+               return -1
+       return (c1 != c2)
+}
+function what_is(what_idx, type_idx, special, item)
+{
+       type_idx = array[what_idx]["type"]
+       special = array[what_idx]["special"]
+       switch (special) {
+       case "base_type":
+               switch (array[what_idx]["encoding"]) {
+               case 5: # signed
+                       printf("%s ", "int" \
+                       8*array[what_idx]["byte_size"] "_t")
+                       break
+               case 7: # unsigned
+                       printf("%s ", "uint" \
+                       8*array[what_idx]["byte_size"] "_t")
+                       break
+               default: # float, signed/unsigned char
+                       printf("%s ", array[what_idx]["name"])
+                       break
+               }
+               break
+       case "enumeration_type":
+               printf("%s ", "uint" 8*array[type_idx]["byte_size"] "_t")
+               break
+       case "pointer_type":
+               printf("%s", "mpers_ptr_t ")
+               break
+       case "array_type":
+               what_is(type_idx)
+               to_return = array[what_idx]["upper_bound"]
+               return to_return
+               break
+       case "structure_type":
+       case "union_type":
+               if (special == "structure_type") {
+                       print "struct {"
+               } else {
+                       print "union {"
+               }
+               for (item in array) {
+                       if ("parent" in array[item] && array[item]["parent"] \
+                               == what_idx) {
+                               returned = what_is(item)
+                               printf("%s", array[item]["name"])
+                               if (returned) {
+                                       printf("%s", "[" returned "]")
+                               }
+                               print ";"
+                       }
+               }
+               printf("%s", "} ")
+               break
+       case "typedef":
+               return what_is(type_idx)
+               break
+       case "member":
+               return what_is(type_idx)
+               break
+       default:
+               what_is(type_idx)
+               break
+       }
+       return 0
+}
+BEGIN {
+       print "#include <inttypes.h>"
+}
+/^<[[:xdigit:]]+>/ {
+       match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches)
+       level = matches[1]
+       idx = "0x" matches[2]
+       array[idx]["idx"] = idx
+       parent[level] = idx
+       if (level > 1) {
+               array[idx]["parent"] = parent[level-1]
+       }
+}
+/^DW_AT_data_member_location/ {
+       match($0, /[[:digit:]]+/, temparray)
+       array[idx]["location"] = temparray[1]
+}
+/^DW_AT_name/ {
+       match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/, temparray)
+       array[idx]["name"] = temparray[1]
+}
+/^DW_AT_byte_size/ {
+       match($0, /[[:digit:]]+/, temparray)
+       array[idx]["byte_size"] = temparray[0]
+}
+/^DW_AT_encoding/ {
+       match($0, /[[:digit:]]+/, temparray)
+       array[idx]["encoding"] = temparray[0]
+}
+/^DW_AT_type/ {
+       match($0, /:[[:space:]]+<(0x[[:xdigit:]]*)>$/, temparray)
+       array[idx]["type"] = temparray[1]
+}
+/^DW_AT_upper_bound/ {
+       match($0, /[[:digit:]]+/, temparray)
+       array[parent[level-1]]["upper_bound"] = temparray[0] + 1
+}
+/^Abbrev Number:[^(]+\(DW_TAG_/ {
+       if (match($0, /typedef|union_type|structure_type|pointer_type\
+|enumeration_type|array_type|base_type|member/, temparray)) {
+               array[idx]["special"] = temparray[0]
+       }
+}
+END {
+       PROCINFO["sorted_in"] = "compare_indices"
+       for (item in array) {
+               if (array[item]["special"] == "pointer_type") {
+                       print "typedef uint" \
+                               8*array[item]["byte_size"] "_t mpers_ptr_t;"
+                       break
+               }
+       }
+       for (item in array) {
+               if (array[item]["name"] == VAR_NAME) {
+                       type=array[item]["type"]
+                       print "typedef"
+                       what_is(array[item]["type"])
+                       print ARCH_FLAG "_" array[type]["name"] ";"
+                       print "#define MPERS_" \
+                               ARCH_FLAG "_" array[type]["name"] " " \
+                               ARCH_FLAG "_" array[type]["name"]
+                       break
+               }
+       }
+}
diff --git a/mpers.sh b/mpers.sh
new file mode 100755 (executable)
index 0000000..fc681a4
--- /dev/null
+++ b/mpers.sh
@@ -0,0 +1,49 @@
+#!/bin/sh -e
+
+export LC_ALL=C
+
+MPERS_AWK="${0%/*}/mpers.awk"
+ARCH_FLAG=$1
+PARSER_FILE=$2
+
+CC="${CC-gcc}"
+CFLAGS="$CFLAGS -gdwarf-4 -c"
+CPP="${CPP-$CC -E}"
+CPPFLAGS="$CPPFLAGS -MM -MG"
+
+VAR_NAME='mpers_target_var'
+BITS_DIR="mpers${ARCH_FLAG}"
+
+mkdir -p ${BITS_DIR}
+set -- $(sed -n \
+       's/^#[[:space:]]*include[[:space:]]\+DEF_MPERS_TYPE(\([^)[:space:]]*\))$/\1/p' \
+               "${PARSER_FILE}")
+for m_type; do
+       f_h="${BITS_DIR}/${m_type}.h"
+       f_c="${BITS_DIR}/${m_type}.c"
+       f_i="${BITS_DIR}/${m_type}.i"
+       f_o="${BITS_DIR}/${m_type}.o"
+       f_d1="${BITS_DIR}/${m_type}.d1"
+       f_d2="${BITS_DIR}/${m_type}.d2"
+       sed -e '
+               /DEF_MPERS_TYPE('"${m_type}"')$/n
+               /DEF_MPERS_TYPE/d
+               /^[[:space:]]*#[[:space:]]*include[[:space:]]\+\"xlat\//d
+               /^#[[:space:]]*include[[:space:]]\+MPERS_DEFS$/ {s//'"${m_type} ${VAR_NAME}"';/;q}
+               ' "${PARSER_FILE}" > "${f_c}"
+       $CPP $CPPFLAGS "${f_c}" > "${f_i}"
+       grep -F -q "${m_type}.h" "${f_i}" ||
+               continue
+       sed -i -e '/DEF_MPERS_TYPE/d' "${f_c}"
+       $CC $CFLAGS $ARCH_FLAG "${f_c}" -o "${f_o}"
+       readelf --debug-dump=info "${f_o}" > "${f_d1}"
+       sed -n '
+               /^[[:space:]]*<1>/,/^[[:space:]]*<1><[^>]\+>: Abbrev Number: 0/!d
+               /^[[:space:]]*<[^>]\+><[^>]\+>: Abbrev Number: 0/d
+               s/^[[:space:]]*<[[:xdigit:]]\+>[[:space:]]\+//
+               s/^[[:space:]]*\(\(<[[:xdigit:]]\+>\)\{2\}\):[[:space:]]\+/\1\n/
+               s/[[:space:]]\+$//
+               p' "${f_d1}" > "${f_d2}"
+       gawk -v VAR_NAME="$VAR_NAME" -v ARCH_FLAG="${ARCH_FLAG#-}" \
+               -f "$MPERS_AWK" "${f_d2}" > "${f_h}"
+done
diff --git a/mpers_test.sh b/mpers_test.sh
new file mode 100755 (executable)
index 0000000..e788446
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/sh -efu
+
+mpers_name="$1"; shift
+srcdir=${0%/*}
+mpers_sh="${srcdir}/mpers.sh"
+
+mpers_dir="mpers-$mpers_name"
+mkdir -p "$mpers_dir"
+
+sample="$mpers_dir/sample.c"
+cat > "$sample" <<EOF
+#include "mpers_type.h"
+#include DEF_MPERS_TYPE(int)
+#include MPERS_DEFS
+EOF
+
+expected="$mpers_dir/sample.expected"
+cat > "$expected" <<EOF
+#include <inttypes.h>
+typedef
+int32_t ${mpers_name}_int;
+#define MPERS_${mpers_name}_int ${mpers_name}_int
+EOF
+
+CFLAGS="$CPPFLAGS -I${srcdir}" \
+CPPFLAGS="$CPPFLAGS -I${srcdir} -DIN_MPERS -DMPERS_IS_${mpers_name}" \
+"$mpers_sh" "-$mpers_name" "$sample"
+cmp "$expected" "$mpers_dir"/int.h > /dev/null
diff --git a/mpers_type.h b/mpers_type.h
new file mode 100644 (file)
index 0000000..4ffd2bf
--- /dev/null
@@ -0,0 +1,15 @@
+#ifdef IN_MPERS
+# define STRINGIFY(a) #a
+# define DEF_MPERS_TYPE(args) STRINGIFY(args.h)
+# ifdef MPERS_IS_m32
+#  define MPERS_PREFIX m32_
+#  define MPERS_DEFS "m32_defs.h"
+# elif defined MPERS_IS_mx32
+#  define MPERS_PREFIX mx32_
+#  define MPERS_DEFS "mx32_defs.h"
+# endif
+#else
+# define MPERS_PREFIX
+# define DEF_MPERS_TYPE(args) "empty.h"
+# define MPERS_DEFS "empty.h"
+#endif
index 396a7dd7d992d5f23f05040983143d43805b8912..00060c9b4c8c983781af579cc29ecff32caf725e 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -89,12 +89,14 @@ const struct_sysent sysent0[] = {
 };
 
 #if SUPPORTED_PERSONALITIES > 1
+# include PERSONALITY1_INCLUDE_FUNCS
 static const struct_sysent sysent1[] = {
 # include "syscallent1.h"
 };
 #endif
 
 #if SUPPORTED_PERSONALITIES > 2
+# include PERSONALITY2_INCLUDE_FUNCS
 static const struct_sysent sysent2[] = {
 # include "syscallent2.h"
 };
@@ -143,6 +145,14 @@ static const char *const signalent1[] = {
 static const struct_ioctlent ioctlent1[] = {
 # include "ioctlent1.h"
 };
+# include PERSONALITY0_INCLUDE_PRINTERS_DECLS
+static const struct_printers printers0 = {
+# include PERSONALITY0_INCLUDE_PRINTERS_DEFS
+};
+# include PERSONALITY1_INCLUDE_PRINTERS_DECLS
+static const struct_printers printers1 = {
+# include PERSONALITY1_INCLUDE_PRINTERS_DEFS
+};
 #endif
 
 #if SUPPORTED_PERSONALITIES > 2
@@ -155,6 +165,10 @@ static const char *const signalent2[] = {
 static const struct_ioctlent ioctlent2[] = {
 # include "ioctlent2.h"
 };
+# include PERSONALITY2_INCLUDE_PRINTERS_DECLS
+static const struct_printers printers2 = {
+# include PERSONALITY2_INCLUDE_PRINTERS_DEFS
+};
 #endif
 
 enum {
@@ -202,7 +216,9 @@ const struct_sysent *sysent = sysent0;
 const char *const *errnoent = errnoent0;
 const char *const *signalent = signalent0;
 const struct_ioctlent *ioctlent = ioctlent0;
+const struct_printers *printers = &printers0;
 #endif
+
 unsigned nsyscalls = nsyscalls0;
 unsigned nerrnos = nerrnos0;
 unsigned nsignals = nsignals0;
@@ -278,6 +294,7 @@ set_personality(int personality)
                nioctlents = nioctlents0;
                signalent = signalent0;
                nsignals = nsignals0;
+               printers = &printers0;
                break;
 
        case 1:
@@ -287,6 +304,7 @@ set_personality(int personality)
                nioctlents = nioctlents1;
                signalent = signalent1;
                nsignals = nsignals1;
+               printers = &printers1;
                break;
 
 # if SUPPORTED_PERSONALITIES > 2
@@ -297,6 +315,7 @@ set_personality(int personality)
                nioctlents = nioctlents2;
                signalent = signalent2;
                nsignals = nsignals2;
+               printers = &printers2;
                break;
 # endif
        }