@@ -802,9 +802,9 @@ String EditorExportPlatformWindows::_get_exe_arch(const String &p_path) const {
802802}
803803
804804Error EditorExportPlatformWindows::fixup_embedded_pck (const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
805- // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data
805+ // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data.
806806
807- if (p_embedded_size + p_embedded_start >= 0x100000000 ) { // Check for total executable size
807+ if (p_embedded_size + p_embedded_start >= 0x100000000 ) { // Check for total executable size.
808808 add_message (EXPORT_MESSAGE_ERROR, TTR (" PCK Embedding" ), TTR (" Windows executables cannot be >= 4 GiB." ));
809809 return ERR_INVALID_DATA;
810810 }
@@ -815,7 +815,7 @@ Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int6
815815 return ERR_CANT_OPEN;
816816 }
817817
818- // Jump to the PE header and check the magic number
818+ // Jump to the PE header and check the magic number.
819819 {
820820 f->seek (0x3c );
821821 uint32_t pe_pos = f->get_32 ();
@@ -828,27 +828,36 @@ Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int6
828828 }
829829 }
830830
831- // Process header
832-
831+ // Process header.
832+ uint32_t sect_alignment = 0x1000 ;
833+ uint32_t image_size = 0 ;
833834 int num_sections;
834- {
835- int64_t header_pos = f->get_position ();
836835
836+ int64_t header_pos = f->get_position ();
837+ int64_t opt_header_pos = 0 ;
838+ {
837839 f->seek (header_pos + 2 );
838840 num_sections = f->get_16 ();
839841 f->seek (header_pos + 16 );
840842 uint16_t opt_header_size = f->get_16 ();
843+ opt_header_pos = f->get_position () + 2 ;
844+
845+ f->seek (opt_header_pos + 32 );
846+ sect_alignment = f->get_32 ();
847+
848+ f->seek (opt_header_pos + 56 );
849+ image_size = f->get_32 ();
841850
842- // Skip rest of header + optional header to go to the section headers
843- f->seek (f-> get_position () + 2 + opt_header_size);
851+ // Skip rest of header + optional header to go to the section headers.
852+ f->seek (opt_header_pos + opt_header_size);
844853 }
845854
846- // Search for the "pck" section
855+ // Search for the "pck" section.
847856
848857 int64_t section_table_pos = f->get_position ();
849858
850- bool found = false ;
851- for (int i = 0 ; i < num_sections; ++i ) {
859+ int pck_old_pos = - 1 ;
860+ for (int i = 0 ; i < num_sections; i++ ) {
852861 int64_t section_header_pos = section_table_pos + i * 40 ;
853862 f->seek (section_header_pos);
854863
@@ -857,23 +866,48 @@ Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int6
857866 section_name[8 ] = ' \0 ' ;
858867
859868 if (strcmp ((char *)section_name, " pck" ) == 0 ) {
860- // "pck" section found, let's patch!
869+ pck_old_pos = i;
861870
862- // Set virtual size to a little to avoid it taking memory (zero would give issues)
863- f->seek (section_header_pos + 8 );
864- f->store_32 (8 );
865-
866- f->seek (section_header_pos + 16 );
867- f->store_32 (p_embedded_size);
868- f->seek (section_header_pos + 20 );
869- f->store_32 (p_embedded_start);
870-
871- found = true ;
871+ // Update virtual size of previous section to avoid gaps in the virtual addresses.
872+ f->seek (section_table_pos + (i - 1 ) * 40 + 8 );
873+ uint32_t virt_size = f->get_32 ();
874+ f->seek (section_table_pos + (i - 1 ) * 40 + 8 );
875+ f->store_32 (virt_size + sect_alignment);
872876 break ;
873877 }
874878 }
879+ if (pck_old_pos >= 0 ) {
880+ // Move section data.
881+ uint8_t section_data[40 ];
882+ for (int i = pck_old_pos; i < num_sections - 1 ; i++) {
883+ f->seek (section_table_pos + (i + 1 ) * 40 );
884+ f->get_buffer (section_data, 40 );
885+ f->seek (section_table_pos + i * 40 );
886+ f->store_buffer (section_data, 40 );
887+ }
888+
889+ // Add "pck" at the end.
890+ f->seek (section_table_pos + (num_sections - 1 ) * 40 );
891+ uint8_t section_name[8 ] = { ' p' , ' c' , ' k' , ' \0 ' , ' \0 ' , ' \0 ' , ' \0 ' , ' \0 ' };
892+ f->store_buffer (section_name, 8 ); // Name.
893+ f->store_32 (8 ); // VirtualSize, set to a little to avoid it taking memory (zero would give issues).
894+ f->store_32 (image_size); // VirtualAddress.
895+ f->store_32 (p_embedded_size); // SizeOfRawData.
896+ f->store_32 (p_embedded_start); // PointerToRawData.
897+ f->store_32 (0 ); // PointerToRelocations, not used.
898+ f->store_32 (0 ); // PointerToLinenumbers, not used.
899+ f->store_16 (0 ); // NumberOfRelocations.
900+ f->store_16 (0 ); // NumberOfLinenumbers.
901+ f->store_32 (0x40000000 ); // Characteristics: Read.
902+
903+ // Update image virtual size.
904+ f->seek (opt_header_pos + 56 );
905+ f->store_32 (image_size + sect_alignment);
906+ }
907+
908+ f->close ();
875909
876- if (!found ) {
910+ if (pck_old_pos == - 1 ) {
877911 add_message (EXPORT_MESSAGE_ERROR, TTR (" PCK Embedding" ), TTR (" Executable \" pck\" section not found." ));
878912 return ERR_FILE_CORRUPT;
879913 }
0 commit comments