diff --git a/core/relinker/elfpatcher/src/windows/WindowsTlsBuilder.cpp b/core/relinker/elfpatcher/src/windows/WindowsTlsBuilder.cpp index 26cc1272c..3fb5379dc 100644 --- a/core/relinker/elfpatcher/src/windows/WindowsTlsBuilder.cpp +++ b/core/relinker/elfpatcher/src/windows/WindowsTlsBuilder.cpp @@ -106,11 +106,14 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector& source, co } if (header.Type != 1 || (header.Flags & 1) == 0) continue; + std::uint64_t decodedEnd = 0; for (auto instruction = instructions.lower_bound(header.MappedAddress); instruction != instructions.end() && *instruction - header.MappedAddress < header.FileSize; ++instruction) { const auto offset = *instruction - header.MappedAddress; const auto* bytes = source.data() + header.Offset + offset; const auto info = decoder.DecodeInstruction(bytes, header.FileSize - offset); const auto rva = image.GetRva(header.MappedAddress + offset, info.Length); + const bool insidePrevious = *instruction < decodedEnd; + decodedEnd = std::max(decodedEnd, *instruction + info.Length); if (info.HasBranchTarget && !info.HasRipRelativeDisp) { const auto target = static_cast(rva) + static_cast(info.Length) + info.BranchDisp; @@ -118,7 +121,7 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector& source, co branchTargets.insert(static_cast(target)); } - if (info.SegmentPrefix != 0) { + if (info.SegmentPrefix != 0 && !(insidePrevious && info.SegmentPrefix != 0x64)) { const auto position = info.OpcodeOffset; bool hasOperandSizePrefix = false; bool supportedPrefixes = info.SegmentPrefix == 0x64; diff --git a/core/relinker/relinker/src/analysis/CodeInstructionCollector.cpp b/core/relinker/relinker/src/analysis/CodeInstructionCollector.cpp index 0e2f7329f..b346b598c 100644 --- a/core/relinker/relinker/src/analysis/CodeInstructionCollector.cpp +++ b/core/relinker/relinker/src/analysis/CodeInstructionCollector.cpp @@ -247,9 +247,21 @@ std::set CodeInstructionCollector::Collect(const std::ve position = next; } } + const auto decodesInSegment = [&](std::uint64_t address) { + for (const auto& header : headers) { + if (header.Type != 1 || (header.Flags & 1) == 0 || address < header.MappedAddress || address - header.MappedAddress >= header.FileSize) continue; + const auto offset = address - header.MappedAddress; + try { + return decoder.DecodeInstruction(bytes.data() + header.Offset + offset, header.FileSize - offset).Length != 0; + } catch (const Codegen::CodegenException&) { + return false; + } + } + return false; + }; for (const auto target : staticTargets) { for (const auto& [skipBegin, skipEnd] : skipped) { - if (skipBegin <= target && target < skipEnd) + if (skipBegin <= target && target < skipEnd && !decodesInSegment(target)) throw Domain::RelinkerException("Code analysis: branch into skipped range tail", target); } } diff --git a/core/relinker/relinker/tests/test_tls_function_coverage.py b/core/relinker/relinker/tests/test_tls_function_coverage.py index 06e108759..420fcc7fb 100644 --- a/core/relinker/relinker/tests/test_tls_function_coverage.py +++ b/core/relinker/relinker/tests/test_tls_function_coverage.py @@ -382,8 +382,8 @@ def pe_bytes_at(pe, rva, size): raise AssertionError(f"Unmapped PE RVA {rva:#x}") -def add_alias(image, size): - struct.pack_into("