From 4a99a6e0dd3000d8e595ec7b4b04f637e66ded6d Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 23 Nov 2018 00:21:41 -0800 Subject: 4761 Bugfix: I forgot about ELF segment offsets when implementing VMAs. Eventually segments grew large enough that I started seeing overlaps. --- subx/010---vm.cc | 11 +++++------ subx/012elf.cc | 8 ++++---- subx/028translate.cc | 2 +- subx/034compute_segment_address.cc | 2 +- 4 files changed, 11 insertions(+), 12 deletions(-) (limited to 'subx') 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 _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 } } -- cgit 1.4.1-2-gfad0