perl 语言中 AUTOLOAD 的用法

这里的 AUTOLOAD可以理解为自动加载。具体来说就是,在正常情况下,我们不能调用一个尚未定义的函数(子例程)。不过,如果在未定义函数的包中有一个名为 AUTOLOAD的函数,那么对未定义函数的调用都会路由至这个 AUTOLOAD函数,并且会为该函数提供相同的参数。因此,我们可以在 AUTOLOAD函数里面针对未定义的函数进行特殊处理,比如实现未定义的函数,然后调用该函数,就好像这个函数一直都存在一样。

比如,下面的示例程序会在你调用未定义函数时发出警告,而不是直接退出:

perl 复制代码
#!/usr/bin/env perl

sub AUTOLOAD {
	our $AUTOLOAD;
	warn "You attempt to call an undefined function: $AUTOLOAD\n";
}

&foo; # $AUTOLOAD will be set to main::foo
print "Exit normally ...\n"

运行结果如下所示:

bash 复制代码
$ ./autoload.pl 
You attempt to call an undefined function: main::foo
Exit normally ...

下面是一个更加实用的例子,即我们在 AUTOLOAD中实现未定义的函数:

perl 复制代码
#!/usr/bin/env perl

sub AUTOLOAD {
	my $name = our $AUTOLOAD;
	*$AUTOLOAD = sub { print "calling function $name(@_)\n"; };
	goto &$AUTOLOAD;
}

foo(30);
goo(40);
hoo(50);

运行结果如下所示:

bash 复制代码
$ ./autoload_2.pl 
calling function main::foo(30)
calling function main::goo(40)
calling function main::hoo(50)

OpenSSL项目中的很多地方都有用到 perl语言,它主要负责项目建构和汇编代码的生成工作。其中,在生成加解密算法汇编优化代码的 perl脚本中,有很多架构都用到了 AUTOLOAD机制去简化汇编指令的书写。下面看一个 OpenSSLx86实现的例子,从 crypto/chacha/asm/chacha-x86_64.pl文件中节选出如下代码:

perl 复制代码
#!/usr/bin/env perl

sub AUTOLOAD()          # thunk [simplified] 32-bit style perlasm
{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
  my $arg = pop;
    $arg = "\$$arg" if ($arg*1 eq $arg);
    $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
}

@x=("%eax","%ebx","%ecx","%edx",map("%r${_}d",(8..11)),
    "%nox","%nox","%nox","%nox",map("%r${_}d",(12..15)));
@t=("%esi","%edi");

sub ROUND {                     # critical path is 24 cycles per round
my ($a0,$b0,$c0,$d0)=@_;
my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
my ($xc,$xc_)=map("\"$_\"",@t);
my @x=map("\"$_\"",@x);

        (
        "&add   (@x[$a0],@x[$b0])",     # Q1
        "&xor   (@x[$d0],@x[$a0])",
        "&rol   (@x[$d0],16)",
         "&add  (@x[$a1],@x[$b1])",     # Q2
         "&xor  (@x[$d1],@x[$a1])",
         "&rol  (@x[$d1],16)",

        "&add   ($xc,@x[$d0])",
        "&xor   (@x[$b0],$xc)",
        "&rol   (@x[$b0],12)",
         "&add  ($xc_,@x[$d1])",
         "&xor  (@x[$b1],$xc_)",
         "&rol  (@x[$b1],12)",
		)
}

foreach (&ROUND(0, 4, 8,12)) { eval; }
foreach (&ROUND(0, 5,10,15)) { eval; }

print "$code\n";

从上面的代码可以看到,表面上,add()xor()rol()这些函数并没有被声明和实现,但该脚本定义了 AUTOLOAD函数,并在 AUTOLOAD函数中进行了统一的处理,比如,将 &add(xx, yy)函数调用转换为了 add yy,xx指令字符串。

因此,上述脚本的运行结果如下所示:

bash 复制代码
$ ./autoload_3.pl 
	add	%r8d,%eax
	xor	%eax,%r12d
	rol	$16,%r12d
	add	%r9d,%ebx
	xor	%ebx,%r13d
	rol	$16,%r13d
	add	%r12d,%esi
	xor	%esi,%r8d
	rol	$12,%r8d
	add	%r13d,%edi
	xor	%edi,%r9d
	rol	$12,%r9d
	add	%r9d,%eax
	xor	%eax,%r15d
	rol	$16,%r15d
	add	%r10d,%ebx
	xor	%ebx,%r12d
	rol	$16,%r12d
	add	%r15d,%esi
	xor	%esi,%r9d
	rol	$12,%r9d
	add	%r12d,%edi
	xor	%edi,%r10d
	rol	$12,%r10d
相关推荐
2501_9304724419 小时前
从物理机到 CVM 全流程落地:部署脚本的 8 个云化改造点(附代码对比)
开发语言·人工智能·架构·腾讯云·perl
bosins3 天前
Windows IIS 配置本地HTTPS 全流程指南:自签名证书 + 端口绑定 + 避坑详解
powershell·openssl
Lsetea7 天前
Nginx报SSL_CTX_use_PrivateKey failed:证书与私钥不匹配怎么排查
nginx·https·ssl证书·openssl·私钥
2601_962298679 天前
正则表达式引擎 哪些
java·python·perl·pcre·正则表达式引擎
Lsetea9 天前
SSL证书快过期怎么自动检查:用OpenSSL checkend做7天预警与线上证书验收
https·ssl证书·openssl·systemd·证书监控
啊阿狸不会拉杆11 天前
《计算机网络-自顶向下方法》1.7 计算机网络和因特网的历史 读书笔记
计算机网络·php·perl
智购科技智能售货柜14 天前
2026自动售货机设备能耗计量系统:从功率监测到能效分析的工程实践~YH
数据库·人工智能·redis·缓存·架构·perl·symfony
黑泽明*16 天前
云计算与服务器基础入门指南
服务器·云计算·perl
智购科技自动售货机厂家22 天前
2026自动售货机AI视觉识别优化:从YOLOv11n模型量化到RKNN部署的端侧推理工程实践~YH
javascript·人工智能·yolo·机器学习·计算机视觉·目标跟踪·perl
蜡台1 个月前
本机 局域网 搭建本地 HTTPS 域名完整方案
网络协议·http·https·openssl