Automatically detect assembly agreement violations

Is there a way for the assembler (or the static analyzer) to warn if the manual assembly code contains assembler violations of the agreement on the purpose of the assembly platform?

The platform I use is ARMv7A with the GNU GAS assembler. The reason for the question is the error that I wrote where my function did not press / enter the required registers (r4-r11 on ARM) upun entry / exit. The registers were broken, which caused the call to fail (fortunately, automatic tests detected an error). Simplified program:

my_function: mov r4, #42 @Trash register r4 in violation of calling convention bx lr @Return from function caller: ... mov r4, #4 @Initialise register r4, to be used later bl my_function @Call my_function with no arguments mov r0, r4 @Set argument r0 as r4 (== 42, but should be 4) bl other_function @Call other_function with (the now trashed) argument r0 

ARM calling convention: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf

+4
source share
1 answer

I don’t think there is such a tool. It is expected that the team programmers are well aware of what they are doing.

However, if you are really after this, you can develop such a tool.

In it, you need to analyze the source code of the assembly and find out the instructions that change the registers that should be saved by the subroutine. The same goes for the instructions for saving / restoring these registers.

You will also need to find out where the routines start and end. The beginning can be recognized by noting that the label denoting the entry point into the subprogram is defined as public / global / whatever, basically that it should be visible from the outside by the linker. Another possible heuristic is that the label is used in call instructions or regardless of its equivalent. Likewise, you can determine the end of a routine by specifying instructions or sequences of them that return.

There are times when it is difficult to understand the beginning and the end, or whether the register was really destroyed or saved. Some of them can be solved using additional heuristics. The rest may lead to warnings by default. It is probably best to have false negatives, false alarms, then vice versa. If the code is small, figuring out whether the warning is significant or not should be easy.

For this task, you should consider some scripting or scripting languages ​​that can process strings, support regular expressions and support the "standard" containers and the algorithms that work with them (search / sort / etc). Perl and Python could do the job well. I would not recommend doing this in C or C ++, because you will need to rewrite and discard many small fragments during the development process. Compilation is an additional obstacle, no matter how small it may be. Debugging low-level code or templates is not fun.

0
source

Source: https://habr.com/ru/post/1437243/


All Articles