从编译器asm输出反向工程数组尺寸/结构布局? [英] Reverse engineer array dimensions / struct layout from compiler asm output?
问题描述
在此代码中,A和B是用#define
定义的常量. A和B的值是什么?
In this code, A and B are constants defined with #define
. What are the values of A and B?
typedef struct {
int x[A][B];
long y;
} str1;
typedef struct {
char array[B];
int t;
short S[A];
long u;
} str2;
void setVal(str1 *p, str2 *q) {
long v1 = q->t;
long v2 = q->u;
p->y = v1+v2;
}
为setVal
过程生成以下汇编代码:
The following assembly code is generated for the setVal
procedure:
setVal:
movslq 8(%rsi), %rax
addq 32(%rsi), %rax
movq %rax, 184(%rdi)
ret
推荐答案
结构具有以下对齐要求:
The structure has the following alignment requirements:
-
char
可以从任何字节开始 -
short
可能以偶数字节开头 -
int
可以从字节开始,可以被四整除 -
long
可以从字节开始,可以被8整除
- a
char
may start at any byte - a
short
may start at even byte - an
int
may start at byte, divisible by four - a
long
may start at byte, divisible by eight
str1.y
字段是long
,从184
开始,这意味着str1.x
可以容纳184
或180
字节.
The str1.y
field is a long
and starts at 184
, this implies, that str1.x
may hold either 184
or 180
bytes.
str2.t
字段是一个int
,并从8
开始,这意味着str1.array
可以容纳5
至8
个字节.
The str2.t
field is an int
and starts at 8
, this implies, that str1.array
may hold from 5
to 8
bytes.
str2.u
字段是long
,起始于32
,这意味着str2.S
的字节数可能从14
到20
.
The str2.u
field is a long
and starts at 32
, this implies, that str2.S
may hold from 14
to 20
bytes.
这是str1
结构字段的图:
+---------------+---+--------+
| int x[A][B] | ? | long y |
+---------------+---+--------+
| 184 | 8 |
+-------------------+--------+
这是str2
字段的示意图:
+---------------+---+-------+------------+---+--------+
| char array[B] | ? | int t | short S[A] | ? | long u |
+---------------+---+-------+------------+---+--------+
| 8 | 4 | 20 | 8 |
+-------------------+-------+----------------+--------+
在那之后,您应该解决以下系统:
After that, you should solve the following system:
177 <= 4 * A * B <= 184
5 <= B <= 8
14 <= A * 2 <= 20 // 7 <= A <= 10
答案是:A = 9
,B = 5
您可以使用编译器来测试您的答案(以及每个不等式的范围),该编译器遵循产生原始代码的编译器所使用的相同ABI/调用约定.它使用8字节long
:请注意addq
(而不是addl
)的64位操作数大小和8字节存储.因此,我们可以推断出它很可能是x86-64 System V ABI,而不是Windows x86-64调用约定(使用4字节long
).
You can test your answer (and the ranges for each inequality) using a compiler that follows the same ABI / calling convention used by the compiler that produced the original code. It uses 8-byte long
: note the 64-bit operand size for the addq
, instead of addl
, and the 8-byte store. Thus, we can infer that it's most likely the x86-64 System V ABI, not the Windows x86-64 calling convention (which uses 4-byte long
).
Godbolt编译器浏览器具有gcc,clang,ICC和MSVC.前三个以Linux为目标,但MSVC以Windows调用约定为目标,因此对于较小的long
需要较少对齐的结构布局,就不会达成共识.
The Godbolt compiler explorer has gcc, clang, ICC, and MSVC. The first 3 target Linux, but MSVC targets the Windows calling convention and thus won't agree on struct layout with a smaller long
requiring less alignment.
Replacing int x[A][B]
with char t[177]
(or other sizes) proves that 177 is the minimum and 184 is the maximum size that that leads to a store to 184(%rdi)
. So we could have written 176 < 4*A*B <= 184
. Or, to keep things to multiples of 4, 180 <= 4*A*B <= 184
is also more or less correct; we can rule out 177..179 based on the size of int
.
这篇关于从编译器asm输出反向工程数组尺寸/结构布局?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!