1 |
2 |
drasko |
#!/usr/bin/python
|
2 |
|
|
|
3 |
|
|
import re, elf, sys, os
|
4 |
|
|
from optparse import OptionParser
|
5 |
|
|
|
6 |
|
|
# May need to do something about this
|
7 |
|
|
toolprefix = "arm-none-linux-gnueabi-"
|
8 |
|
|
objdump = toolprefix + "objdump"
|
9 |
|
|
objcopy = toolprefix + "objcopy"
|
10 |
|
|
readelf = toolprefix + "readelf"
|
11 |
|
|
egrep = "egrep"
|
12 |
|
|
snames_file = "section_names.txt"
|
13 |
|
|
|
14 |
|
|
def get_section_names(path):
|
15 |
|
|
rest, filename = os.path.split(path)
|
16 |
|
|
sections = []
|
17 |
|
|
os.system(readelf + " -l " + path + " > readelf.out")
|
18 |
|
|
os.system(egrep + r' "(\.){1}(\w){1}" ' + " readelf.out > sections.out")
|
19 |
|
|
for line in file('sections.out'):
|
20 |
|
|
secnum, secname = str.split(line)
|
21 |
|
|
sections.append((secnum,secname))
|
22 |
|
|
print "Sections:\n" + str(sections)
|
23 |
|
|
return sections
|
24 |
|
|
|
25 |
|
|
helpmsg = \
|
26 |
|
|
'''Usage:
|
27 |
|
|
lmamove.py <filename> <[<op>]offset>
|
28 |
|
|
|
29 |
|
|
Where <filename> is the file to modify, <offset> is the offset to be added,
|
30 |
|
|
subtracted or assigned, depending on the <op>, which can be either + or -
|
31 |
|
|
|
32 |
|
|
!!! NOTE THIS TOOL IS NOT VERY USEFUL BECAUSE IT TURNS OUT THAT SOME SECTIONS
|
33 |
|
|
ARE LIKELY TO BE PUT TOGETHER INTO THE SAME SEGMENT. For example (.text with .rodata)
|
34 |
|
|
and (.data with .bss) Therefore moving one sectoin's LMA confuses what to do with the
|
35 |
|
|
other section. The segment layout is almost always not same as initial after LMA
|
36 |
|
|
modification with objcopy. !!!
|
37 |
|
|
'''
|
38 |
|
|
|
39 |
|
|
def check_args():
|
40 |
|
|
if len(sys.argv) < 3:
|
41 |
|
|
print helpmsg
|
42 |
|
|
sys.exit()
|
43 |
|
|
filename = sys.argv[1]
|
44 |
|
|
if not os.path.exists(filename):
|
45 |
|
|
print "Given path: " + filename + " does not exist.\n"
|
46 |
|
|
sys.exit()
|
47 |
|
|
|
48 |
|
|
def move_sections(path, sections, op, offset):
|
49 |
|
|
for secnum, secname in sections:
|
50 |
|
|
os.system(objcopy + " --change-section-lma " + secname + op + offset + " " + path)
|
51 |
|
|
|
52 |
|
|
def lmamove():
|
53 |
|
|
'''
|
54 |
|
|
Moves an ARM ELF executable's LMA by moving each of its sections by
|
55 |
|
|
the given offset. It uses binutils (namely readelf and objcopy) to do
|
56 |
|
|
the actual work. Normally objcopy supports a similar operation; moving
|
57 |
|
|
of VMA of the whole program by --adjust-vma switch. But it only supports
|
58 |
|
|
modifying LMAs by section. Therefore this script extracts all loadable
|
59 |
|
|
section names and moves them one by one in order to move the whole program.
|
60 |
|
|
'''
|
61 |
|
|
check_args()
|
62 |
|
|
filename = sys.argv[1]
|
63 |
|
|
offset = sys.argv[2]
|
64 |
|
|
|
65 |
|
|
if offset[0] in "+-":
|
66 |
|
|
op = offset[0]
|
67 |
|
|
offset = offset[1:]
|
68 |
|
|
else:
|
69 |
|
|
op = "+"
|
70 |
|
|
|
71 |
|
|
if offset[:1] == "0x":
|
72 |
|
|
offset = int(offset, 16)
|
73 |
|
|
section_names = get_section_names(filename)
|
74 |
|
|
move_sections(filename, section_names, op, offset)
|
75 |
|
|
print("Done.\n")
|
76 |
|
|
|
77 |
|
|
if __name__ == "__main__":
|
78 |
|
|
lmamove()
|