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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 012elf.cc</title>
<meta name="Generator" content="Vim/8.1">
<meta name="plugin-version" content="vim8.1_v1">
<meta name="syntax" content="cpp">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal-light">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #c6c6c6; }
body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; }
a { color:inherit; }
* { font-size:12pt; font-size: 1em; }
.CommentedCode { color: #8a8a8a; }
.LineNr { }
.Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; }
.Comment { color: #005faf; }
.Delimiter { color: #c000c0; }
.Special { color: #d70000; }
.Identifier { color: #af5f00; }
.Constant { color: #008787; }
.PreProc { color: #c000c0; }
.cSpecial { color: #008000; }
-->
</style>
<script type='text/javascript'>
<!--
/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
var lineNum;
lineNum = window.location.hash;
lineNum = lineNum.substr(1); /* strip off '#' */
if (lineNum.indexOf('L') == -1) {
lineNum = 'L'+lineNum;
}
var lineElem = document.getElementById(lineNum);
/* Always jump to new location even if the line was hidden inside a fold, or
* we corrected the raw number to a line ID.
*/
if (lineElem) {
lineElem.scrollIntoView(true);
}
return true;
}
if ('onhashchange' in window) {
window.onhashchange = JumpToLine;
}
-->
</script>
</head>
<body onload='JumpToLine();'>
<a href='https://github.com/akkartik/mu/blob/master/012elf.cc'>https://github.com/akkartik/mu/blob/master/012elf.cc</a>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="Comment">//: Loading SubX programs from ELF binaries.</span>
<span id="L2" class="LineNr"> 2 </span><span class="Comment">//: This will allow us to run them natively on a Linux kernel.</span>
<span id="L3" class="LineNr"> 3 </span><span class="Comment">//: Based on <a href="https://github.com/kragen/stoneknifeforth/blob/702d2ebe1b/386.c">https://github.com/kragen/stoneknifeforth/blob/702d2ebe1b/386.c</a></span>
<span id="L4" class="LineNr"> 4 </span>
<span id="L5" class="LineNr"> 5 </span><span class="Delimiter">:(before "End Main")</span>
<span id="L6" class="LineNr"> 6 </span>assert<span class="Delimiter">(</span>argc > <span class="Constant">1</span><span class="Delimiter">);</span>
<span id="L7" class="LineNr"> 7 </span><span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L102'>is_equal</a><span class="Delimiter">(</span>argv[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span>
<span id="L8" class="LineNr"> 8 </span> <span class="Comment">// Outside of tests, traces must be explicitly requested.</span>
<span id="L9" class="LineNr"> 9 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><span class="Special"><a href='003trace.cc.html#L448'>Trace_file</a></span><span class="Delimiter">.</span>is_open<span class="Delimiter">())</span> <span class="Special"><a href='003trace.cc.html#L72'>Trace_stream</a></span> = <span class="Normal">new</span> trace_stream<span class="Delimiter">;</span>
<span id="L10" class="LineNr"> 10 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"=== Starting to run"</span> << end<span class="Delimiter">();</span>
<span id="L11" class="LineNr"> 11 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>argc <= <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L12" class="LineNr"> 12 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Not enough arguments provided.\n"</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L13" class="LineNr"> 13 </span> <span class="Delimiter">}</span>
<span id="L14" class="LineNr"> 14 </span> <a href='000organization.cc.html#L150'>reset</a><span class="Delimiter">();</span>
<span id="L15" class="LineNr"> 15 </span> cerr << std::hex<span class="Delimiter">;</span>
<span id="L16" class="LineNr"> 16 </span> <a href='012elf.cc.html#L24'>load_elf</a><span class="Delimiter">(</span>argv[<span class="Constant">2</span>]<span class="Delimiter">,</span> argc<span class="Delimiter">,</span> argv<span class="Delimiter">);</span>
<span id="L17" class="LineNr"> 17 </span> <span class="Normal">while</span> <span class="Delimiter">(</span><a href='010vm.cc.html#L26'>EIP</a> < <span class="Special"><a href='010vm.cc.html#L157'>End_of_program</a></span><span class="Delimiter">)</span> <span class="Comment">// weak final-gasp termination check</span>
<span id="L18" class="LineNr"> 18 </span> <a href='010vm.cc.html#L264'>run_one_instruction</a><span class="Delimiter">();</span>
<span id="L19" class="LineNr"> 19 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"executed past end of the world: "</span> << <a href='010vm.cc.html#L26'>EIP</a> << <span class="Constant">" vs "</span> << <span class="Special"><a href='010vm.cc.html#L157'>End_of_program</a></span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span>
<span id="L20" class="LineNr"> 20 </span> <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span>
<span id="L21" class="LineNr"> 21 </span><span class="Delimiter">}</span>
<span id="L22" class="LineNr"> 22 </span>
<span id="L23" class="LineNr"> 23 </span><span class="Delimiter">:(code)</span>
<span id="L24" class="LineNr"> 24 </span><span class="Normal">void</span> <a href='012elf.cc.html#L24'>load_elf</a><span class="Delimiter">(</span><span class="Normal">const</span> string& filename<span class="Delimiter">,</span> <span class="Normal">int</span> argc<span class="Delimiter">,</span> <span class="Normal">char</span>* argv[]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L25" class="LineNr"> 25 </span> <span class="Normal">int</span> fd = open<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> O_RDONLY<span class="Delimiter">);</span>
<span id="L26" class="LineNr"> 26 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>fd < <span class="Constant">0</span><span class="Delimiter">)</span> <a href='003trace.cc.html#L228'>raise</a> << filename<span class="Delimiter">.</span>c_str<span class="Delimiter">()</span> << <span class="Constant">": open"</span> << <a href='012elf.cc.html#L179'>perr</a><span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L27" class="LineNr"> 27 </span> <span class="Normal">off_t</span> size = lseek<span class="Delimiter">(</span>fd<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">SEEK_END</span><span class="Delimiter">);</span>
<span id="L28" class="LineNr"> 28 </span> lseek<span class="Delimiter">(</span>fd<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">SEEK_SET</span><span class="Delimiter">);</span>
<span id="L29" class="LineNr"> 29 </span> <span class="Normal">uint8_t</span>* elf_contents = <span class="Normal">static_cast</span><<span class="Normal">uint8_t</span>*><span class="Delimiter">(</span>malloc<span class="Delimiter">(</span>size<span class="Delimiter">));</span>
<span id="L30" class="LineNr"> 30 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>elf_contents == <span class="Constant">NULL</span><span class="Delimiter">)</span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"malloc("</span> << size << <span class="Constant">')'</span> << <a href='012elf.cc.html#L179'>perr</a><span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L31" class="LineNr"> 31 </span> <span class="Normal">ssize_t</span> read_size = read<span class="Delimiter">(</span>fd<span class="Delimiter">,</span> elf_contents<span class="Delimiter">,</span> size<span class="Delimiter">);</span>
<span id="L32" class="LineNr"> 32 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>size != read_size<span class="Delimiter">)</span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"read → "</span> << size << <span class="Constant">" (!= "</span> << read_size << <span class="Constant">')'</span> << <a href='012elf.cc.html#L179'>perr</a><span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L33" class="LineNr"> 33 </span> <a href='012elf.cc.html#L37'>load_elf_contents</a><span class="Delimiter">(</span>elf_contents<span class="Delimiter">,</span> size<span class="Delimiter">,</span> argc<span class="Delimiter">,</span> argv<span class="Delimiter">);</span>
<span id="L34" class="LineNr"> 34 </span> free<span class="Delimiter">(</span>elf_contents<span class="Delimiter">);</span>
<span id="L35" class="LineNr"> 35 </span><span class="Delimiter">}</span>
<span id="L36" class="LineNr"> 36 </span>
<span id="L37" class="LineNr"> 37 </span><span class="Normal">void</span> <a href='012elf.cc.html#L37'>load_elf_contents</a><span class="Delimiter">(</span><span class="Normal">uint8_t</span>* elf_contents<span class="Delimiter">,</span> <span class="Normal">size_t</span> size<span class="Delimiter">,</span> <span class="Normal">int</span> argc<span class="Delimiter">,</span> <span class="Normal">char</span>* argv[]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L38" class="LineNr"> 38 </span> <span class="Normal">uint8_t</span> magic[<span class="Constant">5</span>] = <span class="Delimiter">{</span><span class="Constant">0</span><span class="Delimiter">};</span>
<span id="L39" class="LineNr"> 39 </span> memcpy<span class="Delimiter">(</span>magic<span class="Delimiter">,</span> elf_contents<span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">);</span>
<span id="L40" class="LineNr"> 40 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>memcmp<span class="Delimiter">(</span>magic<span class="Delimiter">,</span> <span class="Constant">"\177ELF"</span><span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">)</span> != <span class="Constant">0</span><span class="Delimiter">)</span>
<span id="L41" class="LineNr"> 41 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Invalid ELF file; starts with \"" << magic << '"</span>' << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L42" class="LineNr"> 42 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>elf_contents[<span class="Constant">4</span>] != <span class="Constant">1</span><span class="Delimiter">)</span>
<span id="L43" class="LineNr"> 43 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Only 32-bit ELF files (4-byte words; virtual addresses up to 4GB) supported.\n"</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L44" class="LineNr"> 44 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>elf_contents[<span class="Constant">5</span>] != <span class="Constant">1</span><span class="Delimiter">)</span>
<span id="L45" class="LineNr"> 45 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Only little-endian ELF files supported.\n"</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L46" class="LineNr"> 46 </span> <span class="Comment">// unused: remaining 10 bytes of e_ident</span>
<span id="L47" class="LineNr"> 47 </span> <span class="Normal">uint32_t</span> e_machine_type = <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span>&elf_contents[<span class="Constant">16</span>]<span class="Delimiter">);</span>
<span id="L48" class="LineNr"> 48 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>e_machine_type != <span class="Constant">0x00030002</span><span class="Delimiter">)</span>
<span id="L49" class="LineNr"> 49 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"ELF type/machine 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << e_machine_type << <span class="Constant">" isn't i386 executable\n"</span> << die<span class="Delimiter">();</span>
<span id="L50" class="LineNr"> 50 </span> <span class="Comment">// unused: e_version. We only support version 1, and later versions will be backwards compatible.</span>
<span id="L51" class="LineNr"> 51 </span> <span class="Normal">uint32_t</span> e_entry = <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span>&elf_contents[<span class="Constant">24</span>]<span class="Delimiter">);</span>
<span id="L52" class="LineNr"> 52 </span> <span class="Normal">uint32_t</span> e_phoff = <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span>&elf_contents[<span class="Constant">28</span>]<span class="Delimiter">);</span>
<span id="L53" class="LineNr"> 53 </span> <span class="Comment">// unused: e_shoff</span>
<span id="L54" class="LineNr"> 54 </span> <span class="Comment">// unused: e_flags</span>
<span id="L55" class="LineNr"> 55 </span> <span class="Normal">uint32_t</span> e_ehsize = <a href='012elf.cc.html#L174'>u16_in</a><span class="Delimiter">(</span>&elf_contents[<span class="Constant">40</span>]<span class="Delimiter">);</span>
<span id="L56" class="LineNr"> 56 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>e_ehsize < <span class="Constant">52</span><span class="Delimiter">)</span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Invalid binary; ELF header too small\n"</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L57" class="LineNr"> 57 </span> <span class="Normal">uint32_t</span> e_phentsize = <a href='012elf.cc.html#L174'>u16_in</a><span class="Delimiter">(</span>&elf_contents[<span class="Constant">42</span>]<span class="Delimiter">);</span>
<span id="L58" class="LineNr"> 58 </span> <span class="Normal">uint32_t</span> e_phnum = <a href='012elf.cc.html#L174'>u16_in</a><span class="Delimiter">(</span>&elf_contents[<span class="Constant">44</span>]<span class="Delimiter">);</span>
<span id="L59" class="LineNr"> 59 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Constant">90</span><span class="Delimiter">,</span> <span class="Constant">"load"</span><span class="Delimiter">)</span> << e_phnum << <span class="Constant">" entries in the program header, each "</span> << e_phentsize << <span class="Constant">" bytes long"</span> << end<span class="Delimiter">();</span>
<span id="L60" class="LineNr"> 60 </span> <span class="Comment">// unused: e_shentsize</span>
<span id="L61" class="LineNr"> 61 </span> <span class="Comment">// unused: e_shnum</span>
<span id="L62" class="LineNr"> 62 </span> <span class="Comment">// unused: e_shstrndx</span>
<span id="L63" class="LineNr"> 63 </span>
<span id="L64" class="LineNr"> 64 </span> set<<span class="Normal">uint32_t</span>> overlap<span class="Delimiter">;</span> <span class="Comment">// to detect overlapping segments</span>
<span id="L65" class="LineNr"> 65 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">size_t</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < e_phnum<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span>
<span id="L66" class="LineNr"> 66 </span> <a href='012elf.cc.html#L107'>load_segment_from_program_header</a><span class="Delimiter">(</span>elf_contents<span class="Delimiter">,</span> i<span class="Delimiter">,</span> size<span class="Delimiter">,</span> e_phoff + i*e_phentsize<span class="Delimiter">,</span> e_ehsize<span class="Delimiter">,</span> overlap<span class="Delimiter">);</span>
<span id="L67" class="LineNr"> 67 </span>
<span id="L68" class="LineNr"> 68 </span> <span class="Comment">// initialize code and stack</span>
<span id="L69" class="LineNr"> 69 </span> assert<span class="Delimiter">(</span>overlap<span class="Delimiter">.</span>find<span class="Delimiter">(</span><a href='012elf.cc.html#L152'>STACK_SEGMENT</a><span class="Delimiter">)</span> == overlap<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
<span id="L70" class="LineNr"> 70 </span> <span class="Special"><a href='010vm.cc.html#L154'>Mem</a></span><span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>vma<span class="Delimiter">(</span><a href='012elf.cc.html#L152'>STACK_SEGMENT</a><span class="Delimiter">));</span>
<span id="L71" class="LineNr"> 71 </span> assert<span class="Delimiter">(</span>overlap<span class="Delimiter">.</span>find<span class="Delimiter">(</span><a href='012elf.cc.html#L153'>AFTER_STACK</a><span class="Delimiter">)</span> == overlap<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
<span id="L72" class="LineNr"> 72 </span> <span class="Comment">// The stack grows downward.</span>
<span id="L73" class="LineNr"> 73 </span> <span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u = <a href='012elf.cc.html#L153'>AFTER_STACK</a><span class="Delimiter">;</span>
<span id="L74" class="LineNr"> 74 </span> <span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[EBP]<span class="Delimiter">.</span>u = <span class="Constant">0</span><span class="Delimiter">;</span>
<span id="L75" class="LineNr"> 75 </span> <a href='010vm.cc.html#L26'>EIP</a> = e_entry<span class="Delimiter">;</span>
<span id="L76" class="LineNr"> 76 </span>
<span id="L77" class="LineNr"> 77 </span> <span class="Comment">// initialize args on stack</span>
<span id="L78" class="LineNr"> 78 </span> <span class="Comment">// no envp for now</span>
<span id="L79" class="LineNr"> 79 </span> <span class="Comment">// we wastefully use a separate page of memory for argv</span>
<span id="L80" class="LineNr"> 80 </span> <span class="Special"><a href='010vm.cc.html#L154'>Mem</a></span><span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>vma<span class="Delimiter">(</span><a href='012elf.cc.html#L154'>ARGV_DATA_SEGMENT</a><span class="Delimiter">));</span>
<span id="L81" class="LineNr"> 81 </span> <span class="Normal">uint32_t</span> argv_data = <a href='012elf.cc.html#L154'>ARGV_DATA_SEGMENT</a><span class="Delimiter">;</span>
<span id="L82" class="LineNr"> 82 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = argc-<span class="Constant">1</span><span class="Delimiter">;</span> i >= <span class="Comment">/*</span><span class="Comment">skip 'subx_bin' and 'run'</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">;</span> --i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L83" class="LineNr"> 83 </span> <a href='012elf.cc.html#L94'>push</a><span class="Delimiter">(</span>argv_data<span class="Delimiter">);</span>
<span id="L84" class="LineNr"> 84 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">size_t</span> j = <span class="Constant">0</span><span class="Delimiter">;</span> j <= strlen<span class="Delimiter">(</span>argv[i]<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L85" class="LineNr"> 85 </span> assert<span class="Delimiter">(</span>overlap<span class="Delimiter">.</span>find<span class="Delimiter">(</span>argv_data<span class="Delimiter">)</span> == overlap<span class="Delimiter">.</span>end<span class="Delimiter">());</span> <span class="Comment">// don't bother comparing ARGV and STACK</span>
<span id="L86" class="LineNr"> 86 </span> <a href='010vm.cc.html#L231'>write_mem_u8</a><span class="Delimiter">(</span>argv_data<span class="Delimiter">,</span> argv[i][j]<span class="Delimiter">);</span>
<span id="L87" class="LineNr"> 87 </span> argv_data += <span class="Normal">sizeof</span><span class="Delimiter">(</span><span class="Normal">char</span><span class="Delimiter">);</span>
<span id="L88" class="LineNr"> 88 </span> assert<span class="Delimiter">(</span>argv_data < <a href='012elf.cc.html#L154'>ARGV_DATA_SEGMENT</a> + <a href='010vm.cc.html#L89'>SEGMENT_ALIGNMENT</a><span class="Delimiter">);</span>
<span id="L89" class="LineNr"> 89 </span> <span class="Delimiter">}</span>
<span id="L90" class="LineNr"> 90 </span> <span class="Delimiter">}</span>
<span id="L91" class="LineNr"> 91 </span> <a href='012elf.cc.html#L94'>push</a><span class="Delimiter">(</span>argc-<span class="Comment">/*</span><span class="Comment">skip 'subx_bin' and 'run'</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">);</span>
<span id="L92" class="LineNr"> 92 </span><span class="Delimiter">}</span>
<span id="L93" class="LineNr"> 93 </span>
<span id="L94" class="LineNr"> 94 </span><span class="Normal">void</span> <a href='012elf.cc.html#L94'>push</a><span class="Delimiter">(</span><span class="Normal">uint32_t</span> val<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L95" class="LineNr"> 95 </span> <span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u -= <span class="Constant">4</span><span class="Delimiter">;</span>
<span id="L96" class="LineNr"> 96 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u < <a href='012elf.cc.html#L152'>STACK_SEGMENT</a><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L97" class="LineNr"> 97 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"The stack overflowed its segment. "</span>
<span id="L98" class="LineNr"> 98 </span> << <span class="Constant">"Maybe SPACE_FOR_SEGMENT should be larger? "</span>
<span id="L99" class="LineNr"> 99 </span> << <span class="Constant">"Or you need to carve out an exception for the stack segment "</span>
<span id="L100" class="LineNr">100 </span> << <span class="Constant">"to be larger.\n"</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L101" class="LineNr">101 </span> <span class="Delimiter">}</span>
<span id="L102" class="LineNr">102 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Special">Callstack_depth</span>+<span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"decrementing <a href='010vm.cc.html#L14'>ESP</a> to 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << <span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u << end<span class="Delimiter">();</span>
<span id="L103" class="LineNr">103 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Special">Callstack_depth</span>+<span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"pushing value 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << val << end<span class="Delimiter">();</span>
<span id="L104" class="LineNr">104 </span> <a href='010vm.cc.html#L239'>write_mem_u32</a><span class="Delimiter">(</span><span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u<span class="Delimiter">,</span> val<span class="Delimiter">);</span>
<span id="L105" class="LineNr">105 </span><span class="Delimiter">}</span>
<span id="L106" class="LineNr">106 </span>
<span id="L107" class="LineNr">107 </span><span class="Normal">void</span> <a href='012elf.cc.html#L107'>load_segment_from_program_header</a><span class="Delimiter">(</span><span class="Normal">uint8_t</span>* elf_contents<span class="Delimiter">,</span> <span class="Normal">int</span> segment_index<span class="Delimiter">,</span> <span class="Normal">size_t</span> size<span class="Delimiter">,</span> <span class="Normal">uint32_t</span> offset<span class="Delimiter">,</span> <span class="Normal">uint32_t</span> e_ehsize<span class="Delimiter">,</span> set<<span class="Normal">uint32_t</span>>& overlap<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L108" class="LineNr">108 </span> <span class="Normal">uint32_t</span> p_type = <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span>&elf_contents[offset]<span class="Delimiter">);</span>
<span id="L109" class="LineNr">109 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Constant">90</span><span class="Delimiter">,</span> <span class="Constant">"load"</span><span class="Delimiter">)</span> << <span class="Constant">"program header at offset "</span> << offset << <span class="Constant">": type "</span> << p_type << end<span class="Delimiter">();</span>
<span id="L110" class="LineNr">110 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>p_type != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L111" class="LineNr">111 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Constant">90</span><span class="Delimiter">,</span> <span class="Constant">"load"</span><span class="Delimiter">)</span> << <span class="Constant">"ignoring segment at offset "</span> << offset << <span class="Constant">" of non PT_LOAD type "</span> << p_type << <span class="Constant">" (see <a href="http://refspecs.linuxbase.org/elf/elf.pdf)">http://refspecs.linuxbase.org/elf/elf.pdf)</a>"</span> << end<span class="Delimiter">();</span>
<span id="L112" class="LineNr">112 </span> <span class="Identifier">return</span><span class="Delimiter">;</span>
<span id="L113" class="LineNr">113 </span> <span class="Delimiter">}</span>
<span id="L114" class="LineNr">114 </span> <span class="Normal">uint32_t</span> p_offset = <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span>&elf_contents[offset + <span class="Constant">4</span>]<span class="Delimiter">);</span>
<span id="L115" class="LineNr">115 </span> <span class="Normal">uint32_t</span> p_vaddr = <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span>&elf_contents[offset + <span class="Constant">8</span>]<span class="Delimiter">);</span>
<span id="L116" class="LineNr">116 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>e_ehsize > p_vaddr<span class="Delimiter">)</span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Invalid binary; program header overlaps ELF header\n"</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L117" class="LineNr">117 </span> <span class="Comment">// unused: p_paddr</span>
<span id="L118" class="LineNr">118 </span> <span class="Normal">uint32_t</span> p_filesz = <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span>&elf_contents[offset + <span class="Constant">16</span>]<span class="Delimiter">);</span>
<span id="L119" class="LineNr">119 </span> <span class="Normal">uint32_t</span> p_memsz = <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span>&elf_contents[offset + <span class="Constant">20</span>]<span class="Delimiter">);</span>
<span id="L120" class="LineNr">120 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>p_filesz != p_memsz<span class="Delimiter">)</span>
<span id="L121" class="LineNr">121 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Can't yet handle segments where p_filesz != p_memsz (see <a href="http://refspecs.linuxbase.org/elf/elf.pdf)">http://refspecs.linuxbase.org/elf/elf.pdf)</a>\n"</span> << die<span class="Delimiter">();</span>
<span id="L122" class="LineNr">122 </span>
<span id="L123" class="LineNr">123 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>p_offset + p_filesz > size<span class="Delimiter">)</span>
<span id="L124" class="LineNr">124 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Invalid binary; segment at offset "</span> << offset << <span class="Constant">" is too large: wants to end at "</span> << p_offset+p_filesz << <span class="Constant">" but the file ends at "</span> << size << <span class="cSpecial">'\n'</span> << <a href='003trace.cc.html#L173'>die</a><span class="Delimiter">();</span>
<span id="L125" class="LineNr">125 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>p_memsz >= <a href='010vm.cc.html#L89'>SEGMENT_ALIGNMENT</a><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L126" class="LineNr">126 </span> <a href='003trace.cc.html#L228'>raise</a> << <span class="Constant">"Code segment too small for SubX; for now please manually increase SEGMENT_ALIGNMENT.\n"</span> << end<span class="Delimiter">();</span>
<span id="L127" class="LineNr">127 </span> <span class="Identifier">return</span><span class="Delimiter">;</span>
<span id="L128" class="LineNr">128 </span> <span class="Delimiter">}</span>
<span id="L129" class="LineNr">129 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Constant">90</span><span class="Delimiter">,</span> <span class="Constant">"load"</span><span class="Delimiter">)</span> << <span class="Constant">"blitting file offsets ("</span> << p_offset << <span class="Constant">", "</span> << <span class="Delimiter">(</span>p_offset+p_filesz<span class="Delimiter">)</span> << <span class="Constant">") to addresses ("</span> << p_vaddr << <span class="Constant">", "</span> << <span class="Delimiter">(</span>p_vaddr+p_memsz<span class="Delimiter">)</span> << <span class="Constant">')'</span> << end<span class="Delimiter">();</span>
<span id="L130" class="LineNr">130 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>size > p_memsz<span class="Delimiter">)</span> size = p_memsz<span class="Delimiter">;</span>
<span id="L131" class="LineNr">131 </span> <span class="Special"><a href='010vm.cc.html#L154'>Mem</a></span><span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>vma<span class="Delimiter">(</span>p_vaddr<span class="Delimiter">));</span>
<span id="L132" class="LineNr">132 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">size_t</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < p_filesz<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L133" class="LineNr">133 </span> assert<span class="Delimiter">(</span>overlap<span class="Delimiter">.</span>find<span class="Delimiter">(</span>p_vaddr+i<span class="Delimiter">)</span> == overlap<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
<span id="L134" class="LineNr">134 </span> <a href='010vm.cc.html#L231'>write_mem_u8</a><span class="Delimiter">(</span>p_vaddr+i<span class="Delimiter">,</span> elf_contents[p_offset+i]<span class="Delimiter">);</span>
<span id="L135" class="LineNr">135 </span> overlap<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>p_vaddr+i<span class="Delimiter">);</span>
<span id="L136" class="LineNr">136 </span> <span class="Delimiter">}</span>
<span id="L137" class="LineNr">137 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>segment_index == <span class="Constant">0</span> && <span class="Special"><a href='010vm.cc.html#L157'>End_of_program</a></span> < p_vaddr+p_memsz<span class="Delimiter">)</span>
<span id="L138" class="LineNr">138 </span> <span class="Special"><a href='010vm.cc.html#L157'>End_of_program</a></span> = p_vaddr+p_memsz<span class="Delimiter">;</span>
<span id="L139" class="LineNr">139 </span><span class="Delimiter">}</span>
<span id="L140" class="LineNr">140 </span>
<span id="L141" class="LineNr">141 </span><span class="Delimiter">:(before "End Includes")</span>
<span id="L142" class="LineNr">142 </span><span class="Comment">// Very primitive/fixed/insecure ELF segments for now.</span>
<span id="L143" class="LineNr">143 </span><span class="Comment">// --- inaccessible: 0x00000000 -> 0x08047fff</span>
<span id="L144" class="LineNr">144 </span><span class="Comment">// code: 0x09000000 -> 0x09ffffff (specified in ELF binary)</span>
<span id="L145" class="LineNr">145 </span><span class="Comment">// data: 0x0a000000 -> 0x0affffff (specified in ELF binary)</span>
<span id="L146" class="LineNr">146 </span><span class="Comment">// --- heap gets mmap'd somewhere here ---</span>
<span id="L147" class="LineNr">147 </span><span class="Comment">// stack: 0xbdffffff -> 0xbd000000 (downward; not in ELF binary)</span>
<span id="L148" class="LineNr">148 </span><span class="Comment">// argv hack: 0xbf000000 -> 0xbfffffff (not in ELF binary)</span>
<span id="L149" class="LineNr">149 </span><span class="Comment">// --- reserved for kernel: 0xc0000000 -> ...</span>
<span id="L150" class="LineNr">150 </span><span class="Normal">const</span> <span class="Normal">uint32_t</span> <a href='012elf.cc.html#L150'>START_HEAP</a> = <span class="Constant">0x0b000000</span><span class="Delimiter">;</span>
<span id="L151" class="LineNr">151 </span><span class="Normal">const</span> <span class="Normal">uint32_t</span> <a href='012elf.cc.html#L151'>END_HEAP</a> = <span class="Constant">0xbd000000</span><span class="Delimiter">;</span>
<span id="L152" class="LineNr">152 </span><span class="Normal">const</span> <span class="Normal">uint32_t</span> <a href='012elf.cc.html#L152'>STACK_SEGMENT</a> = <span class="Constant">0xbd000000</span><span class="Delimiter">;</span>
<span id="L153" class="LineNr">153 </span><span class="Normal">const</span> <span class="Normal">uint32_t</span> <a href='012elf.cc.html#L153'>AFTER_STACK</a> = <span class="Constant">0xbe000000</span><span class="Delimiter">;</span>
<span id="L154" class="LineNr">154 </span><span class="Normal">const</span> <span class="Normal">uint32_t</span> <a href='012elf.cc.html#L154'>ARGV_DATA_SEGMENT</a> = <span class="Constant">0xbf000000</span><span class="Delimiter">;</span>
<span id="L155" class="LineNr">155 </span><span class="Comment">// When updating the above memory map, don't forget to update `mmap`'s</span>
<span id="L156" class="LineNr">156 </span><span class="Comment">// implementation in the 'syscalls' layer.</span>
<span id="L157" class="LineNr">157 </span><span class="Delimiter">:(before "End Dump Info for Instruction")</span>
<span id="L158" class="LineNr">158 </span><span class="CommentedCode">//? dump_stack(); // slow</span>
<span id="L159" class="LineNr">159 </span><span class="Delimiter">:(code)</span>
<span id="L160" class="LineNr">160 </span><span class="Normal">void</span> <a href='012elf.cc.html#L160'>dump_stack</a><span class="Delimiter">()</span> <span class="Delimiter">{</span>
<span id="L161" class="LineNr">161 </span> ostringstream out<span class="Delimiter">;</span>
<span id="L162" class="LineNr">162 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Special">Callstack_depth</span>+<span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"stack:"</span> << end<span class="Delimiter">();</span>
<span id="L163" class="LineNr">163 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">uint32_t</span> a = AFTER_STACK-<span class="Constant">4</span><span class="Delimiter">;</span> a > <span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u<span class="Delimiter">;</span> a -= <span class="Constant">4</span><span class="Delimiter">)</span>
<span id="L164" class="LineNr">164 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Special">Callstack_depth</span>+<span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">" 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << a << <span class="Constant">" => 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << <a href='010vm.cc.html#L172'>read_mem_u32</a><span class="Delimiter">(</span>a<span class="Delimiter">)</span> << end<span class="Delimiter">();</span>
<span id="L165" class="LineNr">165 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Special">Callstack_depth</span>+<span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">" 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << <span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u << <span class="Constant">" => 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << <a href='010vm.cc.html#L172'>read_mem_u32</a><span class="Delimiter">(</span><span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u<span class="Delimiter">)</span> << <span class="Constant">" <=== ESP"</span> << end<span class="Delimiter">();</span>
<span id="L166" class="LineNr">166 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">uint32_t</span> a = <span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u-<span class="Constant">4</span><span class="Delimiter">;</span> a > <span class="Special"><a href='010vm.cc.html#L25'>Reg</a></span>[ESP]<span class="Delimiter">.</span>u-<span class="Constant">40</span><span class="Delimiter">;</span> a -= <span class="Constant">4</span><span class="Delimiter">)</span>
<span id="L167" class="LineNr">167 </span> <a href='003trace.cc.html#L96'>trace</a><span class="Delimiter">(</span><span class="Special">Callstack_depth</span>+<span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">" 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << a << <span class="Constant">" => 0x"</span> << <a href='010vm.cc.html#L395'>HEXWORD</a> << <a href='010vm.cc.html#L172'>read_mem_u32</a><span class="Delimiter">(</span>a<span class="Delimiter">)</span> << end<span class="Delimiter">();</span>
<span id="L168" class="LineNr">168 </span><span class="Delimiter">}</span>
<span id="L169" class="LineNr">169 </span>
<span id="L170" class="LineNr">170 </span><span class="Normal">inline</span> <span class="Normal">uint32_t</span> <a href='012elf.cc.html#L170'>u32_in</a><span class="Delimiter">(</span><span class="Normal">uint8_t</span>* p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L171" class="LineNr">171 </span> <span class="Identifier">return</span> p[<span class="Constant">0</span>] | p[<span class="Constant">1</span>] << <span class="Constant">8</span> | p[<span class="Constant">2</span>] << <span class="Constant">16</span> | p[<span class="Constant">3</span>] << <span class="Constant">24</span><span class="Delimiter">;</span>
<span id="L172" class="LineNr">172 </span><span class="Delimiter">}</span>
<span id="L173" class="LineNr">173 </span>
<span id="L174" class="LineNr">174 </span><span class="Normal">inline</span> <span class="Normal">uint16_t</span> <a href='012elf.cc.html#L174'>u16_in</a><span class="Delimiter">(</span><span class="Normal">uint8_t</span>* p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L175" class="LineNr">175 </span> <span class="Identifier">return</span> p[<span class="Constant">0</span>] | p[<span class="Constant">1</span>] << <span class="Constant">8</span><span class="Delimiter">;</span>
<span id="L176" class="LineNr">176 </span><span class="Delimiter">}</span>
<span id="L177" class="LineNr">177 </span>
<span id="L178" class="LineNr">178 </span><span class="Delimiter">:(before "End Types")</span>
<span id="L179" class="LineNr">179 </span><span class="Normal">struct</span> <a href='012elf.cc.html#L179'>perr</a> <span class="Delimiter">{};</span>
<span id="L180" class="LineNr">180 </span><span class="Delimiter">:(code)</span>
<span id="L181" class="LineNr">181 </span>ostream& <span class="Normal">operator</span><<<span class="Delimiter">(</span>ostream& os<span class="Delimiter">,</span> <a href='012elf.cc.html#L179'>perr</a> <span class="Comment">/*</span><span class="Comment">unused</span><span class="Comment">*/</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L182" class="LineNr">182 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>errno<span class="Delimiter">)</span>
<span id="L183" class="LineNr">183 </span> os << <span class="Constant">": "</span> << strerror<span class="Delimiter">(</span>errno<span class="Delimiter">);</span>
<span id="L184" class="LineNr">184 </span> <span class="Identifier">return</span> os<span class="Delimiter">;</span>
<span id="L185" class="LineNr">185 </span><span class="Delimiter">}</span>
<span id="L186" class="LineNr">186 </span>
<span id="L187" class="LineNr">187 </span><span class="Delimiter">:(before "End Includes")</span>
<span id="L188" class="LineNr">188 </span><span class="PreProc">#include </span><span class="Constant"><sys/types.h></span>
<span id="L189" class="LineNr">189 </span><span class="PreProc">#include </span><span class="Constant"><sys/stat.h></span>
<span id="L190" class="LineNr">190 </span><span class="PreProc">#include </span><span class="Constant"><fcntl.h></span>
<span id="L191" class="LineNr">191 </span><span class="PreProc">#include </span><span class="Constant"><stdarg.h></span>
<span id="L192" class="LineNr">192 </span><span class="PreProc">#include </span><span class="Constant"><errno.h></span>
<span id="L193" class="LineNr">193 </span><span class="PreProc">#include </span><span class="Constant"><unistd.h></span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
|