How (Not) To Break A Binary Optimizer
It is relatively easy to write code that will break binary optimization.
Charm tries to guard against this by trying to anticipate potential problems
as much as possible and refusing to optimize an executable containing problematic code.
Naturally there are cases, that Charm cannot detect.
This page list some coding practices that should be avoided.
Address Computation
Charm is free to reorder routines in an image.
If you try to determine the size of a routine by substracting
its address from the address of the next routine you will break the optimizer.
(In the future Charm will also reorder data and the same problem may arise there.)
Note, that these problemetaic address computation are not allowed by ansi C and
will usually result in substantially amount of compiler warnings.
Programs that compile cleanly with -Wall or better -Wall -Werror
are usually better suitable for binary optimization.
Similarly, if an executable contains data representing the delta between two addresses
there is usually now way for Charm to update the value and henced the optimized program will be incorrect.
Computed Jump
Sometime the delta is implicit as in following code sequence from glibcs memset:
ENTRY(memset)
mov a4, a1
cmp a3, $8 @ at least 8 bytes to do?
blt 2f
orr a2, a2, a2, lsl $8
orr a2, a2, a2, lsl $16
1:
tst a4, $3 @ aligned yet?
strneb a2, [a4], $1
subne a3, a3, $1
bne 1b
mov ip, a2
1:
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
stmgeia a4!, {a2, ip}
subge a3, a3, $8
bge 1b
2:
movs a3, a3 @ anything left?
RETINSTR(moveq,pc,lr) @ nope
rsb a3, a3, $7
add pc, pc, a3, lsl $2
mov r0, r0
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
RETINSTR(mov,pc,lr)
END(memset)
The last add instruction is a computed jump targeting one the subsequent strbs.
It makes some assumptions about the offsets (deltas) of following instruction which is easily broken
if charm decides to insert nops there.
But not all computed jumps suffer from this problem:
[show gcc produced switch idiom]
Gp Materialization Idiom
[fill in example together with suggestion for a better idiom]
Missing data markers
Some code in glibc has data which is not marked as such (The API mandates that data is marked with a $d
symbol).
This is a problem because if Charm interprets data as instructions it ultimately may change that data.
Luckily, Charm is able to detect the missing datamarker in this case but in order to repairs the problem
special support needs to be added for each new version of glibc.
The following is a listing of such routine with unmarked data:
_start
__libc_open
__libc_close
__libc_read
__libc_write
__libc_nanosleep
__select
__connect_internal