diff --git a/core/relinker/relinker/src/analysis/CodeInstructionCollector.cpp b/core/relinker/relinker/src/analysis/CodeInstructionCollector.cpp index e065dc76e..0e2f7329f 100644 --- a/core/relinker/relinker/src/analysis/CodeInstructionCollector.cpp +++ b/core/relinker/relinker/src/analysis/CodeInstructionCollector.cpp @@ -209,6 +209,44 @@ std::set CodeInstructionCollector::Collect(const std::ve address += info.Length; } } + for (const auto& header : headers) { + if (header.Type != 1 || (header.Flags & 1) == 0 || header.FileSize < 16) continue; + range(header.Offset, header.FileSize); + const auto* text = bytes.data() + header.Offset; + const auto size = static_cast(header.FileSize); + const auto paddedStart = [&](std::size_t address) { return address % 16 == 0 && address >= 2 && text[address - 1] == 0xcc && text[address - 2] == 0xcc; }; + const auto nextPaddedStart = [&](std::size_t address) { + address = (address + 16) & ~std::size_t{15}; + while (address < size && !paddedStart(address)) address += 16; + return address; + }; + for (std::size_t position = nextPaddedStart(0); position < size;) { + if (position + 1 < size && text[position] == 0 && text[position + 1] == 0) { + position = nextPaddedStart(position); + continue; + } + Codegen::DecodedInstructionInfo info; + try { + info = decoder.DecodeInstruction(text + position, size - position); + } catch (const Codegen::CodegenException&) { + position = nextPaddedStart(position); + continue; + } + if (info.Length == 0 || info.Length > size - position) { + position = nextPaddedStart(position); + continue; + } + const auto next = position + info.Length; + const auto crossed = (position & ~std::size_t{15}) + 16; + if (crossed < next && paddedStart(crossed)) { + position = crossed; + continue; + } + const auto opcode = position + info.OpcodeOffset; + if (info.SegmentPrefix == 0x64 && opcode + 2 < next && (text[opcode + 1] & 0xc7) == 0x04 && text[opcode + 2] == 0x25) addRoot(header.MappedAddress + position); + position = next; + } + } for (const auto target : staticTargets) { for (const auto& [skipBegin, skipEnd] : skipped) { if (skipBegin <= target && target < skipEnd) diff --git a/core/relinker/relinker/tests/test_tls_function_coverage.py b/core/relinker/relinker/tests/test_tls_function_coverage.py index 3a8cae4dd..ddc45bbfc 100644 --- a/core/relinker/relinker/tests/test_tls_function_coverage.py +++ b/core/relinker/relinker/tests/test_tls_function_coverage.py @@ -339,6 +339,28 @@ def main(): external[0x1300:0x1310] = external[0x1240:0x1250] external[0x1240:0x1250] = b"\xe8" + struct.pack("