• 沒有找到結果。

III. Design and Implementation

3.3. Implementation Detail

3.3.1. Find All Kinds of Data

3.3.1.1. Data Structure

Although how many memories needed when translating is no concern of our translator, we still want to use a better structure to record these information of the data position.

The most intuitive solution is that use several bits to indicate the data kind of certain half-word. This method is easy to implement, but it cost too much spaces. For example, a binary that contains about one megabytes may need about 200 kilobytes, about one fifth of

21

original binary. Besides, our analyzer and translator has to read every halfword one by one even if where it is translating is a large set of data. If our program can jump to the end of data once it attempts to translate the head of data, less time will be taken in translation.

If we define a part of continuous bytes with same kind as a set, then we can describe a set by giving its start address, end address, and its kind. Figure 11 shows an example. The input data in an undefined set, and our analyzer uses different kinds of methods to discover all kinds of data and marks them. These sets are mutual exclusive, so there is no ambiguous set after analyzing.

Undefined set

Code PC-r data Code Switch table padding Code

Start address End address

Figure 11. An example of set analyzing

Regarding continues bytes as a set is very useful, since it takes much less memories compared with using a bit map, especially when the data set is large, and it is also easy to tell our translator that it meets data and can skip. Furthermore, marking a little set in the

undefined set is easy. Our analyzer just need to create an entry to store the start and end address of the set, and check whether there is the same kind of set before or after it. If true, these two sets can be merged, just like a union operation of two sets, as shown in Figure 12.

Code PC-r data Undefined set PC-r data

0x80f8 0x8114 0x8118 0x8118 0x811c

Code PC-r dataPC-r dataPC-r data Undefined set

0x80f8 0x8114 0x811c

Figure 12. An example of sets union operation

Furthermore, this data structure has more benefits in saving memories. Since the bytes are read sequentially and their address sequence is strictly increasing, our analyzer can discard data whose address is smaller than current halfword. Take Figure 13 and Figure 14 as

22

an example, Figure 13 shows original version, that our analyzer don’t discard any data that is used, and Figure 14 shows a discarding version. The green arrow indicates that where our analyzer is analyzing and the blue arrows indicate that where are LDR instructions that tell our analyzer where are PC-relative data. As a result, the discarding version uses less memory, since almost all cases of PC-relative data can be merged in only one set. In our experience, only two set entry is needed for the binaries generated by GCC.

0x8150 0x813c PC-relative data

0x81e4 0x81dc

0x8210 0x820c

Code PC-r

0x80f8 0x813cdata

Code PC-r

0x8150 0x81dcdata

Code PC-r

0x81e4 0x820c 0x8210data

Figure 13. An example of non-discarding used data version

0x8150 0x813c PC-relative data

Code PC-r

0x80f8 0x813c 0x8150data

PC-relative data

Code PC-r

data

0x80f8 0x813c 0x8150

Figure 14. An example of discarding used data version

Our analyzer uses linked list to maintain different sets, as shown by Figure 15, since popping the front element and inserting the element at back are needed. Normally, a list of set is in increasing order, so our program just have to check the first set of the certain kind of list and decide what to do. Therefore, our program can execute faster.

23

End address Start address Code

PC-relative data Switch table

Padding Unknown

End address Start address

End address Start address

End address Start address

End address Start address

Figure 15. How these sets stored in the memory

3.3.1.2. PC-relative Data

Every time our analyzer finds LDR-prefixed instruction with base register, it passes associated information to the set handler. And this kind of data can be found correctly.

8120: 4b06 ldr r3, [pc, #24]

… … …

8126: 4806 ldr r0, [pc, #24]

… … …

813a: bd10 pop {r4, pc} (end of function) 813c: 00000000 .word 00000000

8140: 000bd36c .word 000bd36c

Figure 16. An example of PC-relative data (using LDR)

Take Figure 16 as an example, at 0x8120, the address of the word program has to load is 0x8120 + 4 + 24 = 0x813c, and 0x8120 + 4 is the value of current PC. So our analyzer can mark 0x813c to 0x813f as relative data. Alignment is also important in handling PC-relative data. At 0x8126 in Figure 16, 0x8126 + 4 + 24 = 0x8142 is not the correct target address, because current PC is not word-aligned. The address must be Align(0x8126 + 4, 4) + 24 = 0x8140.

Due to the alignment of PC-relative data, our analyzer can ensure that the instruction at

24

the address which is not word-aligned is not start point of data, so the probability of mistranslating is lower.

3.3.1.3. Switch Table and Padding

Finite state machine (FSM) is used in our analyzer to find switch tables, because FSM is flexible and easy to implement.

The Left side of Figure 17 is our FSM for finding switch cases, and the arrows with no number indicate other cases that are not listed in the right side of Figure 17. Every time our analyzer reaches the final state, it receives necessary information about generating switch functions, like number of cases, default targets address and addresses of every case. The work of generating switch tables will be done by our translator.

Start

Final 2

6

3, 4 1

1

1. Cmp %case, #case_num 2. Bhi #default_target 3. Tbb [pc, %case]

4. Tbh [pc, %case, lsl #1]

5. Adr %reg, #table_head 6. Ldr pc, [%reg, %case, lsl #2]

Figure 17. Finite State Machine for finding switch cases

If the input is TBB when entering the final state, our analyzer have to check whether the number of cases is an odd number, and mark the next byte after the table as a padding byte if true.

相關文件