about summary refs log tree commit diff stats
path: root/archive/3.transect/compiler8
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-07-26 12:04:54 -0700
committerKartik Agaram <vc@akkartik.com>2019-07-26 12:05:03 -0700
commite355c6931091decf8956878e205fff74afb945a2 (patch)
treec4a3357341f19657fedbfb934d4f611025feb69c /archive/3.transect/compiler8
parent8acdca485850861f19c5416d8868c6d8dbe2ba67 (diff)
downloadmu-e355c6931091decf8956878e205fff74afb945a2.tar.gz
5482
Other phrasings considered:
  - "tractably automate arbitrary manual tests"
  - "make it possible to automate arbitrary manual tests"

Thanks Paul Biggar for the feedback.
Diffstat (limited to 'archive/3.transect/compiler8')
0 files changed, 0 insertions, 0 deletions
me the previous revision' href='/akkartik/mu/blame/subx/034compute_segment_address.cc?h=hlt&id=43711b0e9f18e0225ce14687fb6ea0902aa6fc61'>^
dd7077f7 ^
4a943d4e ^


1bbbf14f ^
73aa4d14 ^

5c368edc ^
1bbbf14f ^



c442a5ad ^
1bbbf14f ^


83c67014 ^


4e8f5fa4 ^
87d5bdb9 ^
a6517ed8 ^

4a99a6e0 ^
1bbbf14f ^

a6517ed8 ^










a6061b9f ^

a6517ed8 ^

8998908e ^
a6061b9f ^


3c46d5a2 ^

a6061b9f ^




8998908e ^













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





                                                                              

                                                                

                          
                            
                                         
                                                                                        






                                
                                          


                                 
 

                           
                          



                                            
                                                                   


                                                                                        


                                                                                                          
                                       
                                                                                                             

                              
                                                                                                                     

   










                                           

                                              

             
 


                                                                            

                                             




                                      













                                                                                
//: ELF binaries have finicky rules about the precise alignment each segment
//: should start at. They depend on the amount of code in a program.
//: We shouldn't expect people to adjust segment addresses everytime they make
//: a change to their programs.
//: Let's start taking the given segment addresses as guidelines, and adjust
//: them as necessary.
//: This gives up a measure of control in placing code and data.

void test_segment_name() {
  run(
      "== code 0x09000000\n"
      "05/add-to-EAX  0x0d0c0b0a/imm32\n"
      // code starts at 0x09000000 + p_offset, which is 0x54 for a single-segment binary
  );
  CHECK_TRACE_CONTENTS(
      "load: 0x09000054 -> 05\n"
      "load: 0x09000055 -> 0a\n"
      "load: 0x09000056 -> 0b\n"
      "load: 0x09000057 -> 0c\n"
      "load: 0x09000058 -> 0d\n"
      "run: add imm32 0x0d0c0b0a to EAX\n"
      "run: storing 0x0d0c0b0a\n"
  );
}

//: compute segment address

:(before "End Transforms")
Transform.push_back(compute_segment_starts);

:(code)
void compute_segment_starts(program& p) {
  trace(3, "transform") << "-- compute segment addresses" << end();
  uint32_t p_offset = /*size of ehdr*/0x34 + SIZE(p.segments)*0x20/*size of each phdr*/;
  for (size_t i = 0;  i < p.segments.size();  ++i) {
    segment& curr = p.segments.at(i);
    if (curr.start >= 0x08000000) {
      // valid address for user space, so assume we're creating a real ELF binary, not just running a test
      curr.start &= 0xfffff000;  // same number of zeros as the p_align used when emitting the ELF binary
      curr.start |= (p_offset & 0xfff);
      trace(99, "transform") << "segment " << i << " begins at address 0x" << HEXWORD << curr.start << end();
    }
    p_offset += size_of(curr);
    assert(p_offset < SEGMENT_ALIGNMENT);  // for now we get less and less available space in each successive segment
  }
}

uint32_t size_of(const segment& s) {
  uint32_t sum = 0;
  for (int i = 0;  i < SIZE(s.lines);  ++i)
    sum += num_bytes(s.lines.at(i));
  return sum;
}

// Assumes all bitfields are packed.
uint32_t num_bytes(const line& inst) {
  uint32_t sum = 0;
  for (int i = 0;  i < SIZE(inst.words);  ++i)
    sum += size_of(inst.words.at(i));
  return sum;
}

int size_of(const word& w) {
  if (has_operand_metadata(w, "disp32") || has_operand_metadata(w, "imm32"))
    return 4;
  else if (has_operand_metadata(w, "disp16"))
    return 2;
  // End size_of(word w) Special-cases
  else
    return 1;
}

//: Dependencies:
//: - We'd like to compute segment addresses before setting up global variables,
//:   because computing addresses for global variables requires knowing where
//:   the data segment starts.
//: - We'd like to finish expanding labels before computing segment addresses,
//:   because it would make computing the sizes of segments more self-contained
//:   (num_bytes).
//:
//: Decision: compute segment addresses before expanding labels, by being
//: aware in this layer of certain operand types that will eventually occupy
//: multiple bytes.
//:
//: The layer to expand labels later hooks into num_bytes() to teach this
//: layer that labels occupy zero space in the binary.