Resurrect tests/auto/corelib/plugin/qpluginloader/machtest

Update the CMake project file to generate the binaries that are to be
tested by tst_qpluginloader.

Update the tested architectures to arm64 and x86_64 like it was done in
2739aa98b1da164b398a37e6018c205d59debf7e for Qt 5.15.

Remove the ppcconverter script that was used to create PowerPC binaries.
This architecture is unsupported since ages.

Remove the comparison with the pointer size and the alignment check.
This isn't valid since commit 2549a88ba2.

Remove the magic header check. This is done by the parser itself since
commit 3b49aa72fe.

Remove the blacklisting of the test.

Fixes: QTBUG-86792
Change-Id: Ib7c8e648bdacca6d6290c0f40a3bb02987365fc9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
bb10
Joerg Bornemann 2024-01-05 21:31:42 +01:00
parent 0995358efa
commit 7fe7ed0a3f
4 changed files with 143 additions and 90 deletions

View File

@ -1,2 +0,0 @@
[loadMachO]
macos cmake

View File

@ -1 +1,138 @@
set_directory_properties(PROPERTIES
_qt_good_targets ""
_qt_stub_targets ""
)
function(add_plugin_binary)
set(no_value_options "")
set(single_value_options NAME ARCH OUT_TARGET)
set(multi_value_options SOURCES)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${no_value_options}" "${single_value_options}" "${multi_value_options}"
)
set(output_name ${arg_NAME}.${arg_ARCH})
set(target tst_qpluginloader.${output_name})
set(${arg_OUT_TARGET} ${target} PARENT_SCOPE)
set_property(DIRECTORY APPEND PROPERTY _qt_${arg_NAME}_targets ${target})
add_library(${target} MODULE ${arg_SOURCES})
add_dependencies(tst_qpluginloader ${target})
set_target_properties(${target} PROPERTIES
OUTPUT_NAME ${output_name}
PREFIX ""
SUFFIX ".dylib"
DEBUG_POSTFIX ""
OSX_ARCHITECTURES ${arg_ARCH}
)
endfunction()
function(add_good_binary)
set(no_value_options "")
set(single_value_options ARCH)
set(multi_value_options "")
cmake_parse_arguments(PARSE_ARGV 0 arg
"${no_value_options}" "${single_value_options}" "${multi_value_options}"
)
add_plugin_binary(
NAME good
ARCH ${arg_ARCH}
SOURCES ../fakeplugin.cpp
OUT_TARGET target
)
# We cannot link against Qt6::Core, because the architecture might not match.
# Extract the include directories from Qt6::Core.
get_target_property(incdirs Qt6::Core INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(${target} PRIVATE ${incdirs})
# Extract the compile definitions from Qt6::Core and disable version tagging.
get_target_property(compdefs Qt6::Core INTERFACE_COMPILE_DEFINITIONS)
target_compile_definitions(${target} PRIVATE
${compdefs}
QT_NO_VERSION_TAGGING
)
endfunction()
function(add_stub_binary)
set(no_value_options "")
set(single_value_options ARCH)
set(multi_value_options "")
cmake_parse_arguments(PARSE_ARGV 0 arg
"${no_value_options}" "${single_value_options}" "${multi_value_options}"
)
add_plugin_binary(
NAME stub
ARCH ${arg_ARCH}
SOURCES stub.cpp
)
endfunction()
function(add_fat_binary)
set(no_value_options "")
set(single_value_options NAME OUT_TARGET)
set(multi_value_options TARGETS)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${no_value_options}" "${single_value_options}" "${multi_value_options}"
)
set(arch_args "")
foreach(dependency IN LISTS arg_TARGETS)
get_target_property(arch ${dependency} OSX_ARCHITECTURES)
list(APPEND arch_args -arch ${arch} $<TARGET_FILE_NAME:${dependency}>)
endforeach()
set(output_name good.fat.${arg_NAME})
set(output_file ${output_name}.dylib)
set(target tst_qpluginloader.${output_name})
set(${arg_OUT_TARGET} ${target} PARENT_SCOPE)
add_custom_command(
OUTPUT ${output_file}
COMMAND lipo -create -output ${output_file} ${arch_args}
DEPENDS ${arg_TARGETS}
)
add_custom_target(${target}
DEPENDS ${output_file}
)
add_dependencies(tst_qpluginloader ${target})
endfunction()
set(archs_to_test arm64 x86_64)
foreach(arch IN LISTS archs_to_test)
add_good_binary(ARCH ${arch})
add_stub_binary(ARCH ${arch})
endforeach()
get_directory_property(good_targets _qt_good_targets)
add_fat_binary(NAME all TARGETS ${good_targets})
set(targets ${good_targets})
list(FILTER targets EXCLUDE REGEX "\\.arm64$")
add_fat_binary(NAME no-arm64 TARGETS ${targets})
set(targets ${good_targets})
list(FILTER targets EXCLUDE REGEX "\\.x86_64$")
add_fat_binary(NAME no-x86_64 TARGETS ${targets})
get_directory_property(stub_targets _qt_stub_targets)
set(targets ${stub_targets})
list(FILTER targets INCLUDE REGEX "\\.arm64$")
add_fat_binary(NAME stub-arm64 TARGETS ${targets})
set(targets ${stub_targets})
list(FILTER targets INCLUDE REGEX "\\.x86_64$")
add_fat_binary(NAME stub-x86_64 TARGETS ${targets})
set(bad_binary_names "")
foreach(i RANGE 1 13)
list(APPEND bad_binary_names "bad${i}.dylib")
endforeach()
add_custom_command(
OUTPUT ${bad_binary_names}
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/generate-bad.pl
)
add_custom_target(tst_qpluginloader_generate_bad_binaries
DEPENDS ${bad_binary_names}
)
add_dependencies(tst_qpluginloader tst_qpluginloader_generate_bad_binaries)

View File

@ -1,74 +0,0 @@
#!/usr/bin/perl
# Copyright (C) 2016 Intel Corporation.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
# Changes the Mach-O file type header to PowerPC.
#
# The header is (from mach-o/loader.h):
# struct mach_header {
# uint32_t magic; /* mach magic number identifier */
# cpu_type_t cputype; /* cpu specifier */
# cpu_subtype_t cpusubtype; /* machine specifier */
# uint32_t filetype; /* type of file */
# uint32_t ncmds; /* number of load commands */
# uint32_t sizeofcmds; /* the size of all the load commands */
# uint32_t flags; /* flags */
# };
#
# The 64-bit header is identical in the first three fields, except for a different
# magic number. We will not touch the magic number, we'll just reset the cputype
# field to the PowerPC type and the subtype field to zero.
#
# We will not change the file's endianness. That means we might create a little-endian
# PowerPC binary, which could not be run in real life.
#
# We will also not change the 64-bit ABI flag, which is found in the cputype's high
# byte. That means we'll create a PPC64 binary if fed a 64-bit input.
#
use strict;
use constant MH_MAGIC => 0xfeedface;
use constant MH_CIGAM => 0xcefaedfe;
use constant MH_MAGIC_64 => 0xfeedfacf;
use constant MH_CIGAM_64 => 0xcffaedfe;
use constant CPU_TYPE_POWERPC => 18;
use constant CPU_SUBTYPE_POWERPC_ALL => 0;
my $infile = shift @ARGV or die("Missing input filename");
my $outfile = shift @ARGV or die("Missing output filename");
open IN, "<$infile" or die("Can't open $infile for reading: $!\n");
open OUT, ">$outfile" or die("Can't open $outfile for writing: $!\n");
binmode IN;
binmode OUT;
# Read the first 12 bytes, which includes the interesting fields of the header
my $buffer;
read(IN, $buffer, 12);
my $magic = vec($buffer, 0, 32);
if ($magic == MH_MAGIC || $magic == MH_MAGIC_64) {
# Big endian
# The low byte of cputype is at offset 7
vec($buffer, 7, 8) = CPU_TYPE_POWERPC;
} elsif ($magic == MH_CIGAM || $magic == MH_CIGAM_64) {
# Little endian
# The low byte of cpytype is at offset 4
vec($buffer, 4, 8) = CPU_TYPE_POWERPC;
} else {
$magic = '';
$magic .= sprintf("%02X ", $_) for unpack("CCCC", $buffer);
die("Invalid input. Unknown magic $magic\n");
}
vec($buffer, 2, 32) = CPU_SUBTYPE_POWERPC_ALL;
print OUT $buffer;
# Copy the rest
while (!eof(IN)) {
read(IN, $buffer, 4096) and
print OUT $buffer or
die("Problem copying: $!\n");
}
close(IN);
close(OUT);

View File

@ -860,22 +860,19 @@ void tst_QPluginLoader::loadMachO_data()
# ifdef Q_PROCESSOR_X86_64
QTest::newRow("machtest/good.x86_64.dylib") << true;
QTest::newRow("machtest/good.i386.dylib") << false;
QTest::newRow("machtest/good.arm64.dylib") << false;
QTest::newRow("machtest/good.fat.no-x86_64.dylib") << false;
QTest::newRow("machtest/good.fat.no-i386.dylib") << true;
# elif defined(Q_PROCESSOR_X86_32)
QTest::newRow("machtest/good.i386.dylib") << true;
QTest::newRow("machtest/good.fat.no-arm64.dylib") << true;
# elif defined(Q_PROCESSOR_ARM)
QTest::newRow("machtest/good.arm64.dylib") << true;
QTest::newRow("machtest/good.x86_64.dylib") << false;
QTest::newRow("machtest/good.fat.no-i386.dylib") << false;
QTest::newRow("machtest/good.fat.no-arm64.dylib") << false;
QTest::newRow("machtest/good.fat.no-x86_64.dylib") << true;
# endif
# ifndef Q_PROCESSOR_POWER_64
QTest::newRow("machtest/good.ppc64.dylib") << false;
# endif
QTest::newRow("machtest/good.fat.all.dylib") << true;
QTest::newRow("machtest/good.fat.stub-x86_64.dylib") << false;
QTest::newRow("machtest/good.fat.stub-i386.dylib") << false;
QTest::newRow("machtest/good.fat.stub-arm64.dylib") << false;
QDir d(QFINDTESTDATA("machtest"));
const QStringList badlist = d.entryList(QStringList() << "bad*.dylib");
@ -903,12 +900,7 @@ void tst_QPluginLoader::loadMachO()
}
QVERIFY(r.pos > 0);
QVERIFY(size_t(r.length) >= sizeof(void*));
QVERIFY(r.pos + r.length < data.size());
QCOMPARE(r.pos & (sizeof(void*) - 1), 0UL);
void *value = *(void**)(data.constData() + r.pos);
QCOMPARE(value, sizeof(void*) > 4 ? (void*)(0xc0ffeec0ffeeL) : (void*)0xc0ffee);
// now that we know it's valid, let's try to make it invalid
ulong offeredlen = r.pos;