aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src/coff_file_reader.cpp
diff options
context:
space:
mode:
authorRobert Schumacher <roschuma@microsoft.com>2017-02-08 15:12:28 -0800
committerGitHub <noreply@github.com>2017-02-08 15:12:28 -0800
commit7ddae17e2f520e83d25f78c078bf8b8a58fff447 (patch)
tree87e2fc5c57a685367ec051b1efbdeb5d3ab43f4d /toolsrc/src/coff_file_reader.cpp
parent5e588ddb5be9e6e27cebcc3be2e1a27f3ca83a50 (diff)
parenta9f7fc6e90feaad50c1221ef9bd56e2620302215 (diff)
downloadvcpkg-7ddae17e2f520e83d25f78c078bf8b8a58fff447.tar.gz
vcpkg-7ddae17e2f520e83d25f78c078bf8b8a58fff447.zip
Merge branch 'master' into master
Diffstat (limited to 'toolsrc/src/coff_file_reader.cpp')
-rw-r--r--toolsrc/src/coff_file_reader.cpp152
1 files changed, 98 insertions, 54 deletions
diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp
index 593bb18d1..f48f912c1 100644
--- a/toolsrc/src/coff_file_reader.cpp
+++ b/toolsrc/src/coff_file_reader.cpp
@@ -1,14 +1,10 @@
+#include "pch.h"
#include "coff_file_reader.h"
-#include <iostream>
-#include <cstdint>
-#include <algorithm>
#include "vcpkg_Checks.h"
-#include <set>
-#include <fstream>
using namespace std;
-namespace vcpkg {namespace COFFFileReader
+namespace vcpkg::COFFFileReader
{
template <class T>
static T reinterpret_bytes(const char* data)
@@ -34,9 +30,9 @@ namespace vcpkg {namespace COFFFileReader
return data;
}
- static void verify_equal_strings(const char* expected, const char* actual, int size)
+ static void verify_equal_strings(const char* expected, const char* actual, int size, const char* label)
{
- Checks::check_exit(memcmp(expected, actual, size) == 0, "Incorrect string found. Expected: %s but found %s", expected, actual);
+ Checks::check_exit(memcmp(expected, actual, size) == 0, "Incorrect string (%s) found. Expected: (%s) but found (%s)", label, expected, actual);
}
static void read_and_verify_PE_signature(fstream& fs)
@@ -52,17 +48,17 @@ namespace vcpkg {namespace COFFFileReader
fs.seekg(offset_to_PE_signature);
char signature[PE_SIGNATURE_SIZE];
fs.read(signature, PE_SIGNATURE_SIZE);
- verify_equal_strings(PE_SIGNATURE, signature, PE_SIGNATURE_SIZE);
+ verify_equal_strings(PE_SIGNATURE, signature, PE_SIGNATURE_SIZE, "PE_SIGNATURE");
fs.seekg(offset_to_PE_signature + PE_SIGNATURE_SIZE, ios_base::beg);
}
- static fpos_t align_to(const fpos_t unaligned_offset, const int alignment_size)
+ static fpos_t align_to_size(const uint64_t unaligned, const uint64_t alignment_size)
{
- fpos_t aligned_offset = unaligned_offset - 1;
- aligned_offset /= alignment_size;
- aligned_offset += 1;
- aligned_offset *= alignment_size;
- return aligned_offset;
+ fpos_t aligned = unaligned - 1;
+ aligned /= alignment_size;
+ aligned += 1;
+ aligned *= alignment_size;
+ return aligned;
}
struct coff_file_header
@@ -77,14 +73,6 @@ namespace vcpkg {namespace COFFFileReader
return ret;
}
- static coff_file_header peek(fstream& fs)
- {
- auto original_pos = fs.tellg().seekpos();
- coff_file_header ret = read(fs);
- fs.seekg(original_pos);
- return ret;
- }
-
MachineType machineType() const
{
static const size_t MACHINE_TYPE_OFFSET = 0;
@@ -113,8 +101,11 @@ namespace vcpkg {namespace COFFFileReader
ret.data.resize(HEADER_SIZE);
fs.read(&ret.data[0], HEADER_SIZE);
- const std::string header_end = ret.data.substr(HEADER_END_OFFSET, HEADER_END_SIZE);
- verify_equal_strings(HEADER_END, header_end.c_str(), HEADER_END_SIZE);
+ if (ret.data[0] != '\0') // Due to freeglut. github issue #223
+ {
+ const std::string header_end = ret.data.substr(HEADER_END_OFFSET, HEADER_END_SIZE);
+ verify_equal_strings(HEADER_END, header_end.c_str(), HEADER_END_SIZE, "LIB HEADER_END");
+ }
return ret;
}
@@ -128,17 +119,53 @@ namespace vcpkg {namespace COFFFileReader
uint64_t member_size() const
{
+ static const size_t ALIGNMENT_SIZE = 2;
+
static const size_t HEADER_SIZE_OFFSET = 48;
static const size_t HEADER_SIZE_FIELD_SIZE = 10;
const std::string as_string = data.substr(HEADER_SIZE_OFFSET, HEADER_SIZE_FIELD_SIZE);
// This is in ASCII decimal representation
const uint64_t value = std::strtoull(as_string.c_str(), nullptr, 10);
- return value;
+
+ const uint64_t aligned = align_to_size(value, ALIGNMENT_SIZE);
+ return aligned;
}
std::string data;
};
+ struct offsets_array
+ {
+ static offsets_array read(fstream& fs, const uint32_t offset_count)
+ {
+ static const size_t OFFSET_WIDTH = 4;
+
+ std::string raw_offsets;
+ const size_t raw_offset_size = offset_count * OFFSET_WIDTH;
+ raw_offsets.resize(raw_offset_size);
+ fs.read(&raw_offsets[0], raw_offset_size);
+
+ offsets_array ret;
+ for (uint32_t i = 0; i < offset_count; ++i)
+ {
+ const std::string value_as_string = raw_offsets.substr(OFFSET_WIDTH * i, OFFSET_WIDTH * (i + 1));
+ const uint32_t value = reinterpret_bytes<uint32_t>(value_as_string.c_str());
+
+ // Ignore offsets that point to offset 0. See vcpkg github #223 #288 #292
+ if (value != 0)
+ {
+ ret.data.push_back(value);
+ }
+ }
+
+ // Sort the offsets, because it is possible for them to be unsorted. See vcpkg github #292
+ std::sort(ret.data.begin(), ret.data.end());
+ return ret;
+ }
+
+ std::vector<uint32_t> data;
+ };
+
struct import_header
{
static const size_t HEADER_SIZE = 20;
@@ -168,14 +195,6 @@ namespace vcpkg {namespace COFFFileReader
return ret;
}
- static import_header peek(fstream& fs)
- {
- auto original_pos = fs.tellg().seekpos();
- import_header ret = read(fs);
- fs.seekg(original_pos);
- return ret;
- }
-
MachineType machineType() const
{
static const size_t MACHINE_TYPE_OFFSET = 6;
@@ -190,14 +209,6 @@ namespace vcpkg {namespace COFFFileReader
std::string data;
};
- static void skip_archive_member(fstream& fs, uint64_t member_size)
- {
- static const size_t ALIGNMENT_SIZE = 2;
-
- const fpos_t new_offset = align_to(member_size, ALIGNMENT_SIZE);
- fs.seekg(new_offset, ios_base::cur);
- }
-
static void read_and_verify_archive_file_signature(fstream& fs)
{
static const char* FILE_START = "!<arch>\n";
@@ -207,10 +218,10 @@ namespace vcpkg {namespace COFFFileReader
char file_start[FILE_START_SIZE];
fs.read(file_start, FILE_START_SIZE);
- verify_equal_strings(FILE_START, file_start, FILE_START_SIZE);
+ verify_equal_strings(FILE_START, file_start, FILE_START_SIZE, "LIB FILE_START");
}
- dll_info read_dll(const fs::path path)
+ dll_info read_dll(const fs::path& path)
{
std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate);
Checks::check_exit(fs.is_open(), "Could not open file %s for reading", path.generic_string());
@@ -221,43 +232,76 @@ namespace vcpkg {namespace COFFFileReader
return {machine};
}
- lib_info read_lib(const fs::path path)
+ struct marker_t
+ {
+ void set_to_offset(const fpos_t position)
+ {
+ this->m_absolute_position = position;
+ }
+
+ void set_to_current_pos(fstream& fs)
+ {
+ this->m_absolute_position = fs.tellg().seekpos();
+ }
+
+ void seek_to_marker(fstream& fs) const
+ {
+ fs.seekg(this->m_absolute_position, ios_base::beg);
+ }
+
+ void advance_by(const uint64_t offset)
+ {
+ this->m_absolute_position += offset;
+ }
+
+ private:
+ fpos_t m_absolute_position = 0;
+ };
+
+ lib_info read_lib(const fs::path& path)
{
std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate);
Checks::check_exit(fs.is_open(), "Could not open file %s for reading", path.generic_string());
read_and_verify_archive_file_signature(fs);
+ marker_t marker;
+ marker.set_to_current_pos(fs);
+
// First Linker Member
const archive_member_header first_linker_member_header = archive_member_header::read(fs);
Checks::check_exit(first_linker_member_header.name().substr(0, 2) == "/ ", "Could not find proper first linker member");
- skip_archive_member(fs, first_linker_member_header.member_size());
+ marker.advance_by(archive_member_header::HEADER_SIZE + first_linker_member_header.member_size());
+ marker.seek_to_marker(fs);
const archive_member_header second_linker_member_header = archive_member_header::read(fs);
Checks::check_exit(second_linker_member_header.name().substr(0, 2) == "/ ", "Could not find proper second linker member");
// The first 4 bytes contains the number of archive members
- const uint32_t archive_member_count = peek_value_from_stream<uint32_t>(fs);
- skip_archive_member(fs, second_linker_member_header.member_size());
+ const uint32_t archive_member_count = read_value_from_stream<uint32_t>(fs);
+ const offsets_array offsets = offsets_array::read(fs, archive_member_count);
+ marker.advance_by(archive_member_header::HEADER_SIZE + second_linker_member_header.member_size());
+ marker.seek_to_marker(fs);
bool hasLongnameMemberHeader = peek_value_from_stream<uint16_t>(fs) == 0x2F2F;
if (hasLongnameMemberHeader)
{
const archive_member_header longnames_member_header = archive_member_header::read(fs);
- skip_archive_member(fs, longnames_member_header.member_size());
+ marker.advance_by(archive_member_header::HEADER_SIZE + longnames_member_header.member_size());
+ marker.seek_to_marker(fs);
}
std::set<MachineType> machine_types;
// Next we have the obj and pseudo-object files
- for (uint32_t i = 0; i < archive_member_count; i++)
+ for (const uint32_t offset : offsets.data)
{
- const archive_member_header header = archive_member_header::read(fs);
+ marker.set_to_offset(offset + archive_member_header::HEADER_SIZE); // Skip the header, no need to read it.
+ marker.seek_to_marker(fs);
const uint16_t first_two_bytes = peek_value_from_stream<uint16_t>(fs);
const bool isImportHeader = getMachineType(first_two_bytes) == MachineType::UNKNOWN;
- const MachineType machine = isImportHeader ? import_header::peek(fs).machineType() : coff_file_header::peek(fs).machineType();
+ const MachineType machine = isImportHeader ? import_header::read(fs).machineType() : coff_file_header::read(fs).machineType();
machine_types.insert(machine);
- skip_archive_member(fs, header.member_size());
}
return {std::vector<MachineType>(machine_types.cbegin(), machine_types.cend())};
}
-}}
+}