diff --git a/CHANGELOG.md b/CHANGELOG.md index bae2bf08a..1f1730a73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,129 +2,135 @@ # dev -* New Feature: Added presentation of section and overlay entropy in `retdec-fileinfo` ([#502](https://github.com/avast-tl/retdec/issues/502), [#507](https://github.com/avast-tl/retdec/pull/507)). -* Enhancement: Updated YARA to version 3.9 ([#527](https://github.com/avast-tl/retdec/pull/527)). +* New Feature: Added presentation of section and overlay entropy in `retdec-fileinfo` ([#502](https://github.com/avast/retdec/issues/502), [#507](https://github.com/avast/retdec/pull/507)). +* New Feature: Added presentation of version info from PE file in `retdec-fileinfo` ([#408](https://github.com/avast/retdec/issues/408), [#519](https://github.com/avast/retdec/pull/519)). +* New Feature: Added presentation of thread-local storage directory from PE file in `retdec-fileinfo` ([#417](https://github.com/avast/retdec/issues/417), [#523](https://github.com/avast/retdec/pull/523)). +* Enhancement: Added macOS and Linux (Ubuntu, Debian, Fedora) release builds ([#526](https://github.com/avast/retdec/issues/526)). +* Enhancement: Added support for using a local repository clone for RetDec external dependencies ([#279](https://github.com/avast/retdec/issues/279)). +* Enhancement: Parallelized compilation of YARA rules during installation ([#540](https://github.com/avast/retdec/issues/540)). +* Enhancement: Updated LLVM to version 8.0.0 ([#110](https://github.com/avast/retdec/issues/110)). +* Enhancement: Updated YARA to version 3.9 ([#527](https://github.com/avast/retdec/pull/527)). # v3.3 (2019-03-18) -* New Feature: Added basic support of 64-bit x86 architecture ([#9](https://github.com/avast-tl/retdec/issues/9), [#513](https://github.com/avast-tl/retdec/pull/513)). -* New Feature: Added presentation of imported types and TypeRef hashes for .NET binaries ([#363](https://github.com/avast-tl/retdec/issues/363), [#364](https://github.com/avast-tl/retdec/issues/364), [#428](https://github.com/avast-tl/retdec/issues/428)). -* New Feature: Added presentation of metadata from binaries written in Visual Basic and detection of P-code ([#138](https://github.com/avast-tl/retdec/issues/138), [#440](https://github.com/avast-tl/retdec/pull/440)). -* New Feature: Added computation and presentation of icon hashes for exact and also similarity matching in PE files ([#339](https://github.com/avast-tl/retdec/issues/339)). -* Enhancement: Distribute YARA rules in a text form in the RetDec support package ([retdec-support #3](https://github.com/avast-tl/retdec-support/issues/3)). -* Enhancement: Updated YARA to version 3.8.1 ([#218](https://github.com/avast-tl/retdec/issues/218)). -* Enhancement: Made `--generate-log` option of `retdec-decompiler.py` work on macOS ([#383](https://github.com/avast-tl/retdec/issues/383), [#450](https://github.com/avast-tl/retdec/pull/450)). -* Enhancement: Replaced recursion with iterative implementation in x87 FPU analysis in `retdec-bin2llvmir` ([#450](https://github.com/avast-tl/retdec/pull/450)). -* Enhancement: The `new` LLVM IR to BIR converter is now the default (and only) back-end's converter. In most cases, this improves code structure and significantly speeds up decompilations ([#211](https://github.com/avast-tl/retdec/issues/211), [#508](https://github.com/avast-tl/retdec/issues/508), [#509](https://github.com/avast-tl/retdec/pull/509)). +* New Feature: Added basic support of 64-bit x86 architecture ([#9](https://github.com/avast/retdec/issues/9), [#513](https://github.com/avast/retdec/pull/513)). +* New Feature: Added presentation of imported types and TypeRef hashes for .NET binaries ([#363](https://github.com/avast/retdec/issues/363), [#364](https://github.com/avast/retdec/issues/364), [#428](https://github.com/avast/retdec/issues/428)). +* New Feature: Added presentation of metadata from binaries written in Visual Basic and detection of P-code ([#138](https://github.com/avast/retdec/issues/138), [#440](https://github.com/avast/retdec/pull/440)). +* New Feature: Added computation and presentation of icon hashes for exact and also similarity matching in PE files ([#339](https://github.com/avast/retdec/issues/339)). +* Enhancement: Distribute YARA rules in a text form in the RetDec support package ([retdec-support #3](https://github.com/avast/retdec-support/issues/3)). +* Enhancement: Updated YARA to version 3.8.1 ([#218](https://github.com/avast/retdec/issues/218)). +* Enhancement: Made `--generate-log` option of `retdec-decompiler.py` work on macOS ([#383](https://github.com/avast/retdec/issues/383), [#450](https://github.com/avast/retdec/pull/450)). +* Enhancement: Replaced recursion with iterative implementation in x87 FPU analysis in `retdec-bin2llvmir` ([#450](https://github.com/avast/retdec/pull/450)). +* Enhancement: The `new` LLVM IR to BIR converter is now the default (and only) back-end's converter. In most cases, this improves code structure and significantly speeds up decompilations ([#211](https://github.com/avast/retdec/issues/211), [#508](https://github.com/avast/retdec/issues/508), [#509](https://github.com/avast/retdec/pull/509)). * Enhancement: The `fileformat` library, and all its object file modules, accept both `std::istream` and `(data, size)` pair, in addition to the original input file path. -* Enhancement: Reduced the needed stack space in `retdec-llvmir2hll` ([#492](https://github.com/avast-tl/retdec/pull/492), [#495](https://github.com/avast-tl/retdec/pull/495)). -* Enhancement: Added support for build and run on FreeBSD and potentially on other BSD OSes ([#476](https://github.com/avast-tl/retdec/pull/476)). +* Enhancement: Reduced the needed stack space in `retdec-llvmir2hll` ([#492](https://github.com/avast/retdec/pull/492), [#495](https://github.com/avast/retdec/pull/495)). +* Enhancement: Added support for build and run on FreeBSD and potentially on other BSD OSes ([#476](https://github.com/avast/retdec/pull/476)). * Enhancement: It is possible to use local PeLib directory instead of remote revision via CMake variable `PELIB_LOCAL_DIR`. This is convenient when modifying both PeLib and RetDec at the same time. -* Enhancement: Improved detection of needed libraries and imported/external functions in ELF binaries ([#457](https://github.com/avast-tl/retdec/issues/457)). +* Enhancement: Improved detection of needed libraries and imported/external functions in ELF binaries ([#457](https://github.com/avast/retdec/issues/457)). * Enhancement: Added semantics for more MIPS instructions. -* Enhancement: Capstone2LlvmIr library refactoring ([#115](https://github.com/avast-tl/retdec/issues/115)). -* Enhancement: Removed the build and runtime dependency on ncurses/libtinfo ([#409](https://github.com/avast-tl/retdec/pull/409)). -* Enhancement: Add a check into our scripts that they are run from an installation directory and not from the `scripts` directory ([#418](https://github.com/avast-tl/retdec/issues/418)). -* Enhancement: Improved corruption checks in `retdec-fileinfo` to recognize cut PE files which are still loadable ([#463](https://github.com/avast-tl/retdec/issues/463)). -* Enhancement: Redesign output files naming scheme ([#132](https://github.com/avast-tl/retdec/issues/132)). -* Fix: Fixed false COFF file format detections ([#421](https://github.com/avast-tl/retdec/issues/421), [#431](https://github.com/avast-tl/retdec/issues/431)). -* Fix: Fixed LLVM IR syntax error: `Global variable initializer type does not match global variable type` ([#436](https://github.com/avast-tl/retdec/issues/436)). -* Fix: Fixed translation of x86 `sbb` instruction ([#401](https://github.com/avast-tl/retdec/issues/401)). -* Fix: Fixed `fileinfo` crash during `Asn1Sequence` initialization when parsing PE certificates ([#256](https://github.com/avast-tl/retdec/issues/256)). -* Fix: Fixed `fileinfo` crash during reconstruction of .NET types ([#458](https://github.com/avast-tl/retdec/issues/458), [#511](https://github.com/avast-tl/retdec/pull/511)). -* Fix: Fixed generation of MIPS branch instructions ([#88](https://github.com/avast-tl/retdec/issues/88)). -* Fix: Fixed generation of empty if blocks in C output ([#83](https://github.com/avast-tl/retdec/issues/83)). -* Fix: Fixed decompilation of simple x86 system calls ([#24](https://github.com/avast-tl/retdec/issues/24)). -* Fix: Fixed potential infinite looping in llvmir2hll's copy propagation pass ([#479](https://github.com/avast-tl/retdec/issues/479)). -* Fix: Fixed `FilesystemPath::isFile()` ([#490](https://github.com/avast-tl/retdec/issues/490), [#491](https://github.com/avast-tl/retdec/pull/491)). -* Fix: Fixed `retdec-signature-from-library-creator.py` when there is a lot of input files by adding an option to `retdec-bin2pat` to have the objects list passed through a text file instead of via program arguments ([#472](https://github.com/avast-tl/retdec/issues/472), [#484](https://github.com/avast-tl/retdec/pull/484)). -* Fix: Stricter rules for PE section names ([#451](https://github.com/avast-tl/retdec/issues/451)). -* Fix: Fixed incorrect return code of `bin2pat` that caused `signature-from-library-creator.py` to silently fail on error ([#473](https://github.com/avast-tl/retdec/issues/473), [#474](https://github.com/avast-tl/retdec/pull/474)). -* Fix: Fixed installation when Python is in a path containing spaces ([#441](https://github.com/avast-tl/retdec/issues/441)). -* Fix: Fixed handling of pointers with segment overrides, including loads/stores from/to zero (null) pointers ([#41](https://github.com/avast-tl/retdec/issues/41), [#169](https://github.com/avast-tl/retdec/issues/169), [#347](https://github.com/avast-tl/retdec/issues/347), [#376](https://github.com/avast-tl/retdec/issues/376), [#391](https://github.com/avast-tl/retdec/pull/391)). -* Fix: Fixed translation of x86 FPU instructions to LLVM IR ([#293](https://github.com/avast-tl/retdec/issues/293)). +* Enhancement: Capstone2LlvmIr library refactoring ([#115](https://github.com/avast/retdec/issues/115)). +* Enhancement: Removed the build and runtime dependency on ncurses/libtinfo ([#409](https://github.com/avast/retdec/pull/409)). +* Enhancement: Add a check into our scripts that they are run from an installation directory and not from the `scripts` directory ([#418](https://github.com/avast/retdec/issues/418)). +* Enhancement: Improved corruption checks in `retdec-fileinfo` to recognize cut PE files which are still loadable ([#463](https://github.com/avast/retdec/issues/463)). +* Enhancement: Redesign output files naming scheme ([#132](https://github.com/avast/retdec/issues/132)). +* Fix: Fixed false COFF file format detections ([#421](https://github.com/avast/retdec/issues/421), [#431](https://github.com/avast/retdec/issues/431)). +* Fix: Fixed LLVM IR syntax error: `Global variable initializer type does not match global variable type` ([#436](https://github.com/avast/retdec/issues/436)). +* Fix: Fixed translation of x86 `sbb` instruction ([#401](https://github.com/avast/retdec/issues/401)). +* Fix: Fixed `fileinfo` crash during `Asn1Sequence` initialization when parsing PE certificates ([#256](https://github.com/avast/retdec/issues/256)). +* Fix: Fixed `fileinfo` crash during reconstruction of .NET types ([#458](https://github.com/avast/retdec/issues/458), [#511](https://github.com/avast/retdec/pull/511)). +* Fix: Fixed generation of MIPS branch instructions ([#88](https://github.com/avast/retdec/issues/88)). +* Fix: Fixed generation of empty if blocks in C output ([#83](https://github.com/avast/retdec/issues/83)). +* Fix: Fixed decompilation of simple x86 system calls ([#24](https://github.com/avast/retdec/issues/24)). +* Fix: Fixed potential infinite looping in llvmir2hll's copy propagation pass ([#479](https://github.com/avast/retdec/issues/479)). +* Fix: Fixed `FilesystemPath::isFile()` ([#490](https://github.com/avast/retdec/issues/490), [#491](https://github.com/avast/retdec/pull/491)). +* Fix: Fixed `retdec-signature-from-library-creator.py` when there is a lot of input files by adding an option to `retdec-bin2pat` to have the objects list passed through a text file instead of via program arguments ([#472](https://github.com/avast/retdec/issues/472), [#484](https://github.com/avast/retdec/pull/484)). +* Fix: Stricter rules for PE section names ([#451](https://github.com/avast/retdec/issues/451)). +* Fix: Fixed incorrect return code of `bin2pat` that caused `signature-from-library-creator.py` to silently fail on error ([#473](https://github.com/avast/retdec/issues/473), [#474](https://github.com/avast/retdec/pull/474)). +* Fix: Fixed installation when Python is in a path containing spaces ([#441](https://github.com/avast/retdec/issues/441)). +* Fix: Fixed handling of pointers with segment overrides, including loads/stores from/to zero (null) pointers ([#41](https://github.com/avast/retdec/issues/41), [#169](https://github.com/avast/retdec/issues/169), [#347](https://github.com/avast/retdec/issues/347), [#376](https://github.com/avast/retdec/issues/376), [#391](https://github.com/avast/retdec/pull/391)). +* Fix: Fixed translation of x86 FPU instructions to LLVM IR ([#293](https://github.com/avast/retdec/issues/293)). # v3.2 (2018-08-16) -* New Feature: Converted shell scripts to Python scripts so that Windows users no longer have to install MSYS2 in order to run RetDec ([#338](https://github.com/avast-tl/retdec/pull/338), [#147](https://github.com/avast-tl/retdec/issues/147)). -* New Feature: Added generation of export-table hashes into `retdec-fileinfo` ([#121](https://github.com/avast-tl/retdec/issues/121), [#321](https://github.com/avast-tl/retdec/pull/321)). -* New Feature: Automatically generate and publicly host an up-to-date Doxygen documentation ([#20](https://github.com/avast-tl/retdec/issues/20)). -* Enhancement: Suppress superfluous ranlib warnings about static libraries having no symbols on macOS ([#271](https://github.com/avast-tl/retdec/issues/271), [#349](https://github.com/avast-tl/retdec/pull/349)). -* Fix: Fixed assertions in statically linked code recognition ([#333](https://github.com/avast-tl/retdec/issues/333)). -* Fix: Fixed aborts due to assertions during decoding of some MIPS binaries ([#335](https://github.com/avast-tl/retdec/issues/335)). -* Fix: Fixed a memory leak when parsing Mach-O files ([#331](https://github.com/avast-tl/retdec/pull/331)). +* New Feature: Converted shell scripts to Python scripts so that Windows users no longer have to install MSYS2 in order to run RetDec ([#338](https://github.com/avast/retdec/pull/338), [#147](https://github.com/avast/retdec/issues/147)). +* New Feature: Added generation of export-table hashes into `retdec-fileinfo` ([#121](https://github.com/avast/retdec/issues/121), [#321](https://github.com/avast/retdec/pull/321)). +* New Feature: Automatically generate and publicly host an up-to-date Doxygen documentation ([#20](https://github.com/avast/retdec/issues/20)). +* Enhancement: Suppress superfluous ranlib warnings about static libraries having no symbols on macOS ([#271](https://github.com/avast/retdec/issues/271), [#349](https://github.com/avast/retdec/pull/349)). +* Fix: Fixed assertions in statically linked code recognition ([#333](https://github.com/avast/retdec/issues/333)). +* Fix: Fixed aborts due to assertions during decoding of some MIPS binaries ([#335](https://github.com/avast/retdec/issues/335)). +* Fix: Fixed a memory leak when parsing Mach-O files ([#331](https://github.com/avast/retdec/pull/331)). # v3.1 (2018-06-07) -* New Feature: `retdec-fileinfo` is now able to detect when a PE file is corrupted and cannot be loaded ([#281](https://github.com/avast-tl/retdec/pull/281)). +* New Feature: `retdec-fileinfo` is now able to detect when a PE file is corrupted and cannot be loaded ([#281](https://github.com/avast/retdec/pull/281)). * New Feature: Added a new tool: `retdec-getsig`. It can be used for creating signatures of packers, compilers, and other tools. * New Feature: The number of bytes read from the input file's entry point by `retdec-fileinfo` is now configurable with the `--ep-bytes` option. -* Enhancement: Complete rewrite of binary to LLVM IR decoding phase ([#116](https://github.com/avast-tl/retdec/issues/116)). -* Enhancement: Added reference checks to statically linked code detection ([#113](https://github.com/avast-tl/retdec/issues/113)). -* Enhancement: Speeded up RetDec rebuild and installation by disabling forced reconfiguration of LLVM ([#294](https://github.com/avast-tl/retdec/pull/294)). -* Enhancement: Added new OS/ABI and tool detections for ELF files ([#244](https://github.com/avast-tl/retdec/issues/244)). -* Enhancement: Improved support for analysis of ELF [core files](http://www.gabriel.urdhr.fr/2015/05/29/core-file/) by `retdec-fileinfo` ([#142](https://github.com/avast-tl/retdec/issues/142)). -* Enhancement: Added support for limiting overall memory when running decompilations and tools ([#270](https://github.com/avast-tl/retdec/issues/270), [#290](https://github.com/avast-tl/retdec/issues/290)). By default, decompilations are now run with limited memory (half of system RAM) to prevent "black screens" (mostly on Windows). Use `--no-memory-limit` to override. +* Enhancement: Complete rewrite of binary to LLVM IR decoding phase ([#116](https://github.com/avast/retdec/issues/116)). +* Enhancement: Added reference checks to statically linked code detection ([#113](https://github.com/avast/retdec/issues/113)). +* Enhancement: Speeded up RetDec rebuild and installation by disabling forced reconfiguration of LLVM ([#294](https://github.com/avast/retdec/pull/294)). +* Enhancement: Added new OS/ABI and tool detections for ELF files ([#244](https://github.com/avast/retdec/issues/244)). +* Enhancement: Improved support for analysis of ELF [core files](http://www.gabriel.urdhr.fr/2015/05/29/core-file/) by `retdec-fileinfo` ([#142](https://github.com/avast/retdec/issues/142)). +* Enhancement: Added support for limiting overall memory when running decompilations and tools ([#270](https://github.com/avast/retdec/issues/270), [#290](https://github.com/avast/retdec/issues/290)). By default, decompilations are now run with limited memory (half of system RAM) to prevent "black screens" (mostly on Windows). Use `--no-memory-limit` to override. * Enhancement: On macOS, you no longer need to have GNU coreutils in `PATH` to build and install RetDec. GNU coreutils are still needed to run RetDec, though. -* Enhancement: Import-table hashes generated by `retdec-fileinfo` are now compatible with import-table hashes from YARA/pefile ([#246](https://github.com/avast-tl/retdec/issues/246)). -* Enhancement: Tool `retdec-macho-extractor` can now extract objects from non-archive Mach-O universal binaries ([#125](https://github.com/avast-tl/retdec/issues/125)). -* Enhancement: References to ticket numbers from our internal issue tracking system were replaced by short descriptions in the `retdec-regression-tests` repository ([retdec-regression-tests #1](https://github.com/avast-tl/retdec-regression-tests/issues/1)). -* Enhancement: Added a missing license for the `retdec-support` repository ([retdec-support #1](https://github.com/avast-tl/retdec-support/issues/1)). +* Enhancement: Import-table hashes generated by `retdec-fileinfo` are now compatible with import-table hashes from YARA/pefile ([#246](https://github.com/avast/retdec/issues/246)). +* Enhancement: Tool `retdec-macho-extractor` can now extract objects from non-archive Mach-O universal binaries ([#125](https://github.com/avast/retdec/issues/125)). +* Enhancement: References to ticket numbers from our internal issue tracking system were replaced by short descriptions in the `retdec-regression-tests` repository ([retdec-regression-tests #1](https://github.com/avast/retdec-regression-tests/issues/1)). +* Enhancement: Added a missing license for the `retdec-support` repository ([retdec-support #1](https://github.com/avast/retdec-support/issues/1)). * Enhancement: Better detection of tools: new signatures and heuristics. YARA signatures are compiled now. -* Enhancement: Added Travis and AppVeyor continuous integration builds ([#2](https://github.com/avast-tl/retdec/issues/2)). -* Enhancement: Build with `-std=c++14` instead of `-std=gnu++14` with GCC on Linux ([#76](https://github.com/avast-tl/retdec/issues/76)). +* Enhancement: Added Travis and AppVeyor continuous integration builds ([#2](https://github.com/avast/retdec/issues/2)). +* Enhancement: Build with `-std=c++14` instead of `-std=gnu++14` with GCC on Linux ([#76](https://github.com/avast/retdec/issues/76)). * Enhancement: Speeded up build by skipping compilation of unnecessary dependencies (e.g. unused LLVM libraries, tools, and examples). * Enhancement: OpenSSL is now automatically built only if it is not found in your system. -* Enhancement: Added support for a system-wide installation ([#94](https://github.com/avast-tl/retdec/issues/94)). -* Enhancement: Prefixed all the installed binaries and scripts with `retdec-` ([#70](https://github.com/avast-tl/retdec/issues/70)). Also, some tools were renamed to make their names more uniform. -* Enhancement: Got rid of all git submodules ([#92](https://github.com/avast-tl/retdec/issues/92), [#93](https://github.com/avast-tl/retdec/issues/93)). Moved sources of all RetDec-related repositories to this main repository. Third-party dependencies are downloaded and built via CMake's external projects. This allows us to have e.g. only a single copy of LLVM ([#14](https://github.com/avast-tl/retdec/issues/14)) and not require a recursive clone ([#48](https://github.com/avast-tl/retdec/issues/48), [#68](https://github.com/avast-tl/retdec/issues/68), [#72](https://github.com/avast-tl/retdec/issues/72)). -* Enhancement: Set a proper `rpath` during installation on Linux and macOS ([#77](https://github.com/avast-tl/retdec/issues/77), [#100](https://github.com/avast-tl/retdec/issues/100)). This allows us to move the installation directory after the installation into another location. -* Enhancement: Added community support for building and running RetDec inside Docker ([#60](https://github.com/avast-tl/retdec/pull/60)). -* Enhancement: Decrease the default timeout when downloading the support package during installation ([#6](https://github.com/avast-tl/retdec/pull/6)). +* Enhancement: Added support for a system-wide installation ([#94](https://github.com/avast/retdec/issues/94)). +* Enhancement: Prefixed all the installed binaries and scripts with `retdec-` ([#70](https://github.com/avast/retdec/issues/70)). Also, some tools were renamed to make their names more uniform. +* Enhancement: Got rid of all git submodules ([#92](https://github.com/avast/retdec/issues/92), [#93](https://github.com/avast/retdec/issues/93)). Moved sources of all RetDec-related repositories to this main repository. Third-party dependencies are downloaded and built via CMake's external projects. This allows us to have e.g. only a single copy of LLVM ([#14](https://github.com/avast/retdec/issues/14)) and not require a recursive clone ([#48](https://github.com/avast/retdec/issues/48), [#68](https://github.com/avast/retdec/issues/68), [#72](https://github.com/avast/retdec/issues/72)). +* Enhancement: Set a proper `rpath` during installation on Linux and macOS ([#77](https://github.com/avast/retdec/issues/77), [#100](https://github.com/avast/retdec/issues/100)). This allows us to move the installation directory after the installation into another location. +* Enhancement: Added community support for building and running RetDec inside Docker ([#60](https://github.com/avast/retdec/pull/60)). +* Enhancement: Decrease the default timeout when downloading the support package during installation ([#6](https://github.com/avast/retdec/pull/6)). * Enhancement: Any shell can be used to install the decompiler, not just Bash. -* Enhancement: Added unofficial support for macOS build ([#7](https://github.com/avast-tl/retdec/issues/7)). -* Enhancement: Allow 32b versions of `bin2llvmir` and `llvmir2hll` on Windows access more memory ([#7](https://github.com/avast-tl/retdec/issues/73)). +* Enhancement: Added unofficial support for macOS build ([#7](https://github.com/avast/retdec/issues/7)). +* Enhancement: Allow 32b versions of `bin2llvmir` and `llvmir2hll` on Windows access more memory ([#7](https://github.com/avast/retdec/issues/73)). * Enhancement: Added a method in `loader::Image` to obtain segment content as a raw data pointer. -* Enhancement: `retdec-fileinfo` now prints raw bytes of Rich Header in the JSON format ([#288](https://github.com/avast-tl/retdec/issues/288)). -* Enhancement: Delayed imports in PE files are now distinguished from non-delayed imports in the output from `retdec-fileinfo` by a boolean flag ([#287](https://github.com/avast-tl/retdec/issues/288)). -* Fix: Add a missing `.c` extension to files generated by `retdec-archive-decompiler.sh` ([#261](https://github.com/avast-tl/retdec/issues/261). -* Fix: Fixed build of yaracpp on 32b Unix-like operating systems ([#299](https://github.com/avast-tl/retdec/issues/299)). -* Fix: Fixed parsing of PE files having corrupted import tables ([#101](https://github.com/avast-tl/retdec/issues/101)). -* Fix: Fixed parsing of delayed imports by ordinals in PE files ([#282](https://github.com/avast-tl/retdec/issues/282)). -* Fix: Fixed ordering of detected tools (e.g. compilers and packers) on systems whose `std::sort()` is not stable ([#262](https://github.com/avast-tl/retdec/issues/262)). -* Fix: When running RetDec on macOS, `gtimeout` is now used instead of `timeout` ([#260](https://github.com/avast-tl/retdec/issues/260)). This fixes the following runtime error when running `retdec-archive-decompiler.sh`: `The `timeout` command is required but it is not available`. +* Enhancement: `retdec-fileinfo` now prints raw bytes of Rich Header in the JSON format ([#288](https://github.com/avast/retdec/issues/288)). +* Enhancement: Delayed imports in PE files are now distinguished from non-delayed imports in the output from `retdec-fileinfo` by a boolean flag ([#287](https://github.com/avast/retdec/issues/288)). +* Fix: Add a missing `.c` extension to files generated by `retdec-archive-decompiler.sh` ([#261](https://github.com/avast/retdec/issues/261). +* Fix: Fixed build of yaracpp on 32b Unix-like operating systems ([#299](https://github.com/avast/retdec/issues/299)). +* Fix: Fixed parsing of PE files having corrupted import tables ([#101](https://github.com/avast/retdec/issues/101)). +* Fix: Fixed parsing of delayed imports by ordinals in PE files ([#282](https://github.com/avast/retdec/issues/282)). +* Fix: Fixed ordering of detected tools (e.g. compilers and packers) on systems whose `std::sort()` is not stable ([#262](https://github.com/avast/retdec/issues/262)). +* Fix: When running RetDec on macOS, `gtimeout` is now used instead of `timeout` ([#260](https://github.com/avast/retdec/issues/260)). This fixes the following runtime error when running `retdec-archive-decompiler.sh`: `The `timeout` command is required but it is not available`. * Fix: When running RetDec on macOS, `greadlink` is now used instead of `readlink`. This fixes runtime errors of the form `readlink: illegal option -- e`. -* Fix: `retdec-decompiler.sh` on macOS no longer requires the GNU version of `sed` ([#257](https://github.com/avast-tl/retdec/issues/257)). -* Fix: `#!/usr/bin/env bash` is now used instead of `#!/bin/bash` to run our scripts ([#258](https://github.com/avast-tl/retdec/issues/258)). -* Fix: Fixed `retdec-fileinfo` crashes when verifying digital signature of PE files ([#87](https://github.com/avast-tl/retdec/issues/87)). -* Fix: Fixed infinite loop in COFF word length detection for rare cases ([#242](https://github.com/avast-tl/retdec/issues/242)). -* Fix: Fixed several ELF bugs causing crashes ([#239](https://github.com/avast-tl/retdec/issues/239), [#240](https://github.com/avast-tl/retdec/issues/240), [#241](https://github.com/avast-tl/retdec/issues/241), [#248](https://github.com/avast-tl/retdec/issues/248)). -* Fix: Fixed unit-tests discovery in `retdec-tests-runner.sh` on macOS ([#238](https://github.com/avast-tl/retdec/issues/238)). -* Fix: Non-printable characters in ELF .dynamic section output are now replaced with hexadecimal codes ([#82](https://github.com/avast-tl/retdec/issues/82)). -* Fix: Fix for several segmentation faults in ELF parsing module ([#89](https://github.com/avast-tl/retdec/issues/89)). -* Fix: Added a workaround for a GCC 5 compilation bug ([#231](https://github.com/avast-tl/retdec/issues/231)). -* Fix: Fix LLVM (and therefore RetDec) build on systems with architecture other than x86 ([llvm #3](https://github.com/avast-tl/llvm/issues/3)). +* Fix: `retdec-decompiler.sh` on macOS no longer requires the GNU version of `sed` ([#257](https://github.com/avast/retdec/issues/257)). +* Fix: `#!/usr/bin/env bash` is now used instead of `#!/bin/bash` to run our scripts ([#258](https://github.com/avast/retdec/issues/258)). +* Fix: Fixed `retdec-fileinfo` crashes when verifying digital signature of PE files ([#87](https://github.com/avast/retdec/issues/87)). +* Fix: Fixed infinite loop in COFF word length detection for rare cases ([#242](https://github.com/avast/retdec/issues/242)). +* Fix: Fixed several ELF bugs causing crashes ([#239](https://github.com/avast/retdec/issues/239), [#240](https://github.com/avast/retdec/issues/240), [#241](https://github.com/avast/retdec/issues/241), [#248](https://github.com/avast/retdec/issues/248)). +* Fix: Fixed unit-tests discovery in `retdec-tests-runner.sh` on macOS ([#238](https://github.com/avast/retdec/issues/238)). +* Fix: Non-printable characters in ELF .dynamic section output are now replaced with hexadecimal codes ([#82](https://github.com/avast/retdec/issues/82)). +* Fix: Fix for several segmentation faults in ELF parsing module ([#89](https://github.com/avast/retdec/issues/89)). +* Fix: Added a workaround for a GCC 5 compilation bug ([#231](https://github.com/avast/retdec/issues/231)). +* Fix: Fix LLVM (and therefore RetDec) build on systems with architecture other than x86 ([llvm #3](https://github.com/avast/llvm/issues/3)). * Fix: Valid Mach-O x64 relocations are no longer ignored. -* Fix: Only a single copy of LLVM (and all other components) is kept ([#14](https://github.com/avast-tl/retdec/issues/14)). +* Fix: Only a single copy of LLVM (and all other components) is kept ([#14](https://github.com/avast/retdec/issues/14)). * Fix: RetDec works even if it is installed to a directory which have whitespaces in its path. -* Fix: Reduced the length of build paths to external projects ([#61](https://github.com/avast-tl/retdec/issues/61)). -* Fix: Build of `googletest` with VS 2017 ([#55](https://github.com/avast-tl/retdec/issues/55)). -* Fix: Build of `retdec-config` when two different compilers are employed ([#52](https://github.com/avast-tl/retdec/issues/52)). -* Fix: Build of the `llvm` submodule with VS 2017 when DIA SDK is installed ([#61](https://github.com/avast-tl/retdec/issues/61)). -* Fix: Ordering of compiler detections ([#39](https://github.com/avast-tl/retdec/issues/39)). -* Fix: Remove duplicate `lib` prefix when installing [libdwarf](https://github.com/avast-tl/libdwarf) libraries ([#31](https://github.com/avast-tl/retdec/issues/31)). -* Fix: When installing the decompiler, do not remove the entire `share` directory ([#12](https://github.com/avast-tl/retdec/issues/12)). +* Fix: Reduced the length of build paths to external projects ([#61](https://github.com/avast/retdec/issues/61)). +* Fix: Build of `googletest` with VS 2017 ([#55](https://github.com/avast/retdec/issues/55)). +* Fix: Build of `retdec-config` when two different compilers are employed ([#52](https://github.com/avast/retdec/issues/52)). +* Fix: Build of the `llvm` submodule with VS 2017 when DIA SDK is installed ([#61](https://github.com/avast/retdec/issues/61)). +* Fix: Ordering of compiler detections ([#39](https://github.com/avast/retdec/issues/39)). +* Fix: Remove duplicate `lib` prefix when installing [libdwarf](https://github.com/avast/libdwarf) libraries ([#31](https://github.com/avast/retdec/issues/31)). +* Fix: When installing the decompiler, do not remove the entire `share` directory ([#12](https://github.com/avast/retdec/issues/12)). * Fix: Improve OS type detection when installing the decompiler. -* Fix: Remove useless OS type detection when running decompilations ([#10](https://github.com/avast-tl/retdec/issues/10)). +* Fix: Remove useless OS type detection when running decompilations ([#10](https://github.com/avast/retdec/issues/10)). * Fix: Filesystem path in utils now returns correct information when it is appended with another path. -* Fix: Plain output of `fileinfo` now escapes non-printable characters in subject/issuer name/organization of PE certificates ([#253](https://github.com/avast-tl/retdec/issues/253)). -* Fix: Invalid dates are no longer shown in the output of `fileinfo` ([#251](https://github.com/avast-tl/retdec/issues/251)). -* Fix: Fixed crash of `fileinfo` when accessing slightly corrupted security directory ([#255](https://github.com/avast-tl/retdec/issues/255), [#250](https://github.com/avast-tl/retdec/issues/250)). -* Fix: Delayed imports are now ignored when calculating import-table hashes for PE files ([#287](https://github.com/avast-tl/retdec/issues/287)). -* Fix: Import-table hashes for Mach-O binaries are now always generated even if commands for library loading are not ordered ([#285](https://github.com/avast-tl/retdec/issues/287)). -* Fix: OpenSSL can now be built on ARM architectures (Linux and Windows) and other non-recognized architectures (Linux only) ([#299](https://github.com/avast-tl/retdec/issues/299)). -* Fix: Decompilation in raw mode (`--mode raw`) no longer removes the original input file when cleanup option is used (`--cleanup`) ([#309](https://github.com/avast-tl/retdec/issues/309)). -* Fix: Retdec can now be cross-compiled ([yaracpp #2](https://github.com/avast-tl/yaracpp/pull/2)). +* Fix: Plain output of `fileinfo` now escapes non-printable characters in subject/issuer name/organization of PE certificates ([#253](https://github.com/avast/retdec/issues/253)). +* Fix: Invalid dates are no longer shown in the output of `fileinfo` ([#251](https://github.com/avast/retdec/issues/251)). +* Fix: Fixed crash of `fileinfo` when accessing slightly corrupted security directory ([#255](https://github.com/avast/retdec/issues/255), [#250](https://github.com/avast/retdec/issues/250)). +* Fix: Delayed imports are now ignored when calculating import-table hashes for PE files ([#287](https://github.com/avast/retdec/issues/287)). +* Fix: Import-table hashes for Mach-O binaries are now always generated even if commands for library loading are not ordered ([#285](https://github.com/avast/retdec/issues/287)). +* Fix: OpenSSL can now be built on ARM architectures (Linux and Windows) and other non-recognized architectures (Linux only) ([#299](https://github.com/avast/retdec/issues/299)). +* Fix: Decompilation in raw mode (`--mode raw`) no longer removes the original input file when cleanup option is used (`--cleanup`) ([#309](https://github.com/avast/retdec/issues/309)). +* Fix: Retdec can now be cross-compiled ([yaracpp #2](https://github.com/avast/yaracpp/pull/2)). # v3.0 (2017-12-13) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd4831169..494c86204 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ endfunction() # bin directory, where they are automatically picked up by executables. # # For more details, see -# - https://github.com/avast-tl/retdec/issues/77 +# - https://github.com/avast/retdec/issues/77 # - https://cmake.org/Wiki/CMake_RPATH_handling if(APPLE) set(CMAKE_INSTALL_RPATH "@executable_path/../lib") diff --git a/Dockerfile b/Dockerfile index a5841f817..bb389393c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN apt-get -y update && \ libtool USER retdec -RUN git clone https://github.com/avast-tl/retdec && \ +RUN git clone https://github.com/avast/retdec && \ cd retdec && \ mkdir build && \ cd build && \ diff --git a/LICENSE-THIRD-PARTY b/LICENSE-THIRD-PARTY index 50bcfe781..e0e6ca0c9 100644 --- a/LICENSE-THIRD-PARTY +++ b/LICENSE-THIRD-PARTY @@ -5,29 +5,29 @@ In the event that we accidentally failed to list a required notice, please bring it to our attention by contacting the repository owner. RetDec uses the following third-party libraries or other resources: -1) Capstone2LlvmIR: https://github.com/avast-tl/capstone2llvmir -2) Ctypes: https://github.com/avast-tl/ctypes -3) Demangler: https://github.com/avast-tl/demangler -4) Fileformat: https://github.com/avast-tl/fileformat -5) Fnc-patterns: https://github.com/avast-tl/fnc-patterns +1) Capstone2LlvmIR: https://github.com/avast/capstone2llvmir +2) Ctypes: https://github.com/avast/ctypes +3) Demangler: https://github.com/avast/demangler +4) Fileformat: https://github.com/avast/fileformat +5) Fnc-patterns: https://github.com/avast/fnc-patterns 6) Libdwarf: https://www.prevanders.net/dwarf.html 7) Libelf: https://github.com/WolfgangSt/libelf 8) LLVM: https://llvm.org/ -9) PDBparser: https://github.com/avast-tl/pdbparser -10) RetDec-config: https://github.com/avast-tl/retdec-config -11) Tl-cpputils: https://github.com/avast-tl/tl-cpputils +9) PDBparser: https://github.com/avast/pdbparser +10) RetDec-config: https://github.com/avast/retdec-config +11) Tl-cpputils: https://github.com/avast/tl-cpputils 12) Capstone Engine: http://www.capstone-engine.org/ 13) RapidJSON: https://github.com/Tencent/rapidjson 14) Elfio: http://elfio.sourceforge.net/ 15) OpenSSL: https://www.openssl.org/ -16) PeLib: https://github.com/avast-tl/pelib +16) PeLib: https://github.com/avast/pelib 17) TinyXML-2: https://github.com/leethomason/tinyxml2 -18) yaracpp: https://github.com/avast-tl/yaracpp -19) yaramod: https://github.com/avast-tl/yaramod +18) yaracpp: https://github.com/avast/yaracpp +19) yaramod: https://github.com/avast/yaramod 20) JsonCpp: https://github.com/open-source-parsers/jsoncpp 21) optional_lite: https://github.com/martinmoene/optional-lite 22) YARA: https://virustotal.github.io/yara/ -23) Google Test: https://github.com/avast-tl/googletest +23) Google Test: https://github.com/avast/googletest 24) Keystone Engine: http://www.keystone-engine.org/ 25) whereami: https://github.com/gpakosz/whereami 26) pybind11: https://github.com/pybind/pybind11 @@ -2275,4 +2275,4 @@ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 64bfcc86c..aec5eab5d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # RetDec -[![Travis CI build status](https://travis-ci.org/avast-tl/retdec.svg?branch=master)](https://travis-ci.org/avast-tl/retdec) +[![Travis CI build status](https://travis-ci.org/avast/retdec.svg?branch=master)](https://travis-ci.org/avast/retdec) [![AppVeyor build status](https://ci.appveyor.com/api/projects/status/daqstq396hb8ixjg/branch/master?svg=true -)](https://ci.appveyor.com/project/avast-tl/retdec?branch=master) +)](https://ci.appveyor.com/project/avast/retdec?branch=master) [![TeamCity build status](https://retdec-tc.avast.com/app/rest/builds/aggregated/strob:(buildType:(project:(id:Retdec)))/statusIcon)](https://retdec-tc.avast.com/project.html?projectId=Retdec&guest=1) [RetDec](https://retdec.com/) is a retargetable machine-code decompiler based on [LLVM](https://llvm.org/). @@ -28,7 +28,7 @@ Features: * Generation of call graphs, control-flow graphs, and various statistics. For more information, check out our -* [Wiki](https://github.com/avast-tl/retdec/wiki) (in progress) +* [Wiki](https://github.com/avast/retdec/wiki) (in progress) * Botconf 2017 talk: [slides](https://retdec.com/static/publications/retdec-slides-botconf-2017.pdf), [video](https://www.youtube.com/watch?v=HHFvtt5b6yY) * REcon Montreal 2018 talk: [slides](https://retdec.com/static/publications/retdec-slides-recon-2018.pdf) * [Publications](https://retdec.com/publications/) @@ -39,7 +39,7 @@ Currently, we support Windows (7 or later), Linux, macOS, and (experimentally) F ### Windows -1. Either download and unpack a [pre-built package](https://github.com/avast-tl/retdec/releases), or build and install the decompiler by yourself (the process is described below). +1. Either download and unpack a [pre-built package](https://github.com/avast/retdec/releases), or build and install the decompiler by yourself (the process is described below). 2. Install [Microsoft Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48145). @@ -59,7 +59,7 @@ Currently, we support Windows (7 or later), Linux, macOS, and (experimentally) F ### Linux -1. There are currently no pre-built packages for Linux. You will have to build and install the decompiler by yourself. The process is described below. +1. Either download and unpack a [pre-built package](https://github.com/avast/retdec/releases), or build and install the decompiler by yourself (the process is described below). 2. After you have built the decompiler, you will need to install the following packages via your distribution's package manager: @@ -77,7 +77,7 @@ Currently, we support Windows (7 or later), Linux, macOS, and (experimentally) F ### macOS -1. There are currently no pre-built packages for macOS. You will have to build and install the decompiler by yourself. The process is described below. +1. Either download and unpack a [pre-built package](https://github.com/avast/retdec/releases), or build and install the decompiler by yourself (the process is described below). 2. After you have built the decompiler, you will need to install the following packages: @@ -148,7 +148,7 @@ sudo dnf install gcc gcc-c++ cmake make git perl python3 bison flex autoconf aut On Arch Linux, the required packages can be installed with `pacman`: ```sh -sudo pacman -S base-devel cmake git perl python3 bison flex autoconf automake libtool pkg-config m4 zlib upx doxygen graphviz +sudo pacman --needed -S base-devel cmake git perl python3 bison flex autoconf automake libtool pkg-config m4 zlib upx doxygen graphviz ``` #### Windows @@ -156,7 +156,7 @@ sudo pacman -S base-devel cmake git perl python3 bison flex autoconf automake li * Microsoft Visual C++ (version >= Visual Studio 2015 Update 2) * [CMake](https://cmake.org/) (version >= 3.6) * [Git](https://git-scm.com/) -* [Flex + Bison](https://sourceforge.net/projects/winflexbison/files/win_flex_bison3-latest.zip/download) ([mirror](https://github.com/avast-tl/retdec-support/releases/download/2018-07-27/win_flex_bison3-latest.zip)) from the [Win flex-bison project](https://sourceforge.net/projects/winflexbison/). Add the extracted directory to the system `Path` ([HOWTO](https://www.computerhope.com/issues/ch000549.htm)). +* [Flex + Bison](https://sourceforge.net/projects/winflexbison/files/win_flex_bison3-latest.zip/download) ([mirror](https://github.com/avast/retdec-support/releases/download/2018-07-27/win_flex_bison3-latest.zip)) from the [Win flex-bison project](https://sourceforge.net/projects/winflexbison/). Add the extracted directory to the system `Path` ([HOWTO](https://www.computerhope.com/issues/ch000549.htm)). * [Active Perl](https://www.activestate.com/activeperl). It needs to be the first Perl in `PATH`, or it has to be provided to CMake using `CMAKE_PROGRAM_PATH` variable, e.g. `-DCMAKE_PROGRAM_PATH=/c/perl/bin`. * [Python](https://www.python.org/) (version >= 3.4) * Optional: [Doxygen](http://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.13-setup.exe) and [Graphviz](https://graphviz.gitlab.io/_pages/Download/windows/graphviz-2.38.msi) for generating API documentation @@ -165,7 +165,7 @@ sudo pacman -S base-devel cmake git perl python3 bison flex autoconf automake li Packages should be preferably installed via [Homebrew](https://brew.sh). -* Full Xcode installation ([including command-line tools](https://github.com/frida/frida/issues/338#issuecomment-426777849), see [#425](https://github.com/avast-tl/retdec/issues/425) and [#433](https://github.com/avast-tl/retdec/issues/433)) +* Full Xcode installation ([including command-line tools](https://github.com/frida/frida/issues/338#issuecomment-426777849), see [#425](https://github.com/avast/retdec/issues/425) and [#433](https://github.com/avast/retdec/issues/433)) * [CMake](https://cmake.org/) (version >= 3.6) * [Git](https://git-scm.com/) * [Perl](https://www.perl.org/) @@ -192,10 +192,10 @@ OR ### Process -Note: Although RetDec now supports a system-wide installation ([#94](https://github.com/avast-tl/retdec/issues/94)), unless you use your distribution's package manager to install it, we recommend installing RetDec locally into a designated directory. The reason for this is that uninstallation will be easier as you will only need to remove a single directory. To perform a local installation, run `cmake` with the `-DCMAKE_INSTALL_PREFIX=` parameter, where `` is directory into which RetDec will be installed (e.g. `$HOME/projects/retdec-install` on Linux and macOS, and `C:\projects\retdec-install` on Windows). +Note: Although RetDec now supports a system-wide installation ([#94](https://github.com/avast/retdec/issues/94)), unless you use your distribution's package manager to install it, we recommend installing RetDec locally into a designated directory. The reason for this is that uninstallation will be easier as you will only need to remove a single directory. To perform a local installation, run `cmake` with the `-DCMAKE_INSTALL_PREFIX=` parameter, where `` is directory into which RetDec will be installed (e.g. `$HOME/projects/retdec-install` on Linux and macOS, and `C:\projects\retdec-install` on Windows). * Clone the repository: - * `git clone https://github.com/avast-tl/retdec` + * `git clone https://github.com/avast/retdec` * Linux: * `cd retdec` * `mkdir build && cd build` @@ -224,7 +224,7 @@ Note: Although RetDec now supports a system-wide installation ([#94](https://git * `make install` * FreeBSD: * `sudo pkg install git cmake` - * `git clone https://github.com/avast-tl/retdec` + * `git clone https://github.com/avast/retdec` * `cd retdec` * `mkdir build && cd build` * ```sh @@ -251,6 +251,7 @@ You can pass the following additional parameters to `cmake`: * `-DRETDEC_COMPILE_YARA=OFF` to disable YARA rules compilation at installation step (enabled by default). * `-DCMAKE_BUILD_TYPE=Debug` to build with debugging information, which is useful during development. By default, the project is built in the `Release` mode. This has no effect on Windows, but the same thing can be achieved by running `cmake --build .` with the `--config Debug` parameter. * `-DCMAKE_PROGRAM_PATH=` to use Perl at `` (probably useful only on Windows). +* `-D_LOCAL_DIR=` where `` is from `{CAPSTONE, ELFIO, GOOGLETEST, JSONCPP, KEYSTONE, LIBDWARF, LLVM, PELIB, RAPIDJSON, TINYXML, YARACPP, YARAMOD}` (e.g. `-DCAPSTONE_LOCAL_DIR=`), to use the local repository clone at `` for RetDec dependency instead of downloading a fresh copy at build time. Multiple such options may be used at the same time. ## Build in Docker @@ -355,20 +356,20 @@ See the [project documentation](https://retdec-tc.avast.com/repository/download/ ## Related Repositories -* [retdec-idaplugin](https://github.com/avast-tl/retdec-idaplugin) -- Embeds RetDec into IDA (Interactive Disassembler) and makes its use much easier. -* [retdec-regression-tests-framework](https://github.com/avast-tl/retdec-regression-tests-framework) -- A framework for writing and running regression tests for RetDec and related tools. This is a must if you plan to contribute to the RetDec project. -* [retdec-regression-tests](https://github.com/avast-tl/retdec-regression-tests) -- A suite of regression tests for RetDec and related tools. +* [retdec-idaplugin](https://github.com/avast/retdec-idaplugin) -- Embeds RetDec into IDA (Interactive Disassembler) and makes its use much easier. +* [retdec-regression-tests-framework](https://github.com/avast/retdec-regression-tests-framework) -- A framework for writing and running regression tests for RetDec and related tools. This is a must if you plan to contribute to the RetDec project. +* [retdec-regression-tests](https://github.com/avast/retdec-regression-tests) -- A suite of regression tests for RetDec and related tools. * [vim-syntax-retdecdsm](https://github.com/s3rvac/vim-syntax-retdecdsm) -- Vim syntax-highlighting file for the output from the RetDec's disassembler (`.dsm` files). ## License -Copyright (c) 2017 Avast Software, licensed under the MIT license. See the [`LICENSE`](https://github.com/avast-tl/retdec/blob/master/LICENSE) file for more details. +Copyright (c) 2017 Avast Software, licensed under the MIT license. See the [`LICENSE`](https://github.com/avast/retdec/blob/master/LICENSE) file for more details. -RetDec uses third-party libraries or other resources listed, along with their licenses, in the [`LICENSE-THIRD-PARTY`](https://github.com/avast-tl/retdec/blob/master/LICENSE-THIRD-PARTY) file. +RetDec uses third-party libraries or other resources listed, along with their licenses, in the [`LICENSE-THIRD-PARTY`](https://github.com/avast/retdec/blob/master/LICENSE-THIRD-PARTY) file. ## Contributing -See [RetDec contribution guidelines](https://github.com/avast-tl/retdec/wiki/Contribution-Guidelines). +See [RetDec contribution guidelines](https://github.com/avast/retdec/wiki/Contribution-Guidelines). ## Acknowledgements diff --git a/deps/capstone/CMakeLists.txt b/deps/capstone/CMakeLists.txt index 56ee10e7c..3efeb78df 100644 --- a/deps/capstone/CMakeLists.txt +++ b/deps/capstone/CMakeLists.txt @@ -7,46 +7,94 @@ if(CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -ExternalProject_Add(capstone-project - URL https://github.com/avast-tl/capstone/archive/27c713fe4f6eaf9721785932d850b6291a6073fe.zip - URL_HASH SHA256=4d8d0461d7d5737893253698cd0b6d0d64545c1a74b166e8b1d823156a3109cb - DOWNLOAD_NAME capstone.zip - CMAKE_ARGS - # This does not work on MSVC, but may be useful on Linux. - -DCMAKE_BUILD_TYPE=Release - -DCAPSTONE_BUILD_STATIC=ON - -DCAPSTONE_BUILD_SHARED=OFF - -DCAPSTONE_BUILD_STATIC_RUNTIME=OFF - -DCAPSTONE_BUILD_TESTS=OFF - -DCAPSTONE_X86_ATT_DISABLE=OFF - # Enabled architectures. - -DCAPSTONE_ARM_SUPPORT=ON - -DCAPSTONE_ARM64_SUPPORT=ON - -DCAPSTONE_MIPS_SUPPORT=ON - -DCAPSTONE_PPC_SUPPORT=ON - -DCAPSTONE_X86_SUPPORT=ON - # Disabled architectures. - -DCAPSTONE_M68K_SUPPORT=OFF - -DCAPSTONE_SPARC_SUPPORT=OFF - -DCAPSTONE_SYSZ_SUPPORT=OFF - -DCAPSTONE_XCORE_SUPPORT=OFF - -DCAPSTONE_TMS320C64X_SUPPORT=OFF - -DCAPSTONE_M680X_SUPPORT=OFF - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable the update step. - UPDATE_COMMAND "" - # Disable the install step. - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) +if(CAPSTONE_LOCAL_DIR) + message(STATUS "Capstone: using local Capstone directory.") + + ExternalProject_Add(capstone-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${CAPSTONE_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + -DCAPSTONE_BUILD_STATIC=ON + -DCAPSTONE_BUILD_SHARED=OFF + -DCAPSTONE_BUILD_STATIC_RUNTIME=OFF + -DCAPSTONE_BUILD_TESTS=OFF + -DCAPSTONE_X86_ATT_DISABLE=OFF + # Enabled architectures. + -DCAPSTONE_ARM_SUPPORT=ON + -DCAPSTONE_MIPS_SUPPORT=ON + -DCAPSTONE_PPC_SUPPORT=ON + -DCAPSTONE_X86_SUPPORT=ON + # Disabled architectures. + -DCAPSTONE_ARM64_SUPPORT=OFF + -DCAPSTONE_M68K_SUPPORT=OFF + -DCAPSTONE_SPARC_SUPPORT=OFF + -DCAPSTONE_SYSZ_SUPPORT=OFF + -DCAPSTONE_XCORE_SUPPORT=OFF + -DCAPSTONE_TMS320C64X_SUPPORT=OFF + -DCAPSTONE_M680X_SUPPORT=OFF + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + ) + force_configure_step(capstone-project) +else() + message(STATUS "Capstone: using remote Capstone revision.") + + ExternalProject_Add(capstone-project + URL https://github.com/avast/capstone/archive/27c713fe4f6eaf9721785932d850b6291a6073fe.zip + URL_HASH SHA256=4d8d0461d7d5737893253698cd0b6d0d64545c1a74b166e8b1d823156a3109cb + DOWNLOAD_NAME capstone.zip + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + -DCAPSTONE_BUILD_STATIC=ON + -DCAPSTONE_BUILD_SHARED=OFF + -DCAPSTONE_BUILD_STATIC_RUNTIME=OFF + -DCAPSTONE_BUILD_TESTS=OFF + -DCAPSTONE_X86_ATT_DISABLE=OFF + # Enabled architectures. + -DCAPSTONE_ARM_SUPPORT=ON + -DCAPSTONE_MIPS_SUPPORT=ON + -DCAPSTONE_PPC_SUPPORT=ON + -DCAPSTONE_X86_SUPPORT=ON + -DCAPSTONE_ARM64_SUPPORT=ON + # Disabled architectures. + -DCAPSTONE_M68K_SUPPORT=OFF + -DCAPSTONE_SPARC_SUPPORT=OFF + -DCAPSTONE_SYSZ_SUPPORT=OFF + -DCAPSTONE_XCORE_SUPPORT=OFF + -DCAPSTONE_TMS320C64X_SUPPORT=OFF + -DCAPSTONE_M680X_SUPPORT=OFF + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(CAPSTONE_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(capstone-project binary_dir) + message(STATUS "Capstone: path to Capstone directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() -# Set include directories. ExternalProject_Get_Property(capstone-project source_dir) ExternalProject_Get_Property(capstone-project binary_dir) diff --git a/deps/elfio/CMakeLists.txt b/deps/elfio/CMakeLists.txt index ef9b542fa..d60f4bdc2 100644 --- a/deps/elfio/CMakeLists.txt +++ b/deps/elfio/CMakeLists.txt @@ -7,30 +7,65 @@ if(CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -ExternalProject_Add(elfio-project - URL https://github.com/avast-tl/elfio/archive/f85f07390b756fee61408dfe0b04ae4fb86c5477.zip - URL_HASH SHA256=bc821b602cad22de1d671f0314b1171e4bca7ca1aabc85eb2d32945ed8dfcc66 - DOWNLOAD_NAME elfio.zip - CMAKE_ARGS - # This does not work on MSVC, but may be useful on Linux. - -DCMAKE_BUILD_TYPE=Release - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable the configure step - header only. - CONFIGURE_COMMAND "" - # Disable the build step. - BUILD_COMMAND "" - # Disable the update step. - UPDATE_COMMAND "" - # Disable the install step. - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) +if(ELFIO_LOCAL_DIR) + message(STATUS "ELFIO: using local ELFIO directory.") + + ExternalProject_Add(elfio-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${ELFIO_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the configure step - header only. + CONFIGURE_COMMAND "" + # Disable the build step. + BUILD_COMMAND "" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + ) + force_configure_step(elfio-project) +else() + message(STATUS "ELFIO: using remote ELFIO revision.") + + ExternalProject_Add(elfio-project + URL https://github.com/avast/elfio/archive/f85f07390b756fee61408dfe0b04ae4fb86c5477.zip + URL_HASH SHA256=bc821b602cad22de1d671f0314b1171e4bca7ca1aabc85eb2d32945ed8dfcc66 + DOWNLOAD_NAME elfio.zip + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the configure step - header only. + CONFIGURE_COMMAND "" + # Disable the build step. + BUILD_COMMAND "" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(ELFIO_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(elfio-project binary_dir) + message(STATUS "ELFIO: path to ELFIO directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() ExternalProject_Get_Property(elfio-project source_dir) diff --git a/deps/googletest/CMakeLists.txt b/deps/googletest/CMakeLists.txt index 597b3c6ef..68f00d3b0 100644 --- a/deps/googletest/CMakeLists.txt +++ b/deps/googletest/CMakeLists.txt @@ -9,30 +9,65 @@ if(CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -ExternalProject_Add(googletest - URL https://github.com/google/googletest/archive/83fa0cb17dad47a1d905526dcdddb5b96ed189d2.zip - URL_HASH SHA256=3b7cf6bfd1fdec3204933b4c0419c010e89b2409dcd8cbc1ac6a78aab058e2b0 - DOWNLOAD_NAME googletest.zip - CMAKE_ARGS - # This does not work on MSVC, but is useful on Linux. - -DCMAKE_BUILD_TYPE=Release - # Without this, googletest's CMakeLists.txt replaces "/MD" (dynamic run-time) with "-MT" (static runtime). - # Default config for most applications is "/MD", so this will cause problems if linked with "-MT" googletest. - # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx - -Dgtest_force_shared_crt=ON - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable the update step. - UPDATE_COMMAND "" - # Disable the install step. - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) +if(GOOGLETEST_LOCAL_DIR) + message(STATUS "Googletest: using local Googletest directory.") + + ExternalProject_Add(googletest + DOWNLOAD_COMMAND "" + SOURCE_DIR "${GOOGLETEST_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but is useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Without this, googletest's CMakeLists.txt replaces "/MD" (dynamic run-time) with "-MT" (static runtime). + # Default config for most applications is "/MD", so this will cause problems if linked with "-MT" googletest. + # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx + -Dgtest_force_shared_crt=ON + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + ) + force_configure_step(googletest) +else() + message(STATUS "Googletest: using remote Googletest revision.") + + ExternalProject_Add(googletest + URL https://github.com/google/googletest/archive/83fa0cb17dad47a1d905526dcdddb5b96ed189d2.zip + URL_HASH SHA256=3b7cf6bfd1fdec3204933b4c0419c010e89b2409dcd8cbc1ac6a78aab058e2b0 + DOWNLOAD_NAME googletest.zip + CMAKE_ARGS + # This does not work on MSVC, but is useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Without this, googletest's CMakeLists.txt replaces "/MD" (dynamic run-time) with "-MT" (static runtime). + # Default config for most applications is "/MD", so this will cause problems if linked with "-MT" googletest. + # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx + -Dgtest_force_shared_crt=ON + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(GOOGLETEST_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(googletest binary_dir) + message(STATUS "Googletest: path to Googletest directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() # Set include directories. ExternalProject_Get_Property(googletest source_dir) diff --git a/deps/jsoncpp/CMakeLists.txt b/deps/jsoncpp/CMakeLists.txt index 274eddace..ee564eaa2 100644 --- a/deps/jsoncpp/CMakeLists.txt +++ b/deps/jsoncpp/CMakeLists.txt @@ -7,31 +7,67 @@ if(CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -ExternalProject_Add(jsoncpp-project - URL https://github.com/open-source-parsers/jsoncpp/archive/1.8.4.zip - URL_HASH SHA256=2979436dbd4c48a3284dca9fa8f212298425ba3920ed6bacdda8905a94b111a8 - DOWNLOAD_NAME jsoncpp.zip - CMAKE_ARGS - # This does not work on MSVC, but may be useful on Linux. - -DCMAKE_BUILD_TYPE=Release - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable unused options. - -DJSONCPP_WITH_TESTS=OFF - -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF - -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF - -DBUILD_SHARED_LIBS=OFF - # Disable the update step. - UPDATE_COMMAND "" - # Disable the install step. - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) +if(JSONCPP_LOCAL_DIR) + message(STATUS "JsonCpp: using local JsonCpp directory.") + + ExternalProject_Add(jsoncpp-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${JSONCPP_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable unused options. + -DJSONCPP_WITH_TESTS=OFF + -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF + -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF + -DBUILD_SHARED_LIBS=OFF + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + ) + force_configure_step(jsoncpp-project) +else() + message(STATUS "JsonCpp: using remote JsonCpp revision.") + + ExternalProject_Add(jsoncpp-project + URL https://github.com/open-source-parsers/jsoncpp/archive/1.8.4.zip + URL_HASH SHA256=2979436dbd4c48a3284dca9fa8f212298425ba3920ed6bacdda8905a94b111a8 + DOWNLOAD_NAME jsoncpp.zip + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable unused options. + -DJSONCPP_WITH_TESTS=OFF + -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF + -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF + -DBUILD_SHARED_LIBS=OFF + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(JSONCPP_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(jsoncpp-project binary_dir) + message(STATUS "JsonCpp: path to JsonCpp directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() # Set include directories. ExternalProject_Get_Property(jsoncpp-project source_dir) diff --git a/deps/keystone/CMakeLists.txt b/deps/keystone/CMakeLists.txt index 681e8fda4..5584d6268 100644 --- a/deps/keystone/CMakeLists.txt +++ b/deps/keystone/CMakeLists.txt @@ -7,33 +7,68 @@ if(CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -ExternalProject_Add(keystone-project - URL https://github.com/keystone-engine/keystone/archive/d7ba8e378e5284e6384fc9ecd660ed5f6532e922.zip - URL_HASH SHA256=13bd00e062e9c778fe76aaab5c163348b3c9457c0e9b2a4c2fb3e2d8747694ca - DOWNLOAD_NAME keystone.zip - CMAKE_ARGS - # This does not work on MSVC, but may be useful on Linux. - -DCMAKE_BUILD_TYPE=Release - # Force python3 version set in this cmake file. - # Python is used to generate LLVMBuild.cmake file. Python2 generates this file - # with UNIX paths, which do not work. Python3 generates proper Windows paths. - -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} - -DKEYSTONE_BUILD_STATIC_RUNTIME=OFF - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable the update step. - UPDATE_COMMAND "" - # Disable the install step. - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) +if(KEYSTONE_LOCAL_DIR) + message(STATUS "Keystone: using local Keystone directory.") + + ExternalProject_Add(keystone-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${KEYSTONE_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Force python3 version set in this cmake file. + # Python is used to generate LLVMBuild.cmake file. Python2 generates this file + # with UNIX paths, which do not work. Python3 generates proper Windows paths. + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DKEYSTONE_BUILD_STATIC_RUNTIME=OFF + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + ) + force_configure_step(keystone-project) +else() + message(STATUS "Keystone: using remote Keystone revision.") + + ExternalProject_Add(keystone-project + URL https://github.com/keystone-engine/keystone/archive/d7ba8e378e5284e6384fc9ecd660ed5f6532e922.zip + URL_HASH SHA256=13bd00e062e9c778fe76aaab5c163348b3c9457c0e9b2a4c2fb3e2d8747694ca + DOWNLOAD_NAME keystone.zip + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Force python3 version set in this cmake file. + # Python is used to generate LLVMBuild.cmake file. Python2 generates this file + # with UNIX paths, which do not work. Python3 generates proper Windows paths. + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DKEYSTONE_BUILD_STATIC_RUNTIME=OFF + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(KEYSTONE_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(keystone-project binary_dir) + message(STATUS "Keystone: path to Keystone directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() -# Set include directories. ExternalProject_Get_Property(keystone-project source_dir) ExternalProject_Get_Property(keystone-project binary_dir) diff --git a/deps/libdwarf/CMakeLists.txt b/deps/libdwarf/CMakeLists.txt index 05207d508..3839a4fe9 100644 --- a/deps/libdwarf/CMakeLists.txt +++ b/deps/libdwarf/CMakeLists.txt @@ -9,27 +9,56 @@ endif() set(LIBDWARF_INSTALL_DIR "${PROJECT_BINARY_DIR}/external/src/libdwarf-project-install") -ExternalProject_Add(libdwarf-project - URL https://github.com/avast-tl/libdwarf/archive/85465d5e235cc2d2f90d04016d6aca1a452d0e73.zip - URL_HASH SHA256=2864aa7b46529778476190e90359669eb35799ad273233c4df2203bec7db0738 - DOWNLOAD_NAME libdwarf.zip - CMAKE_ARGS - # This does not work on MSVC, but may be useful on Linux. - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=${LIBDWARF_INSTALL_DIR} - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable the update step. - UPDATE_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) - -# Set include directories. +if(LIBDWARF_LOCAL_DIR) + message(STATUS "LibDwarf: using local LibDwarf directory.") + + ExternalProject_Add(libdwarf-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${LIBDWARF_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_INSTALL_PREFIX=${LIBDWARF_INSTALL_DIR} + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + ) + force_configure_step(libdwarf-project) +else() + message(STATUS "LibDwarf: using remote LibDwarf revision.") + + ExternalProject_Add(libdwarf-project + URL https://github.com/avast/libdwarf/archive/85465d5e235cc2d2f90d04016d6aca1a452d0e73.zip + URL_HASH SHA256=2864aa7b46529778476190e90359669eb35799ad273233c4df2203bec7db0738 + DOWNLOAD_NAME libdwarf.zip + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_INSTALL_PREFIX=${LIBDWARF_INSTALL_DIR} + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(LIBDWARF_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(libdwarf-project binary_dir) + message(STATUS "LibDwarf: path to LibDwarf directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() + ExternalProject_Get_Property(libdwarf-project source_dir) ExternalProject_Get_Property(libdwarf-project binary_dir) diff --git a/deps/llvm/CMakeLists.txt b/deps/llvm/CMakeLists.txt index 9976fa996..5275daa17 100644 --- a/deps/llvm/CMakeLists.txt +++ b/deps/llvm/CMakeLists.txt @@ -27,57 +27,152 @@ endif() # install only some tools from LLVM, not all the libraries and tools. include(ExternalProject) -ExternalProject_Add(llvm-project - URL https://github.com/avast-tl/llvm/archive/3d1e5d0bc1122a027e83f57c86851a027dd09112.zip - URL_HASH SHA256=069fdb818c75c1aecad1d24848fd0fe7359ca16871aae595a1389274ba92815d - DOWNLOAD_NAME llvm.zip - CMAKE_ARGS - # Force a release build (we don't need to debug LLVM). - # This has no effect on Windows with MSVC, but is useful on Linux. - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} - - # Force Python3. - -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} - - # Targets to be build. - -DLLVM_TARGETS_TO_BUILD=X86 - - # Disable the generation of targets for tests (we don't need them). - -DLLVM_INCLUDE_TESTS=NO - - # Our tools depending on LLVM require RTTI, so build LLVM with it. - -DLLVM_REQUIRES_RTTI=YES - - # When building in the debug mode (=> assertions are enabled), we - # have to build LLVM with assertions. This prevents link errors - # when building the middle-end and back-end (see - # https://github.com/oclint/oclint/issues/129). - -DLLVM_ENABLE_ASSERTIONS=${IS_DEBUG_BUILD} - - # Disable the emission of warnings, which are useless since we do - # not modify the LLVM sources (of course, except for a few - # exceptions). - -DLLVM_ENABLE_WARNINGS=NO - - # Disable build of unnecessary LLVM parts. - -DLLVM_BUILD_TOOLS=OFF - -DLLVM_BUILD_UTILS=OFF - -DLLVM_BUILD_RUNTIME=OFF - # We don't want this so that we don't have to link with tinfo. - # It looks like terminal colors are working even without this. - -DLLVM_ENABLE_TERMINFO=OFF - - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" +if(LLVM_LOCAL_DIR) + message(STATUS "LLVM: using local LLVM directory.") + + ExternalProject_Add(llvm-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${LLVM_LOCAL_DIR}" + CMAKE_ARGS + # Force a release build (we don't need to debug LLVM). + # This has no effect on Windows with MSVC, but is useful on Linux. + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} + + # Force Python3. + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + + # Targets to be build. + -DLLVM_TARGETS_TO_BUILD=X86 + + # Our tools depending on LLVM require RTTI, so build LLVM with it. + -DLLVM_REQUIRES_RTTI=YES + + # When building in the debug mode (=> assertions are enabled), we + # have to build LLVM with assertions. This prevents link errors + # when building the middle-end and back-end (see + # https://github.com/oclint/oclint/issues/129). + -DLLVM_ENABLE_ASSERTIONS=${IS_DEBUG_BUILD} + + # Disable the emission of warnings, which are useless since we do + # not modify the LLVM sources (of course, except for a few + # exceptions). + -DLLVM_ENABLE_WARNINGS=NO + + # Disable the generation of targets for tests (we don't need them). + -DLLVM_INCLUDE_TOOLS=OFF + -DLLVM_INCLUDE_UTILS=OFF + -DLLVM_INCLUDE_RUNTIMES=OFF + -DLLVM_INCLUDE_EXAMPLES=OFF + -DLLVM_INCLUDE_TESTS=OFF + -DLLVM_INCLUDE_GO_TESTS=OFF + -DLLVM_INCLUDE_BENCHMARKS=OFF + -DLLVM_INCLUDE_DOCS=OFF + + # Disable build of unnecessary LLVM parts. + -DLLVM_BUILD_TOOLS=OFF + -DLLVM_BUILD_UTILS=OFF + -DLLVM_BUILD_RUNTIMES=OFF + -DLLVM_BUILD_RUNTIME=OFF + -DLLVM_BUILD_EXAMPLES=OFF + -DLLVM_BUILD_TESTS=OFF + -DLLVM_BUILD_BENCHMARKS=OFF + -DLLVM_BUILD_DOCS=OFF + # We don't want this so that we don't have to link with tinfo. + # It looks like terminal colors are working even without this. + -DLLVM_ENABLE_TERMINFO=OFF + + # Necessary for builds with older MS Visual Studios (e.g. 2015). + -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON + + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + + # Disable the installation right after build (we want to install the + # needed libraries and tools manually). + INSTALL_COMMAND "" + ) + force_configure_step(llvm-project) +else() + message(STATUS "LLVM: using remote LLVM revision.") + + ExternalProject_Add(llvm-project + URL https://github.com/avast/llvm/archive/82632c555520b4f490d33c799aa1256817d734d2.zip + URL_HASH SHA256=634f42177b36d1017ba09a53a9e3a8347cbf388579fa7eaecb9cb0028edeea77 + DOWNLOAD_NAME llvm.zip + CMAKE_ARGS + # Force a release build (we don't need to debug LLVM). + # This has no effect on Windows with MSVC, but is useful on Linux. + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} + + # Force Python3. + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + + # Targets to be build. + -DLLVM_TARGETS_TO_BUILD=X86 + + # Our tools depending on LLVM require RTTI, so build LLVM with it. + -DLLVM_REQUIRES_RTTI=YES + + # When building in the debug mode (=> assertions are enabled), we + # have to build LLVM with assertions. This prevents link errors + # when building the middle-end and back-end (see + # https://github.com/oclint/oclint/issues/129). + -DLLVM_ENABLE_ASSERTIONS=${IS_DEBUG_BUILD} + + # Disable the emission of warnings, which are useless since we do + # not modify the LLVM sources (of course, except for a few + # exceptions). + -DLLVM_ENABLE_WARNINGS=NO + + # Disable the generation of targets for tests (we don't need them). + -DLLVM_INCLUDE_TOOLS=OFF + -DLLVM_INCLUDE_UTILS=OFF + -DLLVM_INCLUDE_RUNTIMES=OFF + -DLLVM_INCLUDE_EXAMPLES=OFF + -DLLVM_INCLUDE_TESTS=OFF + -DLLVM_INCLUDE_GO_TESTS=OFF + -DLLVM_INCLUDE_BENCHMARKS=OFF + -DLLVM_INCLUDE_DOCS=OFF + + # Disable build of unnecessary LLVM parts. + -DLLVM_BUILD_TOOLS=OFF + -DLLVM_BUILD_UTILS=OFF + -DLLVM_BUILD_RUNTIMES=OFF + -DLLVM_BUILD_RUNTIME=OFF + -DLLVM_BUILD_EXAMPLES=OFF + -DLLVM_BUILD_TESTS=OFF + -DLLVM_BUILD_BENCHMARKS=OFF + -DLLVM_BUILD_DOCS=OFF + # We don't want this so that we don't have to link with tinfo. + # It looks like terminal colors are working even without this. + -DLLVM_ENABLE_TERMINFO=OFF + + # Necessary for builds with older MS Visual Studios (e.g. 2015). + -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON + + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + + # Disable the installation right after build (we want to install the + # needed libraries and tools manually). + INSTALL_COMMAND "" + ) +endif() - # Disable the installation right after build (we want to install the - # needed libraries and tools manually). - INSTALL_COMMAND "" -) +check_if_variable_changed(LLVM_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(llvm-project binary_dir) + message(STATUS "LLVM: path to LLVM directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() # Add libraries. ExternalProject_Get_Property(llvm-project binary_dir) @@ -89,8 +184,10 @@ set(LLVM_LIB_LIST LLVMBitWriter LLVMIRReader LLVMObject + LLVMBinaryFormat LLVMInstCombine LLVMSupport + LLVMDemangle LLVMipo LLVMAsmParser LLVMBitReader diff --git a/deps/pelib/CMakeLists.txt b/deps/pelib/CMakeLists.txt index 3adf07e8e..0cde37a51 100644 --- a/deps/pelib/CMakeLists.txt +++ b/deps/pelib/CMakeLists.txt @@ -31,8 +31,8 @@ else() message(STATUS "PeLib: using remote PeLib revision.") ExternalProject_Add(pelib-project - URL https://github.com/avast-tl/pelib/archive/10bd64227023a2a37f075db3de9f4626dfbfb2b9.zip - URL_HASH SHA256=f6dec6a8cecdec6191412f5486ba26a3283b85a6419c9341a3c227e36fce5ce8 + URL https://github.com/avast-tl/pelib/archive/2d03e34811e01c4ac1e403fd6cb9b323534aa803.zip + URL_HASH SHA256=d06ffb3bb561ece6e554dc58c4f10bfee8fbe21e23ccf79639a5b14743d64a0a DOWNLOAD_NAME pelib.zip CMAKE_ARGS # This does not work on MSVC, but may be useful on Linux. diff --git a/deps/rapidjson/CMakeLists.txt b/deps/rapidjson/CMakeLists.txt index 4ae43d04e..e34c2b2a9 100644 --- a/deps/rapidjson/CMakeLists.txt +++ b/deps/rapidjson/CMakeLists.txt @@ -7,31 +7,67 @@ if(CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -ExternalProject_Add(rapidjson-project - URL https://github.com/Tencent/rapidjson/archive/v1.1.0.zip - URL_HASH SHA256=8e00c38829d6785a2dfb951bb87c6974fa07dfe488aa5b25deec4b8bc0f6a3ab - DOWNLOAD_NAME rapidjson.zip - CMAKE_ARGS - # This does not work on MSVC, but may be useful on Linux. - -DCMAKE_BUILD_TYPE=Release - -DRAPIDJSON_BUILD_DOC=OFF - -DRAPIDJSON_BUILD_EXAMPLES=OFF - -DRAPIDJSON_BUILD_TESTS=OFF - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable the build step. - BUILD_COMMAND "" - # Disable the update step. - UPDATE_COMMAND "" - # Disable the install step. - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) +if(RAPIDJSON_LOCAL_DIR) + message(STATUS "RapidJSON: using local RapidJSON directory.") + + ExternalProject_Add(rapidjson-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${RAPIDJSON_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + -DRAPIDJSON_BUILD_DOC=OFF + -DRAPIDJSON_BUILD_EXAMPLES=OFF + -DRAPIDJSON_BUILD_TESTS=OFF + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the build step. + BUILD_COMMAND "" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + ) + force_configure_step(rapidjson-project) +else() + message(STATUS "RapidJSON: using remote RapidJSON revision.") + + ExternalProject_Add(rapidjson-project + URL https://github.com/Tencent/rapidjson/archive/v1.1.0.zip + URL_HASH SHA256=8e00c38829d6785a2dfb951bb87c6974fa07dfe488aa5b25deec4b8bc0f6a3ab + DOWNLOAD_NAME rapidjson.zip + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + -DRAPIDJSON_BUILD_DOC=OFF + -DRAPIDJSON_BUILD_EXAMPLES=OFF + -DRAPIDJSON_BUILD_TESTS=OFF + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the build step. + BUILD_COMMAND "" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(RAPIDJSON_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(rapidjson-project binary_dir) + message(STATUS "RapidJSON: path to RapidJSON directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() ExternalProject_Get_Property(rapidjson-project source_dir) diff --git a/deps/tinyxml2/CMakeLists.txt b/deps/tinyxml2/CMakeLists.txt index bf42f81f8..0281d8b9f 100644 --- a/deps/tinyxml2/CMakeLists.txt +++ b/deps/tinyxml2/CMakeLists.txt @@ -7,31 +7,67 @@ if(CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -ExternalProject_Add(tinyxml2-project - URL https://github.com/leethomason/tinyxml2/archive/cc1745b552dd12bb1297a99f82044f83b06729e0.zip - URL_HASH SHA256=de255ce39ba1efe20cbffdebd3eea2d08f1269d03440a4fd60e142b0481c3f00 - DOWNLOAD_NAME tinyxml2.zip - CMAKE_ARGS - # This does not work on MSVC, but may be useful on Linux. - -DCMAKE_BUILD_TYPE=Release - # Build only static library. - -DBUILD_STATIC_LIBS:BOOL=ON - -DBUILD_SHARED_LIBS:BOOL=OFF - # Do not build tests. - -DBUILD_TESTS:BOOL=OFF - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable the update step. - UPDATE_COMMAND "" - # Disable the install step. - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) +if(TINYXML_LOCAL_DIR) + message(STATUS "TinyXML: using local TinyXML directory.") + + ExternalProject_Add(tinyxml2-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${TINYXML_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Build only static library. + -DBUILD_STATIC_LIBS:BOOL=ON + -DBUILD_SHARED_LIBS:BOOL=OFF + # Do not build tests. + -DBUILD_TESTS:BOOL=OFF + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + ) + force_configure_step(tinyxml2-project) +else() + message(STATUS "TinyXML: using remote TinyXML revision.") + + ExternalProject_Add(tinyxml2-project + URL https://github.com/leethomason/tinyxml2/archive/cc1745b552dd12bb1297a99f82044f83b06729e0.zip + URL_HASH SHA256=de255ce39ba1efe20cbffdebd3eea2d08f1269d03440a4fd60e142b0481c3f00 + DOWNLOAD_NAME tinyxml2.zip + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Build only static library. + -DBUILD_STATIC_LIBS:BOOL=ON + -DBUILD_SHARED_LIBS:BOOL=OFF + # Do not build tests. + -DBUILD_TESTS:BOOL=OFF + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(TINYXML_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(tinyxml2-project binary_dir) + message(STATUS "TinyXML: path to TinyXML directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() # Set include directories. ExternalProject_Get_Property(tinyxml2-project source_dir) diff --git a/deps/yaracpp/CMakeLists.txt b/deps/yaracpp/CMakeLists.txt index 95227a08f..80e0e8627 100644 --- a/deps/yaracpp/CMakeLists.txt +++ b/deps/yaracpp/CMakeLists.txt @@ -31,7 +31,7 @@ else() message(STATUS "YaraCpp: using remote YaraCpp revision.") ExternalProject_Add(yaracpp-project - URL https://github.com/avast-tl/yaracpp/archive/f5d97cd746398a49b23e62b62994722597407543.zip + URL https://github.com/avast/yaracpp/archive/f5d97cd746398a49b23e62b62994722597407543.zip URL_HASH SHA256=fece1814b0fac2888fc3356d414348f065c2d2eff86c27fee39e45b4a0b5e2c6 DOWNLOAD_NAME yaracpp.zip CMAKE_ARGS diff --git a/deps/yaramod/CMakeLists.txt b/deps/yaramod/CMakeLists.txt index 008528644..95738d3ab 100644 --- a/deps/yaramod/CMakeLists.txt +++ b/deps/yaramod/CMakeLists.txt @@ -11,26 +11,57 @@ if(CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -ExternalProject_Add(yaramod-project - URL https://github.com/avast-tl/yaramod/archive/v2.4.1.zip - URL_HASH SHA256=e8341feba2cea4d00a1f31a3b24823511cf0e77e80621b635e57643aa5c5acee - DOWNLOAD_NAME yaramod.zip - CMAKE_ARGS - # This does not work on MSVC, but may be useful on Linux. - -DCMAKE_BUILD_TYPE=Release - # Force the use of the same compiler as used to build the top-level - # project. Otherwise, the external project may pick up a different - # compiler, which may result in link errors. - "${CMAKE_C_COMPILER_OPTION}" - "${CMAKE_CXX_COMPILER_OPTION}" - # Disable the update step. - UPDATE_COMMAND "" - # Disable the install step. - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON -) +if(YARAMOD_LOCAL_DIR) + message(STATUS "YaraMod: using local YaraMod directory.") + + ExternalProject_Add(yaramod-project + DOWNLOAD_COMMAND "" + SOURCE_DIR "${YARAMOD_LOCAL_DIR}" + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + ) + force_configure_step(yaramod-project) +else() + message(STATUS "YaraMod: using remote YaraMod revision.") + + ExternalProject_Add(yaramod-project + URL https://github.com/avast/yaramod/archive/v2.5.0.zip + URL_HASH SHA256=872d04dbb8c7c14aebe04fd6f091d37e8d252e3f80f1b8dae921e3ff629f53b3 + DOWNLOAD_NAME yaramod.zip + CMAKE_ARGS + # This does not work on MSVC, but may be useful on Linux. + -DCMAKE_BUILD_TYPE=Release + # Force the use of the same compiler as used to build the top-level + # project. Otherwise, the external project may pick up a different + # compiler, which may result in link errors. + "${CMAKE_C_COMPILER_OPTION}" + "${CMAKE_CXX_COMPILER_OPTION}" + # Disable the update step. + UPDATE_COMMAND "" + # Disable the install step. + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_CONFIGURE ON + LOG_BUILD ON + ) +endif() + +check_if_variable_changed(YARAMOD_LOCAL_DIR CHANGED) +if(CHANGED) + ExternalProject_Get_Property(yaramod-project binary_dir) + message(STATUS "YaraMod: path to YaraMod directory changed -> cleaning CMake files in ${binary_dir}.") + clean_cmake_files(${binary_dir}) +endif() ExternalProject_Get_Property(yaramod-project source_dir) ExternalProject_Get_Property(yaramod-project binary_dir) diff --git a/doc/doxygen/doxygen.h b/doc/doxygen/doxygen.h index 71dcc3879..7b655d022 100644 --- a/doc/doxygen/doxygen.h +++ b/doc/doxygen/doxygen.h @@ -8,5 +8,5 @@ @mainpage This is an automatically generated API documentation for the -RetDec project. +RetDec project. */ diff --git a/include/retdec/bin2llvmir/optimizations/globals/dead_global_assign.h b/include/retdec/bin2llvmir/optimizations/globals/dead_global_assign.h index 334bf5b76..d87faf867 100644 --- a/include/retdec/bin2llvmir/optimizations/globals/dead_global_assign.h +++ b/include/retdec/bin2llvmir/optimizations/globals/dead_global_assign.h @@ -47,7 +47,7 @@ class DeadGlobalAssign: public GlobalToLocalAndDeadGlobalAssign { virtual ~DeadGlobalAssign() override; static const char *getPassArg(); - virtual const char *getPassName() const override; + virtual llvm::StringRef getPassName() const override; public: static char ID; diff --git a/include/retdec/bin2llvmir/optimizations/globals/global_to_local.h b/include/retdec/bin2llvmir/optimizations/globals/global_to_local.h index 1dd7a84b4..4730e3d83 100644 --- a/include/retdec/bin2llvmir/optimizations/globals/global_to_local.h +++ b/include/retdec/bin2llvmir/optimizations/globals/global_to_local.h @@ -100,7 +100,7 @@ class GlobalToLocal: public GlobalToLocalAndDeadGlobalAssign { virtual ~GlobalToLocal() override; static const char *getPassArg(); - virtual const char *getPassName() const override; + virtual llvm::StringRef getPassName() const override; public: static char ID; diff --git a/include/retdec/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.h b/include/retdec/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.h index e9f094c27..bc0953405 100644 --- a/include/retdec/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.h +++ b/include/retdec/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.h @@ -145,7 +145,6 @@ class GlobalToLocalAndDeadGlobalAssign: public llvm::ModulePass { void addFilteredRUse(llvm::Instruction &rUse); void addFilteredLUses(const std::set &lUses); void addFilteredRUses(const std::set &rUses); - bool wasSomethingOptimized(); FuncInfo &getFuncInfoFor(llvm::Function &func); void printFuncInfos(); diff --git a/include/retdec/bin2llvmir/optimizations/idioms/idioms_analysis.h b/include/retdec/bin2llvmir/optimizations/idioms/idioms_analysis.h index e10d9abe5..1814d81a3 100644 --- a/include/retdec/bin2llvmir/optimizations/idioms/idioms_analysis.h +++ b/include/retdec/bin2llvmir/optimizations/idioms/idioms_analysis.h @@ -27,11 +27,6 @@ #include "retdec/bin2llvmir/optimizations/idioms/idioms_vstudio.h" #include "retdec/bin2llvmir/providers/config.h" -#ifdef DEBUG_TYPE -#undef DEBUG_TYPE // "idioms" -#endif // DEBUG_TYPE "idioms" -#define DEBUG_TYPE "idioms" - namespace retdec { namespace bin2llvmir { @@ -54,10 +49,6 @@ class IdiomsAnalysis: private: bool analyse(llvm::Function & f, llvm::Pass * p, int (IdiomsAnalysis::*exchanger)(llvm::Function &, llvm::Pass *) const, const char * fname); bool analyse(llvm::BasicBlock & bb, llvm::Instruction * (IdiomsAnalysis::*exchanger)(llvm::BasicBlock::iterator) const, const char * fname); - - void print_dbg(const char * str, const llvm::Instruction & i) const { - DEBUG(llvm::errs() << str << " detected an idiom starting at " << i.getName() << "\n"); - } }; } // namespace bin2llvmir diff --git a/include/retdec/bin2llvmir/optimizations/value_protect/value_protect.h b/include/retdec/bin2llvmir/optimizations/value_protect/value_protect.h index 0a87215df..d4326564c 100644 --- a/include/retdec/bin2llvmir/optimizations/value_protect/value_protect.h +++ b/include/retdec/bin2llvmir/optimizations/value_protect/value_protect.h @@ -31,7 +31,7 @@ namespace bin2llvmir { * * Every even run generates these protections. * Every odd run removes them - * (partially, see https://github.com/avast-tl/retdec/issues/301). + * (partially, see https://github.com/avast/retdec/issues/301). */ class ValueProtect : public llvm::ModulePass { diff --git a/include/retdec/bin2llvmir/providers/asm_instruction.h b/include/retdec/bin2llvmir/providers/asm_instruction.h index 9d3df2d4b..7e0f28d8a 100644 --- a/include/retdec/bin2llvmir/providers/asm_instruction.h +++ b/include/retdec/bin2llvmir/providers/asm_instruction.h @@ -98,7 +98,7 @@ class AsmInstruction bool instructionsCanBeErased(); bool eraseInstructions(); - llvm::TerminatorInst* makeTerminal(); + llvm::Instruction* makeTerminal(); llvm::BasicBlock* makeStart(const std::string& name = ""); llvm::BasicBlock* getBasicBlock() const; diff --git a/include/retdec/bin2llvmir/utils/ir_modifier.h b/include/retdec/bin2llvmir/utils/ir_modifier.h index 344695ad2..eda7a064c 100644 --- a/include/retdec/bin2llvmir/utils/ir_modifier.h +++ b/include/retdec/bin2llvmir/utils/ir_modifier.h @@ -10,6 +10,7 @@ #include #include +#include "retdec/bin2llvmir/providers/abi/abi.h" #include "retdec/bin2llvmir/providers/config.h" #include "retdec/bin2llvmir/providers/fileimage.h" @@ -134,7 +135,9 @@ bool IrModifier::localize( auto* ptr = definition->getPointerOperand(); auto* f = definition->getFunction(); - auto* local = new llvm::AllocaInst(ptr->getType()->getPointerElementType()); + auto* local = new llvm::AllocaInst( + ptr->getType()->getPointerElementType(), + Abi::DEFAULT_ADDR_SPACE); local->insertBefore(&f->getEntryBlock().front()); new llvm::StoreInst(definition->getValueOperand(), local, definition); diff --git a/include/retdec/fileformat/fftypes.h b/include/retdec/fileformat/fftypes.h index 3ea50776c..539f431a9 100644 --- a/include/retdec/fileformat/fftypes.h +++ b/include/retdec/fileformat/fftypes.h @@ -32,6 +32,7 @@ #include "retdec/fileformat/types/strings/string.h" #include "retdec/fileformat/types/symbol_table/macho_symbol.h" #include "retdec/fileformat/types/symbol_table/symbol_table.h" +#include "retdec/fileformat/types/tls_info/tls_info.h" namespace retdec { namespace fileformat { diff --git a/include/retdec/fileformat/file_format/coff/coff_format.h b/include/retdec/fileformat/file_format/coff/coff_format.h index 89cc3ae8e..513c8fa34 100644 --- a/include/retdec/fileformat/file_format/coff/coff_format.h +++ b/include/retdec/fileformat/file_format/coff/coff_format.h @@ -7,10 +7,21 @@ #ifndef RETDEC_FILEFORMAT_FILE_FORMAT_COFF_COFF_FORMAT_H #define RETDEC_FILEFORMAT_FILE_FORMAT_COFF_COFF_FORMAT_H -#include +// Do not include in this header. +// It defines many symbols that are also defined in winnt.h. +// Including it here may cause name collisions later if this header +// is included somewhere where winnt.h is also included. #include "retdec/fileformat/file_format/file_format.h" +namespace llvm { +namespace object { + +class COFFObjectFile; + +} // namespace object +} // namespace llvm + namespace retdec { namespace fileformat { diff --git a/include/retdec/fileformat/file_format/file_format.h b/include/retdec/fileformat/file_format/file_format.h index a09675156..c5197e65c 100644 --- a/include/retdec/fileformat/file_format/file_format.h +++ b/include/retdec/fileformat/file_format/file_format.h @@ -83,6 +83,7 @@ class FileFormat : public retdec::utils::ByteValueStorage, private retdec::utils RichHeader *richHeader; ///< rich header PdbInfo *pdbInfo; ///< information about related PDB debug file CertificateTable *certificateTable; ///< table of certificates + TlsInfo *tlsInfo; ///< thread-local information ElfCoreInfo *elfCoreInfo; ///< information about core file structures Format fileFormat; ///< format of input file LoaderErrorInfo _ldrErrInfo; ///< loader error (e.g. Windows loader error for PE files) @@ -231,6 +232,7 @@ class FileFormat : public retdec::utils::ByteValueStorage, private retdec::utils const RichHeader* getRichHeader() const; const PdbInfo* getPdbInfo() const; const CertificateTable* getCertificateTable() const; + const TlsInfo* getTlsInfo() const; const ElfCoreInfo* getElfCoreInfo() const; const Symbol* getSymbol(const std::string &name) const; const Symbol* getSymbol(unsigned long long address) const; diff --git a/include/retdec/fileformat/file_format/macho/macho_format.h b/include/retdec/fileformat/file_format/macho/macho_format.h index bd31a7083..203e47425 100644 --- a/include/retdec/fileformat/file_format/macho/macho_format.h +++ b/include/retdec/fileformat/file_format/macho/macho_format.h @@ -11,7 +11,6 @@ #include #include -#include #include "retdec/fileformat/file_format/file_format.h" diff --git a/include/retdec/fileformat/file_format/pe/pe_format.h b/include/retdec/fileformat/file_format/pe/pe_format.h index a52dcc931..bf4fe53d9 100644 --- a/include/retdec/fileformat/file_format/pe/pe_format.h +++ b/include/retdec/fileformat/file_format/pe/pe_format.h @@ -72,6 +72,7 @@ class PeFormat : public FileFormat void loadResourceNodes(std::vector &nodes, const std::vector &levels); void loadResources(); void loadCertificates(); + void loadTlsInformation(); /// @} /// @name Signature verification methods diff --git a/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser.h b/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser.h index 2676a0eb3..aec33202d 100644 --- a/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser.h +++ b/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser.h @@ -72,6 +72,12 @@ class PeFormatParser virtual bool getDebugEntryPointerToRawData(unsigned long long index, unsigned long long& pointerToRawData) const = 0; virtual unsigned long long getResourceDirectoryOffset() const = 0; virtual const PeLib::ResourceNode* getResourceTreeRoot() const = 0; + virtual unsigned long long getTlsStartAddressOfRawData() const = 0; + virtual unsigned long long getTlsEndAddressOfRawData() const = 0; + virtual unsigned long long getTlsAddressOfIndex() const = 0; + virtual unsigned long long getTlsAddressOfCallBacks() const = 0; + virtual unsigned long long getTlsSizeOfZeroFill() const = 0; + virtual unsigned long long getTlsCharacteristics() const = 0; virtual std::unique_ptr getClrHeader() const = 0; virtual unsigned long long getNumberOfRelocations() const = 0; virtual unsigned long long getNumberOfRelocationData(unsigned long long index) const = 0; diff --git a/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser32.h b/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser32.h index 9cf0c7c92..fd40873a0 100644 --- a/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser32.h +++ b/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser32.h @@ -68,6 +68,12 @@ class PeFormatParser32 : public PeFormatParser virtual bool getDebugEntryPointerToRawData(unsigned long long index, unsigned long long& pointerToRawData) const override; virtual unsigned long long getResourceDirectoryOffset() const override; virtual const PeLib::ResourceNode* getResourceTreeRoot() const override; + virtual unsigned long long getTlsStartAddressOfRawData() const override; + virtual unsigned long long getTlsEndAddressOfRawData() const override; + virtual unsigned long long getTlsAddressOfIndex() const override; + virtual unsigned long long getTlsAddressOfCallBacks() const override; + virtual unsigned long long getTlsSizeOfZeroFill() const override; + virtual unsigned long long getTlsCharacteristics() const override; virtual std::unique_ptr getClrHeader() const override; virtual unsigned long long getNumberOfRelocations() const override; virtual unsigned long long getNumberOfRelocationData(unsigned long long index) const override; diff --git a/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser64.h b/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser64.h index 97cd14f27..dead166aa 100644 --- a/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser64.h +++ b/include/retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser64.h @@ -68,6 +68,12 @@ class PeFormatParser64 : public PeFormatParser virtual bool getDebugEntryPointerToRawData(unsigned long long index, unsigned long long& pointerToRawData) const override; virtual unsigned long long getResourceDirectoryOffset() const override; virtual const PeLib::ResourceNode* getResourceTreeRoot() const override; + virtual unsigned long long getTlsStartAddressOfRawData() const override; + virtual unsigned long long getTlsEndAddressOfRawData() const override; + virtual unsigned long long getTlsAddressOfIndex() const override; + virtual unsigned long long getTlsAddressOfCallBacks() const override; + virtual unsigned long long getTlsSizeOfZeroFill() const override; + virtual unsigned long long getTlsCharacteristics() const override; virtual std::unique_ptr getClrHeader() const override; virtual unsigned long long getNumberOfRelocations() const override; virtual unsigned long long getNumberOfRelocationData(unsigned long long index) const override; diff --git a/include/retdec/fileformat/file_format/pe/pe_template.h b/include/retdec/fileformat/file_format/pe/pe_template.h index 21ecc7653..57fe06d83 100644 --- a/include/retdec/fileformat/file_format/pe/pe_template.h +++ b/include/retdec/fileformat/file_format/pe/pe_template.h @@ -706,6 +706,66 @@ template const PeLib::ResourceNode* peResourceTreeRoot(const PeLib::Re return resources.getRoot(); } +/** + * Get TLS directory startAddressOfRawData + * @param tls Parser of TLS directory + * @return StartAddressOfRawData of TLS directory + */ +template unsigned long long peTlsStartAddressOfRawData(const PeLib::TlsDirectory &tls) +{ + return tls.getStartAddressOfRawData(); +} + +/** + * Get TLS directory endAddressOfRawData + * @param tls Parser of TLS directory + * @return EndAddressOfRawData of TLS directory + */ +template unsigned long long peTlsEndAddressOfRawData(const PeLib::TlsDirectory &tls) +{ + return tls.getEndAddressOfRawData(); +} + +/** + * Get TLS directory addressOfIndex + * @param tls Parser of TLS directory + * @return AddressOfIndex of TLS directory + */ +template unsigned long long peTlsAddressOfIndex(const PeLib::TlsDirectory &tls) +{ + return tls.getAddressOfIndex(); +} + +/** + * Get TLS directory addressOfCallBacks + * @param tls Parser of TLS directory + * @return AddressOfCallBacks of TLS directory + */ +template unsigned long long peTlsAddressOfCallBacks(const PeLib::TlsDirectory &tls) +{ + return tls.getAddressOfCallBacks(); +} + +/** + * Get TLS directory sizeOfZeroFill + * @param tls Parser of TLS directory + * @return SizeOfZeroFill of TLS directory + */ +template unsigned long long peTlsSizeOfZeroFill(const PeLib::TlsDirectory &tls) +{ + return tls.getSizeOfZeroFill(); +} + +/** + * Get TLS directory characteristics + * @param tls Parser of TLS directory + * @return Characteristics of TLS directory + */ +template unsigned long long peTlsCharacteristics(const PeLib::TlsDirectory &tls) +{ + return tls.getCharacteristics(); +} + /** * Get CLR header * @param comHeader Parser of PE COM/CLR directory diff --git a/include/retdec/fileformat/types/resource_table/resource_table.h b/include/retdec/fileformat/types/resource_table/resource_table.h index 6a957c0b8..ca4c71038 100644 --- a/include/retdec/fileformat/types/resource_table/resource_table.h +++ b/include/retdec/fileformat/types/resource_table/resource_table.h @@ -8,6 +8,7 @@ #define RETDEC_FILEFORMAT_TYPES_RESOURCE_TABLE_RESOURCE_TABLE_H #include +#include #include #include "retdec/fileformat/types/resource_table/resource.h" @@ -23,16 +24,23 @@ class ResourceTable { private: using resourcesIterator = std::vector>::const_iterator; - std::vector> table; ///< stored resources - std::vector iconGroups; ///< icon groups - std::vector icons; ///< icons - std::string iconHashCrc32; ///< iconhash CRC32 - std::string iconHashMd5; ///< iconhash MD5 - std::string iconHashSha256; ///< iconhash SHA256 - std::string iconPerceptualAvgHash; ///< icon perceptual hash AvgHash + std::vector> table; ///< stored resources + std::vector resourceVersions; ///< version info resources + std::vector iconGroups; ///< icon groups + std::vector icons; ///< icons + std::vector> languages; ///< supported languages, LCID and code page + std::vector> strings; ///< version info strings + std::string iconHashCrc32; ///< iconhash CRC32 + std::string iconHashMd5; ///< iconhash MD5 + std::string iconHashSha256; ///< iconhash SHA256 + std::string iconPerceptualAvgHash; ///< icon perceptual hash AvgHash std::string computePerceptualAvgHash(const ResourceIcon &icon) const; - std::string computePercetualDCTpHash(const ResourceIcon &icon) const; + bool parseVersionInfo(const std::vector &bytes); + bool parseVersionInfoChild(const std::vector &bytes, std::size_t &offset); + bool parseVarFileInfoChild(const std::vector &bytes, std::size_t &offset); + bool parseStringFileInfoChild(const std::vector &bytes, std::size_t &offset); + bool parseVarString(const std::vector &bytes, std::size_t &offset); public: ResourceTable(); ~ResourceTable(); @@ -40,9 +48,13 @@ class ResourceTable /// @name Getters /// @{ std::size_t getNumberOfResources() const; + std::size_t getNumberOfLanguages() const; + std::size_t getNumberOfStrings() const; std::size_t getSizeInFile() const; std::size_t getLoadedSize() const; const Resource* getResource(std::size_t rIndex) const; + const std::pair* getLanguage(std::size_t rIndex) const; + const std::pair* getString(std::size_t rIndex) const; const Resource* getResourceWithName(const std::string &rName) const; const Resource* getResourceWithName(std::size_t rId) const; const Resource* getResourceWithType(const std::string &rType) const; @@ -65,8 +77,10 @@ class ResourceTable /// @name Other methods /// @{ void computeIconHashes(); + void parseVersionInfoResources(); void clear(); void addResource(std::unique_ptr&& newResource); + void addResourceVersion(Resource *ver); void addResourceIcon(ResourceIcon *icon); void addResourceIconGroup(ResourceIconGroup *iGroup); void linkResourceIconGroups(); diff --git a/include/retdec/fileformat/types/symbol_table/macho_symbol.h b/include/retdec/fileformat/types/symbol_table/macho_symbol.h index 25b6b4893..88cfb86d9 100644 --- a/include/retdec/fileformat/types/symbol_table/macho_symbol.h +++ b/include/retdec/fileformat/types/symbol_table/macho_symbol.h @@ -10,7 +10,6 @@ #include #include -#include #include "retdec/fileformat/types/export_table/export.h" #include "retdec/fileformat/types/import_table/import.h" diff --git a/include/retdec/fileformat/types/tls_info/tls_info.h b/include/retdec/fileformat/types/tls_info/tls_info.h new file mode 100644 index 000000000..12e030066 --- /dev/null +++ b/include/retdec/fileformat/types/tls_info/tls_info.h @@ -0,0 +1,69 @@ +/** + * @file include/retdec/fileformat/types/tls_info/tls_info.h + * @brief Class for information about thread-local storage. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#ifndef RETDEC_FILEFORMAT_TYPES_TLS_INFO_TLS_INFO_H +#define RETDEC_FILEFORMAT_TYPES_TLS_INFO_TLS_INFO_H + +#include +#include + +namespace retdec { +namespace fileformat { + +/** + * Information about TLS + */ +class TlsInfo +{ + private: + std::vector callBacks; ///< addresses of callback functions + std::uint64_t rawDataStartAddr; ///< start address of raw data + std::uint64_t rawDataEndAddr; ///< end address of raw data + std::uint64_t indexAddr; ///< address of index + std::uint64_t callBacksAddr; ///< address of array of callbacks + std::uint32_t zeroFillSize; ///< size of zero fill + std::uint32_t characteristics; ///< characteristics + bool rawDataStartAddrValid; ///< member validity flag + bool rawDataEndAddrValid; ///< member validity flag + bool indexAddrValid; ///< member validity flag + bool callBacksAddrValid; ///< member validity flag + bool zeroFillSizeValid; ///< member validity flag + bool characteristicsValid; ///< member validity flag + public: + TlsInfo(); + ~TlsInfo(); + + /// @name Getters + /// @{ + bool getRawDataStartAddr(std::uint64_t &res) const; + bool getRawDataEndAddr(std::uint64_t &res) const; + bool getIndexAddr(std::uint64_t &res) const; + bool getCallBacksAddr(std::uint64_t &res) const; + bool getZeroFillSize(std::uint32_t &res) const; + bool getCharacteristics(std::uint32_t &res) const; + const std::vector &getCallBacks() const; + /// @} + + /// @name Setters + /// @{ + void setRawDataStartAddr(std::uint64_t sAddr); + void setRawDataEndAddr(std::uint64_t eAddr); + void setIndexAddr(std::uint64_t iAddr); + void setCallBacksAddr(std::uint64_t cbAddr); + void setZeroFillSize(std::uint32_t zFill); + void setCharacteristics(std::uint32_t chars); + /// @} + + /// @name Other methods + /// @{ + void addCallBack(std::uint64_t cb); + /// @} +}; + +} // namespace fileformat +} // namespace retdec + +#endif diff --git a/include/retdec/fileformat/utils/other.h b/include/retdec/fileformat/utils/other.h index 2f15fdee8..7310882ca 100644 --- a/include/retdec/fileformat/utils/other.h +++ b/include/retdec/fileformat/utils/other.h @@ -20,6 +20,7 @@ std::string getFileFormatNameFromEnum(Format format); std::vector getSupportedFileFormats(); std::vector getSupportedArchitectures(); std::string lcidToStr(std::size_t lcid); +std::string codePageToStr(std::size_t cpage); double computeDataEntropy(const std::uint8_t *data, std::size_t dataLen); } // namespace fileformat diff --git a/include/retdec/llvmir2hll/llvm/llvmir2bir_converter/cfg_node.h b/include/retdec/llvmir2hll/llvm/llvmir2bir_converter/cfg_node.h index c0986441a..7c07f9644 100644 --- a/include/retdec/llvmir2hll/llvm/llvmir2bir_converter/cfg_node.h +++ b/include/retdec/llvmir2hll/llvm/llvmir2bir_converter/cfg_node.h @@ -17,7 +17,7 @@ namespace llvm { class BasicBlock; -class TerminatorInst; +class Instruction; class Value; } // namespace llvm @@ -70,7 +70,7 @@ class CFGNode: public SharableFromThis, /// @name Operations with terminator instruction of the last basic block /// @{ - llvm::TerminatorInst *getTerm() const; + llvm::Instruction *getTerm() const; llvm::Value *getCond() const; /// @} diff --git a/include/retdec/macho-extractor/break_fat.h b/include/retdec/macho-extractor/break_fat.h index a09f74b9d..4c48a7ba4 100644 --- a/include/retdec/macho-extractor/break_fat.h +++ b/include/retdec/macho-extractor/break_fat.h @@ -10,7 +10,6 @@ #include #include #include -#include namespace retdec { namespace macho_extractor { diff --git a/include/retdec/utils/string.h b/include/retdec/utils/string.h index 1432708e9..aa68a4660 100644 --- a/include/retdec/utils/string.h +++ b/include/retdec/utils/string.h @@ -52,6 +52,7 @@ std::string toUpper(std::string str); std::string toWide(const std::string &str, std::string::size_type length); std::string unicodeToAscii(const std::uint8_t *bytes, std::size_t nBytes); +std::string unicodeToAscii(const std::uint8_t *bytes, std::size_t nBytes, std::size_t &nRead); std::string readNullTerminatedAscii(const std::uint8_t *bytes, std::size_t bytesLen, std::size_t offset = 0, std::size_t maxBytes = 0, bool failOnExceed = false); diff --git a/scripts/retdec-config.py b/scripts/retdec-config.py index 8392fd2c9..cabba155c 100644 --- a/scripts/retdec-config.py +++ b/scripts/retdec-config.py @@ -143,13 +143,15 @@ '-x86-addr-spaces', '-value-protect', ] + BIN2LLVMIR_LLVM_PASSES_ONLY + BIN2LLVMIR_LLVM_PASSES_ONLY + [ + '-inst-opt', '-simple-types', '-stack-ptr-op-remove', - '-inst-opt', '-idioms', '-global-to-local', '-dead-global-assign', '-instcombine', + '-inst-opt', + '-idioms', '-phi2seq', '-value-protect', ] + BIN2LLVMIR_PARAMS_DISABLES diff --git a/scripts/retdec-decompiler.py b/scripts/retdec-decompiler.py index a6c5c0fc3..eb445b112 100644 --- a/scripts/retdec-decompiler.py +++ b/scripts/retdec-decompiler.py @@ -7,6 +7,7 @@ import argparse import glob import importlib +import json import os import shutil import sys @@ -569,35 +570,46 @@ def _cleanup(self): utils.remove_file_forced(sig) def _generate_log(self): - log_file = self.output_file + '.decompilation.log' log_decompilation_end_date = str(int(time.time())) - self.log_fileinfo_output = self._json_escape(self.log_fileinfo_output) - self.log_unpacker_output = self._json_escape(self.log_unpacker_output) - self.log_bin2llvmir_output = self._json_escape(self.log_bin2llvmir_output) - self.log_llvmir2hll_output = self._json_escape(self.log_llvmir2hll_output) - - log_structure = '{\n\t\"input_file\" : \"%s\",\n\t\"pdb_file\" : \"%s\",\n\t\"start_date\" : \"%s\",\n\t\"' \ - 'end_date\" : \"%s\",\n\t\"mode\" : \"%s\",\n\t\"arch\" : \"%s\",\n\t\"format\" : \"%s\",\n\t\"' \ - 'fileinfo_rc\" : \"%s\",\n\t\"unpacker_rc\" : \"%s\",\n\t\"bin2llvmir_rc\" : \"%s\",\n\t\"' \ - 'llvmir2hll_rc\" : \"%s\",\n\t\"fileinfo_output\" : \"%s\",\n\t\"unpacker_output\" : \"%s\",' \ - '\n\t\"bin2llvmir_output\" : \"%s\",\n\t\"llvmir2hll_output\" : \"%s\",\n\t\"fileinfo_runtime\"' \ - ' : \"%s\",\n\t\"bin2llvmir_runtime\" : \"%s\",\n\t\"llvmir2hll_runtime\" : \"%s\",\n\t\"' \ - 'fileinfo_memory\" : \"%s\",\n\t\"bin2llvmir_memory\" : \"%s\",\n\t\"llvmir2hll_memory\"' \ - ' : \"%s\"\n}\n' - - json_string = log_structure % ( - self.input_file, self.pdb_file, self.log_decompilation_start_date, log_decompilation_end_date, self.mode, - self.arch, self.format, self.log_fileinfo_rc, self.log_unpacker_rc, self.log_bin2llvmir_rc, - self.log_llvmir2hll_rc, self.log_fileinfo_output, self.log_unpacker_output, self.log_bin2llvmir_output, - self.log_llvmir2hll_output, self.log_fileinfo_time, self.log_bin2llvmir_time, self.log_llvmir2hll_time, - self.log_fileinfo_memory, self.log_bin2llvmir_memory, self.log_llvmir2hll_memory) - - with open(log_file, 'w+') as f: - f.write(json_string) - - def _json_escape(self, string): - return string.rstrip('\r\n').replace('\n', r'\n') if string else None + self.log_fileinfo_output = self.log_fileinfo_output + self.log_unpacker_output = self.log_unpacker_output + self.log_bin2llvmir_output = self.log_bin2llvmir_output + self.log_llvmir2hll_output = self.log_llvmir2hll_output + + log = { + 'input_file': self.input_file, + 'pdb_file': self.pdb_file, + 'start_date': self.log_decompilation_start_date, + 'end_date': log_decompilation_end_date, + 'mode': self.mode, + 'arch': self.arch, + 'format': self.format, + 'fileinfo_rc': self.log_fileinfo_rc, + 'unpacker_rc': self.log_unpacker_rc, + 'bin2llvmir_rc': self.log_bin2llvmir_rc, + 'llvmir2hll_rc': self.log_llvmir2hll_rc, + 'fileinfo_output': self.log_fileinfo_output, + 'unpacker_output': self.log_unpacker_output, + 'bin2llvmir_output': self.log_bin2llvmir_output, + 'llvmir2hll_output': self.log_llvmir2hll_output, + 'fileinfo_runtime': self.log_fileinfo_time, + 'bin2llvmir_runtime': self.log_bin2llvmir_time, + 'llvmir2hll_runtime': self.log_llvmir2hll_time, + 'fileinfo_memory': self.log_fileinfo_memory, + 'bin2llvmir_memory': self.log_bin2llvmir_memory, + 'llvmir2hll_memory': self.log_llvmir2hll_memory, + } + + # The consumer of the log currently assumes that all values are + # strings, so ensure that everything is a string. + for k, v in log.items(): + log[k] = str(v) + + log_file = self.output_file + '.decompilation.log' + with open(log_file, 'w') as f: + json.dump(log, f, indent=4) + f.write('\n') def decompile(self): # Check arguments and set default values for unset options. @@ -1217,7 +1229,7 @@ def decompile(self): CmdRunner.run_cmd(['dot', '-T' + self.args.graph_format, self.output_file + '.cg.dot', '-o', self.output_file + '.cg.' + self.args.graph_format], print_run_msg=True) else: - print('Please install \'Graphviz\' to generate graphics.') + print('Please install \'Graphviz\' to generate graphics and ensure it is in PATH.') if self.args.backend_emit_cfg and self.args.backend_cfg_conversion == 'auto': if utils.tool_exists('dot'): @@ -1225,7 +1237,7 @@ def decompile(self): CmdRunner.run_cmd(['dot', '-T' + self.args.graph_format, cfg, '-o', os.path.splitext(cfg)[0] + '.' + self.args.graph_format], print_run_msg=True) else: - print('Please install \'Graphviz\' to generate graphics.') + print('Please install \'Graphviz\' to generate graphics and ensure it is in PATH.') # Remove trailing whitespace and the last redundant empty new line from the # generated output (if any). It is difficult to do this in the back-end, so we diff --git a/scripts/retdec-utils.py b/scripts/retdec-utils.py index baf51dfd1..05dc82aef 100644 --- a/scripts/retdec-utils.py +++ b/scripts/retdec-utils.py @@ -25,7 +25,7 @@ class CmdRunner: """A runner of external commands.""" - # Taken from https://github.com/avast-tl/retdec-regression-tests-framework/blob/master/regression_tests/cmd_runner.py + # Taken from https://github.com/avast/retdec-regression-tests-framework/blob/master/regression_tests/cmd_runner.py @classmethod def run_cmd(cls, cmd, input='', timeout=None, buffer_output=False, discard_stdout=False, discard_stderr=False, print_run_msg=False): @@ -297,12 +297,12 @@ def check_python_version(): def ensure_script_is_being_run_from_installed_retdec(): # Use this function to assist our users when they try to run the scripts # from the 'retdec/scripts' directory instead of from an installed RetDec. - # See https://github.com/avast-tl/retdec/issues/418 + # See https://github.com/avast/retdec/issues/418 if not os.path.dirname(__file__).endswith('bin'): print_error_and_die( 'You need to build and install RetDec first and then run the installed script via ' '`python $RETDEC_INSTALL_DIR/bin/retdec-decompiler.py`.\n' - 'For more details, see https://github.com/avast-tl/retdec#installation-and-use' + 'For more details, see https://github.com/avast/retdec#installation-and-use' ) diff --git a/src/ar-extractor/archive_wrapper.cpp b/src/ar-extractor/archive_wrapper.cpp index c29a7a74f..92aa3b388 100644 --- a/src/ar-extractor/archive_wrapper.cpp +++ b/src/ar-extractor/archive_wrapper.cpp @@ -116,7 +116,7 @@ ArchiveWrapper::ArchiveWrapper( return; } - Error error; + Error error = Error::success(); archive = std::make_unique(buffer.get()->getMemBufferRef(), error); if (error) { errorMessage = toString(std::move(error)); @@ -265,22 +265,22 @@ bool ArchiveWrapper::extract( // Map for non-unique names - counts number of name occurrences. std::map nameMap; - Error error; + Error error = Error::success(); for (const auto &child : archive->children(error)) { if (checkError(error, errorMessage)) { return false; } // Try to get name. - const auto nameOrErr = child.getName(); - std::string name = !nameOrErr ? "invalid_name" : fixName(*nameOrErr); + auto nameOrErr = child.getName(); + std::string name = nameOrErr ? fixName(nameOrErr->str()) : "invalid_name"; // Increment name count and fix name if it is not unique. if (++nameMap[name] != 1) { name += "." + std::to_string(nameMap[name]); } - const auto bufferOrErr = child.getBuffer(); + auto bufferOrErr = child.getBuffer(); if (!bufferOrErr) { errorMessage = "Could not get file buffer"; return false; @@ -313,13 +313,13 @@ bool ArchiveWrapper::extractByName( std::string &errorMessage, const std::string &outputPath) const { - Error error; + Error error = Error::success(); for (const auto &child : archive->children(error)) { if (checkError(error, errorMessage)) { return false; } - const auto nameOrErr = child.getName(); + auto nameOrErr = child.getName(); if (!nameOrErr) { // Could not get name. continue; @@ -331,7 +331,7 @@ bool ArchiveWrapper::extractByName( } // Get buffer and try to write to a file. - const auto bufferOrErr = child.getBuffer(); + auto bufferOrErr = child.getBuffer(); if (!bufferOrErr) { errorMessage = "Could not get file buffer"; return false; @@ -367,7 +367,7 @@ bool ArchiveWrapper::extractByIndex( std::string &errorMessage, const std::string &outputPath) const { - Error error; + Error error = Error::success(); std::size_t counter = 0; for (const auto &child : archive->children(error)) { if (checkError(error, errorMessage)) { @@ -380,7 +380,7 @@ bool ArchiveWrapper::extractByIndex( } // Get buffer and try to write to a file. - const auto bufferOrErr = child.getBuffer(); + auto bufferOrErr = child.getBuffer(); if (!bufferOrErr) { errorMessage = "Could not get file buffer"; return false; @@ -389,8 +389,8 @@ bool ArchiveWrapper::extractByIndex( std::string path; if (outputPath.empty()) { // No path given - use object name. - const auto nameOrErr = child.getName(); - path = !nameOrErr ? "invalid_name" : fixName(nameOrErr->str()); + auto nameOrErr = child.getName(); + path = nameOrErr ? fixName(nameOrErr->str()) : "invalid_name"; } else { path = outputPath; @@ -422,7 +422,7 @@ bool ArchiveWrapper::getNames( std::vector &result, std::string &errorMessage) const { - Error error; + Error error = Error::success(); for (const auto &child : archive->children(error)) { if (checkError(error, errorMessage)) { return false; @@ -452,7 +452,7 @@ bool ArchiveWrapper::getCount( std::size_t &count, std::string &errorMessage) const { - Error error; + Error error = Error::success(); count = 0; // Reset counter. const auto &ar = archive; for (auto i = ar->child_begin(error), e = ar->child_end(); i != e; ++i) { diff --git a/src/ar-extractor/detection.cpp b/src/ar-extractor/detection.cpp index 6380168db..161f5f0d2 100644 --- a/src/ar-extractor/detection.cpp +++ b/src/ar-extractor/detection.cpp @@ -7,8 +7,9 @@ #include #include +#include +#include #include -#include #include #include "retdec/utils/string.h" diff --git a/src/bin2llvmir/analyses/traversal/func_traversal_analysis.cpp b/src/bin2llvmir/analyses/traversal/func_traversal_analysis.cpp index 6c4ae1491..85bde13d1 100644 --- a/src/bin2llvmir/analyses/traversal/func_traversal_analysis.cpp +++ b/src/bin2llvmir/analyses/traversal/func_traversal_analysis.cpp @@ -4,6 +4,7 @@ * @copyright (c) 2017 Avast Software, licensed under the MIT license */ +#include #include #include diff --git a/src/bin2llvmir/optimizations/globals/dead_global_assign.cpp b/src/bin2llvmir/optimizations/globals/dead_global_assign.cpp index 933612f97..370d51392 100644 --- a/src/bin2llvmir/optimizations/globals/dead_global_assign.cpp +++ b/src/bin2llvmir/optimizations/globals/dead_global_assign.cpp @@ -50,7 +50,7 @@ const char *DeadGlobalAssign::getPassArg() { } // Override. -const char *DeadGlobalAssign::getPassName() const { +llvm::StringRef DeadGlobalAssign::getPassName() const { return PASS_NAME; } diff --git a/src/bin2llvmir/optimizations/globals/global_to_local.cpp b/src/bin2llvmir/optimizations/globals/global_to_local.cpp index 1800a7972..f82b862aa 100644 --- a/src/bin2llvmir/optimizations/globals/global_to_local.cpp +++ b/src/bin2llvmir/optimizations/globals/global_to_local.cpp @@ -50,7 +50,7 @@ const char *GlobalToLocal::getPassArg() { } // Override. -const char *GlobalToLocal::getPassName() const { +llvm::StringRef GlobalToLocal::getPassName() const { return PASS_NAME; } diff --git a/src/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.cpp b/src/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.cpp index 5e1ac8822..b956439bd 100644 --- a/src/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.cpp +++ b/src/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.cpp @@ -19,6 +19,7 @@ #include "retdec/bin2llvmir/optimizations/globals/dead_global_assign.h" #include "retdec/bin2llvmir/optimizations/globals/global_to_local.h" #include "retdec/bin2llvmir/optimizations/globals/global_to_local_and_dead_global_assign.h" +#include "retdec/bin2llvmir/providers/abi/abi.h" #define DEBUG_TYPE "global-to-local-and-dead-global-assign" @@ -197,11 +198,6 @@ void addMappingOfLocalVarToGlobalVarInConfig(Config* config, const llvm::Functio } // anonymous namespace -STATISTIC(CreatedLocVars, "Number of created local variables"); -STATISTIC(NumDeadGlobalAssign, "Number of removed dead global assigns"); -STATISTIC(NumGlobalDeclDeleted, "Number of removed declarations for global " - "variables"); - // It is the address of the variable that matters, not the value, so we can // initialize the ID to anything. char GlobalToLocalAndDeadGlobalAssign::ID = 0; @@ -291,7 +287,7 @@ bool GlobalToLocalAndDeadGlobalAssign::runOnModule(Module &module) { doOptimization(module, globsToOptimize); - return wasSomethingOptimized(); + return false; } /** @@ -558,7 +554,6 @@ void GlobalToLocalAndDeadGlobalAssign::removeGlobsWithoutUse( auto it(globs.begin()); while (it != globs.end()) { if (UsesAnalysis::hasNoUse(*it)) { - ++NumGlobalDeclDeleted; globs.erase(it++); } else { ++it; @@ -617,14 +612,6 @@ void GlobalToLocalAndDeadGlobalAssign::addFilteredRUses(const std::set 0 || NumGlobalDeclDeleted > 0 || - NumDeadGlobalAssign > 0; -} - /** * @brief Returns function info for @a func. * @@ -907,7 +894,6 @@ void GlobalToLocalAndDeadGlobalAssign::FuncInfo::removeDeadGlobalAssigns() { } if (i->second.empty()) { - ++NumDeadGlobalAssign; i->first->eraseFromParent(); } } @@ -1062,6 +1048,7 @@ Value *GlobalToLocalAndDeadGlobalAssign::FuncInfo::getLocVarFor( --lowerIt; allocaInst = new AllocaInst( globValue.getType()->getPointerElementType(), + Abi::DEFAULT_ADDR_SPACE, newVarName ); allocaInst->insertAfter(lowerIt->second); @@ -1072,6 +1059,7 @@ Value *GlobalToLocalAndDeadGlobalAssign::FuncInfo::getLocVarFor( BasicBlock &entryBB(func.getEntryBlock()); allocaInst = new AllocaInst( globValue.getType()->getPointerElementType(), + Abi::DEFAULT_ADDR_SPACE, newVarName, &entryBB.front() ); @@ -1083,7 +1071,6 @@ Value *GlobalToLocalAndDeadGlobalAssign::FuncInfo::getLocVarFor( globValue.getName() ); convertedGlobsToLoc[globValue.getName()] = allocaInst; - ++CreatedLocVars; return allocaInst; } diff --git a/src/bin2llvmir/optimizations/idioms/idioms_analysis.cpp b/src/bin2llvmir/optimizations/idioms/idioms_analysis.cpp index 43a2f4d08..724622868 100644 --- a/src/bin2llvmir/optimizations/idioms/idioms_analysis.cpp +++ b/src/bin2llvmir/optimizations/idioms/idioms_analysis.cpp @@ -11,11 +11,6 @@ using namespace llvm; namespace retdec { namespace bin2llvmir { -/* - * Stats of exchanged idioms. - */ -STATISTIC(NumIdioms, "Number of idioms exchanged in total"); - /** * Analyse given BasicBlock and use instruction exchanger to transform * instruction idioms @@ -35,12 +30,9 @@ bool IdiomsAnalysis::analyse(llvm::BasicBlock & bb, llvm::Instruction * (IdiomsA Instruction * res = (this->*exchanger)(insn); if (res) { - ++NumIdioms; - change_made = true; (*insn).replaceAllUsesWith(res); - print_dbg(fname, *insn); // Move the name to the new instruction first. res->takeName(&*insn); @@ -292,8 +284,6 @@ bool IdiomsAnalysis::analyse(llvm::Function & f, llvm::Pass * p, int (IdiomsAnal num_idioms += IdiomsGCC::exchangeCondBitShiftDivMultiBB(f, p); - NumIdioms += num_idioms; - return num_idioms == 0; } diff --git a/src/bin2llvmir/optimizations/idioms/idioms_gcc.cpp b/src/bin2llvmir/optimizations/idioms/idioms_gcc.cpp index 7feecaed1..6a5a5d636 100644 --- a/src/bin2llvmir/optimizations/idioms/idioms_gcc.cpp +++ b/src/bin2llvmir/optimizations/idioms/idioms_gcc.cpp @@ -495,9 +495,8 @@ Instruction * IdiomsGCC::exchangeCopysign(BasicBlock::iterator iter) const { if (! match(&val, m_Or(m_Value(op_and1), m_Value(op_and2)))) return nullptr; - // left hand side of or is (A & 0x7FFFFFFF)? - if (! match(op_and1, m_And(m_Value(op_a), m_ConstantInt(cnst1))) - && ! match(op_and1, m_And(m_ConstantInt(cnst1), m_Value(op_a)))) + // left hand side of or is not (A & 0x7FFFFFFF)? + if (! match(op_and1, m_c_And(m_Value(op_a), m_ConstantInt(cnst1)))) { // left hand side of or is (fabsf(A)? op_and1 = llvm_utils::skipCasts(op_and1); @@ -515,6 +514,25 @@ Instruction * IdiomsGCC::exchangeCopysign(BasicBlock::iterator iter) const { } } + // right hand side of or is not (A & 0x7FFFFFFF)? + if (! match(op_and2, m_c_And(m_Value(op_a), m_ConstantInt(cnst1)))) + { + // right hand side of or is (fabsf(A)? + op_and2 = llvm_utils::skipCasts(op_and2); + if (isa(op_and2) + && cast(op_and2)->getCalledFunction() + && cast(op_and2)->getCalledFunction()->getIntrinsicID() == Intrinsic::fabs) + { + auto* call = cast(op_and2); + op_a = call->getArgOperand(0); + cnst1 = cast(ConstantInt::get(op_and1->getType(), 0x7FFFFFFF)); + } + else + { + return nullptr; + } + } + unsigned second_cnst; // or is commutative, mark next constant if (*cnst1->getValue().getRawData() != 0x7FFFFFFF) { if (*cnst1->getValue().getRawData() != 0x80000000) @@ -526,8 +544,8 @@ Instruction * IdiomsGCC::exchangeCopysign(BasicBlock::iterator iter) const { } // right hand side of or - if (! match(op_and2, m_And(m_Value(op_b), m_ConstantInt(cnst2))) - && ! match(op_and2, m_And(m_ConstantInt(cnst2), m_Value(op_b)))) + if (! match(op_and2, m_c_And(m_Value(op_b), m_ConstantInt(cnst2))) + && ! match(op_and1, m_c_And(m_Value(op_b), m_ConstantInt(cnst2)))) return nullptr; if (*cnst2->getValue().getRawData() != second_cnst) diff --git a/src/bin2llvmir/optimizations/idioms/idioms_llvm.cpp b/src/bin2llvmir/optimizations/idioms/idioms_llvm.cpp index 611bdbd2d..cfa985ed5 100644 --- a/src/bin2llvmir/optimizations/idioms/idioms_llvm.cpp +++ b/src/bin2llvmir/optimizations/idioms/idioms_llvm.cpp @@ -65,7 +65,7 @@ Instruction * IdiomsLLVM::exchangeCompareEq(BasicBlock::iterator iter) const { return nullptr; // ~(A^B) --> icmp eq i1 A, B - if (! BinaryOperator::isNot(&val)) + if (! match(&val, m_Not(m_Value()))) return nullptr; op_xor = val.getOperand(0); diff --git a/src/bin2llvmir/optimizations/inst_opt/inst_opt.cpp b/src/bin2llvmir/optimizations/inst_opt/inst_opt.cpp index f534414db..f916c8012 100644 --- a/src/bin2llvmir/optimizations/inst_opt/inst_opt.cpp +++ b/src/bin2llvmir/optimizations/inst_opt/inst_opt.cpp @@ -4,9 +4,11 @@ * @copyright (c) 2017 Avast Software, licensed under the MIT license */ +#include #include #include "retdec/bin2llvmir/optimizations/inst_opt/inst_opt.h" +#include "retdec/bin2llvmir/utils/debug.h" using namespace llvm; using namespace PatternMatch; @@ -439,6 +441,110 @@ bool castSequenceWrapper(llvm::Instruction* insn) return changed; } +/** + * \code{.ll} + * store float %val, float* bitcast (i32* @gv to float*) + * ==> + * %conv = bitcast float %val to i32 + * store i32 %conv, i32* @gv + * \endcode + * + * This is countering an undesirable LLVM instrcombine optimization + * that is going the other way. + */ +bool storeToBitcastPointer(llvm::Instruction* insn) +{ + Value* val; + Value* op; + if (!match(insn, m_Store(m_Value(val), m_BitCast(m_Value(op)))) + || !op->getType()->getPointerElementType()->isFirstClassType() + || op->getType()->getPointerElementType()->isAggregateType() + || op->getType()->getPointerElementType()->isPointerTy()) + { + return false; + } + + if (!BitCastInst::isBitCastable( + val->getType(), + op->getType()->getPointerElementType())) + { + return false; + } + + auto* conv = CastInst::CreateBitOrPointerCast( + val, + op->getType()->getPointerElementType(), + "", + insn); + new StoreInst(conv, op, insn); + + auto* bitcastI = dyn_cast(insn->getOperand(1)); + auto* bitcastCE = dyn_cast(insn->getOperand(1)); + insn->eraseFromParent(); + if (bitcastI && bitcastI->use_empty()) + { + bitcastI->eraseFromParent(); + } + if (bitcastCE && bitcastCE->use_empty()) + { + bitcastCE->destroyConstant(); + } + + return true; +} + +/** + * \code{.ll} + * %1 = load float, float* bitcast (i32* @g to float*) + * ==> + * %1 = load i32, i32* @g + * %2 = bitcast i32 %1 to float + * + * %1 = load i8*, i8** bitcast (i32* @g to i8**) + * ==> + * %1 = load i32, i32* @g + * %2 = inttoptr i32 %1 to i8* + * \endcode + */ +bool loadFromBitcastPointer(llvm::Instruction* insn) +{ + Value* op; + if (!match(insn, m_Load(m_BitCast(m_Value(op)))) + || !op->getType()->getPointerElementType()->isFirstClassType() + || op->getType()->getPointerElementType()->isAggregateType()) + { + return false; + } + + if (!BitCastInst::isBitOrNoopPointerCastable( + op->getType()->getPointerElementType(), + insn->getType(), + insn->getModule()->getDataLayout())) + { + return false; + } + + auto* l = new LoadInst(op, "", insn); + l->setAlignment(cast(insn)->getAlignment()); + auto* conv = CastInst::CreateBitOrPointerCast(l, insn->getType(), "", insn); + insn->replaceAllUsesWith(conv); + + auto* bitcastI = dyn_cast(insn->getOperand(0)); + auto* bitcastCE = dyn_cast(insn->getOperand(0)); + + insn->eraseFromParent(); + if (bitcastI && bitcastI->use_empty()) + { + bitcastI->eraseFromParent(); + } + if (bitcastCE && bitcastCE->use_empty()) + { + bitcastCE->destroyConstant(); + } + + return true; +} + /** * Order here is important. * More specific patterns must go first, more general later. @@ -456,6 +562,8 @@ std::vector optimizations = &orAndXX, &addSequence, &castSequenceWrapper, + &storeToBitcastPointer, + &loadFromBitcastPointer, }; bool optimize(llvm::Instruction* insn) diff --git a/src/bin2llvmir/optimizations/param_return/param_return.cpp b/src/bin2llvmir/optimizations/param_return/param_return.cpp index ec5fa6a18..ea99fec29 100644 --- a/src/bin2llvmir/optimizations/param_return/param_return.cpp +++ b/src/bin2llvmir/optimizations/param_return/param_return.cpp @@ -354,7 +354,7 @@ CallInst* ParamReturn::getWrapper(Function* fnc) const auto next = ai.getNext(); while (next.isValid()) { - if (!next.empty() && !isa(next.front())) + if (!next.empty() && !next.front()->isTerminator()) { single = false; break; @@ -860,15 +860,15 @@ void ParamReturn::connectWrappers(const DataFlowEntry& de) return; } - if (wrappedCall->getNumArgOperands() != fnc->getArgumentList().size()) + if (wrappedCall->getNumArgOperands() != fnc->arg_size()) { // TODO: enable assert and inspect these cases. return; } - assert(wrappedCall->getNumArgOperands() == fnc->getArgumentList().size()); + assert(wrappedCall->getNumArgOperands() == fnc->arg_size()); unsigned i = 0; - for (auto& a : fnc->getArgumentList()) + for (auto& a : fnc->args()) { auto* conv = IrModifier::convertValueToType(&a, wrappedCall->getArgOperand(i)->getType(), wrappedCall); wrappedCall->setArgOperand(i++, conv); diff --git a/src/bin2llvmir/optimizations/phi2seq/phi2seq.cpp b/src/bin2llvmir/optimizations/phi2seq/phi2seq.cpp index 1e301915d..9aca423ee 100644 --- a/src/bin2llvmir/optimizations/phi2seq/phi2seq.cpp +++ b/src/bin2llvmir/optimizations/phi2seq/phi2seq.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "retdec/bin2llvmir/optimizations/phi2seq/phi2seq.h" @@ -188,7 +189,7 @@ BasicBlock &PHI2Seq::createPreBBAndSolveConnection(const VarDependAnalysis:: */ void PHI2Seq::updateBBTermInstr(BasicBlock &bbToUpdate, BasicBlock &oldSucc, BasicBlock &newSucc) { - TerminatorInst *termInstr(bbToUpdate.getTerminator()); + auto *termInstr(bbToUpdate.getTerminator()); for (unsigned j = 0, k = termInstr->getNumSuccessors(); j < k; ++j) { if (termInstr->getSuccessor(j)->getName() == oldSucc.getName()) { termInstr->setSuccessor(j, &newSucc); diff --git a/src/bin2llvmir/optimizations/simple_types/simple_types.cpp b/src/bin2llvmir/optimizations/simple_types/simple_types.cpp index 70085e566..e6f8dc019 100644 --- a/src/bin2llvmir/optimizations/simple_types/simple_types.cpp +++ b/src/bin2llvmir/optimizations/simple_types/simple_types.cpp @@ -311,7 +311,7 @@ void SimpleTypesAnalysis::buildEqSets(Module& M) continue; } - for (auto& arg : F.getArgumentList()) + for (auto& arg : F.args()) { processRoot(&arg); } diff --git a/src/bin2llvmir/optimizations/value_protect/value_protect.cpp b/src/bin2llvmir/optimizations/value_protect/value_protect.cpp index 5b756c90f..648bf76ea 100644 --- a/src/bin2llvmir/optimizations/value_protect/value_protect.cpp +++ b/src/bin2llvmir/optimizations/value_protect/value_protect.cpp @@ -566,7 +566,7 @@ llvm::Function* ValueProtect::createFunction(llvm::Type* t) /** * TODO: Only partial removal, see: - * https://github.com/avast-tl/retdec/issues/301 + * https://github.com/avast/retdec/issues/301 */ bool ValueProtect::unprotect() { diff --git a/src/bin2llvmir/providers/asm_instruction.cpp b/src/bin2llvmir/providers/asm_instruction.cpp index 4c28b0781..c68b4e65e 100644 --- a/src/bin2llvmir/providers/asm_instruction.cpp +++ b/src/bin2llvmir/providers/asm_instruction.cpp @@ -522,14 +522,14 @@ bool AsmInstruction::eraseInstructions() /** * Make this ASM instruction terminal -- last in BB, ending with - * @c TerminatorInst. + * terminator @c Instruction. * If it already is terminal, nothing is modified and an existing terminator is * returned. * If it is not terminal yet, BB is split on the next ASM instruction, this * instruction ends with an unconditional branch to the new BB, and this branch * is returned. */ -llvm::TerminatorInst* AsmInstruction::makeTerminal() +llvm::Instruction* AsmInstruction::makeTerminal() { auto next = getNext(); if (next.isValid()) @@ -542,16 +542,16 @@ llvm::TerminatorInst* AsmInstruction::makeTerminal() next.getBasicBlock()->splitBasicBlock( next.getLlvmToAsmInstruction(), names::generateBasicBlockName(next.getAddress())); - auto* b = dyn_cast_or_null(back()); - assert(b); + auto* b = dyn_cast_or_null(back()); + assert(b->isTerminator()); return b; } // Next in different BB -> no need to split -> ends with terminator. // else { - auto* b = dyn_cast_or_null(back()); - assert(b); + auto* b = dyn_cast_or_null(back()); + assert(b->isTerminator()); return b; } } @@ -559,8 +559,8 @@ llvm::TerminatorInst* AsmInstruction::makeTerminal() // else { - auto* b = dyn_cast_or_null(back()); - assert(b); + auto* b = dyn_cast_or_null(back()); + assert(b->isTerminator()); return b; } } diff --git a/src/bin2llvmir/providers/lti.cpp b/src/bin2llvmir/providers/lti.cpp index c58e646fa..f51f4690e 100644 --- a/src/bin2llvmir/providers/lti.cpp +++ b/src/bin2llvmir/providers/lti.cpp @@ -378,9 +378,9 @@ Lti::FunctionPair Lti::getPairFunctionFree(const std::string& n) GlobalValue::ExternalLinkage, name); - assert(ltiFnc->getParameterCount() == ret->getArgumentList().size() + assert(ltiFnc->getParameterCount() == ret->arg_size() || (ltiFnc->getParameterCount() == 1 - && ret->getArgumentList().empty() + && ret->arg_empty() && getLlvmType(ltiFnc->getParameterType(1))->isVoidTy())); std::size_t i = 1; std::size_t e = ltiFnc->getParameterCount(); diff --git a/src/bin2llvmir/utils/ir_modifier.cpp b/src/bin2llvmir/utils/ir_modifier.cpp index 2ff192e25..fe440b571 100644 --- a/src/bin2llvmir/utils/ir_modifier.cpp +++ b/src/bin2llvmir/utils/ir_modifier.cpp @@ -9,6 +9,7 @@ #include #include "retdec/utils/string.h" +#include "retdec/bin2llvmir/providers/abi/abi.h" #include "retdec/bin2llvmir/providers/asm_instruction.h" #include "retdec/bin2llvmir/providers/names.h" #include "retdec/bin2llvmir/utils/debug.h" @@ -551,7 +552,7 @@ IrModifier::StackPair IrModifier::getStackVariable( return {ret, csv}; } - ret = new AllocaInst(type, n); + ret = new AllocaInst(type, Abi::DEFAULT_ADDR_SPACE, n); auto it = inst_begin(fnc); assert(it != inst_end(fnc)); // -> create bb, insert alloca. @@ -722,7 +723,11 @@ llvm::Value* IrModifier::changeObjectDeclarationType( if (auto* alloca = dyn_cast(val)) { - auto* ret = new AllocaInst(toType, alloca->getName(), alloca); + auto* ret = new AllocaInst( + toType, + Abi::DEFAULT_ADDR_SPACE, + alloca->getName(), + alloca); ret->takeName(alloca); return ret; } @@ -1349,9 +1354,8 @@ llvm::Argument* IrModifier::modifyFunctionArgumentType( args.push_back(&a == arg ? type : a.getType()); } auto* nf = modifyFunction(f, f->getReturnType(), args).first; - auto& al = nf->getArgumentList(); std::size_t i = 0; - for (auto& a : al) + for (auto& a : nf->args()) { if (i == arg->getArgNo()) { @@ -1378,7 +1382,11 @@ llvm::AllocaInst* IrModifier::createAlloca( return nullptr; } - return new AllocaInst(ty, name, &fnc->getEntryBlock().front()); + return new AllocaInst( + ty, + Abi::DEFAULT_ADDR_SPACE, + name, + &fnc->getEntryBlock().front()); } /** diff --git a/src/bin2llvmirtool/bin2llvmir.cpp b/src/bin2llvmirtool/bin2llvmir.cpp index 311052707..675f7e55a 100644 --- a/src/bin2llvmirtool/bin2llvmir.cpp +++ b/src/bin2llvmirtool/bin2llvmir.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -233,7 +233,7 @@ class ModulePassPrinter : public ModulePass return false; } - const char *getPassName() const override + llvm::StringRef getPassName() const override { return PassName.c_str(); } @@ -255,7 +255,7 @@ static inline void addPassWithPossibleVerification( Pass *P, const std::string& phaseName = std::string()) { - std::string pn = phaseName.empty() ? P->getPassName() : phaseName; + std::string pn = phaseName.empty() ? P->getPassName().str() : phaseName; PM.add(new ModulePassPrinter(pn)); PM.add(P); @@ -275,7 +275,7 @@ static inline void addPassWithoutVerification( Pass *P, const std::string& phaseName = std::string()) { - std::string pn = phaseName.empty() ? P->getPassName() : phaseName; + std::string pn = phaseName.empty() ? P->getPassName().str() : phaseName; PM.add(new ModulePassPrinter(pn)); PM.add(P); @@ -355,9 +355,9 @@ std::unique_ptr createLlvmModule(LLVMContext& Context) /** * Create bitcode output file object. */ -std::unique_ptr createBitcodeOutputFile() +std::unique_ptr createBitcodeOutputFile() { - std::unique_ptr Out; + std::unique_ptr Out; if (OutputFilename.empty()) { @@ -365,11 +365,11 @@ std::unique_ptr createBitcodeOutputFile() } std::error_code EC; - Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); + Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::F_None)); if (EC) { throw std::runtime_error( - "failed to create llvm::tool_output_file for .bc: " + EC.message() + "failed to create llvm::ToolOutputFile for .bc: " + EC.message() ); } @@ -379,9 +379,9 @@ std::unique_ptr createBitcodeOutputFile() /** * Create assembly output file object. */ -std::unique_ptr createAssemblyOutputFile() +std::unique_ptr createAssemblyOutputFile() { - std::unique_ptr Out; + std::unique_ptr Out; std::string out = OutputFilename; if (out.empty()) @@ -397,11 +397,11 @@ std::unique_ptr createAssemblyOutputFile() } std::error_code EC; - Out.reset(new tool_output_file(asmOut, EC, sys::fs::F_None)); + Out.reset(new ToolOutputFile(asmOut, EC, sys::fs::F_None)); if (EC) { throw std::runtime_error( - "failed to create llvm::tool_output_file for .dsm: " + EC.message() + "failed to create llvm::ToolOutputFile for .dsm: " + EC.message() ); } @@ -458,9 +458,9 @@ int _main(int argc, char **argv) { const PassInfo *PassInf = PassList[i]; Pass *P = nullptr; - if (PassInf->getTargetMachineCtor()) + if (PassInf->getNormalCtor()) { - P = PassInf->getTargetMachineCtor()(nullptr); + P = PassInf->getNormalCtor()(); } else if (PassInf->getNormalCtor()) { @@ -469,7 +469,7 @@ int _main(int argc, char **argv) else { throw std::runtime_error(std::string("cannot create pass: ") - + PassInf->getPassName()); + + PassInf->getPassName().str()); } if (P) @@ -485,7 +485,7 @@ int _main(int argc, char **argv) } // Write bitcode to the output as the last step. - std::unique_ptr bcOut = createBitcodeOutputFile(); + std::unique_ptr bcOut = createBitcodeOutputFile(); raw_ostream *bcOs = &bcOut->os(); bool PreserveBitcodeUseListOrder = false; addPassWithoutVerification( @@ -493,7 +493,7 @@ int _main(int argc, char **argv) createBitcodeWriterPass(*bcOs, PreserveBitcodeUseListOrder)); // Write assembly to the output as the last step. - std::unique_ptr llOut = createAssemblyOutputFile(); + std::unique_ptr llOut = createAssemblyOutputFile(); raw_ostream *llOs = &llOut->os(); bool PreserveAssemblyUseListOrder = false; addPassWithoutVerification( diff --git a/src/capstone2llvmir/capstone2llvmir_impl.cpp b/src/capstone2llvmir/capstone2llvmir_impl.cpp index e5a55ab5c..1174e6f81 100644 --- a/src/capstone2llvmir/capstone2llvmir_impl.cpp +++ b/src/capstone2llvmir/capstone2llvmir_impl.cpp @@ -816,7 +816,7 @@ llvm::CallInst* Capstone2LlvmIrTranslator_impl::generateCallFunc llvm::IRBuilder<>& irb, llvm::Value* t) { - auto* a1t = _callFunction->getArgumentList().front().getType(); + auto* a1t = _callFunction->arg_begin()->getType(); t = irb.CreateSExtOrTrunc(t, a1t); _branchGenerated = irb.CreateCall(_callFunction, {t}); return _branchGenerated; @@ -830,7 +830,7 @@ llvm::CallInst* Capstone2LlvmIrTranslator_impl::generateCondCall { auto bodyIrb = generateIfThen(cond, irb); - auto* a1t = _callFunction->getArgumentList().front().getType(); + auto* a1t = _callFunction->arg_begin()->getType(); t = bodyIrb.CreateSExtOrTrunc(t, a1t); _branchGenerated = bodyIrb.CreateCall(_callFunction, {t}); _inCondition = true; @@ -856,7 +856,7 @@ llvm::CallInst* Capstone2LlvmIrTranslator_impl::generateReturnFu llvm::IRBuilder<>& irb, llvm::Value* t) { - auto* a1t = _returnFunction->getArgumentList().front().getType(); + auto* a1t = _returnFunction->arg_begin()->getType(); t = irb.CreateSExtOrTrunc(t, a1t); _branchGenerated = irb.CreateCall(_returnFunction, {t}); return _branchGenerated; @@ -870,7 +870,7 @@ llvm::CallInst* Capstone2LlvmIrTranslator_impl::generateCondRetu { auto bodyIrb = generateIfThen(cond, irb); - auto* a1t = _returnFunction->getArgumentList().front().getType(); + auto* a1t = _returnFunction->arg_begin()->getType(); t = bodyIrb.CreateSExtOrTrunc(t, a1t); _branchGenerated = bodyIrb.CreateCall(_returnFunction, {t}); _inCondition = true; @@ -896,7 +896,7 @@ llvm::CallInst* Capstone2LlvmIrTranslator_impl::generateBranchFu llvm::IRBuilder<>& irb, llvm::Value* t) { - auto* a1t = _branchFunction->getArgumentList().front().getType(); + auto* a1t = _branchFunction->arg_begin()->getType(); t = irb.CreateSExtOrTrunc(t, a1t); _branchGenerated = irb.CreateCall(_branchFunction, {t}); return _branchGenerated; @@ -925,7 +925,9 @@ llvm::CallInst* Capstone2LlvmIrTranslator_impl::generateCondBran llvm::Value* cond, llvm::Value* t) { - auto* a1t = _condBranchFunction->getArgumentList().back().getType(); + auto aIt = _condBranchFunction->arg_begin(); + ++aIt; + auto* a1t = aIt->getType(); t = irb.CreateSExtOrTrunc(t, a1t); _branchGenerated = irb.CreateCall(_condBranchFunction, {cond, t}); return _branchGenerated; diff --git a/src/fileformat/CMakeLists.txt b/src/fileformat/CMakeLists.txt index e876011c2..b8e1873ff 100644 --- a/src/fileformat/CMakeLists.txt +++ b/src/fileformat/CMakeLists.txt @@ -32,10 +32,10 @@ set(FILEFORMAT_SOURCES types/relocation_table/relocation_table.cpp types/relocation_table/relocation.cpp types/resource_table/resource.cpp - types/resource_table/resource_table.cpp - types/resource_table/resource_tree.cpp types/resource_table/resource_icon.cpp types/resource_table/resource_icon_group.cpp + types/resource_table/resource_table.cpp + types/resource_table/resource_tree.cpp types/resource_table/bitmap_image.cpp types/certificate_table/certificate.cpp types/certificate_table/certificate_table.cpp @@ -59,6 +59,7 @@ set(FILEFORMAT_SOURCES types/strings/string.cpp types/note_section/elf_notes.cpp types/note_section/elf_core.cpp + types/tls_info/tls_info.cpp file_format/pe/pe_format_parser/pe_format_parser64.cpp file_format/pe/pe_format_parser/pe_format_parser.cpp file_format/pe/pe_format_parser/pe_format_parser32.cpp diff --git a/src/fileformat/file_format/coff/coff_format.cpp b/src/fileformat/file_format/coff/coff_format.cpp index 71b9438cb..1325246a5 100644 --- a/src/fileformat/file_format/coff/coff_format.cpp +++ b/src/fileformat/file_format/coff/coff_format.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include "retdec/utils/string.h" @@ -409,6 +410,12 @@ void CoffFormat::loadRelocations() { const auto *ffSec = getSection(secIndex); const auto *coffSec = file->getCOFFSection(sec); + + if (coffSec->PointerToRelocations >= getFileLength()) + { + continue; + } + for(const auto &reloc : file->getRelocations(coffSec)) { Relocation rel; diff --git a/src/fileformat/file_format/file_format.cpp b/src/fileformat/file_format/file_format.cpp index 17b8a4e7b..bbdde9bc2 100644 --- a/src/fileformat/file_format/file_format.cpp +++ b/src/fileformat/file_format/file_format.cpp @@ -187,6 +187,7 @@ void FileFormat::init() richHeader = nullptr; pdbInfo = nullptr; certificateTable = nullptr; + tlsInfo = nullptr; elfCoreInfo = nullptr; fileFormat = Format::UNDETECTABLE; stateIsValid = readFile(fileStream, bytes) && stateIsValid; @@ -232,6 +233,7 @@ void FileFormat::clear() delete richHeader; delete pdbInfo; delete certificateTable; + delete tlsInfo; delete elfCoreInfo; for(auto *item : sections) @@ -1551,13 +1553,23 @@ const PdbInfo* FileFormat::getPdbInfo() const /** * Get information about certificate table - * @return Pointer to certificate table of @c nullptr if file has no certificates + * @return Pointer to certificate table or @c nullptr if file has no certificates */ const CertificateTable* FileFormat::getCertificateTable() const { return certificateTable; } +/** + * Get information about TLS + * @return Pointer to TLS information or @c nullptr if file has no certificates + */ +const TlsInfo* FileFormat::getTlsInfo() const +{ + return tlsInfo; +} + + /** * Get information about ELF core file * @return Pointer to ELF core info of @c nullptr if file has no certificates diff --git a/src/fileformat/file_format/macho/macho_format.cpp b/src/fileformat/file_format/macho/macho_format.cpp index 064f6db53..bbcd0d57a 100644 --- a/src/fileformat/file_format/macho/macho_format.cpp +++ b/src/fileformat/file_format/macho/macho_format.cpp @@ -951,7 +951,8 @@ void MachOFormat::dyldInfoCommand(const llvm::object::MachOObjectFile::LoadComma } Export exportSym; - for(auto &exportRef : file->exports()) + Error err = Error::success(); + for(auto &exportRef : file->exports(err)) { exportSym.setAddress(offsetToAddress(exportRef.address())); exportSym.invalidateOrdinalNumber(); @@ -967,6 +968,10 @@ void MachOFormat::dyldInfoCommand(const llvm::object::MachOObjectFile::LoadComma exportTable->addExport(exportSym); } + if (err) + { + // ignore errors + } } // Imports @@ -977,7 +982,8 @@ void MachOFormat::dyldInfoCommand(const llvm::object::MachOObjectFile::LoadComma if(startPtr + command.bind_off + command.bind_size <= endPtr) { - for(const auto &importRef : file->bindTable()) + Error err = Error::success(); + for(const auto &importRef : file->bindTable(err)) { auto importSym = getImportFromBindEntry(importRef); if(!importSym) @@ -987,11 +993,16 @@ void MachOFormat::dyldInfoCommand(const llvm::object::MachOObjectFile::LoadComma importTable->addImport(std::move(importSym)); } + if (err) + { + // ignore errors + } } if(startPtr + command.lazy_bind_off + command.lazy_bind_size <= endPtr) { - for(const auto &importRef : file->lazyBindTable()) + Error err = Error::success(); + for(const auto &importRef : file->lazyBindTable(err)) { auto importSym = getImportFromBindEntry(importRef); if(!importSym) @@ -1001,11 +1012,16 @@ void MachOFormat::dyldInfoCommand(const llvm::object::MachOObjectFile::LoadComma importTable->addImport(std::move(importSym)); } + if (err) + { + // ignore errors + } } if(startPtr + command.weak_bind_off + command.weak_bind_size <= endPtr) { - for(const auto &importRef : file->weakBindTable()) + Error err = Error::success(); + for(const auto &importRef : file->weakBindTable(err)) { auto importSym = getImportFromBindEntry(importRef); if(!importSym) @@ -1015,6 +1031,10 @@ void MachOFormat::dyldInfoCommand(const llvm::object::MachOObjectFile::LoadComma importTable->addImport(std::move(importSym)); } + if (err) + { + // ignore errors + } } } @@ -1027,7 +1047,8 @@ void MachOFormat::dyldInfoCommand(const llvm::object::MachOObjectFile::LoadComma */ std::unique_ptr MachOFormat::getImportFromBindEntry(const llvm::object::MachOBindEntry &input) { - if(input.malformed() || input.segmentIndex() >= getDeclaredNumberOfSegments()) + if(input.segmentIndex() < 0 + || static_cast(input.segmentIndex()) >= getDeclaredNumberOfSegments()) { return nullptr; } @@ -1225,7 +1246,7 @@ std::vector MachOFormat::getMachOUniversalArchitectures() const for(auto i = fatFile->begin_objects(), e = fatFile->end_objects(); i != e; ++i) { - std::string archName = i->getArchTypeName(); + std::string archName = i->getArchFlagName(); if(archName.empty()) { archName = "unknown subtype "; diff --git a/src/fileformat/file_format/pe/pe_format.cpp b/src/fileformat/file_format/pe/pe_format.cpp index c4930a0ec..f648a7fda 100644 --- a/src/fileformat/file_format/pe/pe_format.cpp +++ b/src/fileformat/file_format/pe/pe_format.cpp @@ -369,6 +369,7 @@ void PeFormat::initStructures() file->readDelayImportDirectory(); file->readExportDirectory(); file->readDebugDirectory(); + file->readTlsDirectory(); file->readResourceDirectory(); file->readSecurityDirectory(); file->readComHeaderDirectory(); @@ -427,6 +428,7 @@ void PeFormat::initStructures() loadPdbInfo(); loadResources(); loadCertificates(); + loadTlsInformation(); loadDotnetHeaders(); loadVisualBasicHeader(); computeSectionTableHashes(); @@ -1513,6 +1515,11 @@ void PeFormat::loadResources() resourceTable->addResourceIconGroup(static_cast(resource.get())); iconGroupIDcounter++; } + else if (type == "Version") + { + resource = std::make_unique(); + resourceTable->addResourceVersion(resource.get()); + } else { resource = std::make_unique(); @@ -1551,7 +1558,7 @@ void PeFormat::loadResources() } resourceTable->linkResourceIconGroups(); - + resourceTable->parseVersionInfoResources(); loadResourceIconHash(); for (auto&& addressRange : formatParser->getResourceDirectoryOccupiedAddresses()) @@ -1727,6 +1734,48 @@ void PeFormat::loadCertificates() BIO_free(bio); } +/** + * Load thread-local storage information + */ +void PeFormat::loadTlsInformation() +{ + unsigned long long rva = 0, size = 0; + if (!getDataDirectoryRelative(PELIB_IMAGE_DIRECTORY_ENTRY_TLS, rva, size) || size == 0) + { + return; + } + + tlsInfo = new TlsInfo(); + tlsInfo->setRawDataStartAddr(formatParser->getTlsStartAddressOfRawData()); + tlsInfo->setRawDataEndAddr(formatParser->getTlsEndAddressOfRawData()); + tlsInfo->setIndexAddr(formatParser->getTlsAddressOfIndex()); + tlsInfo->setZeroFillSize(formatParser->getTlsSizeOfZeroFill()); + tlsInfo->setCharacteristics(formatParser->getTlsCharacteristics()); + + auto callBacksAddr = formatParser->getTlsAddressOfCallBacks(); + tlsInfo->setCallBacksAddr(callBacksAddr); + + const auto &allBytes = getBytes(); + DynamicBuffer structContent(allBytes); + + unsigned long long callBacksOffset; + if (getOffsetFromAddress(callBacksOffset, callBacksAddr)) + { + while (allBytes.size() >= callBacksOffset + sizeof(std::uint32_t)) + { + auto cbAddr = structContent.read(callBacksOffset); + callBacksOffset += sizeof(std::uint32_t); + + if (cbAddr == 0) + { + break; + } + + tlsInfo->addCallBack(cbAddr); + } + } +} + /** * Load .NET headers. */ diff --git a/src/fileformat/file_format/pe/pe_format_parser/pe_format_parser32.cpp b/src/fileformat/file_format/pe/pe_format_parser/pe_format_parser32.cpp index f592ed240..d0865b15f 100644 --- a/src/fileformat/file_format/pe/pe_format_parser/pe_format_parser32.cpp +++ b/src/fileformat/file_format/pe/pe_format_parser/pe_format_parser32.cpp @@ -278,6 +278,36 @@ const PeLib::ResourceNode* PeFormatParser32::getResourceTreeRoot() const return peResourceTreeRoot(peFile->resDir()); } +unsigned long long PeFormatParser32::getTlsStartAddressOfRawData() const +{ + return peTlsStartAddressOfRawData(peFile->tlsDir()); +} + +unsigned long long PeFormatParser32::getTlsEndAddressOfRawData() const +{ + return peTlsEndAddressOfRawData(peFile->tlsDir()); +} + +unsigned long long PeFormatParser32::getTlsAddressOfIndex() const +{ + return peTlsAddressOfIndex(peFile->tlsDir()); +} + +unsigned long long PeFormatParser32::getTlsAddressOfCallBacks() const +{ + return peTlsAddressOfCallBacks(peFile->tlsDir()); +} + +unsigned long long PeFormatParser32::getTlsSizeOfZeroFill() const +{ + return peTlsSizeOfZeroFill(peFile->tlsDir()); +} + +unsigned long long PeFormatParser32::getTlsCharacteristics() const +{ + return peTlsCharacteristics(peFile->tlsDir()); +} + std::unique_ptr PeFormatParser32::getClrHeader() const { return peGetClrHeader(peFile->comDir()); diff --git a/src/fileformat/file_format/pe/pe_format_parser/pe_format_parser64.cpp b/src/fileformat/file_format/pe/pe_format_parser/pe_format_parser64.cpp index 28ff56c20..57a937a41 100644 --- a/src/fileformat/file_format/pe/pe_format_parser/pe_format_parser64.cpp +++ b/src/fileformat/file_format/pe/pe_format_parser/pe_format_parser64.cpp @@ -278,6 +278,36 @@ const PeLib::ResourceNode* PeFormatParser64::getResourceTreeRoot() const return peResourceTreeRoot(peFile->resDir()); } +unsigned long long PeFormatParser64::getTlsStartAddressOfRawData() const +{ + return peTlsStartAddressOfRawData(peFile->tlsDir()); +} + +unsigned long long PeFormatParser64::getTlsEndAddressOfRawData() const +{ + return peTlsEndAddressOfRawData(peFile->tlsDir()); +} + +unsigned long long PeFormatParser64::getTlsAddressOfIndex() const +{ + return peTlsAddressOfIndex(peFile->tlsDir()); +} + +unsigned long long PeFormatParser64::getTlsAddressOfCallBacks() const +{ + return peTlsAddressOfCallBacks(peFile->tlsDir()); +} + +unsigned long long PeFormatParser64::getTlsSizeOfZeroFill() const +{ + return peTlsSizeOfZeroFill(peFile->tlsDir()); +} + +unsigned long long PeFormatParser64::getTlsCharacteristics() const +{ + return peTlsCharacteristics(peFile->tlsDir()); +} + std::unique_ptr PeFormatParser64::getClrHeader() const { return peGetClrHeader(peFile->comDir()); diff --git a/src/fileformat/types/certificate_table/certificate.cpp b/src/fileformat/types/certificate_table/certificate.cpp index 0dc6380ab..03674a9d9 100644 --- a/src/fileformat/types/certificate_table/certificate.cpp +++ b/src/fileformat/types/certificate_table/certificate.cpp @@ -244,7 +244,7 @@ void Certificate::loadSignatureAlgorithm() void Certificate::loadSerialNumber() { if (auto sn = X509_get_serialNumber(certImpl)) - retdec::utils::bytesToHexString(sn->data, sn->length, serialNumber); + retdec::utils::bytesToHexString(sn->data, sn->length, serialNumber, 0, 0, /*uppercase=*/false); } void Certificate::loadIssuerAndSubject() @@ -279,8 +279,8 @@ void Certificate::calculateHashes() SHA1(reinterpret_cast(tmp.data()), tmp.size(), sha1Bytes.data()); SHA256(reinterpret_cast(tmp.data()), tmp.size(), sha256Bytes.data()); - retdec::utils::bytesToHexString(sha1Bytes, sha1Digest); - retdec::utils::bytesToHexString(sha256Bytes, sha256Digest); + retdec::utils::bytesToHexString(sha1Bytes, sha1Digest, 0, 0, /*uppercase=*/false); + retdec::utils::bytesToHexString(sha256Bytes, sha256Digest, 0, 0, /*uppercase=*/false); } /** diff --git a/src/fileformat/types/resource_table/resource_icon_group.cpp b/src/fileformat/types/resource_table/resource_icon_group.cpp index 48e360887..ef508d0f3 100644 --- a/src/fileformat/types/resource_table/resource_icon_group.cpp +++ b/src/fileformat/types/resource_table/resource_icon_group.cpp @@ -11,7 +11,7 @@ namespace { // Icon priority list -constexpr std::pair iconPriorities[] = +constexpr std::pair iconPriorities[] = { {32, 32}, {24, 32}, diff --git a/src/fileformat/types/resource_table/resource_table.cpp b/src/fileformat/types/resource_table/resource_table.cpp index 8a807be21..fbea87d46 100644 --- a/src/fileformat/types/resource_table/resource_table.cpp +++ b/src/fileformat/types/resource_table/resource_table.cpp @@ -9,14 +9,71 @@ #include "retdec/crypto/crypto.h" #include "retdec/utils/conversion.h" +#include "retdec/utils/dynamic_buffer.h" +#include "retdec/utils/string.h" +#include "retdec/utils/alignment.h" +#include "retdec/fileformat/utils/other.h" #include "retdec/fileformat/types/resource_table/resource_table.h" #include "retdec/fileformat/types/resource_table/bitmap_image.h" using namespace retdec::utils; +namespace { + +constexpr std::size_t VI_KEY_SIZE = 32; ///< unicode "VS_VERSION_INFO" +constexpr std::size_t VFI_KEY_SIZE = 24; ///< unicode "VarFileInfo" +constexpr std::size_t SFI_KEY_SIZE = 30; ///< unicode "StringFileInfo" +constexpr std::size_t VAR_KEY_SIZE = 24; ///< unicode "Translation" +constexpr std::size_t STRTAB_KEY_SIZE = 18; ///< 8 unicode hex digits + +constexpr std::uint32_t FFI_SIGNATURE = 0xFEEF04BD; ///< fixed file info signature + +enum class VersionInfoType {BINARY = 0, STRING = 1}; + +struct FixedFileInfo +{ + std::uint32_t signature; ///< signature FFI_SIGNATURE + std::uint16_t strucVersionMaj; ///< binary major version number + std::uint16_t strucVersionMin; ///< binary minor version number + std::uint32_t fileVersionMaj; ///< file major version number + std::uint32_t fileVersionMin; ///< file minor version number + std::uint64_t productVersion; ///< product version number + std::uint32_t fileFlagsMask; ///< validity mask of fileFalgs member + std::uint32_t fileFlags; ///< file flags + std::uint32_t fileOS; ///< target operating system + std::uint32_t fileType; ///< type of file + std::uint32_t fileSubtype; ///< subtype of file + std::uint64_t timestamp; ///< timestamp + + static std::size_t structSize() + { + return + sizeof(signature) + sizeof(strucVersionMaj) + sizeof(strucVersionMin) + sizeof(fileVersionMaj) + + sizeof(fileVersionMin) + sizeof(productVersion) + sizeof(fileFlagsMask) + sizeof(fileFlags) + + sizeof(fileOS) + sizeof(fileType) + sizeof(fileSubtype) + sizeof(timestamp); + } +}; + +struct VersionInfoHeader +{ + std::uint16_t length; ///< length of whole structure + std::uint16_t valueLength; ///< length of following structure + std::uint16_t type; ///< type of data + + static std::size_t structSize() + { + return sizeof(length) + sizeof(valueLength) + sizeof(type); + } +}; + +} // anonymous namespace + + namespace retdec { namespace fileformat { + + /** * Constructor */ @@ -84,6 +141,24 @@ std::size_t ResourceTable::getNumberOfResources() const return table.size(); } +/** + * Get number of supported languages + * @return Number of supported languages + */ +std::size_t ResourceTable::getNumberOfLanguages() const +{ + return languages.size(); +} + +/** + * Get number of strings + * @return Number of strings + */ +std::size_t ResourceTable::getNumberOfStrings() const +{ + return strings.size(); +} + /** * Get total declared size of resources * @return Total declared size of resources @@ -126,6 +201,26 @@ const Resource* ResourceTable::getResource(std::size_t rIndex) const return (rIndex < getNumberOfResources()) ? table[rIndex].get() : nullptr; } +/** + * Get selected language + * @param rIndex Index of selected language (indexed from 0) + * @return Pointer to selected language or @c nullptr if language index is invalid + */ +const std::pair* ResourceTable::getLanguage(std::size_t rIndex) const +{ + return (rIndex < getNumberOfLanguages()) ? &languages[rIndex] : nullptr; +} + +/** + * Get selected string + * @param rIndex Index of selected string (indexed from 0) + * @return Pointer to selected string or @c nullptr if string index is invalid + */ +const std::pair* ResourceTable::getString(std::size_t rIndex) const +{ + return (rIndex < getNumberOfStrings()) ? &strings[rIndex] : nullptr; +} + /** * Get resource by name * @param rName Name of the resource to get @@ -341,6 +436,297 @@ void ResourceTable::computeIconHashes() iconPerceptualAvgHash = computePerceptualAvgHash(*priorIcon); } +/** + * Parse all version information resources + */ +void ResourceTable::parseVersionInfoResources() +{ + std::vector bytes; + + for (auto ver : resourceVersions) + { + if (!ver->getBytes(bytes)) + { + continue; + } + parseVersionInfo(bytes); + } +} + +/** + * Parse version information + * @param bytes Resource bytes + * @return @c true if parsing was successful, @c false otherwise + */ +bool ResourceTable::parseVersionInfo(const std::vector &bytes) +{ + VersionInfoHeader vih; + if (bytes.size() < vih.structSize()) + { + return false; + } + + std::size_t offset = 0; + + DynamicBuffer structContent(bytes, retdec::utils::Endianness::LITTLE); + vih.length = structContent.read(offset); offset += sizeof(vih.length); + vih.valueLength = structContent.read(offset); offset += sizeof(vih.valueLength); + vih.type = structContent.read(offset); offset += sizeof(vih.type); + + std::string key = retdec::utils::unicodeToAscii(&bytes.data()[offset], bytes.size() - offset); + if (key != "VS_VERSION_INFO") + { + return false; + } + + offset += VI_KEY_SIZE; + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + + FixedFileInfo ffi; + if (vih.valueLength == ffi.structSize()) + { + if (bytes.size() < offset + ffi.structSize()) + { + return false; + } + + ffi.signature = structContent.read(offset); offset += sizeof(ffi.signature); + ffi.strucVersionMin = structContent.read(offset); offset += sizeof(ffi.strucVersionMin); + ffi.strucVersionMaj = structContent.read(offset); offset += sizeof(ffi.strucVersionMaj); + std::uint32_t t1 = structContent.read(offset); + ffi.fileVersionMaj = t1 >> 16; offset += sizeof(ffi.fileVersionMaj); + ffi.fileVersionMin = t1 & 0xFFFF; offset += sizeof(ffi.fileVersionMin); + std::uint64_t t2 = structContent.read(offset); + ffi.productVersion = t2 >> 16; offset += sizeof(ffi.productVersion); + ffi.fileFlagsMask = structContent.read(offset); offset += sizeof(ffi.fileFlagsMask); + ffi.fileFlags = structContent.read(offset); offset += sizeof(ffi.fileFlags); + ffi.fileOS = structContent.read(offset); offset += sizeof(ffi.fileOS); + ffi.fileType = structContent.read(offset); offset += sizeof(ffi.fileType); + ffi.fileSubtype = structContent.read(offset); offset += sizeof(ffi.fileSubtype); + ffi.timestamp = structContent.read(offset); offset += sizeof(ffi.timestamp); + + if (ffi.signature != FFI_SIGNATURE) + { + return false; + } + } + + else if (vih.valueLength != 0) + { + return false; + } + + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + while (offset < vih.length) + { + if (!parseVersionInfoChild(bytes, offset)) + { + return false; + } + } + + return true; +} + +/** + * Parse Version Info child + * @param bytes Resource bytes + * @param offset Offset to Version Info Child structure + * @return @c true if parsing was successful, @c false otherwise + */ +bool ResourceTable::parseVersionInfoChild(const std::vector &bytes, std::size_t &offset) +{ + std::size_t origOffset = offset; + VersionInfoHeader chh; + if (bytes.size() < offset + chh.structSize()) + { + return false; + } + + DynamicBuffer structContent(bytes, retdec::utils::Endianness::LITTLE); + chh.length = structContent.read(offset); offset += sizeof(chh.length); + chh.valueLength = structContent.read(offset); offset += sizeof(chh.valueLength); + chh.type = structContent.read(offset); offset += sizeof(chh.type); + + std::string key = retdec::utils::unicodeToAscii(&bytes.data()[offset], bytes.size() - offset); + + if (key == "VarFileInfo") + { + offset += VFI_KEY_SIZE; + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + + for (std::size_t targetOffset = origOffset + chh.length; offset < targetOffset; ) + { + if (!parseVarFileInfoChild(bytes, offset)) + { + return false; + } + } + } + else if (key == "StringFileInfo") + { + offset += SFI_KEY_SIZE; + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + + for (std::size_t targetOffset = origOffset + chh.length; offset < targetOffset; ) + { + if (!parseStringFileInfoChild(bytes, offset)) + { + return false; + } + } + } + else + { + return false; + } + + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + return true; +} + +/** + * Parse VarFileInfo structure + * @param bytes Resource bytes + * @param offset Offset to structure + * @return @c true if parsing was successful, @c false otherwise + */ +bool ResourceTable::parseVarFileInfoChild(const std::vector &bytes, std::size_t &offset) +{ + VersionInfoHeader var; + if (bytes.size() < offset + var.structSize()) + { + return false; + } + + DynamicBuffer structContent(bytes, retdec::utils::Endianness::LITTLE); + var.length = structContent.read(offset); offset += sizeof(var.length); + var.valueLength = structContent.read(offset); offset += sizeof(var.valueLength); + var.type = structContent.read(offset); offset += sizeof(var.type); + + std::string key = retdec::utils::unicodeToAscii(&bytes.data()[offset], bytes.size() - offset); + if (key != "Translation") + { + return false; + } + + offset += VAR_KEY_SIZE; + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + if (bytes.size() < offset + var.valueLength || var.valueLength % sizeof(std::uint32_t)) + { + return false; + } + + for (std::size_t targetOffset = offset + var.valueLength; offset < targetOffset; ) + { + std::uint32_t lang = structContent.read(offset); offset += sizeof(lang); + std::uint16_t lcid = lang & 0xFFFF; + std::uint16_t codePage = lang >> 16; + languages.emplace_back(std::make_pair(lcidToStr(lcid), codePageToStr(codePage))); + } + + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + return true; +} + +/** + * Parse StringFileInfo child + * @param bytes Resource bytes + * @param offset Offset to structure + * @return @c true if parsing was successful, @c false otherwise + */ +bool ResourceTable::parseStringFileInfoChild(const std::vector &bytes, std::size_t &offset) +{ + std::size_t origOffset = offset; + VersionInfoHeader sfih; + if (bytes.size() < offset + sfih.structSize()) + { + return false; + } + + DynamicBuffer structContent(bytes, retdec::utils::Endianness::LITTLE); + sfih.length = structContent.read(offset); offset += sizeof(sfih.length); + sfih.valueLength = structContent.read(offset); offset += sizeof(sfih.valueLength); + sfih.type = structContent.read(offset); offset += sizeof(sfih.type); + + std::size_t nRead; + std::string key = retdec::utils::unicodeToAscii(&bytes.data()[offset], bytes.size() - offset, nRead); + if (nRead != STRTAB_KEY_SIZE) + { + return false; + } + + offset += STRTAB_KEY_SIZE; + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + + for (std::size_t targetOffset = origOffset + sfih.length; offset < targetOffset; ) + { + if (!parseVarString(bytes, offset)) + { + return false; + } + } + + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + return true; +} + +/** + * Parse var string + * @param bytes Resource bytes + * @param offset Offset to structure + * @return @c true if parsing was successful, @c false otherwise + */ +bool ResourceTable::parseVarString(const std::vector &bytes, std::size_t &offset) +{ + std::size_t origOffset = offset; + VersionInfoHeader str; + if (bytes.size() < offset + str.structSize()) + { + return false; + } + + DynamicBuffer structContent(bytes, retdec::utils::Endianness::LITTLE); + str.length = structContent.read(offset); offset += sizeof(str.length); + str.valueLength = structContent.read(offset); offset += sizeof(str.valueLength); + str.type = structContent.read(offset); offset += sizeof(str.type); + + if (bytes.size() < origOffset + str.length || str.length < str.structSize()) + { + return false; + } + + std::size_t targetOffset = origOffset + str.length; + + if (offset > targetOffset) + { + return false; + } + + std::size_t nToRead = targetOffset - offset; + std::size_t nRead; + std::string name = retdec::utils::unicodeToAscii(&bytes.data()[offset], nToRead, nRead); + offset += nRead; + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + + if (offset > targetOffset) + { + return false; + } + + nToRead = targetOffset - offset; + std::string value; + if (nToRead > 0) + { + value = retdec::utils::unicodeToAscii(&bytes.data()[offset], nToRead, nRead); + offset += nRead; + offset = retdec::utils::alignUp(offset, sizeof(std::uint32_t)); + } + + strings.emplace_back(std::make_pair(name, value)); + return true; +} + /** * Delete all records from table */ @@ -358,6 +744,15 @@ void ResourceTable::addResource(std::unique_ptr&& newResource) table.push_back(std::move(newResource)); } +/** + * Add version resource + * @param ver Version resource which will be added + */ +void ResourceTable::addResourceVersion(Resource *ver) +{ + resourceVersions.push_back(ver); +} + /** * Add icon * @param icon Icon which will be added @@ -389,7 +784,7 @@ void ResourceTable::linkResourceIconGroups() continue; } - for(size_t eIndex = 0; eIndex < numberOfEntries; eIndex++) + for(std::size_t eIndex = 0; eIndex < numberOfEntries; eIndex++) { std::size_t entryNameID; if(!iconGroup->getEntryNameID(eIndex, entryNameID)) @@ -399,7 +794,7 @@ void ResourceTable::linkResourceIconGroups() for(auto icon : icons) { - size_t iconNameID, iconSize; + std::size_t iconNameID, iconSize; unsigned short width, height; uint16_t planes, bitCount; uint8_t colorCount; diff --git a/src/fileformat/types/sec_seg/sec_seg.cpp b/src/fileformat/types/sec_seg/sec_seg.cpp index fb34c7ad5..94e912d75 100644 --- a/src/fileformat/types/sec_seg/sec_seg.cpp +++ b/src/fileformat/types/sec_seg/sec_seg.cpp @@ -545,7 +545,7 @@ void SecSeg::computeEntropy() { return; } - + auto data = reinterpret_cast(bytes.data()); auto size = bytes.size(); if (!data || size == 0) diff --git a/src/fileformat/types/tls_info/tls_info.cpp b/src/fileformat/types/tls_info/tls_info.cpp new file mode 100644 index 000000000..52bfc3353 --- /dev/null +++ b/src/fileformat/types/tls_info/tls_info.cpp @@ -0,0 +1,202 @@ +/** + * @file src/fileformat/types/tls_info/tls_info.cpp + * @brief Class for information about thread-local storage. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#include + +#include "retdec/fileformat/types/tls_info/tls_info.h" + +namespace retdec { +namespace fileformat { + +/** + * Constructor + */ +TlsInfo::TlsInfo() : callBacks(0), rawDataStartAddr(0), rawDataEndAddr(0), indexAddr(0), callBacksAddr(0), + zeroFillSize(0), characteristics(0), rawDataStartAddrValid(false), rawDataEndAddrValid(false), + indexAddrValid(false), callBacksAddrValid(false), zeroFillSizeValid(false), + characteristicsValid(false) +{ + +} + +/** + * Destructor + */ +TlsInfo::~TlsInfo() +{ + +} + +/** + * Get start of raw data address + * @param res Variable to store the result to + * @return @c true on success, @c false otherwise + */ +bool TlsInfo::getRawDataStartAddr(std::uint64_t &res) const +{ + if (!rawDataStartAddrValid) + { + return false; + } + res = rawDataStartAddr; + return true; +} + +/** + * Get end of raw data address + * @param res Variable to store the result to + * @return @c true on success, @c false otherwise + */ +bool TlsInfo::getRawDataEndAddr(std::uint64_t &res) const +{ + if (!rawDataEndAddrValid) + { + return false; + } + res = rawDataEndAddr; + return true; +} + +/** + * Get address of index + * @param res Variable to store the result to + * @return @c true on success, @c false otherwise + */ +bool TlsInfo::getIndexAddr(std::uint64_t &res) const +{ + if (!indexAddrValid) + { + return false; + } + res = indexAddr; + return true; +} + +/** + * Get address of callbacks + * @param res Variable to store the result to + * @return @c true on success, @c false otherwise + */ +bool TlsInfo::getCallBacksAddr(std::uint64_t &res) const +{ + if (!callBacksAddrValid) + { + return false; + } + res = callBacksAddr; + return true; +} + +/** + * Get zero fill size + * @param res Variable to store the result to + * @return @c true on success, @c false otherwise + */ +bool TlsInfo::getZeroFillSize(std::uint32_t &res) const +{ + if (!zeroFillSizeValid) + { + return false; + } + res = zeroFillSize; + return true; +} + +/** + * Get characteristics + * @param res Variable to store the result to + * @return @c true on success, @c false otherwise + */ +bool TlsInfo::getCharacteristics(std::uint32_t &res) const +{ + if (!characteristicsValid) + { + return false; + } + res = characteristics; + return true; +} + +/** + * Get addresses of callbacks + * @return Addresses of callbacks + */ +const std::vector &TlsInfo::getCallBacks() const +{ + return callBacks; +} + +/** + * Set start of raw data address + * @param sAddr start of raw data address to set + */ +void TlsInfo::setRawDataStartAddr(std::uint64_t sAddr) +{ + rawDataStartAddr = sAddr; + rawDataStartAddrValid = true; +} + +/** + * Set end of raw data address + * @param eAddr end of raw data address to set + */ +void TlsInfo::setRawDataEndAddr(std::uint64_t eAddr) +{ + rawDataEndAddr = eAddr; + rawDataEndAddrValid = true; +} + +/** + * Set address of index + * @param iAddr address of index to set + */ +void TlsInfo::setIndexAddr(std::uint64_t iAddr) +{ + indexAddr = iAddr; + indexAddrValid = true; +} + +/** + * Set address of callbacks + * @param cbAddr address of callbacks to set + */ +void TlsInfo::setCallBacksAddr(std::uint64_t cbAddr) +{ + callBacksAddr = cbAddr; + callBacksAddrValid = true; +} + +/** + * Set zero fill size + * @param zFill zero fill size to set + */ +void TlsInfo::setZeroFillSize(std::uint32_t zFill) +{ + zeroFillSize = zFill; + zeroFillSizeValid = true; +} + +/** + * Set characteristics + * @param chars characteristics to set + */ +void TlsInfo::setCharacteristics(std::uint32_t chars) +{ + characteristics = chars; + characteristicsValid = true; +} + +/** + * Add callback + * @param cb Callback to add + */ +void TlsInfo::addCallBack(std::uint64_t cb) +{ + callBacks.push_back(cb); +} + +} // namespace fileformat +} // namespace retdec diff --git a/src/fileformat/utils/other.cpp b/src/fileformat/utils/other.cpp index 08a597147..7a8bd7503 100644 --- a/src/fileformat/utils/other.cpp +++ b/src/fileformat/utils/other.cpp @@ -42,6 +42,7 @@ const std::map> architectureMap = const std::unordered_map lcids = { + {0, "Unspecified"}, {1078, "Afrikaans"}, {1052, "Albanian"}, {1118, "Amharic"}, @@ -218,7 +219,6 @@ const std::unordered_map lcids = {1055, "Turkish"}, {1090, "Turkmen"}, {1058, "Ukrainian"}, - {0, "Unicode"}, {1056, "Urdu"}, {2115, "Uzbek - Cyrillic"}, {1091, "Uzbek - Latin"}, @@ -230,6 +230,163 @@ const std::unordered_map lcids = {1077, "Zulu"} }; +const std::unordered_map codePages = +{ + {0, "Unspecified"}, + {37, "IBM037"}, + {437, "IBM437"}, + {500, "IBM500"}, + {708, "ASMO-708"}, + {709, "Arabic (ASMO-449+, BCON V4)"}, + {710, "Arabic - Transparent Arabic"}, + {720, "DOS-720"}, + {737, "ibm737"}, + {775, "ibm775"}, + {850, "ibm850"}, + {852, "ibm852"}, + {855, "IBM855"}, + {857, "ibm857"}, + {858, "IBM00858"}, + {860, "IBM860"}, + {861, "ibm861"}, + {862, "DOS-862"}, + {863, "IBM863"}, + {864, "IBM864"}, + {865, "IBM865"}, + {866, "cp866"}, + {869, "ibm869"}, + {870, "IBM870"}, + {874, "windows-874"}, + {875, "cp875"}, + {932, "shift_jis"}, + {936, "gb2312"}, + {949, "ks_c_5601-1987"}, + {950, "big5"}, + {1026, "IBM1026"}, + {1047, "IBM01047"}, + {1140, "IBM01140"}, + {1141, "IBM01141"}, + {1142, "IBM01142"}, + {1143, "IBM01143"}, + {1144, "IBM01144"}, + {1145, "IBM01145"}, + {1146, "IBM01146"}, + {1147, "IBM01147"}, + {1148, "IBM01148"}, + {1149, "IBM01149"}, + {1200, "utf-16"}, + {1201, "unicodeFFFE"}, + {1250, "windows-1250"}, + {1251, "windows-1251"}, + {1252, "windows-1252"}, + {1253, "windows-1253"}, + {1254, "windows-1254"}, + {1255, "windows-1255"}, + {1256, "windows-1256"}, + {1257, "windows-1257"}, + {1258, "windows-1258"}, + {1361, "Johab"}, + {10000, "macintosh"}, + {10001, "x-mac-japanese"}, + {10002, "x-mac-chinesetrad"}, + {10003, "x-mac-korean"}, + {10004, "x-mac-arabic"}, + {10005, "x-mac-hebrew"}, + {10006, "x-mac-greek"}, + {10007, "x-mac-cyrillic"}, + {10008, "x-mac-chinesesimp"}, + {10010, "x-mac-romanian"}, + {10017, "x-mac-ukrainian"}, + {10021, "x-mac-thai"}, + {10029, "x-mac-ce"}, + {10079, "x-mac-icelandic"}, + {10081, "x-mac-turkish"}, + {10082, "x-mac-croatian"}, + {12000, "utf-32"}, + {12001, "utf-32BE"}, + {20000, "x-Chinese_CNS"}, + {20001, "x-cp20001"}, + {20002, "x_Chinese-Eten"}, + {20003, "x-cp20003"}, + {20004, "x-cp20004"}, + {20005, "x-cp20005"}, + {20105, "x-IA5"}, + {20106, "x-IA5-German"}, + {20107, "x-IA5-Swedish"}, + {20108, "x-IA5-Norwegian"}, + {20127, "us-ascii"}, + {20261, "x-cp20261"}, + {20269, "x-cp20269"}, + {20273, "IBM273"}, + {20277, "IBM277"}, + {20278, "IBM278"}, + {20280, "IBM280"}, + {20284, "IBM284"}, + {20285, "IBM285"}, + {20290, "IBM290"}, + {20297, "IBM297"}, + {20420, "IBM420"}, + {20423, "IBM423"}, + {20424, "IBM424"}, + {20833, "x-EBCDIC-KoreanExtended"}, + {20838, "IBM-Thai"}, + {20866, "koi8-r"}, + {20871, "IBM871"}, + {20880, "IBM880"}, + {20905, "IBM905"}, + {20924, "IBM00924"}, + {20932, "EUC-JP"}, + {20936, "x-cp20936"}, + {20949, "x-cp20949"}, + {21025, "cp1025"}, + {21027, "(deprecated)"}, + {21866, "koi8-u"}, + {28591, "iso-8859-1"}, + {28592, "iso-8859-2"}, + {28593, "iso-8859-3"}, + {28594, "iso-8859-4"}, + {28595, "iso-8859-5"}, + {28596, "iso-8859-6"}, + {28597, "iso-8859-7"}, + {28598, "iso-8859-8"}, + {28599, "iso-8859-9"}, + {28603, "iso-8859-13"}, + {28605, "iso-8859-15"}, + {29001, "x-Europa"}, + {38598, "iso-8859-8-i"}, + {50220, "iso-2022-jp"}, + {50221, "csISO2022JP"}, + {50222, "iso-2022-jp"}, + {50225, "iso-2022-kr"}, + {50227, "x-cp50227"}, + {50229, "ISO 2022 Traditional Chinese"}, + {50930, "EBCDIC Japanese (Katakana) Extended"}, + {50931, "EBCDIC US-Canada and Japanese"}, + {50933, "EBCDIC Korean Extended and Korean"}, + {50935, "EBCDIC Simplified Chinese Extended and Simplified Chinese"}, + {50936, "EBCDIC Simplified Chinese"}, + {50937, "EBCDIC US-Canada and Traditional Chinese"}, + {50939, "EBCDIC Japanese (Latin) Extended and Japanese"}, + {51932, "euc-jp"}, + {51936, "EUC-CN"}, + {51949, "euc-kr"}, + {51950, "EUC Traditional Chinese"}, + {52936, "hz-gb-2312"}, + {54936, "GB18030"}, + {57002, "x-iscii-de"}, + {57003, "x-iscii-be"}, + {57004, "x-iscii-ta"}, + {57005, "x-iscii-te"}, + {57006, "x-iscii-as"}, + {57007, "x-iscii-or"}, + {57008, "x-iscii-ka"}, + {57009, "x-iscii-ma"}, + {57010, "x-iscii-gu"}, + {57011, "x-iscii-pa"}, + {65000, "utf-7"}, + {65001, "utf-8"} +}; + } // anonymous namespace /** @@ -308,6 +465,21 @@ std::string lcidToStr(std::size_t lcid) return l->second; } +/** + * Get string representation of IBM code page + * @param cpage Language code id + * @return String representation of @a code page + */ +std::string codePageToStr(std::size_t cpage) +{ + auto cpg = codePages.find(cpage); + if (cpg == codePages.end()) + { + return numToStr(cpage, std::dec); + } + return cpg->second; +} + /* * Compute entropy of given data * @param data Data to compute entropy from diff --git a/src/fileinfo/CMakeLists.txt b/src/fileinfo/CMakeLists.txt index 2970c8162..2219f185a 100644 --- a/src/fileinfo/CMakeLists.txt +++ b/src/fileinfo/CMakeLists.txt @@ -30,12 +30,13 @@ set(FILEINFO_SOURCES file_information/file_information_types/resource_table/resource.cpp file_information/file_information_types/resource_table/resource_table.cpp file_information/file_information_types/rich_header.cpp - file_information/file_information_types/visual_basic_info.cpp file_information/file_information_types/special_information.cpp file_information/file_information_types/strings.cpp file_information/file_information_types/symbol_table/symbol.cpp file_information/file_information_types/symbol_table/symbol_table.cpp + file_information/file_information_types/tls_info.cpp file_information/file_information_types/type_conversions.cpp + file_information/file_information_types/visual_basic_info.cpp file_presentation/config_presentation.cpp file_presentation/file_presentation.cpp file_presentation/getters/format.cpp @@ -52,12 +53,15 @@ set(FILEINFO_SOURCES file_presentation/getters/iterative_getter/iterative_distribution_getter/relocation_tables_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_distribution_getter/resource_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_distribution_getter/rich_header_plain_getter.cpp - file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_distribution_getter/section_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_distribution_getter/segment_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_distribution_getter/strings_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_distribution_getter/symbol_tables_plain_getter.cpp + file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_distribution_getter/typeref_table_plain_getter.cpp + file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.cpp + file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.cpp + file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_getter.cpp file_presentation/getters/iterative_getter/iterative_simple_getter/certificate_table_plain_getter.cpp file_presentation/getters/iterative_getter/iterative_simple_getter/iterative_simple_getter.cpp diff --git a/src/fileinfo/file_detector/coff_detector.cpp b/src/fileinfo/file_detector/coff_detector.cpp index d5c6af491..05bf00ed3 100644 --- a/src/fileinfo/file_detector/coff_detector.cpp +++ b/src/fileinfo/file_detector/coff_detector.cpp @@ -6,6 +6,7 @@ #include +#include #include #include "retdec/utils/array.h" diff --git a/src/fileinfo/file_detector/file_detector.cpp b/src/fileinfo/file_detector/file_detector.cpp index dae758118..b07a258cc 100644 --- a/src/fileinfo/file_detector/file_detector.cpp +++ b/src/fileinfo/file_detector/file_detector.cpp @@ -212,6 +212,14 @@ void FileDetector::getCertificates() fileInfo.setCertificateTable(fileParser->getCertificateTable()); } +/** + * Get information about TLS + */ +void FileDetector::getTlsInfo() +{ + fileInfo.setTlsInfo(fileParser->getTlsInfo()); +} + /** * Get loader information */ @@ -328,6 +336,7 @@ void FileDetector::getAllInformation() getHashes(); getAdditionalInfo(); getCertificates(); + getTlsInfo(); getLoaderInfo(); getStrings(); } diff --git a/src/fileinfo/file_detector/file_detector.h b/src/fileinfo/file_detector/file_detector.h index cf848be0e..5264bcfbd 100644 --- a/src/fileinfo/file_detector/file_detector.h +++ b/src/fileinfo/file_detector/file_detector.h @@ -34,6 +34,7 @@ class FileDetector : private retdec::utils::NonCopyable void getHashes(); void getStrings(); void getCertificates(); + void getTlsInfo(); void getLoaderInfo(); /// @} protected: diff --git a/src/fileinfo/file_information/file_information.cpp b/src/fileinfo/file_information/file_information.cpp index e8a128749..be0402906 100644 --- a/src/fileinfo/file_information/file_information.cpp +++ b/src/fileinfo/file_information/file_information.cpp @@ -1374,6 +1374,24 @@ std::size_t FileInformation::getNumberOfStoredResources() const return resourceTable.getNumberOfResources(); } +/** + * Get number of supported version info languages + * @return Number of supported version info languages + */ +std::size_t FileInformation::getNumberOfVersionInfoLanguages() const +{ + return resourceTable.getNumberOfLanguages(); +} + +/** + * Get number of version info strings + * @return Number of version info strings + */ +std::size_t FileInformation::getNumberOfVersionInfoStrings() const +{ + return resourceTable.getNumberOfStrings(); +} + /** * Get CRC32 of selected resource * @param index Index of selected resource (indexed from 0) @@ -1470,6 +1488,46 @@ std::string FileInformation::getResourceLanguage(std::size_t index) const return resourceTable.getResourceLanguage(index); } +/** + * Get LCID of selected version info language + * @param index Index of selected version info language (indexed from 0) + * @return LCID of selected version info language + */ +std::string FileInformation::getVersionInfoLanguageLcid(std::size_t index) const +{ + return resourceTable.getLanguageLcid(index); +} + +/** + * Get code page of selected version info language + * @param index Index of selected version info language (indexed from 0) + * @return Code page of selected version info language + */ +std::string FileInformation::getVersionInfoLanguageCodePage(std::size_t index) const +{ + return resourceTable.getLanguageCodePage(index); +} + +/** + * Get name of selected version info string + * @param index Index of selected version info string (indexed from 0) + * @return Name of selected version info string + */ +std::string FileInformation::getVersionInfoStringName(std::size_t index) const +{ + return resourceTable.getStringName(index); +} + +/** + * Get value of selected version info string + * @param index Index of selected version info string (indexed from 0) + * @return Value of selected version info string + */ +std::string FileInformation::getVersionInfoStringValue(std::size_t index) const +{ + return resourceTable.getStringValue(index); +} + /** * Get name ID of selected resource * @param index Index of selected resource (indexed from 0) @@ -2000,6 +2058,94 @@ bool FileInformation::hasCertificateTableCounterSignerCertificate() const return certificateTable.hasCounterSignerCertificate(); } +/** + * Get start address of raw data of TLS + * @param format Format of result (e.g. std::dec, std::hex) + * @return Start address of raw data of TLS + */ +std::string FileInformation::getTlsRawDataStartAddrStr(std::ios_base &(* format)(std::ios_base &)) const +{ + return tlsInfo.getRawDataStartAddrStr(format); +} + +/** + * Get end address of raw data of TLS + * @param format Format of result (e.g. std::dec, std::hex) + * @return End address of raw data of TLS + */ +std::string FileInformation::getTlsRawDataEndAddrStr(std::ios_base &(* format)(std::ios_base &)) const +{ + return tlsInfo.getRawDataEndAddrStr(format); +} + +/** + * Get address of index of TLS + * @param format Format of result (e.g. std::dec, std::hex) + * @return Address of index of TLS + */ +std::string FileInformation::getTlsIndexAddrStr(std::ios_base &(* format)(std::ios_base &)) const +{ + return tlsInfo.getIndexAddrStr(format); +} + +/** + * Get address of callbacks of TLS + * @param format Format of result (e.g. std::dec, std::hex) + * @return Address of callbacks of TLS + */ +std::string FileInformation::getTlsCallBacksAddrStr(std::ios_base &(* format)(std::ios_base &)) const +{ + return tlsInfo.getCallBacksAddrStr(format); +} + +/** + * Get size of zero fill of TLS + * @param format Format of result (e.g. std::dec, std::hex) + * @return Size of zero fill of TLS + */ +std::string FileInformation::getTlsZeroFillSizeStr(std::ios_base &(* format)(std::ios_base &)) const +{ + return tlsInfo.getZeroFillSizeStr(format); +} + +/** + * Get characteristics of TLS + * @return Characteristics of TLS + */ +std::string FileInformation::getTlsCharacteristicsStr() const +{ + return tlsInfo.getCharacteristicsStr(); +} + +/** + * Get number of callbacks of TLS + * @return Number of callbacks of TLS + */ +std::size_t FileInformation::getTlsNumberOfCallBacks() const +{ + return tlsInfo.getNumberOfCallBacks(); +} + +/** + * Get TLS callback + * @param position Position of directory in internal list of directories (0..x) + * @param format Format of result (e.g. std::dec, std::hex) + * @return TLS callback + */ +std::string FileInformation::getTlsCallBackAddrStr(std::size_t position, std::ios_base &(* format)(std::ios_base &)) const +{ + return tlsInfo.getCallBackAddrStr(position, format); +} + +/** + * Check whether TLS is used + * @return @c true if TLS is used, @c false otherwise + */ +bool FileInformation::isTlsUsed() const +{ + return tlsInfo.isUsed(); +} + /** * Get type of data directory * @param position Position of directory in internal list of directories (0..x) @@ -4069,6 +4215,15 @@ void FileInformation::setCertificateTable(const retdec::fileformat::CertificateT certificateTable.setTable(sTable); } +/** + * Set TLS information + * @param info Information TLS + */ +void FileInformation::setTlsInfo(const retdec::fileformat::TlsInfo *info) +{ + tlsInfo.setTlsInfo(info); +} + /** * Set whether the signature is verified * @param verified @c true if verified, otherwise @c false. diff --git a/src/fileinfo/file_information/file_information.h b/src/fileinfo/file_information/file_information.h index a9475aa01..ee2a3cb3f 100644 --- a/src/fileinfo/file_information/file_information.h +++ b/src/fileinfo/file_information/file_information.h @@ -45,6 +45,7 @@ class FileInformation ExportTable exportTable; ///< information about exports ResourceTable resourceTable; ///< information about resources in input file CertificateTable certificateTable; ///< information about certificates + TlsInfo tlsInfo; ///< information about thread-local storage ElfCore elfCoreInfo; ///< information about ELF core files LoaderInfo loaderInfo; ///< information about loaded image std::vector directories; ///< information about data directories @@ -235,6 +236,8 @@ class FileInformation /// @name Getters of @a resourceTable /// @{ std::size_t getNumberOfStoredResources() const; + std::size_t getNumberOfVersionInfoLanguages() const; + std::size_t getNumberOfVersionInfoStrings() const; std::string getResourceCrc32(std::size_t index) const; std::string getResourceMd5(std::size_t index) const; std::string getResourceSha256(std::size_t index) const; @@ -245,6 +248,10 @@ class FileInformation std::string getResourceName(std::size_t index) const; std::string getResourceType(std::size_t index) const; std::string getResourceLanguage(std::size_t index) const; + std::string getVersionInfoLanguageLcid(std::size_t index) const; + std::string getVersionInfoLanguageCodePage(std::size_t index) const; + std::string getVersionInfoStringName(std::size_t index) const; + std::string getVersionInfoStringValue(std::size_t index) const; std::string getResourceNameIdStr(std::size_t index, std::ios_base &(* format)(std::ios_base &)) const; std::string getResourceTypeIdStr(std::size_t index, std::ios_base &(* format)(std::ios_base &)) const; std::string getResourceLanguageIdStr(std::size_t index, std::ios_base &(* format)(std::ios_base &)) const; @@ -304,6 +311,19 @@ class FileInformation bool hasCertificateTableCounterSignerCertificate() const; /// @} + /// @name Getters of @a TLS information + /// @{ + std::string getTlsRawDataStartAddrStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getTlsRawDataEndAddrStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getTlsIndexAddrStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getTlsCallBacksAddrStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getTlsZeroFillSizeStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getTlsCharacteristicsStr() const; + std::size_t getTlsNumberOfCallBacks() const; + std::string getTlsCallBackAddrStr(std::size_t position, std::ios_base &(* format)(std::ios_base &)) const; + bool isTlsUsed() const; + /// @} + /// @name Getters of @a directories /// @{ std::string getDataDirectoryType(std::size_t position) const; @@ -567,6 +587,7 @@ class FileInformation void setResourceTable(const retdec::fileformat::ResourceTable *sTable); void setStrings(const std::vector *sStrings); void setCertificateTable(const retdec::fileformat::CertificateTable *sTable); + void setTlsInfo(const retdec::fileformat::TlsInfo *info); void setSignatureVerified(bool verified); void setLoadedBaseAddress(unsigned long long baseAddress); void setLoaderStatusMessage(const std::string& statusMessage); diff --git a/src/fileinfo/file_information/file_information_types/file_information_types.h b/src/fileinfo/file_information/file_information_types/file_information_types.h index d826e3d97..9788b2b70 100644 --- a/src/fileinfo/file_information/file_information_types/file_information_types.h +++ b/src/fileinfo/file_information/file_information_types/file_information_types.h @@ -24,8 +24,9 @@ #include "fileinfo/file_information/file_information_types/relocation_table/relocation_table.h" #include "fileinfo/file_information/file_information_types/resource_table/resource_table.h" #include "fileinfo/file_information/file_information_types/rich_header.h" -#include "fileinfo/file_information/file_information_types/visual_basic_info.h" #include "fileinfo/file_information/file_information_types/strings.h" #include "fileinfo/file_information/file_information_types/symbol_table/symbol_table.h" +#include "fileinfo/file_information/file_information_types/tls_info.h" +#include "fileinfo/file_information/file_information_types/visual_basic_info.h" #endif diff --git a/src/fileinfo/file_information/file_information_types/resource_table/resource_table.cpp b/src/fileinfo/file_information/file_information_types/resource_table/resource_table.cpp index b51e1c23b..9ba734a5d 100644 --- a/src/fileinfo/file_information/file_information_types/resource_table/resource_table.cpp +++ b/src/fileinfo/file_information/file_information_types/resource_table/resource_table.cpp @@ -34,6 +34,24 @@ std::size_t ResourceTable::getNumberOfResources() const return table ? table->getNumberOfResources() : 0; } +/** + * Get number of supported languages + * @return Number of supported languages + */ +std::size_t ResourceTable::getNumberOfLanguages() const +{ + return table ? table->getNumberOfLanguages() : 0; +} + +/** + * Get number of strings + * @return Number of strings + */ +std::size_t ResourceTable::getNumberOfStrings() const +{ + return table ? table->getNumberOfStrings() : 0; +} + /** * Get CRC32 of selected resource * @param index Index of selected resource (indexed from 0) @@ -146,6 +164,50 @@ std::string ResourceTable::getResourceLanguage(std::size_t index) const return record ? record->getLanguage() : ""; } +/** + * Get LCID of supported language + * @param index Index of selected supported language (indexed from 0) + * @return LCID of supported language + */ +std::string ResourceTable::getLanguageLcid(std::size_t index) const +{ + const auto *record = table ? table->getLanguage(index) : nullptr; + return record ? record->first : ""; +} + +/** + * Get code page of supported language + * @param index Index of selected code page (indexed from 0) + * @return Code page of supported language + */ +std::string ResourceTable::getLanguageCodePage(std::size_t index) const +{ + const auto *record = table ? table->getLanguage(index) : nullptr; + return record ? record->second : ""; +} + +/** + * Get name of selected string + * @param index Index of selected string (indexed from 0) + * @return Name of string + */ +std::string ResourceTable::getStringName(std::size_t index) const +{ + const auto *record = table ? table->getString(index) : nullptr; + return record ? record->first : ""; +} + +/** + * Get value of selected string + * @param index Index of selected string (indexed from 0) + * @return Value of string + */ +std::string ResourceTable::getStringValue(std::size_t index) const +{ + const auto *record = table ? table->getString(index) : nullptr; + return record ? record->second : ""; +} + /** * Get name ID of selected resource * @param index Index of selected resource (indexed from 0) diff --git a/src/fileinfo/file_information/file_information_types/resource_table/resource_table.h b/src/fileinfo/file_information/file_information_types/resource_table/resource_table.h index 1b3b9b85a..ed84c4de3 100644 --- a/src/fileinfo/file_information/file_information_types/resource_table/resource_table.h +++ b/src/fileinfo/file_information/file_information_types/resource_table/resource_table.h @@ -31,6 +31,8 @@ class ResourceTable /// @name Getters /// @{ std::size_t getNumberOfResources() const; + std::size_t getNumberOfLanguages() const; + std::size_t getNumberOfStrings() const; std::string getResourceCrc32(std::size_t index) const; std::string getResourceMd5(std::size_t index) const; std::string getResourceSha256(std::size_t index) const; @@ -43,6 +45,10 @@ class ResourceTable std::string getResourceName(std::size_t index) const; std::string getResourceType(std::size_t index) const; std::string getResourceLanguage(std::size_t index) const; + std::string getLanguageLcid(std::size_t index) const; + std::string getLanguageCodePage(std::size_t index) const; + std::string getStringName(std::size_t index) const; + std::string getStringValue(std::size_t index) const; std::string getResourceNameIdStr(std::size_t index, std::ios_base &(* format)(std::ios_base &)) const; std::string getResourceTypeIdStr(std::size_t index, std::ios_base &(* format)(std::ios_base &)) const; std::string getResourceLanguageIdStr(std::size_t index, std::ios_base &(* format)(std::ios_base &)) const; diff --git a/src/fileinfo/file_information/file_information_types/tls_info.cpp b/src/fileinfo/file_information/file_information_types/tls_info.cpp new file mode 100644 index 000000000..24e778842 --- /dev/null +++ b/src/fileinfo/file_information/file_information_types/tls_info.cpp @@ -0,0 +1,137 @@ +/** + * @file src/fileinfo/file_information/file_information_types/tls_info.cpp + * @brief TLS information. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#include "fileinfo/file_information/file_information_types/tls_info.h" +#include "fileinfo/file_information/file_information_types/type_conversions.h" + +namespace fileinfo { + +/** + * Constructor + */ +TlsInfo::TlsInfo() : tlsInfo(nullptr) +{ + +} + +/** + * Destructor + */ +TlsInfo::~TlsInfo() +{ + +} + +/** + * Get raw data start address + * @param format Format of resulting string (e.g. std::dec, std::hex) + * @return Raw data start address + */ +std::string TlsInfo::getRawDataStartAddrStr(std::ios_base &(* format)(std::ios_base &)) const +{ + std::uint64_t val; + return (tlsInfo && tlsInfo->getRawDataStartAddr(val)) ? getNumberAsString(val, format) : ""; +} + +/** + * Get raw data end address + * @param format Format of resulting string (e.g. std::dec, std::hex) + * @return Raw data end address + */ +std::string TlsInfo::getRawDataEndAddrStr(std::ios_base &(* format)(std::ios_base &)) const +{ + std::uint64_t val; + return (tlsInfo && tlsInfo->getRawDataEndAddr(val)) ? getNumberAsString(val, format) : ""; +} + +/** + * Get index address + * @param format Format of resulting string (e.g. std::dec, std::hex) + * @return Index address + */ +std::string TlsInfo::getIndexAddrStr(std::ios_base &(* format)(std::ios_base &)) const +{ + std::uint64_t val; + return (tlsInfo && tlsInfo->getIndexAddr(val)) ? getNumberAsString(val, format) : ""; +} + +/** + * Get callbacks address + * @param format Format of resulting string (e.g. std::dec, std::hex) + * @return Callbacks address + */ +std::string TlsInfo::getCallBacksAddrStr(std::ios_base &(* format)(std::ios_base &)) const +{ + std::uint64_t val; + return (tlsInfo && tlsInfo->getCallBacksAddr(val)) ? getNumberAsString(val, format) : ""; +} + +/** + * Get zero fill size + * @param format Format of resulting string (e.g. std::dec, std::hex) + * @return Zero fill size + */ +std::string TlsInfo::getZeroFillSizeStr(std::ios_base &(* format)(std::ios_base &)) const +{ + std::uint32_t val; + return (tlsInfo && tlsInfo->getZeroFillSize(val)) ? getNumberAsString(val, format) : ""; +} + +/** + * Get characteristics + * @return Characteristics + */ +std::string TlsInfo::getCharacteristicsStr() const +{ + std::uint32_t val; + return (tlsInfo && tlsInfo->getCharacteristics(val)) ? getBinaryRepresentation(val, 32) : ""; +} + +/** + * Get number of callback addresses + * @return Number of callback addresses + */ +std::size_t TlsInfo::getNumberOfCallBacks() const +{ + return tlsInfo ? tlsInfo->getCallBacks().size() : 0; +} + +/** + * Get callback address + * @param position Index of selected callback (indexed from 0) + * @param format Format of resulting string (e.g. std::dec, std::hex) + * @return Callback address + */ +std::string TlsInfo::getCallBackAddrStr(std::size_t position, std::ios_base &(* format)(std::ios_base &)) const +{ + if (!tlsInfo || position >= getNumberOfCallBacks()) + { + return ""; + } + auto addr = tlsInfo->getCallBacks()[position]; + return getNumberAsString(addr, format); +} + +/** + * Set TLS info + * @param info Instance of class with original information about TLS + */ +void TlsInfo::setTlsInfo(const retdec::fileformat::TlsInfo *info) +{ + tlsInfo = info; +} + +/** + * Check whether TLS is used + * @return @c true if TLS is used, @c false otherwise + */ +bool TlsInfo::isUsed() const +{ + return tlsInfo != nullptr; +} + + +} // namespace fileinfo diff --git a/src/fileinfo/file_information/file_information_types/tls_info.h b/src/fileinfo/file_information/file_information_types/tls_info.h new file mode 100644 index 000000000..c424a68c7 --- /dev/null +++ b/src/fileinfo/file_information/file_information_types/tls_info.h @@ -0,0 +1,46 @@ +/** + * @file src/fileinfo/file_information/file_information_types/tls_info.h + * @brief TLS information. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#ifndef FILEINFO_FILE_INFORMATION_FILE_INFORMATION_TYPES_TLS_INFO_H +#define FILEINFO_FILE_INFORMATION_FILE_INFORMATION_TYPES_TLS_INFO_H + +#include "retdec/fileformat/types/tls_info/tls_info.h" + +namespace fileinfo { + +/** + * Class for import table + */ +class TlsInfo +{ + private: + const retdec::fileformat::TlsInfo *tlsInfo; + public: + TlsInfo(); + ~TlsInfo(); + + /// @name Getters + /// @{ + std::string getRawDataStartAddrStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getRawDataEndAddrStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getIndexAddrStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getCallBacksAddrStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getZeroFillSizeStr(std::ios_base &(* format)(std::ios_base &)) const; + std::string getCharacteristicsStr() const; + std::size_t getNumberOfCallBacks() const; + std::string getCallBackAddrStr(std::size_t position, std::ios_base &(* format)(std::ios_base &)) const; + /// @} + + /// @name Setters + /// @{ + void setTlsInfo(const retdec::fileformat::TlsInfo *info); + bool isUsed() const; + /// @} +}; + +} // namespace fileinfo + +#endif diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.cpp b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.cpp new file mode 100644 index 000000000..cab906a2b --- /dev/null +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.cpp @@ -0,0 +1,104 @@ +/** + * @file src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.cpp + * @brief Methods of TlsInfoPlainGetter class. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#include "retdec/utils/conversion.h" +#include "retdec/utils/string.h" +#include "retdec/fileformat/utils/conversions.h" +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.h" + +using namespace retdec::utils; +using namespace retdec::fileformat; + +namespace fileinfo { + +namespace +{ + +const std::size_t distributionArray[] = {6, 20}; +const std::string headerArray[] = {"i", "address"}; +const std::string headerDesc[] = {"index", "address of callback"}; + +} // anonymous namespace + +/** + * Constructor + * @param fileInfo Information about file + */ +TlsInfoPlainGetter::TlsInfoPlainGetter(FileInformation &fileInfo) : IterativeDistributionGetter(fileInfo) +{ + numberOfStructures = 1; + numberOfStoredRecords.push_back(fileinfo.getTlsNumberOfCallBacks()); + numberOfExtraElements.push_back(0); + title = "TLS info"; + distribution.insert(distribution.begin(), std::begin(distributionArray), std::end(distributionArray)); + commonHeaderElements.insert(commonHeaderElements.begin(), std::begin(headerArray), std::end(headerArray)); + commonHeaderDesc.insert(commonHeaderDesc.begin(), std::begin(headerDesc), std::end(headerDesc)); + loadRecords(); +} + +/** + * Destructor + */ +TlsInfoPlainGetter::~TlsInfoPlainGetter() +{ + +} + +std::size_t TlsInfoPlainGetter::getBasicInfo(std::size_t structIndex, std::vector &desc, std::vector &info) const +{ + if(structIndex >= numberOfStructures || !fileinfo.isTlsUsed()) + { + return 0; + } + + desc.clear(); + info.clear(); + + desc.push_back("Number of callbacks : "); + desc.push_back("Address of start of raw data : "); + desc.push_back("Address of end of raw data : "); + desc.push_back("Address of callbacks : "); + desc.push_back("Address of index : "); + desc.push_back("Size of zero fill : "); + desc.push_back("Characteristics : "); + info.push_back(numToStr(fileinfo.getTlsNumberOfCallBacks())); + info.push_back(fileinfo.getTlsRawDataStartAddrStr(hexWithPrefix)); + info.push_back(fileinfo.getTlsRawDataEndAddrStr(hexWithPrefix)); + info.push_back(fileinfo.getTlsIndexAddrStr(hexWithPrefix)); + info.push_back(fileinfo.getTlsCallBacksAddrStr(hexWithPrefix)); + info.push_back(fileinfo.getTlsZeroFillSizeStr(std::dec)); + info.push_back(fileinfo.getTlsCharacteristicsStr()); + + return info.size(); +} + +bool TlsInfoPlainGetter::loadRecord(std::size_t structIndex, std::size_t recIndex, std::vector &record) +{ + if(structIndex >= numberOfStructures || recIndex >= numberOfStoredRecords[structIndex]) + { + return false; + } + + record.clear(); + record.push_back(numToStr(recIndex)); + record.push_back(fileinfo.getTlsCallBackAddrStr(recIndex, hexWithPrefix)); + return true; +} + +bool TlsInfoPlainGetter::getFlagDescriptors(std::size_t structIndex, std::vector &desc, std::vector &abbv) const +{ + if(structIndex >= numberOfStructures) + { + return false; + } + + desc.clear(); + abbv.clear(); + + return true; +} + +} // namespace fileinfo diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.h b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.h new file mode 100644 index 000000000..b8d8186db --- /dev/null +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.h @@ -0,0 +1,31 @@ +/** + * @file src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.h + * @brief Definition of TlsInfoPlainGetter class. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#ifndef FILEINFO_FILE_PRESENTATION_GETTERS_ITERATIVE_GETTER_ITERATIVE_DISTRIBUTION_GETTER_TLS_INFO_PLAIN_GETTER_H +#define FILEINFO_FILE_PRESENTATION_GETTERS_ITERATIVE_GETTER_ITERATIVE_DISTRIBUTION_GETTER_TLS_INFO_PLAIN_GETTER_H + +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/iterative_distribution_getter.h" + +namespace fileinfo { + +/** + * Getter for TLS information + */ +class TlsInfoPlainGetter : public IterativeDistributionGetter +{ + protected: + virtual bool loadRecord(std::size_t structIndex, std::size_t recIndex, std::vector &record) override; + public: + TlsInfoPlainGetter(FileInformation &fileInfo); + virtual ~TlsInfoPlainGetter() override; + + virtual std::size_t getBasicInfo(std::size_t structIndex, std::vector &desc, std::vector &info) const override; + virtual bool getFlagDescriptors(std::size_t structIndex, std::vector &desc, std::vector &abbv) const override; +}; + +} // namespace fileinfo + +#endif diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.cpp b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.cpp new file mode 100644 index 000000000..be329ec4e --- /dev/null +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.cpp @@ -0,0 +1,93 @@ +/** + * @file src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.cpp + * @brief Definition of VersionInfoLanguageTablePlainGetter class. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#include "retdec/utils/conversion.h" +#include "retdec/utils/string.h" +#include "retdec/fileformat/utils/conversions.h" +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.h" + +using namespace retdec::utils; +using namespace retdec::fileformat; + +namespace fileinfo { + +namespace +{ + +const std::size_t distributionArray[] = {6, 40, 40}; +const std::string headerArray[] = {"i", "lcid", "codePage"}; +const std::string headerDesc[] = {"index", "microsoft language identifier", "IBM code page"}; + +} // anonymous namespace + +/** + * Constructor + * @param fileInfo Information about file + */ +VersionInfoLanguageTablePlainGetter::VersionInfoLanguageTablePlainGetter(FileInformation &fileInfo) : IterativeDistributionGetter(fileInfo) +{ + numberOfStructures = 1; + numberOfStoredRecords.push_back(fileinfo.getNumberOfVersionInfoLanguages()); + numberOfExtraElements.push_back(0); + title = "Version info languages"; + distribution.insert(distribution.begin(), std::begin(distributionArray), std::end(distributionArray)); + commonHeaderElements.insert(commonHeaderElements.begin(), std::begin(headerArray), std::end(headerArray)); + commonHeaderDesc.insert(commonHeaderDesc.begin(), std::begin(headerDesc), std::end(headerDesc)); + loadRecords(); +} + +/** + * Destructor + */ +VersionInfoLanguageTablePlainGetter::~VersionInfoLanguageTablePlainGetter() +{ + +} + +std::size_t VersionInfoLanguageTablePlainGetter::getBasicInfo(std::size_t structIndex, std::vector &desc, std::vector &info) const +{ + if(structIndex >= numberOfStructures || !fileinfo.getNumberOfVersionInfoLanguages()) + { + return 0; + } + + desc.clear(); + info.clear(); + + desc.push_back("Number of languages: "); + info.push_back(numToStr(fileinfo.getNumberOfVersionInfoLanguages())); + + return info.size(); +} + +bool VersionInfoLanguageTablePlainGetter::loadRecord(std::size_t structIndex, std::size_t recIndex, std::vector &record) +{ + if(structIndex >= numberOfStructures || recIndex >= numberOfStoredRecords[structIndex]) + { + return false; + } + + record.clear(); + record.push_back(numToStr(recIndex)); + record.push_back(fileinfo.getVersionInfoLanguageLcid(recIndex)); + record.push_back(fileinfo.getVersionInfoLanguageCodePage(recIndex)); + return true; +} + +bool VersionInfoLanguageTablePlainGetter::getFlagDescriptors(std::size_t structIndex, std::vector &desc, std::vector &abbv) const +{ + if(structIndex >= numberOfStructures) + { + return false; + } + + desc.clear(); + abbv.clear(); + + return true; +} + +} // namespace fileinfo diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.h b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.h new file mode 100644 index 000000000..6e7d353bc --- /dev/null +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.h @@ -0,0 +1,31 @@ +/** + * @file src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.h + * @brief Definition of VersionInfoLanguageTablePlainGetter class. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#ifndef FILEINFO_FILE_PRESENTATION_GETTERS_ITERATIVE_GETTER_ITERATIVE_DISTRIBUTION_GETTER_VERSION_INFO_LANGUAGE_TABLE_PLAIN_GETTER_H +#define FILEINFO_FILE_PRESENTATION_GETTERS_ITERATIVE_GETTER_ITERATIVE_DISTRIBUTION_GETTER_VERSION_INFO_LANGUAGE_TABLE_PLAIN_GETTER_H + +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/iterative_distribution_getter.h" + +namespace fileinfo { + +/** + * Getter for visual basic objects + */ +class VersionInfoLanguageTablePlainGetter : public IterativeDistributionGetter +{ + protected: + virtual bool loadRecord(std::size_t structIndex, std::size_t recIndex, std::vector &record) override; + public: + VersionInfoLanguageTablePlainGetter(FileInformation &fileInfo); + virtual ~VersionInfoLanguageTablePlainGetter() override; + + virtual std::size_t getBasicInfo(std::size_t structIndex, std::vector &desc, std::vector &info) const override; + virtual bool getFlagDescriptors(std::size_t structIndex, std::vector &desc, std::vector &abbv) const override; +}; + +} // namespace fileinfo + +#endif diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.cpp b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.cpp new file mode 100644 index 000000000..92e3994c9 --- /dev/null +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.cpp @@ -0,0 +1,93 @@ +/** + * @file src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.cpp + * @brief Definition of VersionInfoStringTablePlainGetter class. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#include "retdec/utils/conversion.h" +#include "retdec/utils/string.h" +#include "retdec/fileformat/utils/conversions.h" +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.h" + +using namespace retdec::utils; +using namespace retdec::fileformat; + +namespace fileinfo { + +namespace +{ + +const std::size_t distributionArray[] = {6, 40, 40}; +const std::string headerArray[] = {"i", "name", "value"}; +const std::string headerDesc[] = {"index", "string name", "string value"}; + +} // anonymous namespace + +/** + * Constructor + * @param fileInfo Information about file + */ +VersionInfoStringTablePlainGetter::VersionInfoStringTablePlainGetter(FileInformation &fileInfo) : IterativeDistributionGetter(fileInfo) +{ + numberOfStructures = 1; + numberOfStoredRecords.push_back(fileinfo.getNumberOfVersionInfoStrings()); + numberOfExtraElements.push_back(0); + title = "Version info strings"; + distribution.insert(distribution.begin(), std::begin(distributionArray), std::end(distributionArray)); + commonHeaderElements.insert(commonHeaderElements.begin(), std::begin(headerArray), std::end(headerArray)); + commonHeaderDesc.insert(commonHeaderDesc.begin(), std::begin(headerDesc), std::end(headerDesc)); + loadRecords(); +} + +/** + * Destructor + */ +VersionInfoStringTablePlainGetter::~VersionInfoStringTablePlainGetter() +{ + +} + +std::size_t VersionInfoStringTablePlainGetter::getBasicInfo(std::size_t structIndex, std::vector &desc, std::vector &info) const +{ + if(structIndex >= numberOfStructures || !fileinfo.getNumberOfVersionInfoStrings()) + { + return 0; + } + + desc.clear(); + info.clear(); + + desc.push_back("Number of strings: "); + info.push_back(numToStr(fileinfo.getNumberOfVersionInfoStrings())); + + return info.size(); +} + +bool VersionInfoStringTablePlainGetter::loadRecord(std::size_t structIndex, std::size_t recIndex, std::vector &record) +{ + if(structIndex >= numberOfStructures || recIndex >= numberOfStoredRecords[structIndex]) + { + return false; + } + + record.clear(); + record.push_back(numToStr(recIndex)); + record.push_back(replaceNonprintableChars(fileinfo.getVersionInfoStringName(recIndex))); + record.push_back(replaceNonprintableChars(fileinfo.getVersionInfoStringValue(recIndex))); + return true; +} + +bool VersionInfoStringTablePlainGetter::getFlagDescriptors(std::size_t structIndex, std::vector &desc, std::vector &abbv) const +{ + if(structIndex >= numberOfStructures) + { + return false; + } + + desc.clear(); + abbv.clear(); + + return true; +} + +} // namespace fileinfo diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.h b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.h new file mode 100644 index 000000000..2e3195223 --- /dev/null +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.h @@ -0,0 +1,31 @@ +/** + * @file src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.h + * @brief Definition of VersionInfoStringTablePlainGetter class. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#ifndef FILEINFO_FILE_PRESENTATION_GETTERS_ITERATIVE_GETTER_ITERATIVE_DISTRIBUTION_GETTER_VERSION_INFO_STRING_TABLE_PLAIN_GETTER_H +#define FILEINFO_FILE_PRESENTATION_GETTERS_ITERATIVE_GETTER_ITERATIVE_DISTRIBUTION_GETTER_VERSION_INFO_STRING_TABLE_PLAIN_GETTER_H + +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/iterative_distribution_getter.h" + +namespace fileinfo { + +/** + * Getter for visual basic objects + */ +class VersionInfoStringTablePlainGetter : public IterativeDistributionGetter +{ + protected: + virtual bool loadRecord(std::size_t structIndex, std::size_t recIndex, std::vector &record) override; + public: + VersionInfoStringTablePlainGetter(FileInformation &fileInfo); + virtual ~VersionInfoStringTablePlainGetter() override; + + virtual std::size_t getBasicInfo(std::size_t structIndex, std::vector &desc, std::vector &info) const override; + virtual bool getFlagDescriptors(std::size_t structIndex, std::vector &desc, std::vector &abbv) const override; +}; + +} // namespace fileinfo + +#endif diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.cpp b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.cpp index 4596a3326..9a68357d9 100644 --- a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.cpp +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.cpp @@ -1,5 +1,5 @@ /** - * @file src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.h + * @file src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.cpp * @brief Definition of VisualBasicExternTablePlainGetter class. * @copyright (c) 2017 Avast Software, licensed under the MIT license */ diff --git a/src/fileinfo/file_presentation/getters/plain_getters.h b/src/fileinfo/file_presentation/getters/plain_getters.h index 8a01af36d..f67a70592 100644 --- a/src/fileinfo/file_presentation/getters/plain_getters.h +++ b/src/fileinfo/file_presentation/getters/plain_getters.h @@ -23,8 +23,11 @@ #include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/segment_plain_getter.h" #include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/strings_plain_getter.h" #include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/symbol_tables_plain_getter.h" +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/tls_info_plain_getter.h" #include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/typeref_table_plain_getter.h" #include "fileinfo/file_presentation/getters/iterative_getter/iterative_simple_getter/certificate_table_plain_getter.h" +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_language_table_plain_getter.h" +#include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/version_info_string_table_plain_getter.h" #include "fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/visual_basic_extern_table_plain_getter.h" #include "fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.h" #include "fileinfo/file_presentation/getters/simple_getter/dotnet_plain_getter.h" diff --git a/src/fileinfo/file_presentation/json_presentation.cpp b/src/fileinfo/file_presentation/json_presentation.cpp index 5bd81ff7f..3a3da012a 100644 --- a/src/fileinfo/file_presentation/json_presentation.cpp +++ b/src/fileinfo/file_presentation/json_presentation.cpp @@ -375,6 +375,38 @@ void JsonPresentation::presentCertificateAttributes(Json::Value &root) const } } +/** + * Present information about TLS + * @param root Parent node in output document + */ +void JsonPresentation::presentTlsInfo(Json::Value &root) const +{ + if (!fileinfo.isTlsUsed()) + { + return; + } + + Value jTlsInfo; + presentIfNotEmpty("rawDataStartAddress", fileinfo.getTlsRawDataStartAddrStr(hexWithPrefix), jTlsInfo); + presentIfNotEmpty("rawDataEndAddress", fileinfo.getTlsRawDataEndAddrStr(hexWithPrefix), jTlsInfo); + presentIfNotEmpty("indexAddress", fileinfo.getTlsIndexAddrStr(hexWithPrefix), jTlsInfo); + presentIfNotEmpty("callbacksAddress", fileinfo.getTlsCallBacksAddrStr(hexWithPrefix), jTlsInfo); + presentIfNotEmpty("sizeOfZeroFill", fileinfo.getTlsZeroFillSizeStr(std::dec), jTlsInfo); + presentIfNotEmpty("characteristics", fileinfo.getTlsCharacteristicsStr(), jTlsInfo); + + if (fileinfo.getTlsNumberOfCallBacks() > 0) + { + Value jCallbacks; + for (std::size_t i = 0; i < fileinfo.getTlsNumberOfCallBacks(); i++) + { + jCallbacks.append(fileinfo.getTlsCallBackAddrStr(i, hexWithPrefix)); + } + jTlsInfo["callbacks"] = jCallbacks; + } + + root["tlsInfo"] = jTlsInfo; +} + /** * Present information about .NET * @param root Parent node in output document @@ -557,6 +589,45 @@ void JsonPresentation::presentVisualBasicInfo(Json::Value &root) const root["visualBasicInfo"] = jVBasic; } +/** + * Present version information + * @param root Parent node in output document + */ +void JsonPresentation::presentVersionInfo(Json::Value &root) const +{ + Value jVerInfo; + + auto nStrings = fileinfo.getNumberOfVersionInfoStrings(); + if (nStrings) + { + Value jStrings; + for (std::size_t i = 0; i < nStrings; i++) + { + Value jStr; + jStr["name"] = fileinfo.getVersionInfoStringName(i); + jStr["value"] = fileinfo.getVersionInfoStringValue(i); + jStrings.append(jStr); + } + jVerInfo["strings"] = jStrings; + } + + auto nLangs = fileinfo.getNumberOfVersionInfoLanguages(); + if (nLangs) + { + Value jLanguages; + for (std::size_t i = 0; i < nLangs; i++) + { + Value jLang; + jLang["lcid"] = fileinfo.getVersionInfoLanguageLcid(i); + jLang["codePage"] = fileinfo.getVersionInfoLanguageCodePage(i); + jLanguages.append(jLang); + } + jVerInfo["languages"] = jLanguages; + } + + root["versionInfo"] = jVerInfo; +} + /** * Present ELF notes * @param root Parent node in output document @@ -816,8 +887,10 @@ bool JsonPresentation::present() presentLoaderInfo(root); presentPatterns(root); presentCertificateAttributes(root); + presentTlsInfo(root); presentDotnetInfo(root); presentVisualBasicInfo(root); + presentVersionInfo(root); } else { diff --git a/src/fileinfo/file_presentation/json_presentation.h b/src/fileinfo/file_presentation/json_presentation.h index e53023019..305536d58 100644 --- a/src/fileinfo/file_presentation/json_presentation.h +++ b/src/fileinfo/file_presentation/json_presentation.h @@ -32,7 +32,9 @@ class JsonPresentation : public FilePresentation void presentPatterns(Json::Value &root) const; void presentLoaderInfo(Json::Value &root) const; void presentCertificateAttributes(Json::Value &root) const; + void presentTlsInfo(Json::Value &root) const; void presentDotnetInfo(Json::Value &root) const; + void presentVersionInfo(Json::Value &root) const; void presentVisualBasicInfo(Json::Value &root) const; void presentElfNotes(Json::Value &root) const; void presentFlags(Json::Value &root, const std::string &title, const std::string &flags, const std::vector &desc) const; diff --git a/src/fileinfo/file_presentation/plain_presentation.cpp b/src/fileinfo/file_presentation/plain_presentation.cpp index 243dd7755..35fed464e 100644 --- a/src/fileinfo/file_presentation/plain_presentation.cpp +++ b/src/fileinfo/file_presentation/plain_presentation.cpp @@ -753,6 +753,9 @@ bool PlainPresentation::present() presentIterativeDistribution(RelocationTablesPlainGetter(fileinfo), explanatory); presentIterativeDistribution(DynamicSectionsPlainGetter(fileinfo), explanatory); presentIterativeDistribution(ResourcePlainGetter(fileinfo), explanatory); + presentIterativeDistribution(VersionInfoStringTablePlainGetter(fileinfo), explanatory); + presentIterativeDistribution(VersionInfoLanguageTablePlainGetter(fileinfo), explanatory); + presentIterativeDistribution(TlsInfoPlainGetter(fileinfo), explanatory); presentNotes(); diff --git a/src/fileinfo/file_wrapper/macho_wrapper.cpp b/src/fileinfo/file_wrapper/macho_wrapper.cpp index 000d5ac02..ce0c2a8fa 100644 --- a/src/fileinfo/file_wrapper/macho_wrapper.cpp +++ b/src/fileinfo/file_wrapper/macho_wrapper.cpp @@ -4,8 +4,6 @@ * @copyright (c) 2017 Avast Software, licensed under the MIT license */ -#include - #include "fileinfo/file_wrapper/macho_wrapper.h" using namespace llvm::MachO; diff --git a/src/llvmir-emul/llvmir_emul.cpp b/src/llvmir-emul/llvmir_emul.cpp index 2daa3ac8d..1ba4b29d0 100644 --- a/src/llvmir-emul/llvmir_emul.cpp +++ b/src/llvmir-emul/llvmir_emul.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -916,7 +915,7 @@ GenericValue executeGEPOperation( for (; I != E; ++I) { - if (StructType *STy = dyn_cast(*I)) + if (StructType *STy = I.getStructTypeOrNull()) { const StructLayout *SLO = DL.getStructLayout(STy); @@ -927,7 +926,6 @@ GenericValue executeGEPOperation( } else { - SequentialType *ST = cast(*I); // Get the index number for the array... which must be long type... GenericValue IdxGV = GC.getOperandValue(I.getOperand(), SF); @@ -943,7 +941,7 @@ GenericValue executeGEPOperation( assert(BitWidth == 64 && "Invalid index type for getelementptr"); Idx = static_cast(IdxGV.IntVal.getZExtValue()); } - Total += DL.getTypeAllocSize(ST->getElementType()) * Idx; + Total += DL.getTypeAllocSize(I.getIndexedType()) * Idx; } } @@ -1786,7 +1784,7 @@ llvm::GenericValue getConstantValue(const llvm::Constant* C, llvm::Module* m) GV.DoubleVal = GV.IntVal.roundToDouble(); else if (CE->getType()->isX86_FP80Ty()) { - APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended); + APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended()); (void)apf.convertFromAPInt(GV.IntVal, false, APFloat::rmNearestTiesToEven); @@ -1803,7 +1801,7 @@ llvm::GenericValue getConstantValue(const llvm::Constant* C, llvm::Module* m) GV.DoubleVal = GV.IntVal.signedRoundToDouble(); else if (CE->getType()->isX86_FP80Ty()) { - APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended); + APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended()); (void)apf.convertFromAPInt(GV.IntVal, true, APFloat::rmNearestTiesToEven); @@ -1822,12 +1820,15 @@ llvm::GenericValue getConstantValue(const llvm::Constant* C, llvm::Module* m) GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth); else if (Op0->getType()->isX86_FP80Ty()) { - APFloat apf = APFloat(APFloat::x87DoubleExtended, GV.IntVal); + APFloat apf = APFloat(APFloat::x87DoubleExtended(), GV.IntVal); uint64_t v; bool ignored; - (void)apf.convertToInteger(&v, BitWidth, + (void)apf.convertToInteger( + makeMutableArrayRef(v), + BitWidth, CE->getOpcode()==Instruction::FPToSI, - APFloat::rmTowardZero, &ignored); + APFloat::rmTowardZero, + &ignored); GV.IntVal = v; // endian? } return GV; @@ -2009,7 +2010,7 @@ llvm::GenericValue getConstantValue(const llvm::Constant* C, llvm::Module* m) { auto apf = cast(C)->getValueAPF(); bool lostPrecision; - apf.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &lostPrecision); + apf.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &lostPrecision); Result.DoubleVal = apf.convertToDouble(); break; } @@ -2720,12 +2721,12 @@ void LlvmIrEmulator::visitSwitchInst(llvm::SwitchInst& I) // Check to see if any of the cases match... BasicBlock *dest = nullptr; - for (SwitchInst::CaseIt i = I.case_begin(), e = I.case_end(); i != e; ++i) + for (auto Case : I.cases()) { - GenericValue caseVal = _globalEc.getOperandValue(i.getCaseValue(), ec); - if (executeICMP_EQ(condVal, caseVal, elTy).IntVal != false) + GenericValue caseVal = _globalEc.getOperandValue(Case.getCaseValue(), ec); + if (executeICMP_EQ(condVal, caseVal, elTy).IntVal != 0) { - dest = cast(i.getCaseSuccessor()); + dest = cast(Case.getCaseSuccessor()); break; } } diff --git a/src/llvmir2hll/evaluator/arithm_expr_evaluator.cpp b/src/llvmir2hll/evaluator/arithm_expr_evaluator.cpp index 31e89e973..1b1a02b59 100644 --- a/src/llvmir2hll/evaluator/arithm_expr_evaluator.cpp +++ b/src/llvmir2hll/evaluator/arithm_expr_evaluator.cpp @@ -630,7 +630,8 @@ void ArithmExprEvaluator::visit(ShPtr expr) { ShPtr result; if (Maybe constIntPair = castConstPair( constPair)) { - result = performOperationOverApInt(constIntPair, &llvm::APInt::And); + APSIntPair apsIntPair(getAPSIntsFromConstants(constIntPair)); + result = ConstInt::create(apsIntPair.first & apsIntPair.second); } else { canBeEvaluated = false; } @@ -652,7 +653,8 @@ void ArithmExprEvaluator::visit(ShPtr expr) { ShPtr result; if (Maybe constIntPair = castConstPair( constPair)) { - result = performOperationOverApInt(constIntPair, &llvm::APInt::Or); + APSIntPair apsIntPair(getAPSIntsFromConstants(constIntPair)); + result = ConstInt::create(apsIntPair.first | apsIntPair.second); } else { canBeEvaluated = false; } @@ -674,7 +676,8 @@ void ArithmExprEvaluator::visit(ShPtr expr) { ShPtr result; if (Maybe constIntPair = castConstPair( constPair)) { - result = performOperationOverApInt(constIntPair, &llvm::APInt::Xor); + APSIntPair apsIntPair(getAPSIntsFromConstants(constIntPair)); + result = ConstInt::create(apsIntPair.first ^ apsIntPair.second); } else { canBeEvaluated = false; } diff --git a/src/llvmir2hll/ir/const_float.cpp b/src/llvmir2hll/ir/const_float.cpp index 714f15313..70a588125 100644 --- a/src/llvmir2hll/ir/const_float.cpp +++ b/src/llvmir2hll/ir/const_float.cpp @@ -32,17 +32,17 @@ ShPtr getTypeOfValue(const ConstFloat::Type &value) { // The sizes are based on http://llvm.org/docs/LangRef.html#floating-point-types. unsigned size = 0; const auto &semantics = value.getSemantics(); - if (&semantics == &llvm::APFloat::IEEEhalf) { + if (&semantics == &llvm::APFloat::IEEEhalf()) { size = 16; - } else if (&semantics == &llvm::APFloat::IEEEsingle) { + } else if (&semantics == &llvm::APFloat::IEEEsingle()) { size = 32; - } else if (&semantics == &llvm::APFloat::IEEEdouble) { + } else if (&semantics == &llvm::APFloat::IEEEdouble()) { size = 64; - } else if (&semantics == &llvm::APFloat::IEEEquad) { // fp128 + } else if (&semantics == &llvm::APFloat::IEEEquad()) { // fp128 size = 128; - } else if (&semantics == &llvm::APFloat::x87DoubleExtended) { // x86_fp80 + } else if (&semantics == &llvm::APFloat::x87DoubleExtended()) { // x86_fp80 size = 80; - } else if (&semantics == &llvm::APFloat::PPCDoubleDouble) { // ppc_fp128 + } else if (&semantics == &llvm::APFloat::PPCDoubleDouble()) { // ppc_fp128 size = 128; } else { FAIL("unsupported semantics of llvm::APFloat"); diff --git a/src/llvmir2hll/llvm/llvm_support.cpp b/src/llvmir2hll/llvm/llvm_support.cpp index c600ec77f..52dca99dd 100644 --- a/src/llvmir2hll/llvm/llvm_support.cpp +++ b/src/llvmir2hll/llvm/llvm_support.cpp @@ -133,7 +133,7 @@ bool LLVMSupport::isInlinableInst(const llvm::Instruction *i) { // It has to be an expression, and it has to be used exactly once. If it is // dead, we generate it inline where it would go. if (i->getType() == llvm::Type::getVoidTy(i->getContext()) || !i->hasOneUse() || - llvm::isa(i) || llvm::isa(i) || + i->isTerminator() || llvm::isa(i) || llvm::isa(i) || llvm::isa(i) || llvm::isa(i) || llvm::isa(i) || llvm::isa(i)) { @@ -219,7 +219,7 @@ bool LLVMSupport::endsWithRetOrUnreachImpl(llvm::BasicBlock *bb, bool indirect){ } endsWithRetOrUnreachBBSet.insert(bb); - llvm::TerminatorInst *t = bb->getTerminator(); + llvm::Instruction *t = bb->getTerminator(); if (llvm::isa(t) || llvm::isa(t)) { return true; } diff --git a/src/llvmir2hll/llvm/llvmir2bir_converter/cfg_node.cpp b/src/llvmir2hll/llvm/llvmir2bir_converter/cfg_node.cpp index 1890caa17..1ae32c5db 100644 --- a/src/llvmir2hll/llvm/llvmir2bir_converter/cfg_node.cpp +++ b/src/llvmir2hll/llvm/llvmir2bir_converter/cfg_node.cpp @@ -83,7 +83,7 @@ void CFGNode::setLastBB(llvm::BasicBlock *bb) { /** * @brief Returns the terminator instruction of stored basic block in this node. */ -llvm::TerminatorInst *CFGNode::getTerm() const { +llvm::Instruction *CFGNode::getTerm() const { return lastBasicBlock->getTerminator(); } diff --git a/src/llvmir2hll/llvm/llvmir2bir_converter/llvm_instruction_converter.cpp b/src/llvmir2hll/llvm/llvmir2bir_converter/llvm_instruction_converter.cpp index 143ad47d1..d71ff2cab 100644 --- a/src/llvmir2hll/llvm/llvmir2bir_converter/llvm_instruction_converter.cpp +++ b/src/llvmir2hll/llvm/llvmir2bir_converter/llvm_instruction_converter.cpp @@ -691,7 +691,7 @@ ShPtr LLVMInstructionConverter::convertGEPIndices(ShPtr auto indexOp = base; for (auto i = start; i != end; ++i) { auto index = getConverter()->convertValueToExpression(i.getOperand()); - if (i->isStructTy()) { + if (i.isStruct()) { auto indexInt = ucast(index); indexOp = StructIndexOpExpr::create(indexOp, indexInt); } else { diff --git a/src/llvmir2hlltool/llvmir2hll.cpp b/src/llvmir2hlltool/llvmir2hll.cpp index 5055b9b87..8764de963 100644 --- a/src/llvmir2hlltool/llvmir2hll.cpp +++ b/src/llvmir2hlltool/llvmir2hll.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include "retdec/llvmir2hll/analysis/alias_analysis/alias_analysis.h" #include "retdec/llvmir2hll/analysis/alias_analysis/alias_analysis_factory.h" @@ -318,7 +317,7 @@ class Decompiler: public ModulePass { public: explicit Decompiler(raw_pwrite_stream &out); - virtual const char *getPassName() const override { return "Decompiler"; } + virtual llvm::StringRef getPassName() const override { return "Decompiler"; } virtual bool runOnModule(Module &m) override; public: @@ -1025,16 +1024,22 @@ class DecompilerTargetMachine: public TargetMachine { const TargetOptions &options): TargetMachine(t, dataLayoutString, targetTriple, cpu, fs, options) {} - virtual bool addPassesToEmitFile(PassManagerBase &pm, - raw_pwrite_stream &out, CodeGenFileType fileType, - bool disableVerify, AnalysisID startBefore, AnalysisID startAfter, - AnalysisID stopAfter, MachineFunctionInitializer *mfInitializer) override; + virtual bool addPassesToEmitFile( + PassManagerBase &pm, + raw_pwrite_stream &out, + raw_pwrite_stream *, + CodeGenFileType fileType, + bool disableVerify = true, + MachineModuleInfo *MMI = nullptr) override; }; -bool DecompilerTargetMachine::addPassesToEmitFile(PassManagerBase &pm, - raw_pwrite_stream &out, CodeGenFileType fileType, - bool disableVerify, AnalysisID startBefore, AnalysisID startAfter, - AnalysisID stopAfter, MachineFunctionInitializer *mfInitializer) { +bool DecompilerTargetMachine::addPassesToEmitFile( + PassManagerBase &pm, + raw_pwrite_stream &out, + raw_pwrite_stream *, + CodeGenFileType fileType, + bool disableVerify, + MachineModuleInfo *MMI) { if (fileType != TargetMachine::CGFT_AssemblyFile) { return true; } @@ -1057,10 +1062,10 @@ namespace { Target decompilerTarget; -std::unique_ptr getOutputStream() { +std::unique_ptr getOutputStream() { // Open the file. std::error_code ec; - auto out = std::make_unique(OutputFilename, ec, sys::fs::F_None); + auto out = std::make_unique(OutputFilename, ec, sys::fs::F_None); if (ec) { errs() << ec.message() << '\n'; return {}; @@ -1108,14 +1113,14 @@ int compileModule(char **argv, LLVMContext &context) { raw_pwrite_stream &os(out->os()); bool disableVerify = false; - AnalysisID startBefore = nullptr; - AnalysisID startAfter = nullptr; - AnalysisID stopAfter = nullptr; - MachineFunctionInitializer *mfInitializer = nullptr; // Ask the target to add back-end passes as necessary. - if (target->addPassesToEmitFile(pm, os, TargetMachine::CodeGenFileType(), - disableVerify, startBefore, startAfter, stopAfter, mfInitializer)) { + if (target->addPassesToEmitFile( + pm, + os, + nullptr, + TargetMachine::CodeGenFileType(), + disableVerify)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; diff --git a/src/loader/loader/coff/coff_image.cpp b/src/loader/loader/coff/coff_image.cpp index 4b31da4d0..88e6877a3 100644 --- a/src/loader/loader/coff/coff_image.cpp +++ b/src/loader/loader/coff/coff_image.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include "retdec/fileformat/fileformat.h" #include "retdec/loader/loader/coff/coff_image.h" #include "retdec/loader/utils/range.h" diff --git a/src/macho-extractor/break_fat.cpp b/src/macho-extractor/break_fat.cpp index 7223f24aa..e6dcc66e1 100644 --- a/src/macho-extractor/break_fat.cpp +++ b/src/macho-extractor/break_fat.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -74,7 +73,7 @@ std::string cpuTypeToString( std::string getArchName( MachOUniversalBinary::object_iterator &it) { - std::string result = it->getArchTypeName(); + std::string result = it->getArchFlagName(); if(result.empty()) { result = cpuTypeToString(it->getCPUType()); diff --git a/src/utils/memory.cpp b/src/utils/memory.cpp index 464c96e49..e90ae53b1 100644 --- a/src/utils/memory.cpp +++ b/src/utils/memory.cpp @@ -117,7 +117,7 @@ std::size_t getTotalSystemMemoryOnMacOS() { bool limitSystemMemoryOnMacOS(std::size_t limit) { // Warning: We have found that limitSystemMemoryOnPOSIX() does not actually // do anything on macOS. We need to find another way. See - // https://github.com/avast-tl/retdec/issues/379 + // https://github.com/avast/retdec/issues/379 return limitSystemMemoryOnPOSIX(limit); } diff --git a/src/utils/string.cpp b/src/utils/string.cpp index d4278bc7b..5b8bb4130 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -447,6 +447,53 @@ std::string unicodeToAscii(const std::uint8_t *bytes, std::size_t nBytes) return result.str(); } +/** +* @brief Converts unicode @a bytes to ASCII string. +* +* @param[in] bytes Bytes for conversion. +* @param[in] nBytes Number of bytes. +* @param[in] nRead Number of bytes read. Note that this doesn't have to be the length of returned string +* +* @return Converted string in ASCII. +*/ +std::string unicodeToAscii(const std::uint8_t *bytes, std::size_t nBytes, std::size_t &nRead) +{ + std::stringstream result; + if (!bytes || !nBytes) + { + return {}; + } + if (nBytes & 1) + { + nBytes--; + } + + std::size_t i; + for (i = 0; i < nBytes; i += 2) + { + if (bytes[i] == 0 && bytes[i + 1] == 0) + { + i += 2; + break; + } + if (bytes[i + 1] == 0 && isPrintableChar(bytes[i])) + { + result << bytes[i]; + } + else + { + const std::size_t maxC = (1 << (sizeof(std::string::value_type) * CHAR_BIT)) - 1; + const auto val1 = numToStr(bytes[i] & maxC, std::hex); + const auto val2 = numToStr(bytes[i + 1] & maxC, std::hex); + result << "\\x" << std::setw(2) << std::setfill('0') << val1; + result << "\\x" << std::setw(2) << std::setfill('0') << val2; + } + } + + nRead = i; + return result.str(); +} + /** * @brief Read up to @a maxBytes bytes as ASCII string. * diff --git a/support/CMakeLists.txt b/support/CMakeLists.txt index 5d4bbf7ff..dcde2e7b1 100644 --- a/support/CMakeLists.txt +++ b/support/CMakeLists.txt @@ -17,7 +17,7 @@ endif() # Get and install external support package from the retdec-support repository. # This step may erase the entire target support directory, so it needs to go -# first. +# first. # install(CODE " execute_process( diff --git a/support/install-share.py b/support/install-share.py index 25091854e..f4f0ab1c8 100755 --- a/support/install-share.py +++ b/support/install-share.py @@ -58,7 +58,7 @@ def main(): os.makedirs(support_dir, exist_ok=True) # Download archive - arch_url = 'https://github.com/avast-tl/retdec-support/releases/download/%s/%s' % (version, arch_name) + arch_url = 'https://github.com/avast/retdec-support/releases/download/%s/%s' % (version, arch_name) print('Downloading archive from %s ...' % arch_url) try: urllib.request.urlretrieve(arch_url, arch_path) diff --git a/support/install-yara.py b/support/install-yara.py old mode 100644 new mode 100755 index 07b147262..1c031dcde --- a/support/install-yara.py +++ b/support/install-yara.py @@ -9,11 +9,13 @@ """ import fnmatch -import pathlib +import multiprocessing.pool import os +import pathlib import shutil import subprocess import sys +import threading def print_help(): @@ -59,7 +61,25 @@ def copy_yara_patterns(yara_patterns_dir, install_dir): shutil.copy(input, output) -def compile_yara(yarac, install_dir): +def compile_yara_file(input_file, yarac, install_dir, stdout_lock): + """ Compile the given .yara file in the given installation directory using + the provided YARAC program into a *.yarac file. + Remove the source *.yara file. + """ + with stdout_lock: + print('-- Compiling:', input_file) + + output_file = str(pathlib.Path(input_file).with_suffix('.yarac')) + cmd = [yarac, '-w', input_file, output_file] + ret = subprocess.call(cmd) + if ret != 0: + print('Error: yarac failed during compilation of file', input_file, file=sys.stderr) + sys.exit(1) + + os.remove(input_file) + + +def compile_yara_files(yarac, install_dir): """ Compile all *.yara files in the given installation directory using the provided YARAC program into *.yarac files. Remove the source *.yara files. @@ -69,18 +89,15 @@ def compile_yara(yarac, install_dir): for filename in fnmatch.filter(filenames, '*.yara'): inputs.append(os.path.join(root, filename)) - for i in inputs: - fn = pathlib.Path(i) - o = fn.with_suffix('.yarac') - - print('-- Compiling:', i) - cmd = [yarac, '-w'] + [i] + [str(o)] - ret = subprocess.call(cmd) - if ret != 0: - print('Error: yarac failed during compilation of file ', path) - exit(1) + if not inputs: + return - os.remove(i) + stdout_lock = threading.Lock() + with multiprocessing.pool.ThreadPool() as pool: + args = [ + (input_file, yarac, install_dir, stdout_lock) for input_file in inputs + ] + pool.starmap(compile_yara_file, args) def main(): @@ -88,7 +105,7 @@ def main(): copy_yara_patterns(yara_patterns_dir, install_dir) if compile: - compile_yara(yarac, install_dir) + compile_yara_files(yarac, install_dir) sys.exit(0) diff --git a/tests/bin2llvmir/analyses/uses_analysis_tests.cpp b/tests/bin2llvmir/analyses/uses_analysis_tests.cpp index 2a5d1d450..eafae23f4 100644 --- a/tests/bin2llvmir/analyses/uses_analysis_tests.cpp +++ b/tests/bin2llvmir/analyses/uses_analysis_tests.cpp @@ -31,7 +31,7 @@ class UsesAnalysisTests: public Test { UsesAnalysisTests() { module = new Module("test", context); Constant *funcConstant(module->getOrInsertFunction("func1", - Type::getVoidTy(context), AttributeSet(), nullptr)); + Type::getVoidTy(context))); Constant *globConstant(module->getOrInsertGlobal("glob0", Type::getInt32Ty(context))); glob = cast(globConstant); @@ -215,8 +215,7 @@ hasUseOnlyInOneFuncTest) { // // Creating the main part of test is in constructor of this test class. - module->getOrInsertFunction("func2", Type::getVoidTy(context), - AttributeSet(), nullptr); + module->getOrInsertFunction("func2", Type::getVoidTy(context)); new LoadInst(glob, "x", bbInFunc1); EXPECT_TRUE(UsesAnalysis::hasUsesOnlyInOneFunc(*glob)) << @@ -241,7 +240,7 @@ hasNoUseOnlyInOneFuncTest) { // Creating the main part of test is in constructor of this test class. Constant *func2Constant(module->getOrInsertFunction( - "func2", Type::getVoidTy(context), AttributeSet(), nullptr)); + "func2", Type::getVoidTy(context))); BasicBlock *bbInFunc2(BasicBlock::Create(context, "bbFunc2", cast(func2Constant))); new LoadInst(glob, "x", bbInFunc1); diff --git a/tests/bin2llvmir/optimizations/phi2seq/phi2seq_tests.cpp b/tests/bin2llvmir/optimizations/phi2seq/phi2seq_tests.cpp index 861aec917..df5c4708a 100644 --- a/tests/bin2llvmir/optimizations/phi2seq/phi2seq_tests.cpp +++ b/tests/bin2llvmir/optimizations/phi2seq/phi2seq_tests.cpp @@ -32,7 +32,7 @@ class PHI2SeqTests: public LlvmIrTests TEST_F(PHI2SeqTests, OptimizerHasNonEmptyID) { - EXPECT_TRUE(pass.getPassName()) << + EXPECT_FALSE(pass.getPassName().empty()) << "the optimizer should have a non-empty ID"; } diff --git a/tests/bin2llvmir/providers/asm_instruction_tests.cpp b/tests/bin2llvmir/providers/asm_instruction_tests.cpp index a67a6c369..bbedd85d6 100644 --- a/tests/bin2llvmir/providers/asm_instruction_tests.cpp +++ b/tests/bin2llvmir/providers/asm_instruction_tests.cpp @@ -1020,7 +1020,7 @@ TEST_F(AsmInstructionTests, backForValidNonEmptyReturnsLastInstruction) TEST_F(AsmInstructionTests, insertBackForInvalidDoesNotInsert) { auto a = AsmInstruction(); - auto* i = new AllocaInst(Type::getInt32Ty(module->getContext())); + auto* i = new AllocaInst(Type::getInt32Ty(module->getContext()), 0); ASSERT_TRUE(a.isInvalid()); ASSERT_NE(nullptr, i); @@ -1050,7 +1050,7 @@ TEST_F(AsmInstructionTests, insertBackForValidComplexAsmInstruction) auto* mapGv = getGlobalByName("llvm2asm"); AsmInstruction::setLlvmToAsmGlobalVariable(module.get(), mapGv); auto a = AsmInstruction(module.get(), 1234); - auto* i = new AllocaInst(Type::getInt32Ty(module->getContext()), "test"); + auto* i = new AllocaInst(Type::getInt32Ty(module->getContext()), 0, "test"); a.insertBack(i); @@ -1076,7 +1076,7 @@ TEST_F(AsmInstructionTests, insertBackForValidComplexAsmInstruction) TEST_F(AsmInstructionTests, insertBackSafeForInvalidDoesNotInsert) { auto a = AsmInstruction(); - auto* i = new AllocaInst(Type::getInt32Ty(module->getContext())); + auto* i = new AllocaInst(Type::getInt32Ty(module->getContext()), 0); ASSERT_TRUE(a.isInvalid()); ASSERT_NE(nullptr, i); @@ -1106,7 +1106,7 @@ TEST_F(AsmInstructionTests, insertBackSafeForValidComplexAsmInstruction) auto* mapGv = getGlobalByName("llvm2asm"); AsmInstruction::setLlvmToAsmGlobalVariable(module.get(), mapGv); auto a = AsmInstruction(module.get(), 1234); - auto* i = new AllocaInst(Type::getInt32Ty(module->getContext()), "test"); + auto* i = new AllocaInst(Type::getInt32Ty(module->getContext()), 0, "test"); a.insertBackSafe(i); @@ -1137,7 +1137,7 @@ TEST_F(AsmInstructionTests, insertBackSafeForTerminatorAsmInstruction) auto* mapGv = getGlobalByName("llvm2asm"); AsmInstruction::setLlvmToAsmGlobalVariable(module.get(), mapGv); auto a = AsmInstruction(module.get(), 1234); - auto* i = new AllocaInst(Type::getInt32Ty(module->getContext()), "test"); + auto* i = new AllocaInst(Type::getInt32Ty(module->getContext()), 0, "test"); a.insertBackSafe(i); diff --git a/tests/bin2llvmir/utils/instcombine_tests.cpp b/tests/bin2llvmir/utils/instcombine_tests.cpp index 5a99a10a4..d4d1b57db 100644 --- a/tests/bin2llvmir/utils/instcombine_tests.cpp +++ b/tests/bin2llvmir/utils/instcombine_tests.cpp @@ -10,6 +10,7 @@ #include +#include "retdec/bin2llvmir/optimizations/inst_opt/inst_opt_pass.h" #include "retdec/bin2llvmir/optimizations/unreachable_funcs/unreachable_funcs.h" #include "bin2llvmir/utils/llvmir_tests.h" @@ -29,6 +30,8 @@ class InstCombinePassTests: public LlvmIrTests void runOnModule() { LlvmIrTests::runOnModule(); + // This pass counters some undesirable LLVM optimizations. + LlvmIrTests::runOnModule(); } }; @@ -230,6 +233,94 @@ TEST_F(InstCombinePassTests, unreachableBasicBlocksRemove) checkModuleAgainstExpectedIr(exp); } +TEST_F(InstCombinePassTests, undesirableStoreOptimizatonIsNotPerformed) +{ + parseInput(R"( + @g = global i32 0 + + declare double @func() + + define i32 @main(i32 %argc, i8** %argv) { + %func_res = call double @func() + %1 = fptrunc double %func_res to float + %2 = bitcast float %1 to i32 + store i32 %2, i32* @g + ret i32 0 + } + )"); + + runOnModule(); + + std::string exp = R"( + @g = global i32 0 + + declare double @func() + + define i32 @main(i32 %argc, i8** %argv) { + %func_res = call double @func() + %1 = fptrunc double %func_res to float + %2 = bitcast float %1 to i32 + store i32 %2, i32* @g + ret i32 0 + } + )"; + checkModuleAgainstExpectedIr(exp); +} + +TEST_F(InstCombinePassTests, undesirableLoadOptimizatonIsNotPerformed_1) +{ + parseInput(R"( + @g = global i32 0 + + define float @func() { + %1 = load i32, i32* @g, align 4 + %2 = bitcast i32 %1 to float + ret float %2 + } + )"); + + runOnModule(); + + std::string exp = R"( + @g = global i32 0 + + define float @func() { + %1 = load i32, i32* @g, align 4 + %2 = bitcast i32 %1 to float + ret float %2 + } + )"; + checkModuleAgainstExpectedIr(exp); +} + +TEST_F(InstCombinePassTests, undesirableLoadOptimizatonIsNotPerformed_2) +{ + parseInput(R"( + @g = global i32 0 + + define i8 @func() { + %1 = load i32, i32* @g, align 4 + %2 = inttoptr i32 %1 to i8* + %3 = load i8, i8* %2, align 1 + ret i8 %3 + } + )"); + + runOnModule(); + + std::string exp = R"( + @g = global i32 0 + + define i8 @func() { + %1 = load i32, i32* @g, align 4 + %2 = inttoptr i32 %1 to i8* + %3 = load i8, i8* %2, align 1 + ret i8 %3 + } + )"; + checkModuleAgainstExpectedIr(exp); +} + } // namespace tests } // namespace bin2llvmir } // namespace retdec diff --git a/tests/bin2llvmir/utils/llvmir_tests.h b/tests/bin2llvmir/utils/llvmir_tests.h index 00fce3a33..535f6d770 100644 --- a/tests/bin2llvmir/utils/llvmir_tests.h +++ b/tests/bin2llvmir/utils/llvmir_tests.h @@ -7,6 +7,8 @@ #ifndef TESTS_BIN2LLVMIR_UTILS_LLVMIR_TESTS_H #define TESTS_BIN2LLVMIR_UTILS_LLVMIR_TESTS_H +#include + #include #include #include @@ -116,13 +118,29 @@ class LlvmIrTests : public ::testing::Test module = _parseInput(code, context); } + /** + * Remove alignment of LLVM IR's load/store instructions. + */ + std::string removeAlignment(const std::string& code) + { + std::regex e(", align [0-9]+"); + return std::regex_replace(code, e, "");; + } + /** * Check if the IR string from @c actual LLVM module is the same * as @c expected * LLVM IR string. * @param expected LLVM IR string. + * @param removeComments Should the comments be removed before + * comparison? + * @param removeAlign Should the load/store alignment be removed before + * comparison? */ - void checkModuleAgainstExpectedIr(std::string& expected) + void checkModuleAgainstExpectedIr( + std::string& expected, + bool removeComments = true, + bool removeAlign = true) { llvm::LLVMContext expectedContext; auto expectedModule = _parseInput(expected, expectedContext); @@ -135,8 +153,17 @@ class LlvmIrTests : public ::testing::Test ASSERT_FALSE(verifyModule(*module)) << "actual module is not valid:\n" << actualStr; - expectedStr = retdec::utils::removeComments(expectedStr, ';'); - actualStr = retdec::utils::removeComments(actualStr, ';'); + if (removeComments) + { + expectedStr = retdec::utils::removeComments(expectedStr, ';'); + actualStr = retdec::utils::removeComments(actualStr, ';'); + } + + if (removeAlign) + { + expectedStr = removeAlignment(expectedStr); + actualStr = removeAlignment(actualStr); + } EXPECT_TRUE( retdec::utils::removeWhitespace(expectedStr) == diff --git a/tests/llvmir2hll/evaluator/arithm_expr_evaluators/c_arithm_expr_evaluator_tests.cpp b/tests/llvmir2hll/evaluator/arithm_expr_evaluators/c_arithm_expr_evaluator_tests.cpp index ad42758fb..5a2375d51 100644 --- a/tests/llvmir2hll/evaluator/arithm_expr_evaluators/c_arithm_expr_evaluator_tests.cpp +++ b/tests/llvmir2hll/evaluator/arithm_expr_evaluators/c_arithm_expr_evaluator_tests.cpp @@ -832,11 +832,11 @@ TEST_F(CArithmExprEvaluatorTests, SimpleAddDiffAPFloatSemanticsTest) { SCOPED_TRACE("2.0(IEEEhalf) + 4.0(IEEEdouble) -> 6.0(IEEEdouble)"); ShPtr inputExpr(AddOpExpr::create( - ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEhalf, "2.0")), - ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEdouble, "4.0")) + ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEhalf(), "2.0")), + ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEdouble(), "4.0")) )); ShPtr refResult(ConstFloat::create(llvm::APFloat( - llvm::APFloat::IEEEdouble, "6.0"))); + llvm::APFloat::IEEEdouble(), "6.0"))); evaluateAndCheckResult(inputExpr, refResult); } diff --git a/tests/llvmir2hll/hll/hll_writers/c_hll_writer_tests.cpp b/tests/llvmir2hll/hll/hll_writers/c_hll_writer_tests.cpp index 4bba2efe0..3ae140d7e 100644 --- a/tests/llvmir2hll/hll/hll_writers/c_hll_writer_tests.cpp +++ b/tests/llvmir2hll/hll/hll_writers/c_hll_writer_tests.cpp @@ -64,7 +64,7 @@ FloatLiteralIsEmittedWithCorrectSuffix) { // module->addGlobalVar( Variable::create("g", FloatType::create(32)), - ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEsingle, "0.0")) + ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEsingle(), "0.0")) ); auto code = emitCodeForCurrentModule(); @@ -79,7 +79,7 @@ DoubleLiteralIsEmittedWithoutSuffix) { // module->addGlobalVar( Variable::create("g", FloatType::create(64)), - ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEdouble, "0.0")) + ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEdouble(), "0.0")) ); auto code = emitCodeForCurrentModule(); @@ -94,7 +94,7 @@ LongDoubleLiteralIsEmittedWithCorrectSuffix) { // module->addGlobalVar( Variable::create("g", FloatType::create(80)), - ConstFloat::create(llvm::APFloat(llvm::APFloat::x87DoubleExtended, "0.0")) + ConstFloat::create(llvm::APFloat(llvm::APFloat::x87DoubleExtended(), "0.0")) ); auto code = emitCodeForCurrentModule(); diff --git a/tests/llvmir2hll/ir/const_float_tests.cpp b/tests/llvmir2hll/ir/const_float_tests.cpp index 4e2ab7e09..d3b5ace7c 100644 --- a/tests/llvmir2hll/ir/const_float_tests.cpp +++ b/tests/llvmir2hll/ir/const_float_tests.cpp @@ -47,19 +47,19 @@ CreateGetValueTestNegativeValue) { TEST_F(ConstFloatTests, GetSizeReturnsCorrectSizeOfUnderlyingTypeForFloatConstant) { - auto f = ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEsingle, "0.0")); + auto f = ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEsingle(), "0.0")); EXPECT_EQ(32, f->getSize()); } TEST_F(ConstFloatTests, GetSizeReturnsCorrectSizeOfUnderlyingTypeForDoubleConstant) { - auto f = ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEdouble, "0.0")); + auto f = ConstFloat::create(llvm::APFloat(llvm::APFloat::IEEEdouble(), "0.0")); EXPECT_EQ(64, f->getSize()); } TEST_F(ConstFloatTests, GetSizeReturnsCorrectSizeOfUnderlyingTypeForLongDoubleConstant) { - auto f = ConstFloat::create(llvm::APFloat(llvm::APFloat::x87DoubleExtended, "0.0")); + auto f = ConstFloat::create(llvm::APFloat(llvm::APFloat::x87DoubleExtended(), "0.0")); EXPECT_EQ(80, f->getSize()); } diff --git a/tests/llvmir2hll/llvm/llvmir2bir_converter/llvm_value_converter_tests/llvm_constant_converter_tests.cpp b/tests/llvmir2hll/llvm/llvmir2bir_converter/llvm_value_converter_tests/llvm_constant_converter_tests.cpp index f2caf91be..b574469e6 100644 --- a/tests/llvmir2hll/llvm/llvmir2bir_converter/llvm_value_converter_tests/llvm_constant_converter_tests.cpp +++ b/tests/llvmir2hll/llvm/llvmir2bir_converter/llvm_value_converter_tests/llvm_constant_converter_tests.cpp @@ -27,7 +27,7 @@ class LLVMConstantConverterTests: public TestsWithLLVMValueConverter {}; TEST_F(LLVMConstantConverterTests, NonZeroHalfConstantIsConvertedCorrectly) { - auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::IEEEhalf, "3.1415"); + auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::IEEEhalf(), "3.1415"); auto llvmConstant = llvm::ConstantFP::get(context, llvmAPFloatValue); auto birConstant = converter->convertConstantToExpression(llvmConstant); @@ -39,7 +39,7 @@ NonZeroHalfConstantIsConvertedCorrectly) { TEST_F(LLVMConstantConverterTests, NonZeroFloatConstantIsConvertedCorrectly) { - auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::IEEEsingle, "3.1415"); + auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::IEEEsingle(), "3.1415"); auto llvmConstant = llvm::ConstantFP::get(context, llvmAPFloatValue); auto birConstant = converter->convertConstantToExpression(llvmConstant); @@ -51,7 +51,7 @@ NonZeroFloatConstantIsConvertedCorrectly) { TEST_F(LLVMConstantConverterTests, NonZeroDoubleConstantIsConvertedCorrectly) { - auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::IEEEdouble, "3.1415"); + auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::IEEEdouble(), "3.1415"); auto llvmConstant = llvm::ConstantFP::get(context, llvmAPFloatValue); auto birConstant = converter->convertConstantToExpression(llvmConstant); @@ -63,7 +63,7 @@ NonZeroDoubleConstantIsConvertedCorrectly) { TEST_F(LLVMConstantConverterTests, NonZeroX86_FP80ConstantIsConvertedCorrectly) { - auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::x87DoubleExtended, "3.1415"); + auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), "3.1415"); auto llvmConstant = llvm::ConstantFP::get(context, llvmAPFloatValue); auto birConstant = converter->convertConstantToExpression(llvmConstant); @@ -75,7 +75,7 @@ NonZeroX86_FP80ConstantIsConvertedCorrectly) { TEST_F(LLVMConstantConverterTests, NonZeroFP128ConstantIsConvertedCorrectly) { - auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::IEEEquad, "3.1415"); + auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::IEEEquad(), "3.1415"); auto llvmConstant = llvm::ConstantFP::get(context, llvmAPFloatValue); auto birConstant = converter->convertConstantToExpression(llvmConstant); @@ -87,7 +87,7 @@ NonZeroFP128ConstantIsConvertedCorrectly) { TEST_F(LLVMConstantConverterTests, NonZeroPPC_FP128ConstantIsConvertedCorrectly) { - auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::PPCDoubleDouble, "3.1415"); + auto llvmAPFloatValue = llvm::APFloat(llvm::APFloat::PPCDoubleDouble(), "3.1415"); auto llvmConstant = llvm::ConstantFP::get(context, llvmAPFloatValue); auto birConstant = converter->convertConstantToExpression(llvmConstant);