swift-reflection-dump is used by various Reflection unit tests (e.g. Reflection/capture_descriptors.sil and Reflection/typeref_decoding_imported.swift), broadly speaking, generating shared objects and then running the tool over it.
swift-reflection-dump uses an ObjectMemoryReader which takes some executable images and requests for vaddrs and reads from those images. For ELF binaries, Image::scanELFType looks at the program headers, reads segments, and saves them indexed by the program header vaddr. When the ObjectMemoryReader wants to read a given number of bytes from a given vaddr, the relevant segment is accessed by iterating through the stored segments looking whether the specified address and byte range lies inside a segment (see Image::getContentsAtAddress)).
However, ReflectionContext::readELFSections needs to read the section headers. The section table is never loaded and so is not part of a loaded segment. Therefore, Image::scanELF installs a catch-all pseudo-segment which contains the entire executable image.
ReflectionContext reads ELF sections by looking for e_shoff and then subsequent sections by e_shoff + i * e_shentsize. But this is done via the ObjectMemoryReader which wants vaddrs. When the requested offset is not part of a segment, we fall through to the catch-all case and everything is OK, but if the offset when interpreted as a vaddr matches an already-existing segment, we can read garbage as an ELF header, swift-reflection-dump segfaults, and the unit test crashes.
Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 0 | |Component/s | | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 333589a8f959aa825e953c912e67a22aIssue Description:
swift-reflection-dump
is used by various Reflection unit tests (e.g.Reflection/capture_descriptors.sil
andReflection/typeref_decoding_imported.swift
), broadly speaking, generating shared objects and then running the tool over it.swift-reflection-dump
uses anObjectMemoryReader
which takes some executable images and requests for vaddrs and reads from those images. For ELF binaries,Image::scanELFType
looks at the program headers, reads segments, and saves them indexed by the program header vaddr. When theObjectMemoryReader
wants to read a given number of bytes from a given vaddr, the relevant segment is accessed by iterating through the stored segments looking whether the specified address and byte range lies inside a segment (seeImage::getContentsAtAddress
)).However,
ReflectionContext::readELFSections
needs to read the section headers. The section table is never loaded and so is not part of a loaded segment. Therefore,Image::scanELF
installs a catch-all pseudo-segment which contains the entire executable image.ReflectionContext
reads ELF sections by looking fore_shoff
and then subsequent sections bye_shoff
+ i *e_shentsize
. But this is done via theObjectMemoryReader
which wants vaddrs. When the requested offset is not part of a segment, we fall through to the catch-all case and everything is OK, but if the offset when interpreted as a vaddr matches an already-existing segment, we can read garbage as an ELF header,swift-reflection-dump
segfaults, and the unit test crashes.