about summary refs log tree commit diff stats
path: root/subx/028translate.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-09-01 15:58:53 -0700
committerKartik Agaram <vc@akkartik.com>2018-09-01 20:10:06 -0700
commita49bc41365bf6b4f0c006c5fbdcb4b519634c42c (patch)
tree664075c7652dfe7eb75cfdb6c54e7b226215bc2d /subx/028translate.cc
parent6ff9ce26e84f686a96ada723f63ce95879216cca (diff)
downloadmu-a49bc41365bf6b4f0c006c5fbdcb4b519634c42c.tar.gz
4531 - automatically compute segment addresses
Diffstat (limited to 'subx/028translate.cc')
-rw-r--r--subx/028translate.cc40
1 files changed, 32 insertions, 8 deletions
diff --git a/subx/028translate.cc b/subx/028translate.cc
index f3e30126..cc41e715 100644
--- a/subx/028translate.cc
+++ b/subx/028translate.cc
@@ -30,12 +30,28 @@ if (is_equal(argv[1], "translate")) {
   if (trace_contains_errors()) return 1;
   transform(p);
   if (trace_contains_errors()) return 1;
+  compute_segment_offsets(p);
   save_elf(p, argv[3]);
   if (trace_contains_errors()) unlink(argv[3]);
   return 0;
 }
 
+:(before "End segment Fields")
+uint32_t offset;
+:(before "End segment Constructor")
+offset = 0;
 :(code)
+void compute_segment_offsets(program& p) {
+  uint32_t p_offset = /*size of ehdr*/0x34 + SIZE(p.segments)*0x20/*size of each phdr*/;
+  uint32_t cumulative_segment_size = 0;
+  for (size_t i = 0;  i < p.segments.size();  ++i) {
+    segment& curr = p.segments.at(i);
+    curr.offset = p_offset + cumulative_segment_size;
+//?     cerr << "offset " << i << ": " << curr.offset << '\n';
+    cumulative_segment_size += num_words(curr);
+  }
+}
+
 // write out a program to a bare-bones ELF file
 void save_elf(const program& p, const char* filename) {
   ofstream out(filename, ios::binary);
@@ -45,6 +61,12 @@ void save_elf(const program& p, const char* filename) {
   out.close();
 }
 
+uint32_t start(const program& p, const int segment_index) {
+  const segment& seg = p.segments.at(segment_index);
+  if (seg.start != 0) return seg.start;  // if start is already initialized, use it
+  return CODE_START + SEGMENT_SIZE*segment_index + seg.offset;
+}
+
 void write_elf_header(ostream& out, const program& p) {
   char c = '\0';
 #define O(X)  c = (X); out.write(&c, sizeof(c))
@@ -64,7 +86,7 @@ void write_elf_header(ostream& out, const program& p) {
   // e_version
   O(0x01); O(0x00); O(0x00); O(0x00);
   // e_entry
-  int e_entry = p.segments.at(0).start;  // convention
+  int e_entry = start(p, /*segment*/0);  // convention
   emit(e_entry);
   // e_phoff -- immediately after ELF header
   int e_phoff = 0x34;
@@ -91,20 +113,22 @@ void write_elf_header(ostream& out, const program& p) {
   // e_shstrndx
   emit(dummy16);
 
-  uint32_t p_offset = /*size of ehdr*/0x34 + SIZE(p.segments)*0x20/*size of each phdr*/;
   for (int i = 0;  i < SIZE(p.segments);  ++i) {
+    const segment& curr = p.segments.at(i);
     //// phdr
     // p_type
     uint32_t p_type = 0x1;
     emit(p_type);
     // p_offset
+    uint32_t p_offset = curr.offset;
     emit(p_offset);
     // p_vaddr
-    emit(p.segments.at(i).start);
+    uint32_t p_start = start(p, i);
+    emit(p_start);
     // p_paddr
-    emit(p.segments.at(i).start);
+    emit(p_start);
     // p_filesz
-    uint32_t size = size_of(p.segments.at(i));
+    uint32_t size = num_words(curr);
     assert(size < SEGMENT_SIZE);
     emit(size);
     // p_memsz
@@ -126,8 +150,8 @@ void write_elf_header(ostream& out, const program& p) {
     // congruent, modulo the page size." -- http://refspecs.linuxbase.org/elf/elf.pdf (page 95)
     uint32_t p_align = 0x1000;  // default page size on linux
     emit(p_align);
-    if (p_offset % p_align != p.segments.at(i).start % p_align) {
-      raise << "segment starting at 0x" << HEXWORD << p.segments.at(i).start << " is improperly aligned; alignment for p_offset " << p_offset << " should be " << (p_offset % p_align) << " but is " << (p.segments.at(i).start % p_align) << '\n' << end();
+    if (p_offset % p_align != p_start % p_align) {
+      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();
       return;
     }
 
@@ -148,7 +172,7 @@ void write_segment(const segment& s, ostream& out) {
   }
 }
 
-uint32_t size_of(const segment& s) {
+uint32_t num_words(const segment& s) {
   uint32_t sum = 0;
   for (int i = 0;  i < SIZE(s.lines);  ++i)
     sum += SIZE(s.lines.at(i).words);