diff --git a/core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp b/core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp index c862ee74c..483eaed3b 100644 --- a/core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp +++ b/core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp @@ -61,9 +61,15 @@ RelinkResult RelinkerPipeline::Relink(const std::vector& sourceElf } FileByteOffset sceTableBase = 0; - for (const auto& ph : programHeaders) - if (ph.Type == PT_SCE_DYNLIBDATA) - sceTableBase = ph.Offset; + bool hasSceDynlibData = false; + for (const auto& ph : programHeaders) { + if (ph.Type != PT_SCE_DYNLIBDATA) + continue; + if (hasSceDynlibData) + throw RelinkerException("Multiple PT_SCE_DYNLIBDATA segments", ph.Offset); + hasSceDynlibData = true; + sceTableBase = ph.Offset; + } std::vector dynTags; bool hasDynamicSegment = false; @@ -108,7 +114,7 @@ RelinkResult RelinkerPipeline::Relink(const std::vector& sourceElf if (requireExactlyOneOf(osTag, sysvTag, name)) { const std::uint64_t value = getTagValue(osTag); if (value > std::numeric_limits::max() - sceTableBase) - throw RelinkerException(std::string(name) + " is outside the file", value); + throw RelinkerException(std::string("Adding PT_SCE_DYNLIBDATA base to ") + name + " overflows", value); return sceTableBase + value; } return _elfReader->TranslateVirtualAddress(getTagValue(sysvTag)); diff --git a/core/relinker/relinker/tests/test_string_table_bounds.py b/core/relinker/relinker/tests/test_string_table_bounds.py index f130b3d7f..c5f66e25c 100644 --- a/core/relinker/relinker/tests/test_string_table_bounds.py +++ b/core/relinker/relinker/tests/test_string_table_bounds.py @@ -24,12 +24,12 @@ DT_OS_RELAENT = 0x61000033 def fixture(os_tags=False, str_size=16, needed_offset=1, symbol_offset=8, table_bytes=None, outside_bytes=b"", - block_offset=0, strtab_value=None): + block_offset=0, strtab_value=None, duplicate_sce_dynlibdata=False): image = bytearray(0x1000) table_base = block_offset if os_tags else 0 image[:16] = b"\x7fELF\x02\x01\x01" + bytes(9) struct.pack_into("` when one does not fit 15 bytes), not the console's. A Linux point-to-point address without a peer loses `IFF_POINTOPOINT`, and an IPv4 broadcast address the host omits is computed from the netmask. On Windows the flags are only `IFF_UP`, `IFF_RUNNING`, `IFF_LOOPBACK`, `IFF_BROADCAST` and `IFF_MULTICAST`, derived from the adapter: PPP and tunnel adapters get neither `IFF_BROADCAST` nor `IFF_POINTOPOINT` because their peer address is not reported, and an address whose prefix length the host reports as unspecified gets a host mask. - [gethostname](../../core/libs/prx/libc/src/Hostname.cpp) (libc) reports the fixed guest name `AnyPS5` without querying the host machine name. Buffer copying, null queries and `ENAMETOOLONG` follow [FreeBSD gethostname](https://github.com/freebsd/freebsd-src/blob/main/lib/libc/gen/gethostname.c); the console's configurable hostname and its integration with `sysctl` and name resolution are unverified and not implemented.