summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/plugin/qpluginloader/machtest/ppcconverter.pl
blob: 64b937991ade6c1c07916dff642b967bc518894a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/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);