https://github.com/akkartik/mu/blob/master/028translate.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 :(before "End Main")
20 if (is_equal(argv[1], "translate")) {
21 START_TRACING_UNTIL_END_OF_SCOPE;
22 reset();
23
24 program p;
25 string output_filename;
26 for (int i = 2; i < argc; ++i) {
27 if (is_equal(argv[i], "-o")) {
28 ++i;
29 if (i >= argc) {
30 print_translate_usage();
31 cerr << "'-o' must be followed by a filename to write results to\n";
32 exit(1);
33 }
34 output_filename = argv[i];
35 }
36 else {
37 trace(2, "parse") << argv[i] << end();
38 ifstream fin(argv[i]);
39 if (!fin) {
40 cerr << "could not open " << argv[i] << '\n';
41 return 1;
42 }
43 parse(fin, p);
44 if (trace_contains_errors()) return 1;
45 }
46 }
47 if (p.segments.empty()) {
48 print_translate_usage();
49 cerr << "nothing to do; must provide at least one file to read\n";
50 exit(1);
51 }
52 if (output_filename.empty()) {
53 print_translate_usage();
54 cerr << "must provide a filename to write to using '-o'\n";
55 exit(1);
56 }
57 trace(2, "transform") << "begin" << end();
58 transform(p);
59 if (trace_contains_errors()) return 1;
60 trace(2, "translate") << "begin" << end();
61 save_elf(p, output_filename);
62 if (trace_contains_errors()) {
63 unlink(output_filename.c_str());
64 return 1;
65 }
66
67 return 0;
68 }
69
70 :(code)
71 void print_translate_usage() {
72 cerr << "Usage: subx translate file1 file2 ... -o output\n";
73 }
74
75
76 void save_elf(const program& p, const string& filename) {
77 ofstream out(filename.c_str(), ios::binary);
78 save_elf(p, out);
79 out.close();
80 }
81
82 void save_elf(const program& p, ostream& out) {
83
84 if (p.entry == 0) {
85 raise << "no 'Entry' label found\n" << end();
86 return;
87 }
88 if (find(p, "data") == NULL) {
89 raise << "must include a 'data' segment\n" << end();
90 return;
91 }
92
93 write_elf_header(out, p);
94 for (size_t i = 0; i < p.segments.size(); ++i)
95 write_segment(p.segments.at(i), out);
96 }
97
98 void write_elf_header(ostream& out, const program& p) {
99 char c = '\0';
100 #define O(X) c = (X); out.write(&c, sizeof(c))
101
102 #define emit(X) out.write(reinterpret_cast<const char*>(&X), sizeof(X))
103
104
105 O(0x7f); O(0x45); O(0x4c); O(0x46);
106 O(0x1);
107 O(0x1);
108 O(0x1); O(0x0);
109 for (size_t i = 0; i < 8; ++i) { O(0x0); }
110
111 O(0x02); O(0x00);
112
113 O(0x03); O(0x00);
114
115 O(0x01); O(0x00); O(0x00); O(0x00);
116
117 uint32_t e_entry = p.entry;
118
119 emit(e_entry);
120
121 uint32_t e_phoff = 0x34;
122 emit(e_phoff);
123
124 uint32_t dummy32 = 0;
125 emit(dummy32);
126
127 emit(dummy32);
128
129 uint16_t e_ehsize = 0x34;
130 emit(e_ehsize);
131
132 uint16_t e_phentsize = 0x20;
133 emit(e_phentsize);
134
135 uint16_t e_phnum = SIZE(p.segments);
136 emit(e_phnum);
137
138 uint16_t dummy16 = 0x0;
139 emit(dummy16);
140
141 emit(dummy16);
142
143 emit(dummy16);
144
145 uint32_t p_offset = 0x34 + SIZE(p.segments)*0x20;
146 for (int i = 0; i < SIZE(p.segments); ++i) {
147 const segment& curr = p.segments.at(i);
148
149
150 uint32_t p_type = 0x1;
151 emit(p_type);
152
153 emit(p_offset);
154
155 uint32_t p_start = curr.start;
156 emit(p_start);
157
158 emit(p_start);
159
160 uint32_t size = num_words(curr);
161 assert(p_offset + size < SEGMENT_ALIGNMENT);
162 emit(size);
163
164 emit(size);
165
166 uint32_t p_flags = (curr.name == "code") ? 0x5 : 0x6;
167 emit(p_flags);
168
169
170
171
172
173
174
175
176
177
178
179
180 uint32_t p_align = 0x1000;
181 emit(p_align);
182 if (p_offset % p_align != p_start % p_align) {
183 raise << "segment starting at 0x" << HEXWORD << p_start << " is improperly aligned; alignment for p_offset " << p_offset << " should be " << (p_offset % p_align) << " but is " << (p_start % p_align) << '\n' << end();
184 return;
185 }
186
187
188 p_offset += size;
189 }
190 #undef O
191 #undef emit
192 }
193
194 void write_segment(const segment& s, ostream& out) {
195 for (int i = 0; i < SIZE(s.lines); ++i) {
196 const vector<word>& w = s.lines.at(i).words;
197 for (int j = 0; j < SIZE(w); ++j) {
198 uint8_t x = hex_byte(w.at(j).data);
199 out.write(reinterpret_cast<const char*>(&x), 1);
200 }
201 }
202 }
203
204 uint32_t num_words(const segment& s) {
205 uint32_t sum = 0;
206 for (int i = 0; i < SIZE(s.lines); ++i)
207 sum += SIZE(s.lines.at(i).words);
208 return sum;
209 }
210
211 :(before "End Includes")
212 using std::ios;