about summary refs log tree commit diff stats
path: root/prototypes/browse/6.mu
blob: 9685ab43a81f78ed1f0a2711787611f812cc4f49 (plain) (blame)
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
fn main args: (addr array (addr array byte)) -> exit-status/ebx: int {
  var filename/eax: (addr array byte) <- first-arg args
  var file/eax: (addr buffered-file) <- load-file filename
  enable-screen-grid-mode
  enable-keyboard-immediate-mode
  {
    render file, 0x20, 0x30  # nrows, ncols
    var key/eax: byte <- read-key
    compare key, 0x71  # 'q'
    loop-if-!=
  }
  enable-keyboard-type-mode
  enable-screen-type-mode
  exit-status <- copy 0
}

fn render in: (addr buffered-file), nrows: int, ncols: int {
  # hardcoded parameter: page-width
  var toprow/eax: int <- copy 2
  var botrow/ecx: int <- copy toprow
  botrow <- add nrows
  var leftcol/edx: int <- copy 5
  var rightcol/ebx: int <- copy leftcol
  rightcol <- add ncols
  render-page in, toprow, leftcol, botrow, rightcol
}

fn render-page in: (addr buffered-file), toprow: int, leftcol: int, botrow: int, rightcol: int {
  clear toprow, leftcol, botrow, rightcol
  var row/ecx: int <- copy toprow
$line-loop:  {
    compare row, botrow
    break-if->=
    var col/edx: int <- copy leftcol
    move-cursor row, col
    {
      compare col, rightcol
      break-if->=
      var c/eax: byte <- read-byte-buffered in
      compare c, 0xffffffff  # EOF marker
      break-if-= $line-loop
      compare c, 0xa  # newline
      break-if-=  # no need to print newlines
      # print c
      print-byte c
      col <- increment
      loop
    }  # $char-loop
    row <- increment
    loop
  }  # $line-loop
}

fn clear toprow: int, leftcol: int, botrow: int, rightcol: int {
  var row/ecx: int <- copy toprow
  {
    compare row, botrow
    break-if->=
    var col/edx: int <- copy leftcol
    move-cursor row, col
    {
      compare col, rightcol
      break-if->=
      print-string " "
      col <- increment
      loop
    }
    row <- increment
    loop
  }
}

fn first-arg args-on-stack: (addr array (addr array byte)) -> out/eax: (addr array byte) {
  var args/eax: (addr array (addr array byte)) <- copy args-on-stack
  var result/eax: (addr addr array byte) <- index args, 1
  out <- copy *result
}

fn load-file filename: (addr array byte) -> out/eax: (addr buffered-file) {
  var result: (handle buffered-file)
  {
    var tmp1/eax: (addr handle buffered-file) <- address result
    open filename, 0, tmp1
  }
  out <- lookup result
}

fn dump in: (addr buffered-file) {
  var c/eax: byte <- read-byte-buffered in
  compare c, 0xffffffff  # EOF marker
  break-if-=
  print-byte c
  loop
}
class="kt">uint32_t e_entry = p.entry; // Override e_entry emit(e_entry); // e_phoff -- immediately after ELF header uint32_t e_phoff = 0x34; emit(e_phoff); // e_shoff; unused uint32_t dummy32 = 0; emit(dummy32); // e_flags; unused emit(dummy32); // e_ehsize uint16_t e_ehsize = 0x34; emit(e_ehsize); // e_phentsize uint16_t e_phentsize = 0x20; emit(e_phentsize); // e_phnum uint16_t e_phnum = SIZE(p.segments); emit(e_phnum); // e_shentsize uint16_t dummy16 = 0x0; emit(dummy16); // e_shnum emit(dummy16); // 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 emit(p_offset); // p_vaddr uint32_t p_start = curr.start; emit(p_start); // p_paddr emit(p_start); // p_filesz uint32_t size = num_words(curr); assert(p_offset + size < SEGMENT_ALIGNMENT); emit(size); // p_memsz emit(size); // p_flags uint32_t p_flags = (curr.name == "code") ? /*r-x*/0x5 : /*rw-*/0x6; emit(p_flags); // p_align // "As the system creates or augments a process image, it logically copies // a file's segment to a virtual memory segment. When—and if— the system // physically reads the file depends on the program's execution behavior, // system load, and so on. A process does not require a physical page // unless it references the logical page during execution, and processes // commonly leave many pages unreferenced. Therefore delaying physical // reads frequently obviates them, improving system performance. To obtain // this efficiency in practice, executable and shared object files must // have segment images whose file offsets and virtual addresses are // 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_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; } // prepare for next segment p_offset += size; } #undef O #undef emit } void write_segment(const segment& s, ostream& out) { for (int i = 0; i < SIZE(s.lines); ++i) { const vector<word>& w = s.lines.at(i).words; for (int j = 0; j < SIZE(w); ++j) { uint8_t x = hex_byte(w.at(j).data); // we're done with metadata by this point out.write(reinterpret_cast<const char*>(&x), /*sizeof(byte)*/1); } } } 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); return sum; } :(before "End Includes") using std::ios;