fix(relinker): retain imported ELF symbol types through parsing

This commit is contained in:
pista committed 2026-10-23 13:04:40 +09:00
1 parent c0bd62e46e
commit 70329ada1c
5 files changed
+26 -17

No files matched your search

@@ -69,6 +69,7 @@ struct NidReference {
std::int64_t Addend;
bool Weak = false;
bool Function = false;
std::uint8_t SymbolType = 0;
};
struct CallSiteInfo {
@@ -158,7 +158,6 @@ inline constexpr std::uint32_t R_X86_64_IRELATIVE = 37;
inline constexpr std::uint8_t STB_GLOBAL = 1;
inline constexpr std::uint8_t STB_WEAK = 2;
inline constexpr std::uint8_t STT_NOTYPE = 0;
inline constexpr std::uint8_t STT_OBJECT = 1;
inline constexpr std::uint8_t STT_FUNC = 2;
inline constexpr std::uint8_t STT_TLS = 6;
inline constexpr std::uint8_t STV_DEFAULT = 0;
@@ -92,7 +92,7 @@ SysVDynamicSection SysVDynamicSectionBuilder::BuildDynamicSection(
if (ref.Nid.empty()) return static_cast<std::uint8_t>((STB_WEAK << 4) | STT_NOTYPE);
const bool tls = ref.RelocationTypeValue == R_X86_64_DTPMOD64 || ref.RelocationTypeValue == R_X86_64_DTPOFF64
|| ref.RelocationTypeValue == R_X86_64_TPOFF64;
const auto type = tls ? STT_TLS : ref.Function ? STT_FUNC : STT_OBJECT;
const auto type = tls ? STT_TLS : ref.SymbolType;
return static_cast<std::uint8_t>(((ref.Weak ? STB_WEAK : STB_GLOBAL) << 4) | type);
};
@@ -369,8 +369,9 @@ RelinkResult RelinkerPipeline::Relink() {
[](const std::uint8_t byte) { return byte != 0; })))
throw RelinkerException("Unnamed import symbol is not a null symbol entry", symOff);
const bool weak = (raw[symOff + 4] >> 4) == STB_WEAK;
const bool function = (raw[symOff + 4] & 15) == STT_FUNC;
nidRefs.push_back({name, Domain::ImportModule(name, importModules, neededLibraries), relType, pos, rOffset, rAddend, weak, function});
const auto symbolType = static_cast<std::uint8_t>(raw[symOff + 4] & 15);
const bool function = symbolType == STT_FUNC;
nidRefs.push_back({name, Domain::ImportModule(name, importModules, neededLibraries), relType, pos, rOffset, rAddend, weak, function, symbolType});
}
};
@@ -7,25 +7,26 @@ from test_guest_symbol_names import (DYNAMIC, GOT, RELOCATIONS, STRINGS, SYMBOLS
string_table, symbol_name)
from test_guest_intel_trampolines import main_fixture
STT_OBJECT = 1
STT_FUNC = 2
def importing_executable(imports):
def importing_executable(imports, binding=1, relocation_type=6):
image = main_fixture()
strings, offsets = string_table(name for name, _ in imports)
image[STRINGS:STRINGS + len(strings)] = strings
for index, (offset, (_, kind)) in enumerate(zip(offsets, imports), 1):
struct.pack_into("<IBBHQQ", image, SYMBOLS + index * 24, offset, 0x10 | kind, 0, 0, 0, 0)
struct.pack_into("<QQq", image, RELOCATIONS + (index - 1) * 24, GOT + (index - 1) * 8, (index << 32) | 6, 0)
tags = [(5, STRINGS), (10, len(strings)), (6, SYMBOLS), (11, 24), (7, RELOCATIONS), (8, len(imports) * 24), (9, 24), (0, 0)]
struct.pack_into("<IBBHQQ", image, SYMBOLS + index * 24, offset, (binding << 4) | kind, 0, 0, 0, 0)
struct.pack_into("<QQq", image, RELOCATIONS + (index - 1) * 24, GOT + (index - 1) * 8, (index << 32) | relocation_type, 0)
tags = [(5, STRINGS), (10, len(strings)), (6, SYMBOLS), (11, 24)]
if relocation_type == 7:
tags += [(3, GOT), (23, RELOCATIONS), (2, len(imports) * 24), (20, 7)]
else:
tags += [(7, RELOCATIONS), (8, len(imports) * 24), (9, 24)]
tags.append((0, 0))
for index, tag in enumerate(tags):
struct.pack_into("<qQ", image, DYNAMIC + index * 16, *tag)
struct.pack_into("<QQQQQ", image, 120 + 8, DYNAMIC, DYNAMIC, DYNAMIC, len(tags) * 16, len(tags) * 16)
return image
def imported_types(image):
def imported_symbols(image):
tags = dynamic_tags(image)
symbols = file_offset(image, tags[6])
types = {}
@@ -37,16 +38,23 @@ def imported_types(image):
info, = struct.unpack_from("<Q", image, position + 8)
index = info >> 32
if index:
types[symbol_name(image, tags, index)] = image[symbols + index * 24 + 4] & 15
types[symbol_name(image, tags, index)] = image[symbols + index * 24 + 4]
return types
def main():
relinker = Path(sys.argv[1]).resolve()
with tempfile.TemporaryDirectory(prefix="anyps5-import-types-") as directory:
output = relink(relinker, Path(directory), importing_executable([("FFFFFFFFFFF", STT_FUNC), ("DDDDDDDDDDD", STT_OBJECT)]), {})
types = imported_types(output.read_bytes())
assert types == {"FFFFFFFFFFF": STT_FUNC, "DDDDDDDDDDD": STT_OBJECT}, types
for relocation_type in (6, 7):
for binding in (1, 2):
for kind in range(16):
imports = [("FFFFFFFFFFF", 2), ("DDDDDDDDDDD", 1), ("NNNNNNNNNNN", kind)]
case = Path(directory) / f"{relocation_type}-{binding}-{kind}"
case.mkdir()
output = relink(relinker, case, importing_executable(imports, binding, relocation_type), {})
symbols = imported_symbols(output.read_bytes())
expected = {name: (binding << 4) | symbol_type for name, symbol_type in imports}
assert symbols == expected, (relocation_type, binding, kind, symbols, expected)
print("Import symbol type tests passed")