-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathBuildApp.py
145 lines (115 loc) · 4.78 KB
/
BuildApp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import os
import sys
import subprocess
import argparse
from bintotxt import doBinToTxt
appdir = os.path.dirname(os.path.realpath(__file__))
EXPECTED_DIR_STRUCTURE = """ .
├── build-leros-llvm
│ └─── bin
├── leros-lib
│ └─── runtime
└── VelonaCore
└─── applications <- you are here
└─── ${TARGET}
"""
def getSectionSizes(elf):
""" Decodes a readelf -S output to read the sizes of ELF sections;
ie. decodes the following output:
There are 8 section headers, starting at offset 0x235c:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 001000 0003f2 00 AX 0 0 4
[ 2] .data NOBITS 20000000 002000 000000 00 AX 0 0 1
...
"""
headers = subprocess.check_output(["readelf", "-S", elf]).decode('UTF-8')
sectionSizes = {}
for line in headers.splitlines():
line = line.split()
if line and line[0].startswith('['):
if line[2].startswith('.'):
sectionSizes[line[2]] = int(line[6], 16)
return (headers, sectionSizes)
def buildTarget(target):
output_files = []
load_info = ""
# Ensure we are in the VelonaCore/applications folder
os.chdir(appdir)
def VerifyDirExists(dir):
if not os.path.exists(dir):
print("Could not find directory: " + appdir + "/" + dir)
print("Ensure that the following directory structure exists:")
print(EXPECTED_DIR_STRUCTURE)
sys.exit(1)
def TryCall(cmd):
if subprocess.call(cmd) != 0:
print(cmd[0] + " command failed, aborting...")
sys.exit(1)
# Verify directory layout
VerifyDirExists("../../" + "build-leros-llvm")
VerifyDirExists("../../" + "leros-lib")
VerifyDirExists("../../" + "VelonaCore")
VerifyDirExists(target)
# Try to create mem_init folder if not there
TryCall(["mkdir", "-p", "../VelonaCore.srcs/sources_1/mem_init"])
# Generate filenames
elf_fn = target + "/" + target
textseg_bin_fn = elf_fn + ".bin.text"
textseg_txt_fn = "../VelonaCore.srcs/sources_1/mem_init/" + "app.text"
dataseg_bin_fn = elf_fn + ".bin.data"
dataseg_txt_fn = "../VelonaCore.srcs/sources_1/mem_init/" + "app.data"
# Build app using Makefile
TryCall(["make", "TARGET="+target])
output_files.append(elf_fn)
# Extract the raw binary segments using objcopy.
# Before using llvm-objcopy, it must be determined whether a section actually
# contains information -llvm-objcopy crashes if one tries to objcopy a
# section which is non-existant or has a size = 0
(headers, sectionSizes) = getSectionSizes(elf_fn)
data_section_cmds = []
if ".data" in sectionSizes and sectionSizes[".data"] != 0:
data_section_cmds.append("-j")
data_section_cmds.append(".data")
if ".bss" in sectionSizes and sectionSizes[".bss"] != 0:
data_section_cmds.append("-j")
data_section_cmds.append(".bss")
TryCall(["../../build-leros-llvm/bin/llvm-objcopy",
"-O", "binary", "-j", ".text", elf_fn, textseg_bin_fn])
# Convert raw binary to textual binary
doBinToTxt(textseg_bin_fn, textseg_txt_fn, bytesPerLine=2)
# cleanup
TryCall(["rm", "-f", textseg_bin_fn])
output_files.append(textseg_txt_fn)
if data_section_cmds:
TryCall(["../../build-leros-llvm/bin/llvm-objcopy",
"-O", "binary", *data_section_cmds, elf_fn, dataseg_bin_fn])
doBinToTxt(dataseg_bin_fn, dataseg_txt_fn, bytesPerLine=4)
TryCall(["rm", "-f", dataseg_bin_fn])
output_files.append(dataseg_txt_fn)
else:
# A blank file is written to allow for the VHDL sources to stay constant
print("No .data or .bss section in output .elf file")
print("Writing blank app.data file")
with open(dataseg_txt_fn, 'w') as fo:
fo.write('')
return (output_files, headers)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("app", help="Name of application to build")
args = parser.parse_args()
if args.app == None:
parser.print_help()
sys.exit(1)
target = args.app.replace('/','')
print(
"============================ VelonaCore Build system ===========================")
print("Starting build of application: " + target + "\n")
(output_files, headers) = buildTarget(target)
print("\nApplication \"" + target + "\" built successfully")
print("Output files are:")
for f in output_files:
print(" " + f)
print(
"================================================================================")