]>
Commit | Line | Data |
---|---|---|
edd090a2 CF |
1 | #!/usr/bin/perl |
2 | use strict; | |
3 | use File::Temp qw'tempdir'; | |
4 | use File::Spec; | |
5 | use Getopt::Long; | |
6 | my $dir = tempdir(CLEANUP => 1); | |
7 | ||
61522196 CV |
8 | my ($cpu, $ar, $as, $nm, $objcopy, %replace); |
9 | GetOptions('cpu=s'=>\$cpu, 'ar=s'=>\$ar, 'as=s'=>\$as,'nm=s'=>\$nm, 'objcopy=s'=>\$objcopy, 'replace=s'=>\%replace); | |
edd090a2 CF |
10 | |
11 | # Args:: | |
12 | # 1) import lib to create | |
13 | # 2) input dll | |
14 | # 3...) extra objects to add | |
15 | ||
16 | $_ = File::Spec->rel2abs($_) for @ARGV; | |
17 | ||
18 | my $libdll = shift; | |
19 | my $inpdll = shift; | |
20 | ||
21 | open my $nm_fd, '-|', $nm, '-Apg', '--defined-only', $inpdll; | |
22 | my %text = (); | |
23 | my %import = (); | |
24 | my %symfile = (); | |
61522196 CV |
25 | |
26 | my $is64bit = ($cpu eq 'x86_64' ? 1 : 0); | |
27 | my $sym_prefix = ($is64bit ? '' : '_'); | |
28 | ||
edd090a2 CF |
29 | while (<$nm_fd>) { |
30 | chomp; | |
31 | my ($fn, $type, $sym) = /^$inpdll:(.*?):\S+\s+(\S)\s+(\S+)$/o; | |
32 | next unless $fn; | |
33 | $text{$fn} = $sym if $type eq 'T'; | |
34 | $import{$fn} = $sym if $type eq 'I'; | |
35 | $symfile{$sym} = $fn; | |
36 | } | |
37 | close $nm_fd or exit 1; | |
38 | ||
39 | for my $sym (keys %replace) { | |
40 | my $fn; | |
61522196 | 41 | my $_sym = $sym_prefix . $sym; |
edd090a2 CF |
42 | if (!defined($fn = $symfile{$_sym})) { |
43 | $fn = "$sym.o"; | |
44 | $text{$fn} = $_sym; | |
45 | } | |
61522196 | 46 | my $imp_sym = '__imp_' . $sym_prefix . $replace{$sym}; |
edd090a2 CF |
47 | $import{$fn} = $imp_sym; |
48 | } | |
49 | ||
50 | for my $f (keys %text) { | |
51 | my $imp_sym = delete $import{$f}; | |
52 | my $glob_sym = $text{$f}; | |
53 | if (!defined $imp_sym) { | |
54 | delete $text{$f}; | |
61522196 | 55 | } elsif ($imp_sym eq '__imp_' . $sym_prefix) { |
edd090a2 CF |
56 | $text{$f} = 0; |
57 | } else { | |
58 | $text{$f} = 1; | |
59 | open my $as_fd, '|-', $as, '-o', "$dir/t-$f", "-"; | |
61522196 CV |
60 | if ($is64bit) { |
61 | print $as_fd <<EOF; | |
62 | .text | |
63 | .extern $imp_sym | |
64 | .global $glob_sym | |
65 | $glob_sym: | |
66 | jmp *$imp_sym(%rip) | |
67 | EOF | |
68 | } else { | |
69 | print $as_fd <<EOF; | |
b978c43e | 70 | .text |
edd090a2 CF |
71 | .extern $imp_sym |
72 | .global $glob_sym | |
73 | $glob_sym: | |
74 | jmp *$imp_sym | |
75 | EOF | |
61522196 | 76 | } |
edd090a2 CF |
77 | close $as_fd or exit 1; |
78 | } | |
79 | } | |
80 | ||
81 | chdir $dir or die "$0: couldn't cd to $dir - $!\n"; | |
82 | system $ar, 'x', $inpdll; | |
83 | exit 1 if $?; | |
84 | ||
85 | for my $f (keys %text) { | |
86 | if (!$text{$f}) { | |
87 | unlink $f; | |
88 | } else { | |
89 | system $objcopy, '-R', '.text', $f and exit 1; | |
90 | system $objcopy, '-R', '.bss', '-R', '.data', "t-$f" and exit 1; | |
91 | } | |
92 | } | |
93 | ||
94 | unlink $libdll; | |
73bd5752 CF |
95 | system $ar, 'crus', $libdll, glob('*.o'), @ARGV; |
96 | unlink glob('*.o'); | |
97 | exit 1 if $?; | |
98525461 CF |
98 | |
99 | END { | |
100 | chdir '/tmp'; # Allow $dir directory removal on Windows | |
101 | } |