diff --git a/deps/pelib/CMakeLists.txt b/deps/pelib/CMakeLists.txt
index 39ff2ed47..a8bf5b4d6 100644
--- a/deps/pelib/CMakeLists.txt
+++ b/deps/pelib/CMakeLists.txt
@@ -8,8 +8,8 @@ if(CMAKE_CXX_COMPILER)
 endif()
 
 ExternalProject_Add(pelib-project
-	URL https://github.com/avast-tl/pelib/archive/e93eaa7c150f4608a5d02a67f5edc9e54456fe24.zip
-	URL_HASH SHA256=2ffd7e89451c980a1af6d24d4f6dfbb69a660b06ad5de44c481f6431e21de394
+	URL https://github.com/avast-tl/pelib/archive/9ccd3943c1a0917ffdaff5ab983fa7cdbb6dc5a2.zip
+	URL_HASH SHA256=a502c9023a52b3f248b331ce3a12a04c1b668a1d077dc69e03ea86aa9b0543df
 	DOWNLOAD_NAME pelib.zip
 	CMAKE_ARGS
 		# This does not work on MSVC, but may be useful on Linux.
diff --git a/include/retdec/fileformat/file_format/file_format.h b/include/retdec/fileformat/file_format/file_format.h
index bbd629307..7b4259a44 100644
--- a/include/retdec/fileformat/file_format/file_format.h
+++ b/include/retdec/fileformat/file_format/file_format.h
@@ -21,6 +21,20 @@
 namespace retdec {
 namespace fileformat {
 
+/**
+* LoaderErrorInfo - common structure that contains loader error code, error message and user-friendly error message
+*/
+
+struct LoaderErrorInfo
+{
+	LoaderErrorInfo() : loaderErrorCode(0), loaderError(nullptr), loaderErrorUserFriendly(nullptr)
+	{}
+
+	std::uint32_t loaderErrorCode;               // Loader error code, cast to uint32_t
+	const char * loaderError;
+	const char * loaderErrorUserFriendly;
+};
+
 /**
  * FileFormat - abstract class for parsing files
  */
@@ -67,10 +81,11 @@ class FileFormat : public retdec::utils::ByteValueStorage, private retdec::utils
 		PdbInfo *pdbInfo;                                                 ///< information about related PDB debug file
 		CertificateTable *certificateTable;                               ///< table of certificates
 		Format fileFormat;                                                ///< format of input file
+		LoaderErrorInfo _ldrErrInfo;                                      ///< loader error (e.g. Windows loader error for PE files)
 		bool stateIsValid;                                                ///< internal state of instance
 		std::vector<std::pair<std::size_t, std::size_t>> secHashInfo;     ///< information for calculation of section table hash
-		retdec::utils::Maybe<bool> signatureVerified;                    ///< indicates whether the signature is present and also verified
-		retdec::utils::RangeContainer<std::uint64_t> nonDecodableRanges; ///< Address ranges which should not be decoded for instructions.
+		retdec::utils::Maybe<bool> signatureVerified;                     ///< indicates whether the signature is present and also verified
+		retdec::utils::RangeContainer<std::uint64_t> nonDecodableRanges;  ///< Address ranges which should not be decoded for instructions.
 
 		/// @name Clear methods
 		/// @{
@@ -128,7 +143,9 @@ class FileFormat : public retdec::utils::ByteValueStorage, private retdec::utils
 		virtual std::size_t getByteLength() const override;
 		virtual std::size_t getWordLength() const override;
 		virtual std::size_t getNumberOfNibblesInByte() const override;
+
 		/// @}
+		const LoaderErrorInfo & getLoaderErrorInfo() const;
 
 		/// @name Detection methods
 		/// @{
diff --git a/include/retdec/fileformat/file_format/pe/pe_format.h b/include/retdec/fileformat/file_format/pe/pe_format.h
index 2e60ed8f8..cd11a5f50 100644
--- a/include/retdec/fileformat/file_format/pe/pe_format.h
+++ b/include/retdec/fileformat/file_format/pe/pe_format.h
@@ -44,6 +44,7 @@ class PeFormat : public FileFormat
 
 		/// @name Initialization methods
 		/// @{
+		void initLoaderErrorInfo();
 		void initStructures();
 		/// @}
 
@@ -147,6 +148,7 @@ class PeFormat : public FileFormat
 		std::size_t getSizeOfHeapCommit() const;
 		std::size_t getNumberOfDataDirectories() const;
 		std::size_t getDeclaredNumberOfDataDirectories() const;
+
 		int getPeClass() const;
 		bool isDotNet() const;
 		bool isPackedDotNet() const;
diff --git a/include/retdec/fileformat/file_format/pe/pe_template.h b/include/retdec/fileformat/file_format/pe/pe_template.h
index 77137ee04..4c35a65bb 100644
--- a/include/retdec/fileformat/file_format/pe/pe_template.h
+++ b/include/retdec/fileformat/file_format/pe/pe_template.h
@@ -579,7 +579,7 @@ template<int bits> bool peDelayImport(const PeLib::PeHeaderT<bits> &peHeader,
 	import.setAddress(peImageBase(peHeader) + function->address.Value);
 	import.setLibraryIndex(fileIndex);
 	import.invalidateOrdinalNumber();
-	if(library->ordinalNumbersAreValid())
+	if(library->ordinalNumbersAreValid() && function->hint != 0)
 	{
 		import.setOrdinalNumber(function->hint);
 	}
diff --git a/include/retdec/loader/loader/image.h b/include/retdec/loader/loader/image.h
index bea68e453..7136c4dad 100644
--- a/include/retdec/loader/loader/image.h
+++ b/include/retdec/loader/loader/image.h
@@ -74,6 +74,7 @@ class Image : public retdec::utils::ByteValueStorage
 	std::pair<const std::uint8_t*, std::uint64_t> getRawSegmentData(std::uint64_t address) const;
 
 	const std::string& getStatusMessage() const;
+	const retdec::fileformat::LoaderErrorInfo & getLoaderErrorInfo() const;
 
 protected:
 	Segment* insertSegment(std::unique_ptr<Segment> segment);
diff --git a/include/retdec/utils/conversion.h b/include/retdec/utils/conversion.h
index 7c3d14a5e..95fe70f39 100644
--- a/include/retdec/utils/conversion.h
+++ b/include/retdec/utils/conversion.h
@@ -205,16 +205,24 @@ template<typename N> void bytesToHexString(const N *data, std::size_t dataSize,
 		size = (size == 0 || offset + size > dataSize) ? dataSize - offset : size;
 	}
 
-	result.clear();
-	result.reserve(size * 2);
-	std::ostringstream oStr;
-
-	for(std::size_t i = 0; i < size; ++i)
+	// Sample: 4A2A008CF1AEE9BA49D8D1DAA22D8E868365ACE633823D464478239F27ED4F18
+	// Tool: redec-fileinfo.exe, Debug, x64, data = image, dataSize = 0xE1BC00
+	// Optimized: This code now takes 0.106 seconds to convert (measured in VS 2015 IDE)
+	// (down from about 40 seconds)
+	const char * intToHex = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
+	std::size_t hexIndex = 0;
+
+	// Reserve the necessary space for the hexa string
+	result.resize(size * 2);
+
+	// Convert to hexa byte-by-byte. No reallocations
+	for (std::size_t i = 0; i < size; ++i, hexIndex += 2)
 	{
-		byteToHexString(oStr, data[offset + i], uppercase);
-	}
+		std::uint8_t oneByte = data[offset + i];
 
-	result = oStr.str();
+		result[hexIndex + 0] = intToHex[(oneByte >> 0x04) & 0x0F];
+		result[hexIndex + 1] = intToHex[(oneByte >> 0x00) & 0x0F];
+	}
 }
 
 /**
diff --git a/src/fileformat/file_format/file_format.cpp b/src/fileformat/file_format/file_format.cpp
index 329d4cdcc..97b3923c5 100644
--- a/src/fileformat/file_format/file_format.cpp
+++ b/src/fileformat/file_format/file_format.cpp
@@ -117,7 +117,7 @@ bool isAddressFromRegion(const SecSeg *actualRegion, const SecSeg *newRegion, st
  * @param loadFlags Load flags
  */
 FileFormat::FileFormat(std::istream &inputStream, LoadFlags loadFlags) : loadedBytes(&bytes),
-	loadFlags(loadFlags), fileStream(inputStream)
+	loadFlags(loadFlags), fileStream(inputStream), _ldrErrInfo()
 {
 	stateIsValid = !inputStream.fail();
 	init();
@@ -129,7 +129,7 @@ FileFormat::FileFormat(std::istream &inputStream, LoadFlags loadFlags) : loadedB
  * @param loadFlags Load flags
  */
 FileFormat::FileFormat(std::string pathToFile, LoadFlags loadFlags) : loadedBytes(&bytes),
-	loadFlags(loadFlags), filePath(pathToFile), fileStream(auxStream)
+	loadFlags(loadFlags), filePath(pathToFile), fileStream(auxStream), _ldrErrInfo()
 {
 	auxStream.open(filePath, std::ifstream::binary);
 	stateIsValid = auxStream.is_open();
@@ -700,6 +700,15 @@ std::size_t FileFormat::getNumberOfNibblesInByte() const
 	return !getNibbleLength() ? 0 : !(getByteLength() % getNibbleLength()) ? getByteLength() / getNibbleLength() : 0;
 }
 
+/**
+* Get reference to the loader error info
+* @return The LoaderErrorInfo structire
+*/
+const LoaderErrorInfo & FileFormat::getLoaderErrorInfo() const
+{
+	return _ldrErrInfo;
+}
+
 /**
  * Find out if target architecture is x86
  * @return @c true if target architecture is x86, @c false otherwise
diff --git a/src/fileformat/file_format/pe/pe_format.cpp b/src/fileformat/file_format/pe/pe_format.cpp
index 8f1032d99..e581a6e2d 100644
--- a/src/fileformat/file_format/pe/pe_format.cpp
+++ b/src/fileformat/file_format/pe/pe_format.cpp
@@ -305,6 +305,18 @@ PeFormat::~PeFormat()
 	delete formatParser;
 }
 
+/**
+* Init information from PE loader
+*/
+void PeFormat::initLoaderErrorInfo()
+{
+	PeLib::LoaderError ldrError = file->loaderError();
+
+	_ldrErrInfo.loaderErrorCode = static_cast<std::uint32_t>(ldrError);
+	_ldrErrInfo.loaderError = getLoaderErrorString(ldrError, false);
+	_ldrErrInfo.loaderErrorUserFriendly = getLoaderErrorString(ldrError, true);
+}
+
 /**
  * Init internal structures
  */
@@ -332,6 +344,10 @@ void PeFormat::initStructures()
 			file->readResourceDirectory();
 			file->readSecurityDirectory();
 			file->readComHeaderDirectory();
+
+			// Fill-in the loader error info from PE file
+			initLoaderErrorInfo();
+
 			mzHeader = file->mzHeader();
 			switch((peClass = getFileType(filePath)))
 			{
diff --git a/src/fileinfo/file_detector/file_detector.cpp b/src/fileinfo/file_detector/file_detector.cpp
index e7f21b13f..2e59feded 100644
--- a/src/fileinfo/file_detector/file_detector.cpp
+++ b/src/fileinfo/file_detector/file_detector.cpp
@@ -245,8 +245,16 @@ void FileDetector::getCertificates()
 /**
  * Get loader information
  */
+
 void FileDetector::getLoaderInfo()
 {
+	// Propagate loader error no matter if the Image pointer will be created or not
+	auto ldrErrInfo = getFileParser()->getLoaderErrorInfo();
+	if (ldrErrInfo.loaderErrorCode != 0)
+	{
+		fileInfo.setLoaderErrorInfo(ldrErrInfo);
+	}
+
 	std::unique_ptr<retdec::loader::Image> image = retdec::loader::createImage(fileParser);
 	if(!image)
 	{
diff --git a/src/fileinfo/file_information/file_information.cpp b/src/fileinfo/file_information/file_information.cpp
index 3422ff166..fa2749241 100644
--- a/src/fileinfo/file_information/file_information.cpp
+++ b/src/fileinfo/file_information/file_information.cpp
@@ -2716,6 +2716,15 @@ const std::string& FileInformation::getLoaderStatusMessage() const
 	return loaderInfo.getStatusMessage();
 }
 
+/**
+* Gets loader error message.
+* @return The error message of the loader.
+*/
+const retdec::fileformat::LoaderErrorInfo & FileInformation::getLoaderErrorInfo() const
+{
+	return loaderInfo.getLoaderErrorInfo();
+}
+
 /**
  * Checks whether .NET information are used.
  * @return @c true if it is used, otherwise @c false/
@@ -3483,6 +3492,15 @@ void FileInformation::setLoaderStatusMessage(const std::string& statusMessage)
 	loaderInfo.setStatusMessage(statusMessage);
 }
 
+/**
+* Sets loader error message.
+* @param statusMessage The loader error message.
+*/
+void FileInformation::setLoaderErrorInfo(const retdec::fileformat::LoaderErrorInfo & ldrErrInfo)
+{
+	loaderInfo.setLoaderErrorInfo(ldrErrInfo);
+}
+
 /**
  * Sets whether .NET information are used.
  * @param set @c true if used, otherwise @c false.
diff --git a/src/fileinfo/file_information/file_information.h b/src/fileinfo/file_information/file_information.h
index 37566562b..40892bf54 100644
--- a/src/fileinfo/file_information/file_information.h
+++ b/src/fileinfo/file_information/file_information.h
@@ -55,7 +55,7 @@ class FileInformation
 		std::vector<Pattern> malwarePatterns;          ///< detected malware patterns
 		std::vector<Pattern> otherPatterns;            ///< other detected patterns
 		Strings strings;                               ///< detected strings
-		retdec::utils::Maybe<bool> signatureVerified; ///< indicates whether the signature is present and if it is verified
+		retdec::utils::Maybe<bool> signatureVerified;  ///< indicates whether the signature is present and if it is verified
 		DotnetInfo dotnetInfo;                         ///< .NET information
 	public:
 		retdec::cpdetect::ToolInformation toolInfo; ///< detected tools
@@ -400,7 +400,8 @@ class FileInformation
 		std::string getNumberOfLoadedSegmentsStr(std::ios_base &(* format)(std::ios_base &)) const;
 		const LoadedSegment& getLoadedSegment(std::size_t index) const;
 		const std::string& getLoaderStatusMessage() const;
-		/// @}
+		const retdec::fileformat::LoaderErrorInfo & getLoaderErrorInfo() const;
+	    /// @}
 
 		/// @name Getters of @a dotnetInfo
 		/// @{
@@ -492,6 +493,7 @@ class FileInformation
 		void setSignatureVerified(bool verified);
 		void setLoadedBaseAddress(unsigned long long baseAddress);
 		void setLoaderStatusMessage(const std::string& statusMessage);
+		void setLoaderErrorInfo(const retdec::fileformat::LoaderErrorInfo & ldrErrInfo);
 		void setDotnetUsed(bool set);
 		void setDotnetRuntimeVersion(std::uint64_t majorVersion, std::uint64_t minorVersion);
 		void setDotnetMetadataHeaderAddress(std::uint64_t address);
diff --git a/src/fileinfo/file_information/file_information_types/loader_info.cpp b/src/fileinfo/file_information/file_information_types/loader_info.cpp
index db6926992..f00db0b66 100644
--- a/src/fileinfo/file_information/file_information_types/loader_info.cpp
+++ b/src/fileinfo/file_information/file_information_types/loader_info.cpp
@@ -4,6 +4,7 @@
  * @copyright (c) 2017 Avast Software, licensed under the MIT license
  */
 
+#include "retdec/fileformat/file_format/file_format.h"
 #include "fileinfo/file_information/file_information_types/loader_info.h"
 #include "fileinfo/file_information/file_information_types/type_conversions.h"
 
@@ -85,6 +86,11 @@ const std::string& LoaderInfo::getStatusMessage() const
 	return _statusMessage;
 }
 
+const retdec::fileformat::LoaderErrorInfo & LoaderInfo::getLoaderErrorInfo() const
+{
+	return _ldrErrInfo;
+}
+
 void LoaderInfo::setBaseAddress(unsigned long long baseAddress)
 {
 	_baseAddress = baseAddress;
@@ -95,6 +101,11 @@ void LoaderInfo::setStatusMessage(const std::string& statusMessage)
 	_statusMessage = statusMessage;
 }
 
+void LoaderInfo::setLoaderErrorInfo(const retdec::fileformat::LoaderErrorInfo & ldrErrInfo)
+{
+	_ldrErrInfo = ldrErrInfo;
+}
+
 void LoaderInfo::addLoadedSegment(const LoadedSegment& segment)
 {
 	_loadedSegments.push_back(segment);
diff --git a/src/fileinfo/file_information/file_information_types/loader_info.h b/src/fileinfo/file_information/file_information_types/loader_info.h
index 1a7b69d1c..ce4c74de6 100644
--- a/src/fileinfo/file_information/file_information_types/loader_info.h
+++ b/src/fileinfo/file_information/file_information_types/loader_info.h
@@ -37,6 +37,8 @@ class LoaderInfo
 		unsigned long long _baseAddress;
 		std::vector<LoadedSegment> _loadedSegments;
 		std::string _statusMessage;
+		retdec::fileformat::LoaderErrorInfo _ldrErrInfo;
+
 	public:
 		LoaderInfo();
 		~LoaderInfo();
@@ -48,12 +50,14 @@ class LoaderInfo
 		unsigned long long getNumberOfLoadedSegments() const;
 		const LoadedSegment& getLoadedSegment(unsigned long long index) const;
 		const std::string& getStatusMessage() const;
+		const retdec::fileformat::LoaderErrorInfo & getLoaderErrorInfo() const;
 		/// @}
 
 		/// @name Setters
 		/// @{
 		void setBaseAddress(unsigned long long baseAddress);
 		void setStatusMessage(const std::string& statusMessage);
+		void setLoaderErrorInfo(const retdec::fileformat::LoaderErrorInfo & ldrErrInfo);
 		/// @}
 
 		/// @name Other methods
diff --git a/src/fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.cpp b/src/fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.cpp
index 6f04ab462..990fcad3e 100644
--- a/src/fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.cpp
+++ b/src/fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.cpp
@@ -32,6 +32,8 @@ BasicPlainGetter::~BasicPlainGetter()
 
 std::size_t BasicPlainGetter::loadInformation(std::vector<std::string> &desc, std::vector<std::string> &info) const
 {
+	const char * loaderErrorUserFriendly = fileinfo.getLoaderErrorInfo().loaderErrorUserFriendly;
+
 	desc.clear();
 	info.clear();
 
@@ -41,6 +43,11 @@ std::size_t BasicPlainGetter::loadInformation(std::vector<std::string> &desc, st
 	desc.push_back("File format              : ");
 	desc.push_back("File class               : ");
 	desc.push_back("File type                : ");
+
+	// Save the title for loader error (if there was a loader error detected)
+	if(loaderErrorUserFriendly != nullptr)
+		desc.push_back("Loader error             : ");
+
 	desc.push_back("Architecture             : ");
 	desc.push_back("Endianness               : ");
 	desc.push_back("Image base address       : ");
@@ -56,6 +63,11 @@ std::size_t BasicPlainGetter::loadInformation(std::vector<std::string> &desc, st
 	info.push_back(fileinfo.getFileFormat());
 	info.push_back(fileinfo.getFileClass());
 	info.push_back(fileinfo.getFileType());
+
+	// Save the text loader error
+	if(loaderErrorUserFriendly != nullptr)
+		info.push_back(loaderErrorUserFriendly);
+
 	info.push_back(fileinfo.getTargetArchitecture());
 	info.push_back(fileinfo.getEndianness());
 	info.push_back(fileinfo.getImageBaseStr(hexWithPrefix));
diff --git a/src/fileinfo/file_presentation/json_presentation.cpp b/src/fileinfo/file_presentation/json_presentation.cpp
index 758579dce..7b0bc4287 100644
--- a/src/fileinfo/file_presentation/json_presentation.cpp
+++ b/src/fileinfo/file_presentation/json_presentation.cpp
@@ -125,6 +125,26 @@ void JsonPresentation::presentErrors(Json::Value &root) const
 	}
 }
 
+/**
+* Present information about Windows PE loader error
+* @param root Parent node in output document
+*/
+void JsonPresentation::presentLoaderError(Json::Value &root) const
+{
+	auto ldrErrInfo = fileinfo.getLoaderErrorInfo();
+
+	if (ldrErrInfo.loaderErrorCode != 0)
+	{
+		Json::Value loaderErrorNode;
+
+		loaderErrorNode["code"] = ldrErrInfo.loaderErrorCode;
+		loaderErrorNode["code_text"] = ldrErrInfo.loaderError;
+		loaderErrorNode["description"] = ldrErrInfo.loaderErrorUserFriendly;
+
+		root["loaderError"] = loaderErrorNode;
+	}
+}
+
 /**
  * Present information about detected compilers and packers
  * @param root Parent node in output document
@@ -570,6 +590,7 @@ bool JsonPresentation::present()
 	Value root, jEp;
 	root["inputFile"] = fileinfo.getPathToFile();
 	presentErrors(root);
+	presentLoaderError(root);
 	presentSimple(BasicJsonGetter(fileinfo), root);
 	if(presentSimple(EntryPointJsonGetter(fileinfo), jEp))
 	{
diff --git a/src/fileinfo/file_presentation/json_presentation.h b/src/fileinfo/file_presentation/json_presentation.h
index d96d92877..2adb75979 100644
--- a/src/fileinfo/file_presentation/json_presentation.h
+++ b/src/fileinfo/file_presentation/json_presentation.h
@@ -23,6 +23,7 @@ class JsonPresentation : public FilePresentation
 		/// @name Auxiliary presentation methods
 		/// @{
 		void presentErrors(Json::Value &root) const;
+		void presentLoaderError(Json::Value &root) const;
 		void presentCompiler(Json::Value &root) const;
 		void presentLanguages(Json::Value &root) const;
 		void presentRichHeader(Json::Value &root) const;
diff --git a/src/loader/loader/image.cpp b/src/loader/loader/image.cpp
index ef96592e4..f58449fd9 100644
--- a/src/loader/loader/image.cpp
+++ b/src/loader/loader/image.cpp
@@ -424,6 +424,11 @@ void Image::setStatusMessage(const std::string& message)
 	_statusMessage = message;
 }
 
+const retdec::fileformat::LoaderErrorInfo & Image::getLoaderErrorInfo() const
+{
+	return getFileFormat()->getLoaderErrorInfo();
+}
+
 Segment* Image::insertSegment(std::unique_ptr<Segment> segment)
 {
 	_segments.push_back(std::move(segment));