From 7863cbeb4a51f526369859a7ed7ed84db00bd0d9 Mon Sep 17 00:00:00 2001
From: rukaimi <rukaimi@985867f9-ca9c-e1f6-822d-e8a4186388af>
Date: Sat, 8 Sep 2012 12:00:18 +0000
Subject: [PATCH] Fixed relocation rebuilder bug (auto-alignment added) Changed
 samples Removed unneeded code Added version

---
 pe_lib/pe_32_64.cpp               |  4 ++--
 pe_lib/pe_base.cpp                | 26 ++++++++++++++++++++------
 pe_lib/pe_structures.h            |  4 ----
 samples/relocation_adder/main.cpp |  9 +++++----
 samples/resource_editor/main.cpp  |  6 +++---
 5 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/pe_lib/pe_32_64.cpp b/pe_lib/pe_32_64.cpp
index f4467a0..94a91d1 100644
--- a/pe_lib/pe_32_64.cpp
+++ b/pe_lib/pe_32_64.cpp
@@ -675,7 +675,7 @@ const pe_base::image_directory pe<PEClassType>::rebuild_imports(const imported_f
 
 	std::string& raw_data = import_section.get_raw_data();
 
-	//This will be done only is image_section is latest section of image or for section with unaligned raw length of data
+	//This will be done only is image_section is the last section of image or for section with unaligned raw length of data
 	if(raw_data.length() < needed_size + import_settings.get_offset_from_section_start())
 		raw_data.resize(needed_size + import_settings.get_offset_from_section_start()); //Expand section raw data
 	
@@ -944,7 +944,7 @@ const pe_base::image_directory pe<PEClassType>::rebuild_tls(const tls_info& info
 
 	std::string& raw_data = tls_section.get_raw_data();
 
-	//This will be done only is tls_section is latest section of image or for section with unaligned raw length of data
+	//This will be done only is tls_section is the last section of image or for section with unaligned raw length of data
 	if(raw_data.length() < needed_size + offset_from_section_start)
 		raw_data.resize(needed_size + offset_from_section_start); //Expand section raw data
 
diff --git a/pe_lib/pe_base.cpp b/pe_lib/pe_base.cpp
index f800c1f..1b9b78e 100644
--- a/pe_lib/pe_base.cpp
+++ b/pe_lib/pe_base.cpp
@@ -2107,7 +2107,7 @@ const pe_base::image_directory pe_base::rebuild_exports(const export_info& info,
 
 	std::string& raw_data = exports_section.get_raw_data();
 
-	//This will be done only is exports_section is latest section of image or for section with unaligned raw length of data
+	//This will be done only is exports_section is the last section of image or for section with unaligned raw length of data
 	if(raw_data.length() < needed_size + offset_from_section_start)
 		raw_data.resize(needed_size + offset_from_section_start); //Expand section raw data
 
@@ -2615,9 +2615,17 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab
 	//sizeof(IMAGE_BASE_RELOCATION) = ending empty relocation table header
 	//sizeof(DWORD) = for DWORD alignment
 	
+	DWORD current_reloc_data_pos = align_up(offset_from_section_start, sizeof(DWORD));
+	DWORD start_reloc_pos = current_reloc_data_pos;
+
 	//Enumerate relocation tables
 	for(relocation_table_list::const_iterator it = relocs.begin(); it != relocs.end(); ++it)
+	{
 		needed_size += static_cast<DWORD>((*it).get_relocations().size() * sizeof(WORD) /* relocations */ + sizeof(IMAGE_BASE_RELOCATION) /* table header */);
+		//End of each table will be DWORD-aligned
+		if((start_reloc_pos + needed_size) % sizeof(DWORD))
+			needed_size += sizeof(WORD); //Align it with IMAGE_REL_BASED_ABSOLUTE relocation
+	}
 
 	//Check if reloc_section is last one. If it's not, check if there's enough place for relocations data
 	if(&reloc_section != &*(sections_.end() - 1) && 
@@ -2626,12 +2634,10 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab
 
 	std::string& raw_data = reloc_section.get_raw_data();
 
-	//This will be done only is reloc_section is latest section of image or for section with unaligned raw length of data
+	//This will be done only is reloc_section is the last section of image or for section with unaligned raw length of data
 	if(raw_data.length() < needed_size + offset_from_section_start)
 		raw_data.resize(needed_size + offset_from_section_start); //Expand section raw data
 
-	DWORD current_reloc_data_pos = align_up(offset_from_section_start, sizeof(DWORD));
-
 	//Enumerate relocation tables
 	for(relocation_table_list::const_iterator it = relocs.begin(); it != relocs.end(); ++it)
 	{
@@ -2640,6 +2646,8 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab
 		reloc.VirtualAddress = (*it).get_rva();
 		const relocation_table::relocation_list& reloc_list = (*it).get_relocations();
 		reloc.SizeOfBlock = static_cast<DWORD>(sizeof(IMAGE_BASE_RELOCATION) + sizeof(WORD) * reloc_list.size());
+		if((reloc_list.size() * sizeof(WORD)) % sizeof(DWORD)) //If we must align end of relocation table
+			reloc.SizeOfBlock += sizeof(WORD);
 
 		memcpy(&raw_data[current_reloc_data_pos], &reloc, sizeof(reloc));
 		current_reloc_data_pos += sizeof(reloc);
@@ -2652,6 +2660,12 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab
 			memcpy(&raw_data[current_reloc_data_pos], &reloc_value, sizeof(reloc_value));
 			current_reloc_data_pos += sizeof(reloc_value);
 		}
+
+		if(current_reloc_data_pos % sizeof(DWORD)) //If end of table is not DWORD-aligned
+		{
+			memset(&raw_data[current_reloc_data_pos], 0, sizeof(WORD)); //Align it with IMAGE_REL_BASED_ABSOLUTE relocation
+			current_reloc_data_pos += sizeof(WORD);
+		}
 	}
 	
 	{
@@ -2660,7 +2674,7 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab
 		memcpy(&raw_data[current_reloc_data_pos], &reloc, sizeof(reloc));
 	}
 	
-	image_directory ret(rva_from_section_offset(reloc_section, offset_from_section_start), needed_size);
+	image_directory ret(rva_from_section_offset(reloc_section, start_reloc_pos), needed_size);
 	
 	//Adjust section raw and virtual sizes
 	recalculate_section_sizes(reloc_section);
@@ -3673,7 +3687,7 @@ const pe_base::image_directory pe_base::rebuild_resources(resource_directory& in
 
 	std::string& raw_data = resources_section.get_raw_data();
 
-	//This will be done only is resources_section is latest section of image or for section with unaligned raw length of data
+	//This will be done only is resources_section is the last section of image or for section with unaligned raw length of data
 	if(raw_data.length() < needed_size + offset_from_section_start)
 		raw_data.resize(needed_size + offset_from_section_start); //Expand section raw data
 
diff --git a/pe_lib/pe_structures.h b/pe_lib/pe_structures.h
index eb4d9b2..e3fc3cf 100644
--- a/pe_lib/pe_structures.h
+++ b/pe_lib/pe_structures.h
@@ -3,10 +3,6 @@
 #include <Windows.h>
 #endif
 
-//Macros to align TLS data (not used yet)
-#define TLS_ALIGNMENT (2 * sizeof(void *))
-#define TLS_ALIGN(size) (((size) + TLS_ALIGNMENT - 1) & ~(TLS_ALIGNMENT - 1))
-
 #pragma pack(push, 1)
 
 #ifndef _WINNT_
diff --git a/samples/relocation_adder/main.cpp b/samples/relocation_adder/main.cpp
index 96cc7f8..9a48324 100644
--- a/samples/relocation_adder/main.cpp
+++ b/samples/relocation_adder/main.cpp
@@ -25,10 +25,11 @@ int main(int argc, char* argv[])
 		//Создаем экземпляр PE или PE+ класса с помощью фабрики
 		std::auto_ptr<pe_base> image = pe_factory::create_pe(pe_file);
 
-		//Перечислим и получим все полностью записи из таблиц релокаций в PE-файле
-		//Можно было бы абсолютные записи (ABSOLUTE) и не перечислять, передав в вызов false
-		//Эти записи все равно не нужны
-		pe_base::relocation_table_list tables = image->get_relocations(true);
+		//Перечислим и получим все записи из таблиц релокаций в PE-файле, кроме абсолютных
+		//Можно было бы включить в список и абсолютные записи (ABSOLUTE), передав в вызов true
+		//Эти записи не нужны при пересборке релокаций, они используются для выравнивания
+		//и будут добавлены автоматически пересборщиком
+		pe_base::relocation_table_list tables = image->get_relocations();
 		
 		//Создаем новую таблицу релокаций
 		pe_base::relocation_table new_table;
diff --git a/samples/resource_editor/main.cpp b/samples/resource_editor/main.cpp
index e4d39d9..aa1b601 100644
--- a/samples/resource_editor/main.cpp
+++ b/samples/resource_editor/main.cpp
@@ -55,7 +55,7 @@ int main(int argc, char* argv[])
 			return -1;
 		}
 
-		//Получим нашу иконку из этой директории: мы знаем, что ее ID=101 и она одна в директории имен, поэтому делаем так
+		//Получим нашу иконку из этой директории: мы знаем, что ее ID=100 и она одна в директории имен, поэтому делаем так
 		//Получаем ее по нулевому индексу (можно было получить по языку, но это незачем, т.к. она единственная)
 		const pe_resource_viewer::resource_data_info data = res.get_resource_data_by_id(L"CUSTOM", IDR_CUSTOM1);
 
@@ -64,7 +64,7 @@ int main(int argc, char* argv[])
 		//Помните, что сначала идут именованные ресурсы, а потом ресурсы с идентификаторами, и всё сортируется
 		//Создадим группу иконок с именем MAIN_ICON
 		res.add_icon(data.get_data(), //Данные файла иконки
-			L"MAIN_ICON", //Имя группы иконок (помните, у нас три картинки внутри иконки, они будут находиться в этой группе
+			L"MAIN_ICON", //Имя группы иконок (помните, у нас три картинки внутри иконки, они будут находиться в этой группе)
 			0, //Язык - нам неважен
 			pe_resource_manager::icon_place_after_max_icon_id, //Вариант расположения иконок в существующей группе - нам он неважен, так как мы создаем новую группу
 			data.get_codepage(), //Сохраним исходную Codepage
@@ -112,7 +112,7 @@ int main(int argc, char* argv[])
 		
 		//Осталось переименовать старую секцию ресурсов
 		//Она называется .rsrc
-		//Переименование необходимо для того, чтобы Windows Explorer смог считать оттуда иконку
+		//Переименование необходимо для того, чтобы Windows Explorer смог считать из новой секции иконку
 		image->section_from_directory(IMAGE_DIRECTORY_ENTRY_RESOURCE).set_name("oldres");
 
 		//Пересоберем ресурсы
-- 
GitLab