about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-11-23 00:21:41 -0800
committerKartik Agaram <vc@akkartik.com>2018-11-23 00:22:24 -0800
commit4a99a6e0dd3000d8e595ec7b4b04f637e66ded6d (patch)
treeb6d0b7f2145e4370c22fd0142950e648b406b524 /subx
parent6ee77ba7bb47bc4b17df67d2683bdbb84f326e8e (diff)
downloadmu-4a99a6e0dd3000d8e595ec7b4b04f637e66ded6d.tar.gz
4761
Bugfix: I forgot about ELF segment offsets when implementing VMAs. Eventually
segments grew large enough that I started seeing overlaps.
Diffstat (limited to 'subx')
-rw-r--r--subx/010---vm.cc11
-rw-r--r--subx/012elf.cc8
-rw-r--r--subx/028translate.cc2
-rw-r--r--subx/034compute_segment_address.cc2
4 files changed, 11 insertions, 12 deletions
diff --git a/subx/010---vm.cc b/subx/010---vm.cc
index 47b2c3da..7e5b8d79 100644
--- a/subx/010---vm.cc
+++ b/subx/010---vm.cc
@@ -112,9 +112,10 @@ SF = ZF = OF = false;
 //:: simulated RAM
 
 :(before "End Types")
-const uint32_t INITIAL_SEGMENT_SIZE = 0x1000000 - 1;
-// Subtract one just so we can start the first segment at address 1 without
-// overflowing the first segment. Other segments will learn to adjust.
+const uint32_t SEGMENT_ALIGNMENT = 0x1000000;
+inline uint32_t align_upwards(uint32_t x, uint32_t align) {
+  return (x+align-1) & -(align);
+}
 
 // Like in real-world Linux, we'll allocate RAM for our programs in disjoint
 // slabs called VMAs or Virtual Memory Areas.
@@ -123,7 +124,7 @@ struct vma {
   uint32_t end;  // exclusive
   vector<uint8_t> _data;
   vma(uint32_t s, uint32_t e) :start(s), end(e) {}
-  vma(uint32_t s) :start(s), end(s+INITIAL_SEGMENT_SIZE) {}
+  vma(uint32_t s) :start(s), end(align_upwards(s+1, SEGMENT_ALIGNMENT)) {}
   bool match(uint32_t a) {
     return a >= start && a < end;
   }
@@ -136,9 +137,7 @@ struct vma {
     if (_data.size() <= result_index) {
       const int align = 0x1000;
       uint32_t result_size = result_index + 1;  // size needed for result_index to be valid
-      #define align_upwards(x, align)  (((x)+(align)-1) & -(align))
       uint32_t new_size = align_upwards(result_size, align);
-      #undef align_upwards
       // grow at least 2x to maintain some amortized complexity guarantees
       if (new_size < _data.size() * 2)
         new_size = _data.size() * 2;
diff --git a/subx/012elf.cc b/subx/012elf.cc
index 3f8187ba..2ab469e0 100644
--- a/subx/012elf.cc
+++ b/subx/012elf.cc
@@ -80,7 +80,7 @@ void load_elf_contents(uint8_t* elf_contents, size_t size, int argc, char* argv[
       assert(overlap.find(argv_data) == overlap.end());  // don't bother comparing ARGV and STACK
       write_mem_u8(argv_data, argv[i][j]);
       argv_data += sizeof(char);
-      assert(argv_data < ARGV_DATA_SEGMENT + INITIAL_SEGMENT_SIZE);
+      assert(argv_data < ARGV_DATA_SEGMENT + SEGMENT_ALIGNMENT);
     }
   }
   push(argc-/*skip 'subx_bin' and 'run'*/2);
@@ -111,8 +111,8 @@ void load_segment_from_program_header(uint8_t* elf_contents, int segment_index,
 
   if (p_offset + p_filesz > size)
     raise << "Invalid binary; segment at offset " << offset << " is too large: wants to end at " << p_offset+p_filesz << " but the file ends at " << size << '\n' << die();
-  if (p_memsz >= INITIAL_SEGMENT_SIZE) {
-    raise << "Code segment too small for SubX; for now please manually increase INITIAL_SEGMENT_SIZE.\n" << end();
+  if (p_memsz >= SEGMENT_ALIGNMENT) {
+    raise << "Code segment too small for SubX; for now please manually increase SEGMENT_ALIGNMENT.\n" << end();
     return;
   }
   trace(90, "load") << "blitting file offsets (" << p_offset << ", " << (p_offset+p_filesz) << ") to addresses (" << p_vaddr << ", " << (p_vaddr+p_memsz) << ')' << end();
@@ -135,7 +135,7 @@ void load_segment_from_program_header(uint8_t* elf_contents, int segment_index,
 const int CODE_SEGMENT = 0x09000000;
 const int DATA_SEGMENT = 0x0a000000;
 const int STACK_SEGMENT = 0x0b000000;
-const int AFTER_STACK = 0x0b000ffc;  // forget final word because of the off-by-one with INITIAL_SEGMENT_SIZE;
+const int AFTER_STACK = 0x0b000ffc;  // forget final word because of the off-by-one with SEGMENT_ALIGNMENT;
 const int ARGV_DATA_SEGMENT = 0x0c000000;
 :(code)
 void dump_stack() {
diff --git a/subx/028translate.cc b/subx/028translate.cc
index 48c11786..2104d57b 100644
--- a/subx/028translate.cc
+++ b/subx/028translate.cc
@@ -139,7 +139,7 @@ void write_elf_header(ostream& out, const program& p) {
     emit(p_start);
     // p_filesz
     uint32_t size = num_words(p.segments.at(i));
-    assert(p_offset + size < INITIAL_SEGMENT_SIZE);
+    assert(p_offset + size < SEGMENT_ALIGNMENT);
     emit(size);
     // p_memsz
     emit(size);
diff --git a/subx/034compute_segment_address.cc b/subx/034compute_segment_address.cc
index b302e4d8..cf5b789d 100644
--- a/subx/034compute_segment_address.cc
+++ b/subx/034compute_segment_address.cc
@@ -97,7 +97,7 @@ void compute_segment_starts(program& p) {
       trace(99, "transform") << "segment " << i << " begins at address 0x" << HEXWORD << curr.start << end();
     }
     p_offset += size_of(curr);
-    assert(p_offset < INITIAL_SEGMENT_SIZE);  // for now we get less and less available space in each successive segment
+    assert(p_offset < SEGMENT_ALIGNMENT);  // for now we get less and less available space in each successive segment
   }
 }