diff options
-rw-r--r-- | src/binary-writer.cc | 27 | ||||
-rw-r--r-- | test/link/large_code_section.txt | 166 |
2 files changed, 183 insertions, 10 deletions
diff --git a/src/binary-writer.cc b/src/binary-writer.cc index bc42543b..00947afa 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -199,9 +199,9 @@ class BinaryWriter { private: void WriteHeader(const char* name, int index); Offset WriteU32Leb128Space(Offset leb_size_guess, const char* desc); - void WriteFixupU32Leb128Size(Offset offset, - Offset leb_size_guess, - const char* desc); + Offset WriteFixupU32Leb128Size(Offset offset, + Offset leb_size_guess, + const char* desc); void BeginKnownSection(BinarySection section_code, size_t leb_size_guess); void BeginCustomSection(const char* name, size_t leb_size_guess); void EndSection(); @@ -274,22 +274,25 @@ Offset BinaryWriter::WriteU32Leb128Space(Offset leb_size_guess, return result; } -void BinaryWriter::WriteFixupU32Leb128Size(Offset offset, - Offset leb_size_guess, - const char* desc) { +Offset BinaryWriter::WriteFixupU32Leb128Size(Offset offset, + Offset leb_size_guess, + const char* desc) { if (options_->canonicalize_lebs) { Offset size = stream_.offset() - offset - leb_size_guess; Offset leb_size = u32_leb128_length(size); - if (leb_size != leb_size_guess) { + Offset delta = leb_size - leb_size_guess; + if (delta != 0) { Offset src_offset = offset + leb_size_guess; Offset dst_offset = offset + leb_size; stream_.MoveData(dst_offset, src_offset, size); } write_u32_leb128_at(&stream_, offset, size, desc); - stream_.AddOffset(leb_size - leb_size_guess); + stream_.AddOffset(delta); + return delta; } else { Offset size = stream_.offset() - offset - MAX_U32_LEB128_BYTES; write_fixed_u32_leb128_at(&stream_, offset, size, desc); + return 0; } } @@ -338,8 +341,12 @@ void BinaryWriter::BeginCustomSection(const char* name, size_t leb_size_guess) { void BinaryWriter::EndSection() { assert(last_section_leb_size_guess_ != 0); - WriteFixupU32Leb128Size(last_section_offset_, last_section_leb_size_guess_, - "FIXUP section size"); + Offset delta = WriteFixupU32Leb128Size( + last_section_offset_, last_section_leb_size_guess_, "FIXUP section size"); + if (current_reloc_section_ && delta != 0) { + for (Reloc& reloc: current_reloc_section_->relocations) + reloc.offset += delta; + } last_section_leb_size_guess_ = 0; } diff --git a/test/link/large_code_section.txt b/test/link/large_code_section.txt new file mode 100644 index 00000000..01d31844 --- /dev/null +++ b/test/link/large_code_section.txt @@ -0,0 +1,166 @@ +;;; TOOL: run-wasm-link +;;; FLAGS: -r +;; Verify that relocations are generated correctly in sections longer than +;; 128 bytes. We had an issue where the size relocation offsets we not correct +;; due to section payload changing once the section size LEB was fixed up. +(module + (func $local_func (param i32) + call $local_func + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0 + set_local 0 + get_local 0) +) +(;; STDOUT ;;; + +linked.wasm: file format wasm 0x1 + +Sections: + + Type start=0x0000000a end=0x0000000f (size=0x00000005) count: 1 + Function start=0x00000015 end=0x00000017 (size=0x00000002) count: 1 + Code start=0x0000001a end=0x000000a1 (size=0x00000087) count: 1 + Custom start=0x000000a7 end=0x000000bf (size=0x00000018) "name" + Custom start=0x000000c5 end=0x000000d5 (size=0x00000010) "reloc.Code" + +Section Details: + +Type: + - [0] (i32) -> nil +Function: + - func[0] sig=0 <local_func> +Custom: + - name: "name" + - func[0] local_func +Custom: + - name: "reloc.Code" + - section: Code + - R_FUNC_INDEX_LEB offset=0x000005(file=0x00001f) index=0 + +Code Disassembly: + +00001b <local_func>: + 00001e: 10 80 80 80 80 00 | call 0 <local_func> + 00001f: R_FUNC_INDEX_LEB 0 <local_func> + 000024: 21 00 | set_local 0 + 000026: 20 00 | get_local 0 + 000028: 21 00 | set_local 0 + 00002a: 20 00 | get_local 0 + 00002c: 21 00 | set_local 0 + 00002e: 20 00 | get_local 0 + 000030: 21 00 | set_local 0 + 000032: 20 00 | get_local 0 + 000034: 21 00 | set_local 0 + 000036: 20 00 | get_local 0 + 000038: 21 00 | set_local 0 + 00003a: 20 00 | get_local 0 + 00003c: 21 00 | set_local 0 + 00003e: 20 00 | get_local 0 + 000040: 21 00 | set_local 0 + 000042: 20 00 | get_local 0 + 000044: 21 00 | set_local 0 + 000046: 20 00 | get_local 0 + 000048: 21 00 | set_local 0 + 00004a: 20 00 | get_local 0 + 00004c: 21 00 | set_local 0 + 00004e: 20 00 | get_local 0 + 000050: 21 00 | set_local 0 + 000052: 20 00 | get_local 0 + 000054: 21 00 | set_local 0 + 000056: 20 00 | get_local 0 + 000058: 21 00 | set_local 0 + 00005a: 20 00 | get_local 0 + 00005c: 21 00 | set_local 0 + 00005e: 20 00 | get_local 0 + 000060: 21 00 | set_local 0 + 000062: 20 00 | get_local 0 + 000064: 21 00 | set_local 0 + 000066: 20 00 | get_local 0 + 000068: 21 00 | set_local 0 + 00006a: 20 00 | get_local 0 + 00006c: 21 00 | set_local 0 + 00006e: 20 00 | get_local 0 + 000070: 21 00 | set_local 0 + 000072: 20 00 | get_local 0 + 000074: 21 00 | set_local 0 + 000076: 20 00 | get_local 0 + 000078: 21 00 | set_local 0 + 00007a: 20 00 | get_local 0 + 00007c: 21 00 | set_local 0 + 00007e: 20 00 | get_local 0 + 000080: 21 00 | set_local 0 + 000082: 20 00 | get_local 0 + 000084: 21 00 | set_local 0 + 000086: 20 00 | get_local 0 + 000088: 21 00 | set_local 0 + 00008a: 20 00 | get_local 0 + 00008c: 21 00 | set_local 0 + 00008e: 20 00 | get_local 0 + 000090: 21 00 | set_local 0 + 000092: 20 00 | get_local 0 + 000094: 21 00 | set_local 0 + 000096: 20 00 | get_local 0 + 000098: 21 00 | set_local 0 + 00009a: 20 00 | get_local 0 + 00009c: 21 00 | set_local 0 + 00009e: 20 00 | get_local 0 + 0000a0: 0b | end +;;; STDOUT ;;) |