Install public headers, add Arch package, build pepy under Travis and more (#57)

* CMake: Added install directives

* CMake: Added support for find_package(pe-parse)

* Fixed a compilation error on Linux

* CMake: Fix cmake module installation

* Added ArchLinux package

* Finished implementing the address converted example

* peaddrconv: Print the image base address.

* peaddrconv: Enable more warnings.

* Update travis to also build the examples

* Fix a compilation warning on Ubuntu 14.04

* Travis: Add macOS support.

* Better output for Travis, fix a compilation error on macOS.

* Travis: Do not build examples under macOS.

* Travis: Also compile the python module (pepy)

* Readme: Add a section to show how to use the library.

* Windows: Fix a compilation error, enable /analyze (see details).

The nt-headers.h include file is defining several constexpr values
using reserved (by windows.h) names.

These names (i.e.: IMAGE_FILE_MACHINE_UNKNOWN) are in fact macros
defined inside the Windows header files, and causes the preprocessor
to break definitions such as the following one:

constexpr std::uint16_t IMAGE_FILE_MACHINE_UNKNOWN = 0x0;

The fix (for now) consists in including the nt-headers.h file before
windows.h, but we should probably choose whether to use different
names or avoid defining those values (since they are inside the
system header anyway).
This commit is contained in:
Alessandro Gario 2017-11-25 22:01:53 +01:00 committed by Dan Guido
parent e632a37290
commit b60b908fa2
23 changed files with 897 additions and 159 deletions

1
.gitignore vendored
View File

@ -8,4 +8,5 @@ cmake-build-debug
cmake-build-release
build
.vscode
examples_build

View File

@ -1,27 +1,32 @@
language: cpp
os:
- linux
- osx
compiler:
- clang
- gcc
before_install:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update ; fi
script: cmake . && make
- ./travis.sh "$TRAVIS_OS_NAME" initialize
script:
- ./travis.sh "$TRAVIS_OS_NAME" build
matrix:
exclude:
- compiler: gcc
os: osx
env:
global:
- secure: "O+BGqz4ugoVIJbQTh0dJjKRrsSVzkCYSe0WpRzEWK3l8Mw7hqX300g81TxRwTzN2zfUsROMzaeGaXWfGzYakgW59K1WIioaczxtv2MzzUQTbqzJPa+qQoP9bk/b2wJ5jcOL965/rudRju4UiIwuIgzDAMN3nAfIEJgV/2zANLIg="
addons:
coverity_scan:
project:
name: "trailofbits/pe-parse"
description: "Principled, lightweight C/C++ PE parser"
notification_email: dan@trailofbits.com
build_command_prepend: "cmake ."
build_command: "make"
build_command: "./travis.sh linux build"
branch_pattern: master

View File

@ -1,6 +1,10 @@
cmake_minimum_required(VERSION 3.1)
project(pe-parse)
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Default install directory" FORCE)
endif ()
set(CMAKE_VERBOSE_MAKEFILE True)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
@ -9,5 +13,8 @@ endif ()
include(cmake/compilation_flags.cmake)
list(APPEND GLOBAL_CXXFLAGS ${DEFAULT_CXX_FLAGS})
add_subdirectory(parser-library)
add_subdirectory(dump-prog)
add_subdirectory(pe-parser-library)
add_subdirectory(dump-pe)
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")

View File

@ -31,6 +31,19 @@ pe-parse is built using `cmake` and has no major dependencies.
2. `cmake .`
3. `make`
Using the library
=======
Once the library is installed, linking to it is easy! Add the following lines in your CMake project:
```
find_package(peparse REQUIRED)
target_link_libraries(your_target_name ${PEPARSE_LIBRARIES})
target_include_directories(your_target_name PRIVATE ${PEPARSE_INCLUDE_DIRS})
```
You can see a full example in the examples/peaddrconv folder.
Authors
=======
pe-parse was designed and implemented by Andrew Ruef (andrew@trailofbits.com), with significant contributions from [Wesley Shields](https://github.com/wxsBSD).

View File

@ -1,5 +1,5 @@
if (WIN32)
list(APPEND DEFAULT_CXX_FLAGS /W4)
list(APPEND DEFAULT_CXX_FLAGS /W4 /analyze)
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
list(APPEND DEFAULT_CXX_FLAGS /Zi)
@ -24,13 +24,13 @@ else ()
)
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
list(APPEND PROJECT_CXXFLAGS -gdwarf-2 -g3)
list(APPEND DEFAULT_CXX_FLAGS -gdwarf-2 -g3)
endif ()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "This is a debug build; enabling -Weverything...")
list(APPEND PROJECT_CXXFLAGS
list(APPEND DEFAULT_CXX_FLAGS
-Weverything -Wno-c++98-compat -Wno-missing-prototypes
-Wno-missing-variable-declarations -Wno-global-constructors
-Wno-exit-time-destructors -Wno-padded -Wno-error

View File

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.1)
project(dump-prog)
project(dump-pe)
add_executable(${PROJECT_NAME} dump.cpp)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE pe-parser-library)
target_compile_options(${PROJECT_NAME} PRIVATE ${GLOBAL_CXXFLAGS})
install(TARGETS ${PROJECT_NAME} DESTINATION "bin")

View File

@ -22,9 +22,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "parse.h"
#include <iostream>
#include <sstream>
#include <cstring>
#include <parser-library/parse.h>
using namespace std;
using namespace peparse;
@ -273,7 +275,13 @@ int printSecs(void *N,
<< endl;
int main(int argc, char *argv[]) {
if (argc == 2) {
if (argc != 2 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
std::cout << "dump-pe utility from Trail of Bits\n";
std::cout << "Repository: https://github.com/trailofbits/pe-parse\n\n";
std::cout << "Usage:\n\tdump-pe /path/to/executable.exe\n";
return 1;
}
parsed_pe *p = ParsePEFromFile(argv[1]);
if (p != NULL) {
@ -379,6 +387,6 @@ int main(int argc, char *argv[]) {
<< endl;
std::cout << "Location: " << GetPEErrLoc() << endl;
}
}
return 0;
}

View File

@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.1)
project(peaddrconv)
if (WIN32)
list(APPEND PEADDRCONV_CXXFLAGS /W4 /analyze)
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
list(APPEND PEADDRCONV_CXXFLAGS /Zi)
endif ()
if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
list(APPEND PEADDRCONV_CXXFLAGS /WX)
endif ()
else ()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
list(APPEND PEADDRCONV_CXXFLAGS
-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization
-Wformat=2 -Winit-self -Wlong-long -Wmissing-declarations -Wmissing-include-dirs -Wcomment
-Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion
-Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wunused -Wuninitialized
-Wno-missing-declarations
)
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
list(APPEND PEADDRCONV_CXXFLAGS -gdwarf-2 -g3)
endif ()
endif ()
find_package(peparse REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${PEPARSE_LIBRARIES})
target_include_directories(${PROJECT_NAME} PRIVATE ${PEPARSE_INCLUDE_DIRS})
target_compile_options(${PROJECT_NAME} PRIVATE ${PEADDRCONV_CXXFLAGS})
install(TARGETS ${PROJECT_NAME} DESTINATION "bin")

View File

@ -0,0 +1 @@
Note that you have to install the library before you can build this example!

View File

@ -0,0 +1,374 @@
#include <iostream>
#include <limits>
#include <memory>
#include <climits>
#include <cstring>
#include <parser-library/parse.h>
using ParsedPeRef =
std::unique_ptr<peparse::parsed_pe, void (*)(peparse::parsed_pe *)>;
ParsedPeRef openExecutable(const std::string &path) noexcept {
// The factory function does not throw exceptions!
ParsedPeRef obj(peparse::ParsePEFromFile(path.data()),
peparse::DestructParsedPE);
if (!obj) {
return ParsedPeRef(nullptr, peparse::DestructParsedPE);
}
return obj;
}
enum class AddressType {
PhysicalOffset,
RelativeVirtualAddress,
VirtualAddress
};
bool convertAddress(ParsedPeRef &pe,
std::uintptr_t address,
AddressType source_type,
AddressType destination_type,
std::uintptr_t &result) noexcept {
if (source_type == destination_type) {
result = address;
return true;
}
std::uint64_t image_base_address = 0U;
if (pe->peHeader.nt.FileHeader.Machine == peparse::IMAGE_FILE_MACHINE_AMD64) {
image_base_address = pe->peHeader.nt.OptionalHeader64.ImageBase;
} else {
image_base_address = pe->peHeader.nt.OptionalHeader.ImageBase;
}
struct SectionAddressLimits final {
std::uintptr_t lowest_rva;
std::uintptr_t lowest_offset;
std::uintptr_t highest_rva;
std::uintptr_t highest_offset;
};
auto L_getSectionAddressLimits = [](void *N,
peparse::VA secBase,
std::string &secName,
peparse::image_section_header s,
peparse::bounded_buffer *data) -> int {
static_cast<void>(secBase);
static_cast<void>(secName);
static_cast<void>(data);
SectionAddressLimits *section_address_limits =
static_cast<SectionAddressLimits *>(N);
section_address_limits->lowest_rva =
std::min(section_address_limits->lowest_rva,
static_cast<std::uintptr_t>(s.VirtualAddress));
section_address_limits->lowest_offset =
std::min(section_address_limits->lowest_offset,
static_cast<std::uintptr_t>(s.PointerToRawData));
std::uintptr_t sectionSize;
if (s.SizeOfRawData != 0) {
sectionSize = s.SizeOfRawData;
} else {
sectionSize = s.Misc.VirtualSize;
}
section_address_limits->highest_rva =
std::max(section_address_limits->highest_rva,
static_cast<std::uintptr_t>(s.VirtualAddress + sectionSize));
section_address_limits->highest_offset =
std::max(section_address_limits->highest_offset,
static_cast<std::uintptr_t>(s.PointerToRawData + sectionSize));
return 0;
};
SectionAddressLimits section_address_limits = {
std::numeric_limits<std::uintptr_t>::max(),
std::numeric_limits<std::uintptr_t>::max(),
std::numeric_limits<std::uintptr_t>::min(),
std::numeric_limits<std::uintptr_t>::min()};
IterSec(pe.get(), L_getSectionAddressLimits, &section_address_limits);
switch (source_type) {
case AddressType::PhysicalOffset: {
if (address >= section_address_limits.highest_offset) {
return false;
}
if (destination_type == AddressType::RelativeVirtualAddress) {
struct CallbackData final {
bool found;
std::uintptr_t address;
std::uintptr_t result;
};
auto L_inspectSection = [](void *N,
peparse::VA secBase,
std::string &secName,
peparse::image_section_header s,
peparse::bounded_buffer *data) -> int {
static_cast<void>(secBase);
static_cast<void>(secName);
static_cast<void>(data);
std::uintptr_t sectionBaseOffset = s.PointerToRawData;
std::uintptr_t sectionEndOffset = sectionBaseOffset;
if (s.SizeOfRawData != 0) {
sectionEndOffset += s.SizeOfRawData;
} else {
sectionEndOffset += s.Misc.VirtualSize;
}
auto callback_data = static_cast<CallbackData *>(N);
if (callback_data->address >= sectionBaseOffset &&
callback_data->address < sectionEndOffset) {
callback_data->result = s.VirtualAddress + (callback_data->address -
s.PointerToRawData);
callback_data->found = true;
return 1;
}
return 0;
};
CallbackData callback_data = {false, address, 0U};
IterSec(pe.get(), L_inspectSection, &callback_data);
if (!callback_data.found) {
return false;
}
result = callback_data.result;
return true;
} else if (destination_type == AddressType::VirtualAddress) {
std::uintptr_t rva = 0U;
if (!convertAddress(pe,
address,
source_type,
AddressType::RelativeVirtualAddress,
rva)) {
return false;
}
result = image_base_address + rva;
return true;
}
return false;
}
case AddressType::RelativeVirtualAddress: {
if (address < section_address_limits.lowest_rva) {
result = address;
return true;
} else if (address >= section_address_limits.highest_rva) {
return false;
}
if (destination_type == AddressType::PhysicalOffset) {
struct CallbackData final {
bool found;
std::uintptr_t address;
std::uintptr_t result;
};
auto L_inspectSection = [](void *N,
peparse::VA secBase,
std::string &secName,
peparse::image_section_header s,
peparse::bounded_buffer *data) -> int {
static_cast<void>(secBase);
static_cast<void>(secName);
static_cast<void>(data);
std::uintptr_t sectionBaseAddress = s.VirtualAddress;
std::uintptr_t sectionEndAddress =
sectionBaseAddress + s.Misc.VirtualSize;
auto callback_data = static_cast<CallbackData *>(N);
if (callback_data->address >= sectionBaseAddress &&
callback_data->address < sectionEndAddress) {
callback_data->result =
s.PointerToRawData +
(callback_data->address - sectionBaseAddress);
callback_data->found = true;
return 1;
}
return 0;
};
CallbackData callback_data = {false, address, 0U};
IterSec(pe.get(), L_inspectSection, &callback_data);
if (!callback_data.found) {
return false;
}
result = callback_data.result;
return true;
} else if (destination_type == AddressType::VirtualAddress) {
result = image_base_address + address;
return true;
}
return false;
}
case AddressType::VirtualAddress: {
if (address < image_base_address) {
return false;
}
std::uintptr_t rva = address - image_base_address;
return convertAddress(pe,
rva,
AddressType::RelativeVirtualAddress,
destination_type,
result);
}
default: { return false; }
}
}
int main(int argc, char *argv[]) {
if (argc != 3 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
std::cout << "PE address conversion utility from Trail of Bits\n";
std::cout << "Usage:\n\tpeaddrconv /path/to/executable.exe address\n\n";
std::cout << "The <address> parameter is always interpreted as hex!\n";
return 1;
}
const char *executable_path = argv[1];
const char *address_as_string = argv[2];
char *last_parsed_char = nullptr;
errno = 0;
auto address = std::strtoull(address_as_string, &last_parsed_char, 16);
if (address == 0U && *last_parsed_char != 0) {
std::cout << "Invalid address specified\n";
return 1;
} else if (address == ULLONG_MAX && errno == ERANGE) {
std::cout << "The address you specified is too big\n";
return 1;
}
auto pe = openExecutable(executable_path);
if (!pe) {
std::cout << "Failed to open the executable\n\n";
std::cout << "Error: " << peparse::GetPEErr() << " ("
<< peparse::GetPEErrString() << ")\n";
std::cout << "Location: " << peparse::GetPEErrLoc() << "\n";
return 1;
}
std::uint64_t image_base_address = 0U;
if (pe->peHeader.nt.FileHeader.Machine == peparse::IMAGE_FILE_MACHINE_AMD64) {
image_base_address = pe->peHeader.nt.OptionalHeader64.ImageBase;
} else {
image_base_address = pe->peHeader.nt.OptionalHeader.ImageBase;
}
std::cout << "Image base address: 0x" << std::hex << image_base_address
<< "\n";
std::cout << "Converting address 0x" << std::hex << address << "...\n\n";
std::uintptr_t result = 0U;
std::cout << "as Physical offset (off)\n";
std::cout << " to rva:\t";
if (convertAddress(pe,
address,
AddressType::PhysicalOffset,
AddressType::RelativeVirtualAddress,
result)) {
std::cout << "0x" << std::hex << result;
} else {
std::cout << "-";
}
std::cout << "\n";
std::cout << " to va:\t";
if (convertAddress(pe,
address,
AddressType::PhysicalOffset,
AddressType::VirtualAddress,
result)) {
std::cout << "0x" << std::hex << result;
} else {
std::cout << "-";
}
std::cout << "\n\n";
std::cout << "as Relative virtual address (rva)\n";
std::cout << " to off:\t";
if (convertAddress(pe,
address,
AddressType::RelativeVirtualAddress,
AddressType::PhysicalOffset,
result)) {
std::cout << "0x" << std::hex << result;
} else {
std::cout << "-";
}
std::cout << "\n";
std::cout << " to va:\t";
if (convertAddress(pe,
address,
AddressType::RelativeVirtualAddress,
AddressType::VirtualAddress,
result)) {
std::cout << "0x" << std::hex << result;
} else {
std::cout << "-";
}
std::cout << "\n\n";
std::cout << "as Virtual address (va)\n";
std::cout << " to off:\t";
if (convertAddress(pe,
address,
AddressType::VirtualAddress,
AddressType::PhysicalOffset,
result)) {
std::cout << "0x" << std::hex << result;
} else {
std::cout << "-";
}
std::cout << "\n";
std::cout << " to rva:\t";
if (convertAddress(pe,
address,
AddressType::VirtualAddress,
AddressType::RelativeVirtualAddress,
result)) {
std::cout << "0x" << std::hex << result;
} else {
std::cout << "-";
}
std::cout << "\n";
return 0;
}

5
packages/archlinux/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
pkg
src
*.pkg.tar
*.pkg.tar.xz

View File

@ -0,0 +1,18 @@
pkgname=pe-parse
pkgver=1.0
pkgrel=1
arch=("x86_64" "x86")
pkgdesc="PE parsing library from Trail of Bits"
url="https://github.com/trailofbits/pe-parse"
license=('MIT')
makedepends=("cmake")
provides=("pe-parse")
build() {
cmake ../../../
make -j `nproc`
}
package() {
make DESTDIR="$pkgdir/" install
}

View File

@ -1,6 +0,0 @@
cmake_minimum_required(VERSION 3.1)
project(pe-parser-library)
add_library(${PROJECT_NAME} buffer.cpp parse.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_options(${PROJECT_NAME} PRIVATE ${GLOBAL_CXXFLAGS})

View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.1)
project(pe-parser-library)
# List all files explicitly; this will make IDEs happy (i.e. QtCreator, CLion, ...)
list(APPEND PEPARSERLIB_SOURCEFILES
include/parser-library/parse.h
include/parser-library/nt-headers.h
include/parser-library/to_string.h
src/buffer.cpp
src/parse.cpp
)
add_library(${PROJECT_NAME} STATIC ${PEPARSERLIB_SOURCEFILES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_options(${PROJECT_NAME} PRIVATE ${GLOBAL_CXXFLAGS})
install(TARGETS ${PROJECT_NAME} DESTINATION "lib")
install(FILES "cmake/peparse-config.cmake" DESTINATION "lib/cmake/peparse")
install(DIRECTORY "include/parser-library" DESTINATION "include")

View File

@ -0,0 +1,5 @@
find_path(PEPARSE_INCLUDE_DIR "parser-library/parse.h")
find_library(PEPARSE_LIBRARIES NAMES "libpe-parser-library.a")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(libproxy DEFAULT_MSG PEPARSE_INCLUDE_DIR PEPARSE_LIBRARIES)

View File

@ -25,6 +25,7 @@ THE SOFTWARE.
#pragma once
#include <cstdint>
#include <string>
#define _offset(t, f) \
static_cast<std::uint32_t>( \

View File

@ -22,12 +22,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "parse.h"
#include <cstring>
#include <fstream>
// keep this header above "windows.h" because it contains many types
#include <parser-library/parse.h>
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include <intrin.h>
#include <windows.h>
#else

View File

@ -22,15 +22,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "parse.h"
#include "nt-headers.h"
#include "to_string.h"
#include <algorithm>
#include <cstring>
#include <list>
#include <stdexcept>
#include <parser-library/nt-headers.h>
#include <parser-library/parse.h>
#include <parser-library/to_string.h>
using namespace std;
namespace peparse {

View File

@ -25,8 +25,8 @@
* SUCH DAMAGE.
*/
#include "parse.h"
#include <Python.h>
#include <parser-library/parse.h>
#include <structmember.h>
using namespace peparse;
@ -47,8 +47,7 @@ using namespace peparse;
* Needed for compatibility with python3
*/
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size) \
PyObject_HEAD_INIT(type) size,
#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
#endif
#ifndef Py_TYPE
@ -77,9 +76,13 @@ using namespace peparse;
static PyObject *pepy_error;
struct pepy { PyObject_HEAD };
struct pepy {
PyObject_HEAD
};
struct pepy_parsed { PyObject_HEAD parsed_pe *pe; };
struct pepy_parsed {
PyObject_HEAD parsed_pe *pe;
};
struct pepy_section {
PyObject_HEAD PyObject *name;
@ -719,7 +722,8 @@ static PyObject *pepy_parsed_get_bytes(PyObject *self, PyObject *args) {
uint8_t *buf = new (std::nothrow) uint8_t[len];
if (!buf) {
/* in case allocation failed */
PyErr_SetString(pepy_error, "Unable to create initial buffer (allocation failure).");
PyErr_SetString(pepy_error,
"Unable to create initial buffer (allocation failure).");
return NULL;
}
@ -1279,8 +1283,7 @@ static PyObject *pepy_parse(PyObject *self, PyObject *args) {
static PyMethodDef pepy_methods[] = {
{"parse", pepy_parse, METH_VARARGS, "Parse PE from file."}, {NULL}};
static
PyObject* pepi_module_init(void) {
static PyObject *pepi_module_init(void) {
PyObject *m;
if (PyType_Ready(&pepy_parsed_type) < 0 ||
@ -1401,13 +1404,11 @@ PyObject* pepi_module_init(void) {
}
#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC PyInit_pepy(void)
{
PyMODINIT_FUNC PyInit_pepy(void) {
return pepi_module_init();
}
#else
PyMODINIT_FUNC initpepy(void)
{
PyMODINIT_FUNC initpepy(void) {
pepi_module_init();
}
#endif

View File

@ -28,15 +28,15 @@ from distutils.core import setup, Extension
INCLUDE_DIRS = ['/usr/local/include',
'/opt/local/include',
'/usr/include',
'../parser-library']
'../pe-parser-library/include']
LIBRARY_DIRS = ['/usr/lib',
'/usr/local/lib']
extension_mod = Extension('pepy',
sources = ['pepy.cpp',
'../parser-library/parse.cpp',
'../parser-library/buffer.cpp'],
extra_compile_args = ["-g", "-O0"], # Debug only
'../pe-parser-library/src/parse.cpp',
'../pe-parser-library/src/buffer.cpp'],
extra_compile_args = ["-std=c++11", "-g", "-O0"], # Debug only
include_dirs = INCLUDE_DIRS,
library_dirs = LIBRARY_DIRS)

239
travis.sh Executable file
View File

@ -0,0 +1,239 @@
#!/usr/bin/env bash
main() {
if [ $# -ne 2 ] ; then
printf "Usage:\n\ttravis.sh <linux|osx> <initialize|build>\n"
return 1
fi
local platform_name="$1"
local operation_type="$2"
if [[ "${platform_name}" != "osx" && "${platform_name}" != "linux" ]] ; then
printf "Invalid platform: ${platform_name}\n"
return 1
fi
if [[ "${operation_type}" == "initialize" ]] ; then
"${platform_name}_initialize"
return $?
elif [[ "$operation_type" == "build" ]] ; then
"${platform_name}_build"
return $?
else
printf "Invalid operation\n"
return 1
fi
}
get_processor_count() {
which nproc > /dev/null
if [ $? -eq 0 ] ; then
nproc
return 0
fi
which sysctl > /dev/null
if [ $? -eq 0 ] ; then
sysctl -n hw.ncpu
return 0
fi
return 1
}
linux_initialize() {
printf "Initializing platform: linux\n"
local log_file=`mktemp`
printf " > Updating the package database..\n"
sudo apt-get -qq update > "${log_file}" 2>&1
if [ $? -ne 0 ] ; then
printf " x The package database could not be updated\n\n\n"
cat "${log_file}"
return 1
fi
printf " > Installing the required packages...\n"
sudo apt-get install -qqy cmake python2.7 python-dev build-essential realpath > "${log_file}" 2>&1
if [ $? -ne 0 ] ; then
printf " x Could not install the required dependencies\n\n\n"
cat "${log_file}"
return 1
fi
printf " > The system has been successfully initialized\n"
return 0
}
osx_initialize() {
printf "Initializing platform: macOS\n"
local log_file=`mktemp`
printf " > Updating the package database..\n"
brew update > "${log_file}" 2>&1
if [ $? -ne 0 ] ; then
printf " x The package database could not be updated\n\n\n"
cat "${log_file}"
return 1
fi
printf " > Installing CMake...\n"
brew install cmake > "${log_file}" 2>&1
if [ $? -ne 0 ] ; then
printf " x Failed to install CMake\n\n\n"
cat "${log_file}"
fi
printf " > The system has been successfully initialized\n"
return 0
}
common_build() {
printf "Gathering system information...\n"
which cmake > /dev/null
printf " > CMake version: "
if [ $? -eq 0 ] ; then
cmake --version | head -n 1
else
printf "not found\n"
fi
which gcc > /dev/null
printf " > GCC version: "
if [ $? -eq 0 ] ; then
gcc --version | head -n 1
else
printf "not found\n"
fi
which clang > /dev/null
printf " > Clang version: "
if [ $? -eq 0 ] ; then
clang --version | head -n 1
else
printf "not found\n"
fi
printf "\n"
printf "Library\n"
if [ ! -d "build" ] ; then
printf " > Creating the build directory...\n"
mkdir "build"
if [ $? -ne 0 ] ; then
printf " x Failed to create the build directory\n"
return 1
fi
fi
local log_file=`mktemp`
local processor_count=`get_processor_count`
printf " > Configuring...\n"
( cd "build" && cmake .. ) > "$log_file" 2>&1
if [ $? -ne 0 ] ; then
printf " x Configure failed; CMake returned an error.\n\n\n"
cat "$log_file"
return 1
fi
printf " > Building...\n"
( cd "build" && make -j "${processor_count}" ) > "$log_file" 2>&1
if [ $? -ne 0 ] ; then
printf " x The build has failed.\n\n\n"
cat "$log_file"
return 1
fi
printf " > Installing...\n"
sudo touch /usr/lib/test_file > /dev/null 2>&1
if [ $? -ne 0 ] ; then
printf " x Access denied to /usr/lib; examples will not be built\n"
else
( cd "build" && sudo make install ) > "$log_file" 2>&1
if [ $? -ne 0 ] ; then
printf " x Failed to install the library.\n\n\n"
cat "$log_file"
return 1
fi
printf "\n"
printf "Examples\n"
if [ ! -d "examples_build" ] ; then
printf " > Creating the build directory...\n"
mkdir "examples_build"
if [ $? -ne 0 ] ; then
printf " x Failed to create the build directory\n\n\n"
cat "$log_file"
return 1
fi
fi
printf " > Configuring...\n"
( cd "examples_build" && cmake "../examples/peaddrconv" ) > "$log_file" 2>&1
if [ $? -ne 0 ] ; then
printf " x Configure failed; CMake returned an error.\n\n\n"
cat "$log_file"
return 1
fi
printf " > Building...\n"
( cd "examples_build" && make -j "${processor_count}" ) > "$log_file" 2>&1
if [ $? -ne 0 ] ; then
printf " x The build has failed.\n\n\n"
cat "$log_file"
return 1
fi
fi
printf "\n"
printf "pepy\n"
printf " > Building...\n"
( cd python && python2 ./setup.py build ) > "$log_file" 2>&1
if [ $? -ne 0 ] ; then
printf " x Build failed.\n\n\n"
cat "$log_file"
return 1
fi
return 0
}
linux_build() {
printf "Building platform: linux\n"
source /etc/*-release
printf "Distribution: ${DISTRIB_DESCRIPTION}\n\n"
common_build
if [ $? -ne 0 ] ; then
return 1
fi
return 0
}
osx_build() {
printf "Building platform: macOS\n\n"
printf "macOS version: "
sw_vers -productVersion
common_build
if [ $? -ne 0 ] ; then
return 1
fi
return 0
}
main $@
exit $?