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