\
在PHP中做什么?
例如,CSRF4PHP有\FALSE
,\session_id
和\Exception
:
public function __construct($timeout=300, $acceptGet=\FALSE){
$this->timeout = $timeout;
if (\session_id()) {
$this->acceptGet = (bool) $acceptGet;
} else {
throw new \Exception('Could not find session id', 1);
}
}
Run Code Online (Sandbox Code Playgroud) <?php
$show_value = 123;
echo 'sing_quote'.$show_value;
echo "double_quote{$show_value}";
?>
Run Code Online (Sandbox Code Playgroud)
它的操作码是:
1: <?php
2: $show_value = 123;
0 ASSIGN !0, 123
3: echo 'sing_quote'.$show_value;
1 CONCAT 'sing_quote', !0 =>RES[~1]
2 ECHO ~1
4: echo "double_quote{$show_value}";
3 ADD_STRING 'double_quote' =>RES[~2]
4 ADD_VAR ~2, !0 =>RES[~2]
5 ECHO ~2
6 RETURN 1
Run Code Online (Sandbox Code Playgroud) 对于以下代码
<?php
$a=1; $b=$a++; var_dump($b);
$a=1; $b=$a+$a++; var_dump($b);
$a=1; $b=$a+$a+$a++; var_dump($b);
$a=1; $b=$a+$a+$a+$a++; var_dump($b);
$a=1; $b=$a+$a+$a+$a+$a++; var_dump($b);
Run Code Online (Sandbox Code Playgroud)
我得到了这个结果:
int(1)
int(3)
int(3)
int(4)
int(5)
Run Code Online (Sandbox Code Playgroud)
我预计1,2,3,4,5而不是1,3,3,4,5.$a=1; $b=$a+$a++;
我们获得后为什么$b=3
?
PHP 7.1.5-1 + deb.sury.org~xenial + 1(cli)(建于2017年5月11日14:07:52)(NTS)
在x86 中查找任意操作码意味着什么(比方说)的相对快速简便的方法是什么0xC8
?
搜索英特尔软件开发人员手册并不是很有趣...
已经遇到过这么多次,我不知道为什么会这样让我感到好奇.有些班级在宣布之前有效,有些则没有;
例1
$test = new TestClass(); // top of class
class TestClass {
function __construct() {
var_dump(__METHOD__);
}
}
Run Code Online (Sandbox Code Playgroud)
产量
string 'TestClass::__construct' (length=22)
Run Code Online (Sandbox Code Playgroud)
例2
当类扩展另一个类或实现任何接口时
$test = new TestClass(); // top of class
class TestClass implements JsonSerializable {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return json_encode(rand(1, 10));
}
}
Run Code Online (Sandbox Code Playgroud)
产量
Fatal error: Class 'TestClass' not found
Run Code Online (Sandbox Code Playgroud)
例3
让我们尝试上面的同一个班级,但改变位置
class TestClass implements JsonSerializable {
function __construct() {
var_dump(__METHOD__);
}
public function jsonSerialize() {
return json_encode(rand(1, 10));
}
} …
Run Code Online (Sandbox Code Playgroud) 在Java的String类中,trim方法包含:
int off = offset; /* avoid getfield opcode */
char[] val = value; /* avoid getfield opcode */
Run Code Online (Sandbox Code Playgroud)
我对评论"避免getfield操作码"感到有些困惑......
这是什么意思?(我认为这可以避免在字节码中使用getfield,但为什么这是一个Good Thing [TM]?)
难道是防止万一对象创建微调不会做任何事情(因此该返回)或?
我想将X86_64,x86,ARM可执行文件转换为LLVM IR(反汇编).
你建议什么解决方案?
在invokespecial
JVM指令用于调用(初始化方法<init>
)创建新对象时.指令的描述建议(但不澄清)关于是否调用超类的构造函数或当前类的构造函数的决定取决于文件中ACC_SUPER
设置的标志的状态class
.
来自Sun JVM规范:
接下来,选择已解析的方法进行调用,除非满足以下所有条件:
- 为当前类设置ACC_SUPER标志(参见表4.1"类访问和属性修饰符").
- 来源(invokespecial
操作码定义)
ACC_SUPER标志的设置指示Java虚拟机要表达的其invokespecial指令的两个备选语义中的哪一个; 存在ACC_SUPER标志,以便向后兼容Sun的旧编译器为Java编程语言编译的代码.Java虚拟机的所有新实现都应该实现本规范中记录的invokespecial的语义.Java虚拟机指令集的所有新编译器都应设置ACC_SUPER标志.Sun的旧编译器生成了Class_Sile标志,并且未设置ACC_SUPER.Sun的旧Java虚拟机实现会在设置时忽略该标志.
- 来源(ClassFile
格式)
该定义指出该标志是为了与旧编译器向后兼容.然而它继续与之相矛盾Sun's older Java virtual machine implementations ignore the flag if it is set.
该标志是否仍与invokespecial
操作码一起使用?从我所知,它似乎没有任何目的,我找不到建议它曾经做过的资源.
谢谢.
我正在使用启用了APC缓存的PHP:
apc.cache_by_default => On
apc.enabled => On
apc.ttl => 7200
Run Code Online (Sandbox Code Playgroud)
现在我怎么知道它是否100%使用操作码缓存.
例如,让我们说我有这个PHP文件:
<?php
echo "Hi there";
?>
Run Code Online (Sandbox Code Playgroud)
现在运行此文件后,让我们将其更改为 echo "Bye there";
不应该回应"你好",因为7200秒的TTL尚未结束?我对吗?如果是这样,为什么它会回应"再见"?如果我错了,即使更改文件后如何强制它使用操作码缓存?
不要被震惊.这是很多文字,但我害怕没有提供一些详细的信息,我无法真正展示这是什么(并可能得到很多答案,并没有真正解决我的问题).而这绝对不是一项任务(正如他的评论中有人可笑地声称的那样).
由于除非至少设置了一些先决条件,否则根本无法回答此问题,以下是先决条件:
此外,我们需要更好地定义"更好".必须考虑几个属性:
现在通过或多或少的操作码实际意味着我的例子.它可能看起来实际上设置了操作码的数量,因为每个操作需要一个操作码.然而,它并不那么容易.
你可以进行类似的操作
ADD R1, R2, R3
Run Code Online (Sandbox Code Playgroud)
添加R1和R2的值,将结果写入R3.现在考虑以下特殊情况:
ADD R1, R2, R2
ADD R1, 1, R1
Run Code Online (Sandbox Code Playgroud)
这些是您在许多应用程序中可以找到的常见操作.您可以使用现有的操作码来表达它们(除非您需要不同的操作码,因为最后一个操作码具有int值而不是寄存器).但是,您也可以为这些创建特殊的操作码:
ADD2 R1, R2
INC R1
Run Code Online (Sandbox Code Playgroud)
和之前一样.优势在哪里?ADD2只需要两个参数,而不是3个,INC甚至只需要一个参数.因此,这可以在磁盘和/或内存中更紧凑地编码.由于将任何一种形式转换为另一种形式也很容易,因此解码步骤可以在两种方式之间转换以表达这些语句.不过,我不确定这两种形式会影响执行速度.
现在让我们假设您有一个ADD_RRR(R表示寄存器)和一个LOAD来将数据加载到寄存器中.
LOAD value, R2
ADD_RRR R1, R2, R3
Run Code Online (Sandbox Code Playgroud)
您可以拥有这两个操作码并始终在整个代码中使用这样的构造...或者您可以将它们组合成一个名为ADD_RMR(M代表内存)的新操作码
ADD_RMR R1, value, R3
Run Code Online (Sandbox Code Playgroud)
假设您有16位整数和32位整数作为本机类型.寄存器为32位,因此数据类型适合.现在,当您添加两个寄存器时,可以将数据类型设为参数:
ADD int16, R1, R2, R3
ADD int32, R1, R2, R3
Run Code Online (Sandbox Code Playgroud)
例如,对于有符号和无符号整数也是如此.这样,ADD可以是一个短操作码,一个字节,然后你有另一个字节(或者可能只是4位)告诉VM如何解释寄存器(它们是否保持16位或32位值).或者您可以废弃类型编码,而是有两个操作码:
ADD16 R1, R2, R3
ADD32 R1, R2, R3
Run Code Online (Sandbox Code Playgroud)
有些人可能会说两者完全相同 - 只是解释第一种方式,因为16位操作码可行.是的,但是一个非常幼稚的翻译可能看起来很不一样.例如,如果每个操作码有一个函数并使用switch语句调度(不是最好的方式,函数调用开销,switch语句也许不是最优的,我知道),这两个操作码可能如下所示:
case ADD16: add16(p1, p2, …
Run Code Online (Sandbox Code Playgroud) opcode ×10
php ×5
assembly ×2
class ×2
java ×2
apc ×1
bytecode ×1
disassembly ×1
increment ×1
intel ×1
interpreter ×1
jvm ×1
llvm ×1
namespaces ×1
opcache ×1
performance ×1
translation ×1
x86 ×1