diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-09-01 15:58:53 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-09-01 20:10:06 -0700 |
commit | a49bc41365bf6b4f0c006c5fbdcb4b519634c42c (patch) | |
tree | 664075c7652dfe7eb75cfdb6c54e7b226215bc2d /subx/028translate.cc | |
parent | 6ff9ce26e84f686a96ada723f63ce95879216cca (diff) | |
download | mu-a49bc41365bf6b4f0c006c5fbdcb4b519634c42c.tar.gz |
4531 - automatically compute segment addresses
Diffstat (limited to 'subx/028translate.cc')
-rw-r--r-- | subx/028translate.cc | 40 |
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); |