Wednesday, August 17, 2016

Cross Compiling Windows Application and DLLs in (Arch) Linux

Cross compiling 32-bit and 64-bit Windows application in Linux is much easier these days than in the past. Thanks to the Mingw-w64 project.  It's even a little more easier in Arch Linux because most of what you need--including extensive amount of libraries--are already in AUR. For starter, install the cross compiler: https://www.archlinux.org/packages/community/x86_64/mingw-w64-gcc/. Then you can continue to install all other stuff (libraries and their dependencies) that you need. In most cases, you can just build and install the package by using the PKGBUILD file from AUR directly (via: cd ${src_dir}; makepkg -sri ). However, in some cases, you need to make adjustment(s) to the PKGBUILD file.

Let's focus on mingw-w64 in Arch Linux. There are several important matters that you need to take care of to cross compile opensource projects that uses Cmake in Arch Linux to build Windows executables and DLLs:
  • Opensource projects that uses CMAKE build system, need to use the mingw-w64-specific cmake (look at the example PKGBUILD for cmake below).
  • You need to set the include path to the cross compiler toolchain environment include path, not the host include path. 
This is an example PKGBUILD file for a simple Helloworld application that uses boost. It assumes that you have build and install the cross compiled boost DLL in your Arch Linux mingw-w64 environment.
#!/bin/bash

_architectures="x86_64-w64-mingw32 i686-w64-mingw32"

rm -rvf build-*

for _arch in ${_architectures}; do
 mkdir -p build-${_arch} && pushd build-${_arch}
 CMAKE_INCLUDE_PATH="/usr/"${_arch}"/include"
 echo "CMAKE_INCLUDE_PATH = "${CMAKE_INCLUDE_PATH}
 export CMAKE_INCLUDE_PATH
   ${_arch}-cmake ..
 make VERBOSE=1
 popd
done 
The example above is the PKGBUILD file for the sample Helloworld project. You can clone the project over at: https://bitbucket.org/pinczakko/cross_hello_world (direct link: https://bitbucket.org/pinczakko/cross_hello_world.git)

There are also some things to take care if you cross compile opensource projects that uses autotools in Arch Linux to build Windows executables and DLLs:
  • Opensource projects that uses autotools build system, need to use the mingw-w64-specific configure script (look at the example PKGBUILD for configure below).
  • In some cases, you need to "fool" the libtool script to pass the "dynamic/static library integrity" check. You don't need to be afraid with this step because you could always use Linux file utility to verify the compiler output along with wine before testing/using it in real Windows installation.
This is an example PKGBUILD file for popt library:
# Maintainer: Sebastian Morr 
# Modified by Pinczakko for Mingw-w64 cross compilation to 64-bit Windows

pkgname=mingw-w64-popt
_pkgname=popt
pkgver=1.16
pkgrel=1
arch=('any')
pkgdesc="A commandline option parser (mingw-w64)"
makedepends=('mingw-w64-gcc')
license=('custom')
url="http://rpm5.org"
options=(!strip !buildflags staticlibs)
source=("http://rpm5.org/files/${_pkgname}/${_pkgname}-${pkgver}.tar.gz"
        "0001-nl_langinfo.mingw32.patch"
        "197416.all.patch"
        "217602.all.patch"
        "278402-manpage.all.patch"
        "318833.all.patch"
        "356669.all.patch"
        "367153-manpage.all.patch"
        "get-w32-console-maxcols.mingw32.patch"
        "no-uid-stuff-on.mingw32.patch"
        )
sha1sums=('cfe94a15a2404db85858a81ff8de27c8ff3e235e'
          '62640c0a0845cea5f3cd5646d26fd681ea36cadf'
          'bd7c8872f0bb80ec2a8b78596eb3ba5706795133'
          '977fbbe108cf817103f706dd314236e6bace7557'
          '18d169ff43b6ef4ee613272fdb2bbdc01df1f166'
          'a446c763439fe97459c6ea9bea22054a69ea9cc6'
          '2664b32cd6882e3c7da2d1ed3d40b14807a2c604'
          '63e5fdae8160445794458b03fc5a61e7354efada'
          '6599adf3797d7bfb4534bc910372c431fc0efced'
          '4c3b7b302044bd45decec78f7f7d4ece15d9f3f7')

_architectures="i686-w64-mingw32 x86_64-w64-mingw32"

prepare() {
  cd "$srcdir/${_pkgname}-$pkgver"
  patch -p1 -i ../0001-nl_langinfo.mingw32.patch
  patch -p1 -i ../197416.all.patch
  patch -p1 -i ../217602.all.patch
  patch -p1 -i ../278402-manpage.all.patch
  patch -p1 -i ../318833.all.patch
  patch -p1 -i ../356669.all.patch
  patch -p1 -i ../367153-manpage.all.patch
  patch -p1 -i ../get-w32-console-maxcols.mingw32.patch
  patch -p1 -i ../no-uid-stuff-on.mingw32.patch
}

build() {
  # We assume that libtool check on 64-bit Windows DLL is broken
  # in mingw-w64 Linux cross compiler. So, force it to pass all checks
  export lt_cv_deplibs_check_method='pass_all'

  cd "$srcdir/${_pkgname}-$pkgver"
  for _arch in ${_architectures}; do
    mkdir -p build-${_arch} && pushd build-${_arch}
 ${_arch}-configure --enable-shared --enable-static 
    make
 popd
  done
}

package () {
  for _arch in ${_architectures}; do
    cd "${srcdir}/${_pkgname}-${pkgver}/build-${_arch}"
    make install DESTDIR="${pkgdir}"
    rm -rf "${pkgdir}/usr/${_arch}/share/man"
    ${_arch}-strip -x -g "${pkgdir}/usr/${_arch}/bin/"*.dll
    ${_arch}-strip -g "${pkgdir}/usr/${_arch}/lib/"*.a
  done

  install -D -m644 "${srcdir}/${_pkgname}-${pkgver}/COPYING" "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

You can clone the files required to "cross build" popt library at: https://bitbucket.org/pinczakko/cross_mingw-w64-popt (direct link: https://bitbucket.org/pinczakko/cross_mingw-w64-popt.git).

Hopefully, this is useful for those developing Windows application in Linux.

Wednesday, July 27, 2016

Java JAR Reverse Engineering Walkthrough

There are many ways to reverse engineer Java JAR file. However, I found the following steps are the fastest for me to understand the inner working of the Java code that I try to understand:
  1. Extract the target *.class file(s) from the Jar file with: jar -x command.
  2. If the class file(s) is/are recent one (>= java 1.5), use jadretro to condition the class file(s) before passing it through the jad java decompiler. jadretro is at: http://jadretro.sourceforge.net.
  3. Decompile the java class(es) with jad. You can download jad at: http://varaneckas.com/jad/.
  4. Use doxygen (http://www.stack.nl/~dimitri/doxygen/) plus graphviz(http://www.graphviz.org/) to generate the class inheritance and function call graph(s). This should give you an overview of how the class(es) works.
  5. Read the decompilation result as needed. I found that, step 4 will made this step easier as it gives you the hint(s) as to where to start reading the code.
Another approach is to use Radare2 (http://radare.org/r/). But, I've never used Radare for Java decompilation. Therefore, I don't know yet how mature its support. 

Anyway, sometimes interoperability needs forced us to rely on reverse engineering to get insight into how things work. This also applies to Java.

Monday, June 13, 2016

GraphViz Tutorial for The Uninitiated

This is not a tutorial per se. But, it's an example of how a complex graph can be generated by GraphViz DOT. You need to head over to  https://github.com/pinczakko/GraphViz-Samples for the source code. But, for the impatient, this is the result:
Rather complex graph generated from GraphViz DOT
At least this sample shows you how powerful GraphViz is, after investing even just a couple of hours learning the ropes. The bonus is, you can combine your GraphViz DOT code to your Doxygen comments and generate the graph in your code documentation. Isn't that powerful? Head over to http://www.stack.nl/~dimitri/doxygen/manual/diagrams.html for that.

Hopefully, this ease the pain creating your code documentation ;-)


Monday, June 6, 2016

Arch Linux cpupower Missing Library Temporary Fix

If you are experiencing the issue described at https://bbs.archlinux.org/viewtopic.php?id=213404 (copied here for your convenience--courtesy of bartbkr):
After a recent upgrade, when I attempt to use cpupower, I get the following
message:
    cpupower: /usr/lib/libpci.so.3: verion `LIBPCI_3.5' not found (required by cpupower)
I haven't changed any of the setting for cpupower recently and everything was
running smoothly before. Now I can't query the cpu settings any longer.
$ ls /usr/lib/libpci.so*
        /usr/lib/libpci.so
        /usr/lib/libpci.so.3
        /usr/lib/libpci.so.3.4.1

Then, the temporary solution is to downgrade cpupower to version 4.6.1. Follow the general downgrade guide at https://wiki.archlinux.org/index.php/Downgrading_packages. For comparison sake, this is the log of failed cpupower at start-up in my machine:
root@jeez /var/cache/pacman/pkg
 # systemctl status cpupower.service
— cpupower.service - Apply cpupower configuration
   Loaded: loaded (/usr/lib/systemd/system/cpupower.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Mon 2016-06-06 22:07:38 SGT; 44min ago
  Process: 328 ExecStart=/usr/lib/systemd/scripts/cpupower (code=exited, status=1/FAILURE)
 Main PID: 328 (code=exited, status=1/FAILURE)

Jun 06 22:07:37 jeez systemd[1]: Starting Apply cpupower configuration...
Jun 06 22:07:37 jeez cpupower[328]: cpupower: /usr/lib/libpci.so.3: version `LIBPCI_3.5'
Jun 06 22:07:38 jeez systemd[1]: cpupower.service: Main process exited, code=exited, sta
Jun 06 22:07:38 jeez systemd[1]: Failed to start Apply cpupower configuration.
Jun 06 22:07:38 jeez systemd[1]: cpupower.service: Unit entered failed state.
Jun 06 22:07:38 jeez systemd[1]: cpupower.service: Failed with result 'exit-code'.

This is the excerpt the steps that I did to fix the issue via package downgrade:
root@jeez /var/cache/pacman/pkg
 # pacman -U cpupower-4.6-1-x86_64.pkg.tar.xz
loading packages...
warning: downgrading package cpupower (4.6-2 => 4.6-1)
resolving dependencies...
looking for conflicting packages...

Packages (1) cpupower-4.6-1

Total Installed Size:   0.41 MiB
Net Upgrade Size:      -0.10 MiB

:: Proceed with installation? [Y/n] Y
(1/1) checking keys in keyring                            [###############################] 100%
(1/1) checking package integrity                          [###############################] 100%
(1/1) loading package files                               [###############################] 100%
(1/1) checking for file conflicts                         [###############################] 100%
(1/1) checking available disk space                       [###############################] 100%
:: Processing package changes...
(1/1) downgrading cpupower                                [###############################] 100%
:: Running post-transaction hooks...
(1/1) Updating manpage index...
root@jeez /var/cache/pacman/pkg
 # systemctl restart cpupower.service
root@jeez /var/cache/pacman/pkg
 # journalctl -xe
Jun 06 22:51:51 jeez systemd[1]: Starting Apply cpupower configuration...
-- Subject: Unit cpupower.service has begun start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit cpupower.service has begun starting up.
Jun 06 22:51:52 jeez systemd[1]: Started Apply cpupower configuration.
-- Subject: Unit cpupower.service has finished start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit cpupower.service has finished starting up.
--
-- The start-up result is done.
pinczakko@jeez Mon Jun 06 10:52:07pm
~/ systemctl status cpupower.service
— cpupower.service - Apply cpupower configuration
   Loaded: loaded (/usr/lib/systemd/system/cpupower.service; enabled; vendor preset: disabled)
   Active: active (exited) since Mon 2016-06-06 22:51:52 SGT; 26s ago
  Process: 2672 ExecStart=/usr/lib/systemd/scripts/cpupower (code=exited, status=0/SUCCESS)
 Main PID: 2672 (code=exited, status=0/SUCCESS)

Jun 06 22:51:51 jeez systemd[1]: Starting Apply cpupower configuration...
Jun 06 22:51:52 jeez systemd[1]: Started Apply cpupower configuration.

As you see in the shell log above, after downgrading cpupower to version 4.6.1, everything went back to normal. This is only temporary fix until libpci 3.5 promoted from testing to stable. We can go back to cpupower version 4.6.2 by then.