diff options
Diffstat (limited to 'subx/034compute_segment_address.cc')
-rw-r--r-- | subx/034compute_segment_address.cc | 125 |
1 files changed, 12 insertions, 113 deletions
diff --git a/subx/034compute_segment_address.cc b/subx/034compute_segment_address.cc index 47311219..9eb1615d 100644 --- a/subx/034compute_segment_address.cc +++ b/subx/034compute_segment_address.cc @@ -1,12 +1,16 @@ -//: Start allowing us to not specify precise addresses for the start of each -//: segment. +//: 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\n" + "== code 0x09000000\n" "05/add-to-EAX 0x0d0c0b0a/imm32\n" - // code starts at 0x08048000 + p_offset, which is 0x54 for a single-segment binary + // code starts at 0x09000000 + p_offset, which is 0x54 for a single-segment binary ); CHECK_TRACE_CONTENTS( "load: 0x09000054 -> 05\n" @@ -19,113 +23,6 @@ void test_segment_name() { ); } -//: Update the parser to handle non-numeric segment name. -//: -//: We'll also support repeated segments with non-numeric names. - -:(before "End Globals") -map</*name*/string, int> Segment_index; -bool Currently_parsing_named_segment = false; // global to permit cross-layer communication -int Currently_parsing_segment_index = -1; // global to permit cross-layer communication -:(before "End Reset") -Segment_index.clear(); -Currently_parsing_named_segment = false; -Currently_parsing_segment_index = -1; - -:(before "End Segment Parsing Special-cases(segment_title)") -if (!starts_with(segment_title, "0x")) { - Currently_parsing_named_segment = true; - if (!contains_key(Segment_index, segment_title)) { - trace(3, "parse") << "new segment '" << segment_title << "'" << end(); - if (out.segments.empty() && segment_title != "code") { - raise << "first segment must be 'code' but is '" << segment_title << "'\n" << end(); - return; - } - if (SIZE(out.segments) == 1 && segment_title != "data") { - raise << "second segment must be 'data' but is '" << segment_title << "'\n" << end(); - return; - } - put(Segment_index, segment_title, SIZE(out.segments)); - out.segments.push_back(segment()); - } - else { - trace(3, "parse") << "appending to segment '" << segment_title << "'" << end(); - } - Currently_parsing_segment_index = get(Segment_index, segment_title); -} - -:(before "End flush(p, lines) Special-cases") -if (Currently_parsing_named_segment) { - assert(!p.segments.empty()); - trace(3, "parse") << "flushing segment" << end(); - vector<line>& curr_segment_data = p.segments.at(Currently_parsing_segment_index).lines; - curr_segment_data.insert(curr_segment_data.end(), lines.begin(), lines.end()); - lines.clear(); - Currently_parsing_named_segment = false; - Currently_parsing_segment_index = -1; - return; -} - -:(code) -void test_repeated_segment_merges_data() { - run( - "== code\n" - "05/add-to-EAX 0x0d0c0b0a/imm32\n" - "== code\n" // again - "2d/subtract-from-EAX 0xddccbbaa/imm32\n" - ); - CHECK_TRACE_CONTENTS( - "parse: new segment 'code'\n" - "parse: appending to segment 'code'\n" - // first segment - "load: 0x09000054 -> 05\n" - "load: 0x09000055 -> 0a\n" - "load: 0x09000056 -> 0b\n" - "load: 0x09000057 -> 0c\n" - "load: 0x09000058 -> 0d\n" - // second segment - "load: 0x09000059 -> 2d\n" - "load: 0x0900005a -> aa\n" - "load: 0x0900005b -> bb\n" - "load: 0x0900005c -> cc\n" - "load: 0x0900005d -> dd\n" - ); -} - -void test_error_on_missing_segment_header() { - Hide_errors = true; - run( - "05/add-to-EAX 0/imm32\n" - ); - CHECK_TRACE_CONTENTS( - "error: input does not start with a '==' section header\n" - ); -} - -void test_error_on_first_segment_not_code() { - Hide_errors = true; - run( - "== data\n" - "05 00 00 00 00\n" - ); - CHECK_TRACE_CONTENTS( - "error: first segment must be 'code' but is 'data'\n" - ); -} - -void test_error_on_second_segment_not_data() { - Hide_errors = true; - run( - "== code\n" - "05/add-to-EAX 0/imm32\n" - "== bss\n" - "05 00 00 00 00\n" - ); - CHECK_TRACE_CONTENTS( - "error: second segment must be 'data' but is 'bss'\n" - ); -} - //: compute segment address :(before "End Level-2 Transforms") @@ -137,8 +34,10 @@ void compute_segment_starts(program& p) { 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 == 0) { - curr.start = CODE_SEGMENT + i*SPACE_FOR_SEGMENT + p_offset; + 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; trace(99, "transform") << "segment " << i << " begins at address 0x" << HEXWORD << curr.start << end(); } p_offset += size_of(curr); |