mirror of
https://github.com/QuasarApp/pe-parse.git
synced 2025-04-26 12:24:32 +00:00
Directory entry retrieval (#90)
* pe-parser-library: Directory entry extraction Also runs clang-format on all library files. * dump-pe: Refactor, clang-format * pe-parser-library: Use enum for directory kinds * travis: Refactor * travis: Fixup stages * travis: Fix matrix * examples, pe-parser-library, pepy: clang-format * travis: Use minimal for lint * travis: Use find * clang-format: Remove old option * travis: More experimentation * travis: Move addons * travis: Remove coverity * travis: Hackery * travis: Move addons up * .travis: clang-format-8 * examples: clang-format * travis: Fix homebrew * CONTRIBUTING: Add contrib guidelines * travis: Build python ext, reenable coverity Remove old build files. * travis: Re-add coverity secret * travis: Build with coverity in a separate dir
This commit is contained in:
parent
1544c61c38
commit
2c775e5d6a
@ -2,7 +2,6 @@ AlignEscapedNewlinesLeft: true
|
|||||||
AllowShortFunctionsOnASingleLine: false
|
AllowShortFunctionsOnASingleLine: false
|
||||||
BinPackArguments: false
|
BinPackArguments: false
|
||||||
BinPackParameters: false
|
BinPackParameters: false
|
||||||
BreakBeforeBraces: Attach
|
|
||||||
ColumnLimit: 80
|
ColumnLimit: 80
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
IndentWidth: 2
|
IndentWidth: 2
|
||||||
|
70
.travis.yml
70
.travis.yml
@ -1,32 +1,56 @@
|
|||||||
|
__build_stage_script: &__build_stage_script
|
||||||
|
stage: build
|
||||||
language: cpp
|
language: cpp
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
|
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
- gcc
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- ./travis.sh "$TRAVIS_OS_NAME" initialize
|
|
||||||
script:
|
script:
|
||||||
- ./travis.sh "$TRAVIS_OS_NAME" build
|
- mkdir build && cd build
|
||||||
|
- cmake ..
|
||||||
matrix:
|
- make
|
||||||
exclude:
|
- cd ../python
|
||||||
- compiler: gcc
|
- python2 setup.py build
|
||||||
os: osx
|
- python3 setup.py build
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- secure: "O+BGqz4ugoVIJbQTh0dJjKRrsSVzkCYSe0WpRzEWK3l8Mw7hqX300g81TxRwTzN2zfUsROMzaeGaXWfGzYakgW59K1WIioaczxtv2MzzUQTbqzJPa+qQoP9bk/b2wJ5jcOL965/rudRju4UiIwuIgzDAMN3nAfIEJgV/2zANLIg="
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- cmake
|
||||||
|
- python2.7
|
||||||
|
- python-dev
|
||||||
|
- build-essential
|
||||||
|
- realpath
|
||||||
|
- libicu-dev
|
||||||
|
homebrew:
|
||||||
|
packages:
|
||||||
|
- cmake
|
||||||
coverity_scan:
|
coverity_scan:
|
||||||
project:
|
project:
|
||||||
name: "trailofbits/pe-parse"
|
name: "trailofbits/pe-parse"
|
||||||
description: "Principled, lightweight C/C++ PE parser"
|
description: "Principled, lightweight C/C++ PE parser"
|
||||||
notification_email: dan@trailofbits.com
|
notification_email: dan@trailofbits.com
|
||||||
build_command: "./travis.sh linux build"
|
build_command_prepend: mkdir cov_build && cd cov_build && cmake ..
|
||||||
|
build_command: make
|
||||||
branch_pattern: master
|
branch_pattern: master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
include:
|
||||||
|
- stage: lint
|
||||||
|
language: minimal
|
||||||
|
dist: bionic
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- clang-format-8
|
||||||
|
script:
|
||||||
|
- find . \( -name '*.h' \) -or \( -name '*.cpp' \) | xargs clang-format -i -style=file
|
||||||
|
- git diff --exit-code
|
||||||
|
- <<: *__build_stage_script
|
||||||
|
os: linux
|
||||||
|
compiler: clang
|
||||||
|
- <<: *__build_stage_script
|
||||||
|
os: linux
|
||||||
|
compiler: gcc
|
||||||
|
- <<: *__build_stage_script
|
||||||
|
os: osx
|
||||||
|
compiler: clang
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- secure: "O+BGqz4ugoVIJbQTh0dJjKRrsSVzkCYSe0WpRzEWK3l8Mw7hqX300g81TxRwTzN2zfUsROMzaeGaXWfGzYakgW59K1WIioaczxtv2MzzUQTbqzJPa+qQoP9bk/b2wJ5jcOL965/rudRju4UiIwuIgzDAMN3nAfIEJgV/2zANLIg="
|
||||||
|
26
CONTRIBUTING.md
Normal file
26
CONTRIBUTING.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Contributing to pe-parse
|
||||||
|
========================
|
||||||
|
|
||||||
|
Hello, and welcome to the contributing guidelines for pe-parse!
|
||||||
|
|
||||||
|
For general building instructions, see the [README](README.md).
|
||||||
|
|
||||||
|
For licensing information, see the [LICENSE](LICENSE.txt) file. pe-parse includes a CLA; you will be
|
||||||
|
automatically prompted to sign it during your first PR.
|
||||||
|
|
||||||
|
## General contribution guidelines
|
||||||
|
|
||||||
|
* Your changes should be valid C++11
|
||||||
|
* Your changes should work across all major compiler vendors (GCC, Clang, MSVC) and all
|
||||||
|
major operating systems (Linux, macOS, Windows)
|
||||||
|
* Your changes should be auto-formatted with `clang-format -style=file`
|
||||||
|
* Your changes should not introduce *mandatory* third-party dependencies
|
||||||
|
|
||||||
|
## Adding features
|
||||||
|
|
||||||
|
Feature additions to either the parsing library or `dump-pe` are welcome!
|
||||||
|
|
||||||
|
Check out the following issue labels for some contribution ideas:
|
||||||
|
|
||||||
|
* [Enhancements](https://github.com/trailofbits/pe-parse/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
|
||||||
|
* [Hacktoberfest](https://github.com/trailofbits/pe-parse/issues?q=is%3Aissue+is%3Aopen+label%3Ahacktoberfest)
|
@ -22,10 +22,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <parser-library/parse.h>
|
#include <parser-library/parse.h>
|
||||||
|
|
||||||
@ -232,8 +232,8 @@ int printRich(void *N, rich_entry r) {
|
|||||||
|
|
||||||
std::cout << std::setw(10) << "ProdId:" << std::setw(7) << r.ProductId;
|
std::cout << std::setw(10) << "ProdId:" << std::setw(7) << r.ProductId;
|
||||||
std::cout << std::setw(10) << "Build:" << std::setw(7) << r.BuildNumber;
|
std::cout << std::setw(10) << "Build:" << std::setw(7) << r.BuildNumber;
|
||||||
std::cout << std::setw(10) << "Name:"
|
std::cout << std::setw(10) << "Name:" << std::setw(20)
|
||||||
<< std::setw(20) << GetRichProductName(r.ProductId, r.BuildNumber);
|
<< GetRichProductName(r.ProductId, r.BuildNumber);
|
||||||
std::cout << std::setw(10) << "Count:" << std::setw(7) << r.Count << "\n";
|
std::cout << std::setw(10) << "Count:" << std::setw(7) << r.Count << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -275,18 +275,17 @@ int printSecs(void *N,
|
|||||||
if (data)
|
if (data)
|
||||||
std::cout << "Sec Size: " << std::dec << data->bufLen << "\n";
|
std::cout << "Sec Size: " << std::dec << data->bufLen << "\n";
|
||||||
else
|
else
|
||||||
std::cout << "Sec Size: 0" << "\n";
|
std::cout << "Sec Size: 0"
|
||||||
|
<< "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DUMP_FIELD(x) \
|
#define DUMP_FIELD(x) \
|
||||||
std::cout << "" #x << ": 0x"; \
|
std::cout << "" #x << ": 0x"; \
|
||||||
std::cout << std::hex << static_cast<std::uint64_t>(p->peHeader.nt.x) \
|
std::cout << std::hex << static_cast<std::uint64_t>(p->peHeader.nt.x) << "\n";
|
||||||
<< "\n";
|
|
||||||
#define DUMP_DEC_FIELD(x) \
|
#define DUMP_DEC_FIELD(x) \
|
||||||
std::cout << "" #x << ": "; \
|
std::cout << "" #x << ": "; \
|
||||||
std::cout << std::dec << static_cast<std::uint64_t>(p->peHeader.nt.x) \
|
std::cout << std::dec << static_cast<std::uint64_t>(p->peHeader.nt.x) << "\n";
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
if (argc != 2 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
|
if (argc != 2 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
|
||||||
@ -297,8 +296,13 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parsed_pe *p = ParsePEFromFile(argv[1]);
|
parsed_pe *p = ParsePEFromFile(argv[1]);
|
||||||
|
if (p == nullptr) {
|
||||||
|
std::cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")"
|
||||||
|
<< "\n";
|
||||||
|
std::cout << "Location: " << GetPEErrLoc() << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (p != NULL) {
|
|
||||||
// Print Rich header info
|
// Print Rich header info
|
||||||
if (p->peHeader.rich.isPresent) {
|
if (p->peHeader.rich.isPresent) {
|
||||||
std::cout << "Rich header: present\n";
|
std::cout << "Rich header: present\n";
|
||||||
@ -373,15 +377,20 @@ int main(int argc, char *argv[]) {
|
|||||||
#undef DUMP_FIELD
|
#undef DUMP_FIELD
|
||||||
#undef DUMP_DEC_FIELD
|
#undef DUMP_DEC_FIELD
|
||||||
|
|
||||||
std::cout << "Imports: " << "\n";
|
std::cout << "Imports: "
|
||||||
|
<< "\n";
|
||||||
IterImpVAString(p, printImports, NULL);
|
IterImpVAString(p, printImports, NULL);
|
||||||
std::cout << "Relocations: " << "\n";
|
std::cout << "Relocations: "
|
||||||
|
<< "\n";
|
||||||
IterRelocs(p, printRelocs, NULL);
|
IterRelocs(p, printRelocs, NULL);
|
||||||
std::cout << "Symbols (symbol table): " << "\n";
|
std::cout << "Symbols (symbol table): "
|
||||||
|
<< "\n";
|
||||||
IterSymbols(p, printSymbols, NULL);
|
IterSymbols(p, printSymbols, NULL);
|
||||||
std::cout << "Sections: " << "\n";
|
std::cout << "Sections: "
|
||||||
|
<< "\n";
|
||||||
IterSec(p, printSecs, NULL);
|
IterSec(p, printSecs, NULL);
|
||||||
std::cout << "Exports: " << "\n";
|
std::cout << "Exports: "
|
||||||
|
<< "\n";
|
||||||
IterExpVA(p, printExps, NULL);
|
IterExpVA(p, printExps, NULL);
|
||||||
|
|
||||||
// read the first 8 bytes from the entry point and print them
|
// read the first 8 bytes from the entry point and print them
|
||||||
@ -389,7 +398,8 @@ int main(int argc, char *argv[]) {
|
|||||||
if (GetEntryPoint(p, entryPoint)) {
|
if (GetEntryPoint(p, entryPoint)) {
|
||||||
std::cout << "First 8 bytes from entry point (0x";
|
std::cout << "First 8 bytes from entry point (0x";
|
||||||
|
|
||||||
std::cout << std::hex << entryPoint << "):" << "\n";
|
std::cout << std::hex << entryPoint << "):"
|
||||||
|
<< "\n";
|
||||||
for (std::size_t i = 0; i < 8; i++) {
|
for (std::size_t i = 0; i < 8; i++) {
|
||||||
std::uint8_t b;
|
std::uint8_t b;
|
||||||
if (!ReadByteAtVA(p, i + entryPoint, b)) {
|
if (!ReadByteAtVA(p, i + entryPoint, b)) {
|
||||||
@ -402,14 +412,11 @@ int main(int argc, char *argv[]) {
|
|||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Resources: " << "\n";
|
std::cout << "Resources: "
|
||||||
IterRsrc(p, printRsrc, NULL);
|
|
||||||
DestructParsedPE(p);
|
|
||||||
} else {
|
|
||||||
std::cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")"
|
|
||||||
<< "\n";
|
<< "\n";
|
||||||
std::cout << "Location: " << GetPEErrLoc() << "\n";
|
IterRsrc(p, printRsrc, NULL);
|
||||||
}
|
|
||||||
|
DestructParsedPE(p);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
dump_prog = executable(
|
|
||||||
'dump-prog',
|
|
||||||
'dump.cpp',
|
|
||||||
include_directories : [ incdirs ],
|
|
||||||
install : true,
|
|
||||||
install_dir : join_paths(get_option('datadir'), 'pe-parse/examples'),
|
|
||||||
link_with : pe_parser_library)
|
|
@ -1,7 +1,7 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -262,7 +262,8 @@ int main(int argc, char *argv[]) {
|
|||||||
char *last_parsed_char = nullptr;
|
char *last_parsed_char = nullptr;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
std::uint64_t address = std::strtoull(address_as_string, &last_parsed_char, 16);
|
std::uint64_t address =
|
||||||
|
std::strtoull(address_as_string, &last_parsed_char, 16);
|
||||||
if (address == 0U && *last_parsed_char != 0) {
|
if (address == 0U && *last_parsed_char != 0) {
|
||||||
std::cout << "Invalid address specified\n";
|
std::cout << "Invalid address specified\n";
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
project('pe-parse',
|
|
||||||
'cpp',
|
|
||||||
default_options : [ 'cpp_std=c++11' ],
|
|
||||||
license : [ 'MIT' ],
|
|
||||||
)
|
|
||||||
|
|
||||||
subdir('parser-library')
|
|
||||||
subdir('dump-prog')
|
|
@ -1,11 +0,0 @@
|
|||||||
incdirs = include_directories('.')
|
|
||||||
parser_source = [
|
|
||||||
'buffer.cpp',
|
|
||||||
'parse.cpp'
|
|
||||||
]
|
|
||||||
|
|
||||||
pe_parser_library = library('pe-parser-library',
|
|
||||||
sources : parser_source,
|
|
||||||
install : true
|
|
||||||
)
|
|
||||||
install_headers('parse.h', subdir : 'pe-parse')
|
|
@ -47,21 +47,6 @@ constexpr std::uint16_t NT_OPTIONAL_32_MAGIC = 0x10B;
|
|||||||
constexpr std::uint16_t NT_OPTIONAL_64_MAGIC = 0x20B;
|
constexpr std::uint16_t NT_OPTIONAL_64_MAGIC = 0x20B;
|
||||||
constexpr std::uint16_t NT_SHORT_NAME_LEN = 8;
|
constexpr std::uint16_t NT_SHORT_NAME_LEN = 8;
|
||||||
constexpr std::uint16_t SYMTAB_RECORD_LEN = 18;
|
constexpr std::uint16_t SYMTAB_RECORD_LEN = 18;
|
||||||
constexpr std::uint16_t DIR_EXPORT = 0;
|
|
||||||
constexpr std::uint16_t DIR_IMPORT = 1;
|
|
||||||
constexpr std::uint16_t DIR_RESOURCE = 2;
|
|
||||||
constexpr std::uint16_t DIR_EXCEPTION = 3;
|
|
||||||
constexpr std::uint16_t DIR_SECURITY = 4;
|
|
||||||
constexpr std::uint16_t DIR_BASERELOC = 5;
|
|
||||||
constexpr std::uint16_t DIR_DEBUG = 6;
|
|
||||||
constexpr std::uint16_t DIR_ARCHITECTURE = 7;
|
|
||||||
constexpr std::uint16_t DIR_GLOBALPTR = 8;
|
|
||||||
constexpr std::uint16_t DIR_TLS = 9;
|
|
||||||
constexpr std::uint16_t DIR_LOAD_CONFIG = 10;
|
|
||||||
constexpr std::uint16_t DIR_BOUND_IMPORT = 11;
|
|
||||||
constexpr std::uint16_t DIR_IAT = 12;
|
|
||||||
constexpr std::uint16_t DIR_DELAY_IMPORT = 13;
|
|
||||||
constexpr std::uint16_t DIR_COM_DESCRIPTOR = 14;
|
|
||||||
|
|
||||||
// Machine Types
|
// Machine Types
|
||||||
constexpr std::uint16_t IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
|
constexpr std::uint16_t IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
|
||||||
@ -263,6 +248,25 @@ struct data_directory {
|
|||||||
std::uint32_t Size;
|
std::uint32_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum data_directory_kind {
|
||||||
|
DIR_EXPORT = 0,
|
||||||
|
DIR_IMPORT = 1,
|
||||||
|
DIR_RESOURCE = 2,
|
||||||
|
DIR_EXCEPTION = 3,
|
||||||
|
DIR_SECURITY = 4,
|
||||||
|
DIR_BASERELOC = 5,
|
||||||
|
DIR_DEBUG = 6,
|
||||||
|
DIR_ARCHITECTURE = 7,
|
||||||
|
DIR_GLOBALPTR = 8,
|
||||||
|
DIR_TLS = 9,
|
||||||
|
DIR_LOAD_CONFIG = 10,
|
||||||
|
DIR_BOUND_IMPORT = 11,
|
||||||
|
DIR_IAT = 12,
|
||||||
|
DIR_DELAY_IMPORT = 13,
|
||||||
|
DIR_COM_DESCRIPTOR = 14,
|
||||||
|
DIR_RESERVED = 15,
|
||||||
|
};
|
||||||
|
|
||||||
struct optional_header_32 {
|
struct optional_header_32 {
|
||||||
std::uint16_t Magic;
|
std::uint16_t Magic;
|
||||||
std::uint8_t MajorLinkerVersion;
|
std::uint8_t MajorLinkerVersion;
|
||||||
@ -451,4 +455,101 @@ struct reloc_block {
|
|||||||
std::uint32_t PageRVA;
|
std::uint32_t PageRVA;
|
||||||
std::uint32_t BlockSize;
|
std::uint32_t BlockSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct image_load_config_code_integrity {
|
||||||
|
std::uint16_t Flags;
|
||||||
|
std::uint16_t Catalog;
|
||||||
|
std::uint32_t CatalogOffset;
|
||||||
|
std::uint32_t Reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct image_load_config_32 {
|
||||||
|
std::uint32_t Size;
|
||||||
|
std::uint32_t TimeDateStamp;
|
||||||
|
std::uint16_t MajorVersion;
|
||||||
|
std::uint16_t MinorVersion;
|
||||||
|
std::uint32_t GlobalFlagsClear;
|
||||||
|
std::uint32_t GlobalFlagsSet;
|
||||||
|
std::uint32_t CriticalSectionDefaultTimeout;
|
||||||
|
std::uint32_t DeCommitFreeBlockThreshold;
|
||||||
|
std::uint32_t DeCommitTotalFreeThreshold;
|
||||||
|
std::uint32_t LockPrefixTable;
|
||||||
|
std::uint32_t MaximumAllocationSize;
|
||||||
|
std::uint32_t VirtualMemoryThreshold;
|
||||||
|
std::uint32_t ProcessHeapFlags;
|
||||||
|
std::uint32_t ProcessAffinityMask;
|
||||||
|
std::uint16_t CSDVersion;
|
||||||
|
std::uint16_t DependentLoadFlags;
|
||||||
|
std::uint32_t EditList;
|
||||||
|
std::uint32_t SecurityCookie;
|
||||||
|
std::uint32_t SEHandlerTable;
|
||||||
|
std::uint32_t SEHandlerCount;
|
||||||
|
std::uint32_t GuardCFCheckFunctionPointer;
|
||||||
|
std::uint32_t GuardCFDispatchFunctionPointer;
|
||||||
|
std::uint32_t GuardCFFunctionTable;
|
||||||
|
std::uint32_t GuardCFFunctionCount;
|
||||||
|
std::uint32_t GuardFlags;
|
||||||
|
image_load_config_code_integrity CodeIntegrity;
|
||||||
|
std::uint32_t GuardAddressTakenIatEntryTable;
|
||||||
|
std::uint32_t GuardAddressTakenIatEntryCount;
|
||||||
|
std::uint32_t GuardLongJumpTargetTable;
|
||||||
|
std::uint32_t GuardLongJumpTargetCount;
|
||||||
|
std::uint32_t DynamicValueRelocTable;
|
||||||
|
std::uint32_t CHPEMetadataPointer;
|
||||||
|
std::uint32_t GuardRFFailureRoutine;
|
||||||
|
std::uint32_t GuardRFFailureRoutineFunctionPointer;
|
||||||
|
std::uint32_t DynamicValueRelocTableOffset;
|
||||||
|
std::uint16_t DynamicValueRelocTableSection;
|
||||||
|
std::uint16_t Reserved2;
|
||||||
|
std::uint32_t GuardRFVerifyStackPointerFunctionPointer;
|
||||||
|
std::uint32_t HotPatchTableOffset;
|
||||||
|
std::uint32_t Reserved3;
|
||||||
|
std::uint32_t EnclaveConfigurationPointer;
|
||||||
|
std::uint32_t VolatileMetadataPointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct image_load_config_64 {
|
||||||
|
std::uint32_t Size;
|
||||||
|
std::uint32_t TimeDateStamp;
|
||||||
|
std::uint16_t MajorVersion;
|
||||||
|
std::uint16_t MinorVersion;
|
||||||
|
std::uint32_t GlobalFlagsClear;
|
||||||
|
std::uint32_t GlobalFlagsSet;
|
||||||
|
std::uint32_t CriticalSectionDefaultTimeout;
|
||||||
|
std::uint64_t DeCommitFreeBlockThreshold;
|
||||||
|
std::uint64_t DeCommitTotalFreeThreshold;
|
||||||
|
std::uint64_t LockPrefixTable;
|
||||||
|
std::uint64_t MaximumAllocationSize;
|
||||||
|
std::uint64_t VirtualMemoryThreshold;
|
||||||
|
std::uint64_t ProcessAffinityMask;
|
||||||
|
std::uint32_t ProcessHeapFlags;
|
||||||
|
std::uint16_t CSDVersion;
|
||||||
|
std::uint16_t DependentLoadFlags;
|
||||||
|
std::uint64_t EditList;
|
||||||
|
std::uint64_t SecurityCookie;
|
||||||
|
std::uint64_t SEHandlerTable;
|
||||||
|
std::uint64_t SEHandlerCount;
|
||||||
|
std::uint64_t GuardCFCheckFunctionPointer;
|
||||||
|
std::uint64_t GuardCFDispatchFunctionPointer;
|
||||||
|
std::uint64_t GuardCFFunctionTable;
|
||||||
|
std::uint64_t GuardCFFunctionCount;
|
||||||
|
std::uint32_t GuardFlags;
|
||||||
|
image_load_config_code_integrity CodeIntegrity;
|
||||||
|
std::uint64_t GuardAddressTakenIatEntryTable;
|
||||||
|
std::uint64_t GuardAddressTakenIatEntryCount;
|
||||||
|
std::uint64_t GuardLongJumpTargetTable;
|
||||||
|
std::uint64_t GuardLongJumpTargetCount;
|
||||||
|
std::uint64_t DynamicValueRelocTable;
|
||||||
|
std::uint64_t CHPEMetadataPointer;
|
||||||
|
std::uint64_t GuardRFFailureRoutine;
|
||||||
|
std::uint64_t GuardRFFailureRoutineFunctionPointer;
|
||||||
|
std::uint32_t DynamicValueRelocTableOffset;
|
||||||
|
std::uint16_t DynamicValueRelocTableSection;
|
||||||
|
std::uint16_t Reserved2;
|
||||||
|
std::uint64_t GuardRFVerifyStackPointerFunctionPointer;
|
||||||
|
std::uint32_t HotPatchTableOffset;
|
||||||
|
std::uint32_t Reserved3;
|
||||||
|
std::uint64_t EnclaveConfigurationPointer;
|
||||||
|
std::uint64_t VolatileMetadataPointer;
|
||||||
|
};
|
||||||
} // namespace peparse
|
} // namespace peparse
|
||||||
|
@ -137,6 +137,7 @@ enum pe_err {
|
|||||||
PEERR_MAGIC = 9,
|
PEERR_MAGIC = 9,
|
||||||
PEERR_BUFFER = 10,
|
PEERR_BUFFER = 10,
|
||||||
PEERR_ADDRESS = 11,
|
PEERR_ADDRESS = 11,
|
||||||
|
PEERR_SIZE = 12,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool readByte(bounded_buffer *b, std::uint32_t offset, std::uint8_t &out);
|
bool readByte(bounded_buffer *b, std::uint32_t offset, std::uint8_t &out);
|
||||||
@ -167,7 +168,8 @@ typedef struct _parsed_pe {
|
|||||||
// Resolve a Rich header product id / build number pair to a known
|
// Resolve a Rich header product id / build number pair to a known
|
||||||
// product name
|
// product name
|
||||||
typedef std::pair<std::uint16_t, std::uint16_t> ProductKey;
|
typedef std::pair<std::uint16_t, std::uint16_t> ProductKey;
|
||||||
const std::string& GetRichProductName(std::uint16_t prodId, std::uint16_t buildNum);
|
const std::string &GetRichProductName(std::uint16_t prodId,
|
||||||
|
std::uint16_t buildNum);
|
||||||
|
|
||||||
// get parser error status as integer
|
// get parser error status as integer
|
||||||
std::uint32_t GetPEErr();
|
std::uint32_t GetPEErr();
|
||||||
@ -230,4 +232,7 @@ const char *GetMachineAsString(parsed_pe *pe);
|
|||||||
|
|
||||||
// get subsystem as human readable string
|
// get subsystem as human readable string
|
||||||
const char *GetSubsystemAsString(parsed_pe *pe);
|
const char *GetSubsystemAsString(parsed_pe *pe);
|
||||||
|
|
||||||
|
// get a table or string by its data directory entry
|
||||||
|
const void *GetDataDirectoryEntry(parsed_pe *pe, data_directory_kind dirnum);
|
||||||
} // namespace peparse
|
} // namespace peparse
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifdef USE_ICU4C
|
#ifdef USE_ICU4C
|
||||||
#include <unicode/unistr.h>
|
#include <unicode/unistr.h>
|
||||||
|
@ -23,10 +23,11 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <parser-library/nt-headers.h>
|
#include <parser-library/nt-headers.h>
|
||||||
#include <parser-library/parse.h>
|
#include <parser-library/parse.h>
|
||||||
@ -125,14 +126,14 @@ struct parsed_pe_internal {
|
|||||||
// The mapping of Rich header product id / build number pairs
|
// The mapping of Rich header product id / build number pairs
|
||||||
// to strings
|
// to strings
|
||||||
static const std::map<ProductKey, const std::string> ProductMap = {
|
static const std::map<ProductKey, const std::string> ProductMap = {
|
||||||
{std::make_pair(1, 0), "Imported Functions"}
|
{std::make_pair(1, 0), "Imported Functions"}};
|
||||||
};
|
|
||||||
|
|
||||||
static const std::string kUnknownProduct = "<unknown>";
|
static const std::string kUnknownProduct = "<unknown>";
|
||||||
|
|
||||||
// Resolve a Rich header product id / build number pair to a known
|
// Resolve a Rich header product id / build number pair to a known
|
||||||
// product name
|
// product name
|
||||||
const std::string& GetRichProductName(std::uint16_t prodId, std::uint16_t buildNum) {
|
const std::string &GetRichProductName(std::uint16_t prodId,
|
||||||
|
std::uint16_t buildNum) {
|
||||||
auto it = ProductMap.find(std::make_pair(prodId, buildNum));
|
auto it = ProductMap.find(std::make_pair(prodId, buildNum));
|
||||||
if (it != ProductMap.end()) {
|
if (it != ProductMap.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
@ -144,7 +145,8 @@ const std::string& GetRichProductName(std::uint16_t prodId, std::uint16_t buildN
|
|||||||
std::uint32_t err = 0;
|
std::uint32_t err = 0;
|
||||||
std::string err_loc;
|
std::string err_loc;
|
||||||
|
|
||||||
static const char *pe_err_str[] = {"None",
|
static const char *pe_err_str[] = {
|
||||||
|
"None",
|
||||||
"Out of memory",
|
"Out of memory",
|
||||||
"Invalid header",
|
"Invalid header",
|
||||||
"Invalid section",
|
"Invalid section",
|
||||||
@ -155,7 +157,9 @@ static const char *pe_err_str[] = {"None",
|
|||||||
"Unable to stat",
|
"Unable to stat",
|
||||||
"Bad magic",
|
"Bad magic",
|
||||||
"Invalid buffer",
|
"Invalid buffer",
|
||||||
"Invalid address",};
|
"Invalid address",
|
||||||
|
"Invalid size",
|
||||||
|
};
|
||||||
|
|
||||||
std::uint32_t GetPEErr() {
|
std::uint32_t GetPEErr() {
|
||||||
return err;
|
return err;
|
||||||
@ -230,8 +234,9 @@ const char *GetSymbolTableStorageClassName(std::uint8_t id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool readCString(const bounded_buffer &buffer,
|
||||||
readCString(const bounded_buffer &buffer, std::uint32_t off, std::string &result) {
|
std::uint32_t off,
|
||||||
|
std::string &result) {
|
||||||
if (off < buffer.bufLen) {
|
if (off < buffer.bufLen) {
|
||||||
std::uint8_t *p = buffer.buf;
|
std::uint8_t *p = buffer.buf;
|
||||||
std::uint32_t n = buffer.bufLen;
|
std::uint32_t n = buffer.bufLen;
|
||||||
@ -282,7 +287,9 @@ void IterRsrc(parsed_pe *pe, iterRsrc cb, void *cbd) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_resource_id(bounded_buffer *data, std::uint32_t id, std::string &result) {
|
bool parse_resource_id(bounded_buffer *data,
|
||||||
|
std::uint32_t id,
|
||||||
|
std::string &result) {
|
||||||
std::uint16_t len;
|
std::uint16_t len;
|
||||||
if (!readWord(data, id, len)) {
|
if (!readWord(data, id, len)) {
|
||||||
return false;
|
return false;
|
||||||
@ -388,9 +395,10 @@ bool parse_resource_table(bounded_buffer *sectionData,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* .rsrc can accomodate up to 2**31 levels, but Windows only uses 3 by convention.
|
/* .rsrc can accomodate up to 2**31 levels, but Windows only uses 3 by
|
||||||
* As such, any depth above 3 indicates potentially unchecked recusion.
|
* convention. As such, any depth above 3 indicates potentially unchecked
|
||||||
* See: https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-rsrc-section
|
* recusion. See:
|
||||||
|
* https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-rsrc-section
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PE_ERR(PEERR_RESC);
|
PE_ERR(PEERR_RESC);
|
||||||
@ -575,7 +583,8 @@ bool getSections(bounded_buffer *b,
|
|||||||
// now we have the section header information, so fill in a section
|
// now we have the section header information, so fill in a section
|
||||||
// object appropriately
|
// object appropriately
|
||||||
section thisSec;
|
section thisSec;
|
||||||
for (std::uint32_t charIndex = 0; charIndex < NT_SHORT_NAME_LEN; charIndex++) {
|
for (std::uint32_t charIndex = 0; charIndex < NT_SHORT_NAME_LEN;
|
||||||
|
charIndex++) {
|
||||||
std::uint8_t c = curSec.Name[charIndex];
|
std::uint8_t c = curSec.Name[charIndex];
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
break;
|
break;
|
||||||
@ -825,7 +834,9 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readRichHeader(bounded_buffer *rich_buf, std::uint32_t key, rich_header &rich_hdr) {
|
bool readRichHeader(bounded_buffer *rich_buf,
|
||||||
|
std::uint32_t key,
|
||||||
|
rich_header &rich_hdr) {
|
||||||
if (rich_buf == nullptr) {
|
if (rich_buf == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -883,7 +894,6 @@ bool readRichHeader(bounded_buffer *rich_buf, std::uint32_t key, rich_header &ri
|
|||||||
|
|
||||||
// Preserve the individual entry
|
// Preserve the individual entry
|
||||||
rich_hdr.Entries.push_back(entry);
|
rich_hdr.Entries.push_back(entry);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preserve the end signature aka "Rich" magic
|
// Preserve the end signature aka "Rich" magic
|
||||||
@ -960,7 +970,8 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Split the Rich header out into its own buffer
|
// Split the Rich header out into its own buffer
|
||||||
bounded_buffer *richBuf = splitBuffer(file, 0x80, rich_end_signature_offset + 4);
|
bounded_buffer *richBuf =
|
||||||
|
splitBuffer(file, 0x80, rich_end_signature_offset + 4);
|
||||||
if (richBuf == nullptr) {
|
if (richBuf == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -992,12 +1003,12 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
|
|||||||
std::uint32_t rem_size;
|
std::uint32_t rem_size;
|
||||||
if (p.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
// signature + file_header + optional_header_32
|
// signature + file_header + optional_header_32
|
||||||
rem_size =
|
rem_size = sizeof(std::uint32_t) + sizeof(file_header) +
|
||||||
sizeof(std::uint32_t) + sizeof(file_header) + sizeof(optional_header_32);
|
sizeof(optional_header_32);
|
||||||
} else if (p.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
// signature + file_header + optional_header_64
|
// signature + file_header + optional_header_64
|
||||||
rem_size =
|
rem_size = sizeof(std::uint32_t) + sizeof(file_header) +
|
||||||
sizeof(std::uint32_t) + sizeof(file_header) + sizeof(optional_header_64);
|
sizeof(optional_header_64);
|
||||||
} else {
|
} else {
|
||||||
PE_ERR(PEERR_MAGIC);
|
PE_ERR(PEERR_MAGIC);
|
||||||
deleteBuffer(ntBuf);
|
deleteBuffer(ntBuf);
|
||||||
@ -1529,8 +1540,8 @@ bool getImports(parsed_pe *p) {
|
|||||||
ent.moduleName = modName;
|
ent.moduleName = modName;
|
||||||
p->internal->imports.push_back(ent);
|
p->internal->imports.push_back(ent);
|
||||||
} else {
|
} else {
|
||||||
std::string symName =
|
std::string symName = "ORDINAL_" + modName + "_" +
|
||||||
"ORDINAL_" + modName + "_" + to_string<std::uint32_t>(oval, std::dec);
|
to_string<std::uint32_t>(oval, std::dec);
|
||||||
|
|
||||||
importent ent;
|
importent ent;
|
||||||
|
|
||||||
@ -1579,7 +1590,8 @@ bool getSymbolTable(parsed_pe *p) {
|
|||||||
|
|
||||||
std::uint32_t offset = p->peHeader.nt.FileHeader.PointerToSymbolTable;
|
std::uint32_t offset = p->peHeader.nt.FileHeader.PointerToSymbolTable;
|
||||||
|
|
||||||
for (std::uint32_t i = 0; i < p->peHeader.nt.FileHeader.NumberOfSymbols; i++) {
|
for (std::uint32_t i = 0; i < p->peHeader.nt.FileHeader.NumberOfSymbols;
|
||||||
|
i++) {
|
||||||
symbol sym;
|
symbol sym;
|
||||||
|
|
||||||
// Read name
|
// Read name
|
||||||
@ -1607,7 +1619,8 @@ bool getSymbolTable(parsed_pe *p) {
|
|||||||
strOffset += sizeof(std::uint8_t);
|
strOffset += sizeof(std::uint8_t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (std::uint8_t n = 0; n < NT_SHORT_NAME_LEN && sym.name.shortName[n] != 0;
|
for (std::uint8_t n = 0;
|
||||||
|
n < NT_SHORT_NAME_LEN && sym.name.shortName[n] != 0;
|
||||||
n++) {
|
n++) {
|
||||||
sym.strName.push_back(static_cast<char>(sym.name.shortName[n]));
|
sym.strName.push_back(static_cast<char>(sym.name.shortName[n]));
|
||||||
}
|
}
|
||||||
@ -2192,4 +2205,48 @@ const char *GetSubsystemAsString(parsed_pe *pe) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void *GetDataDirectoryEntry(parsed_pe *pe, data_directory_kind dirnum) {
|
||||||
|
if (pe == nullptr) {
|
||||||
|
PE_ERR(PEERR_NONE);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_directory dir;
|
||||||
|
VA addr;
|
||||||
|
if (pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
|
dir = pe->peHeader.nt.OptionalHeader.DataDirectory[dirnum];
|
||||||
|
addr = dir.VirtualAddress + pe->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
|
} else if (pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
|
dir = pe->peHeader.nt.OptionalHeader64.DataDirectory[dirnum];
|
||||||
|
addr = dir.VirtualAddress + pe->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
|
} else {
|
||||||
|
PE_ERR(PEERR_MAGIC);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir.Size <= 0) {
|
||||||
|
PE_ERR(PEERR_SIZE);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
section sec;
|
||||||
|
if (!getSecForVA(pe->internal->secs, addr, sec)) {
|
||||||
|
PE_ERR(PEERR_SECTVA);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto off = static_cast<std::uint32_t>(addr - sec.sectionBase);
|
||||||
|
if (off + dir.Size >= sec.sectionData->bufLen) {
|
||||||
|
PE_ERR(PEERR_SIZE);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "off: 0x" << std::hex << off << std::endl;
|
||||||
|
|
||||||
|
std::vector<uint8_t> rawEntry(sec.sectionData->buf + off,
|
||||||
|
sec.sectionData->buf + off + dir.Size);
|
||||||
|
|
||||||
|
return rawEntry.data();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace peparse
|
} // namespace peparse
|
||||||
|
@ -22,17 +22,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <parser-library/to_string.h>
|
|
||||||
#include <locale>
|
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
#include <locale>
|
||||||
|
#include <parser-library/to_string.h>
|
||||||
|
|
||||||
namespace peparse {
|
namespace peparse {
|
||||||
// See https://stackoverflow.com/questions/38688417/utf-conversion-functions-in-c11
|
// See
|
||||||
std::string from_utf16(const UCharString &u)
|
// https://stackoverflow.com/questions/38688417/utf-conversion-functions-in-c11
|
||||||
{
|
std::string from_utf16(const UCharString &u) {
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
// std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>convert; // Doesn't compile with Visual Studio.
|
// std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>convert;
|
||||||
// See https://stackoverflow.com/questions/32055357/visual-studio-c-2015-stdcodecvt-with-char16-t-or-char32-t
|
// // Doesn't compile with Visual Studio. See
|
||||||
|
// https://stackoverflow.com/questions/32055357/visual-studio-c-2015-stdcodecvt-with-char16-t-or-char32-t
|
||||||
std::wstring_convert<std::codecvt_utf8<std::int16_t>, std::int16_t> convert;
|
std::wstring_convert<std::codecvt_utf8<std::int16_t>, std::int16_t> convert;
|
||||||
auto p = reinterpret_cast<const std::int16_t *>(u.data());
|
auto p = reinterpret_cast<const std::int16_t *>(u.data());
|
||||||
return convert.to_bytes(p, p + u.size());
|
return convert.to_bytes(p, p + u.size());
|
||||||
|
@ -26,8 +26,7 @@ THE SOFTWARE.
|
|||||||
#include <unicode/unistr.h>
|
#include <unicode/unistr.h>
|
||||||
|
|
||||||
namespace peparse {
|
namespace peparse {
|
||||||
std::string from_utf16(const UCharString &u)
|
std::string from_utf16(const UCharString &u) {
|
||||||
{
|
|
||||||
icu::UnicodeString utf16_string = icu::UnicodeString(u.data(), u.length());
|
icu::UnicodeString utf16_string = icu::UnicodeString(u.data(), u.length());
|
||||||
std::string result;
|
std::string result;
|
||||||
utf16_string.toUTF8String(result);
|
utf16_string.toUTF8String(result);
|
||||||
|
@ -704,7 +704,8 @@ static PyObject *pepy_parsed_get_entry_point(PyObject *self, PyObject *args) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *pepy_parsed_get_machine_as_str(PyObject *self, PyObject *args) {
|
static PyObject *pepy_parsed_get_machine_as_str(PyObject *self,
|
||||||
|
PyObject *args) {
|
||||||
PyObject *ret;
|
PyObject *ret;
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|
||||||
@ -721,7 +722,8 @@ static PyObject *pepy_parsed_get_machine_as_str(PyObject *self, PyObject *args)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *pepy_parsed_get_subsystem_as_str(PyObject *self, PyObject *args) {
|
static PyObject *pepy_parsed_get_subsystem_as_str(PyObject *self,
|
||||||
|
PyObject *args) {
|
||||||
PyObject *ret;
|
PyObject *ret;
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|
||||||
@ -1079,8 +1081,7 @@ static PyObject *pepy_parsed_get_relocations(PyObject *self, PyObject *args) {
|
|||||||
|
|
||||||
#define PEPY_PARSED_GET(ATTR, VAL) \
|
#define PEPY_PARSED_GET(ATTR, VAL) \
|
||||||
static PyObject *pepy_parsed_get_##ATTR(PyObject *self, void *closure) { \
|
static PyObject *pepy_parsed_get_##ATTR(PyObject *self, void *closure) { \
|
||||||
PyObject *ret = \
|
PyObject *ret = PyLong_FromUnsignedLongLong( \
|
||||||
PyLong_FromUnsignedLongLong( \
|
|
||||||
((pepy_parsed *) self)->pe->peHeader.nt.VAL); \
|
((pepy_parsed *) self)->pe->peHeader.nt.VAL); \
|
||||||
if (!ret) \
|
if (!ret) \
|
||||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
||||||
|
210
travis.sh
210
travis.sh
@ -1,210 +0,0 @@
|
|||||||
#!/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 libicu-dev > "${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; the 'install' step will be skipped\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
|
|
||||||
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 $?
|
|
Loading…
x
Reference in New Issue
Block a user