@@ -1535,6 +1535,15 @@ void ObjCProcessor::ProcessObjCData()
15351535 m_relocationPointerRewrites.clear ();
15361536}
15371537
1538+ void ObjCProcessor::ProcessObjCLiterals ()
1539+ {
1540+ ProcessCFStrings ();
1541+ ProcessNSConstantArrays ();
1542+ ProcessNSConstantDictionaries ();
1543+ ProcessNSConstantIntegerNumbers ();
1544+ ProcessNSConstantFloatingPointNumbers ();
1545+ ProcessNSConstantDatas ();
1546+ }
15381547
15391548void ObjCProcessor::ProcessCFStrings ()
15401549{
@@ -1651,6 +1660,274 @@ void ObjCProcessor::ProcessCFStrings()
16511660 }
16521661}
16531662
1663+ void ObjCProcessor::ProcessNSConstantArrays ()
1664+ {
1665+ m_symbolQueue = new SymbolQueue ();
1666+ uint64_t ptrSize = m_data->GetAddressSize ();
1667+
1668+ auto idType = Type::NamedType (m_data, m_typeNames.id );
1669+ StructureBuilder nsConstantArrayBuilder;
1670+ nsConstantArrayBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1671+ nsConstantArrayBuilder.AddMember (Type::IntegerType (ptrSize, false ), " count" );
1672+ nsConstantArrayBuilder.AddMember (Type::PointerType (ptrSize, idType), " objects" );
1673+ auto type = finalizeStructureBuilder (m_data, nsConstantArrayBuilder, " __NSConstantArray" );
1674+ m_typeNames.nsConstantArray = type.first ;
1675+
1676+ auto reader = GetReader ();
1677+ if (auto arrays = GetSectionWithName (" __objc_arrayobj" ))
1678+ {
1679+ auto start = arrays->GetStart ();
1680+ auto end = arrays->GetEnd ();
1681+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantArray )->GetWidth ();
1682+ m_data->BeginBulkModifySymbols ();
1683+ for (view_ptr_t i = start; i < end; i += typeWidth)
1684+ {
1685+ reader->Seek (i + ptrSize);
1686+ uint64_t count = reader->ReadPointer ();
1687+ auto dataLoc = ReadPointerAccountingForRelocations (reader.get ());
1688+ DefineObjCSymbol (
1689+ DataSymbol, Type::ArrayType (idType, count), fmt::format (" nsarray_{:x}_data" , i), dataLoc, true );
1690+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantArray ),
1691+ fmt::format (" nsarray_{:x}" , i), i, true );
1692+ }
1693+ auto id = m_data->BeginUndoActions ();
1694+ m_symbolQueue->Process ();
1695+ m_data->EndBulkModifySymbols ();
1696+ m_data->ForgetUndoActions (id);
1697+ }
1698+ delete m_symbolQueue;
1699+ }
1700+
1701+ void ObjCProcessor::ProcessNSConstantDictionaries ()
1702+ {
1703+ m_symbolQueue = new SymbolQueue ();
1704+ uint64_t ptrSize = m_data->GetAddressSize ();
1705+
1706+ auto idType = Type::NamedType (m_data, m_typeNames.id );
1707+ StructureBuilder nsConstantDictionaryBuilder;
1708+ nsConstantDictionaryBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1709+ nsConstantDictionaryBuilder.AddMember (Type::IntegerType (ptrSize, false ), " options" );
1710+ nsConstantDictionaryBuilder.AddMember (Type::IntegerType (ptrSize, false ), " count" );
1711+ nsConstantDictionaryBuilder.AddMember (Type::PointerType (ptrSize, idType), " keys" );
1712+ nsConstantDictionaryBuilder.AddMember (Type::PointerType (ptrSize, idType), " objects" );
1713+ auto type = finalizeStructureBuilder (m_data, nsConstantDictionaryBuilder, " __NSConstantDictionary" );
1714+ m_typeNames.nsConstantDictionary = type.first ;
1715+
1716+ auto reader = GetReader ();
1717+ if (auto dicts = GetSectionWithName (" __objc_dictobj" ))
1718+ {
1719+ auto start = dicts->GetStart ();
1720+ auto end = dicts->GetEnd ();
1721+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantDictionary )->GetWidth ();
1722+ m_data->BeginBulkModifySymbols ();
1723+ for (view_ptr_t i = start; i < end; i += typeWidth)
1724+ {
1725+ reader->Seek (i + (ptrSize * 2 ));
1726+ // TODO: Do we need to do anything with `options`? It appears to always be 1.
1727+ uint64_t count = reader->ReadPointer ();
1728+ auto keysLoc = ReadPointerAccountingForRelocations (reader.get ());
1729+ auto objectsLoc = ReadPointerAccountingForRelocations (reader.get ());
1730+ DefineObjCSymbol (
1731+ DataSymbol, Type::ArrayType (idType, count), fmt::format (" nsdict_{:x}_keys" , i), keysLoc, true );
1732+ DefineObjCSymbol (
1733+ DataSymbol, Type::ArrayType (idType, count), fmt::format (" nsdict_{:x}_objects" , i), objectsLoc, true );
1734+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantDictionary ),
1735+ fmt::format (" nsdict_{:x}" , i), i, true );
1736+ }
1737+ auto id = m_data->BeginUndoActions ();
1738+ m_symbolQueue->Process ();
1739+ m_data->EndBulkModifySymbols ();
1740+ m_data->ForgetUndoActions (id);
1741+ }
1742+ delete m_symbolQueue;
1743+ }
1744+
1745+ void ObjCProcessor::ProcessNSConstantIntegerNumbers ()
1746+ {
1747+ m_symbolQueue = new SymbolQueue ();
1748+ uint64_t ptrSize = m_data->GetAddressSize ();
1749+
1750+ StructureBuilder nsConstantIntegerNumberBuilder;
1751+ nsConstantIntegerNumberBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1752+ nsConstantIntegerNumberBuilder.AddMember (Type::PointerType (ptrSize, Type::IntegerType (1 , true )), " encoding" );
1753+ nsConstantIntegerNumberBuilder.AddMember (Type::IntegerType (ptrSize, true ), " value" );
1754+ auto type = finalizeStructureBuilder (m_data, nsConstantIntegerNumberBuilder, " __NSConstantIntegerNumber" );
1755+ m_typeNames.nsConstantIntegerNumber = type.first ;
1756+
1757+ auto reader = GetReader ();
1758+ if (auto numbers = GetSectionWithName (" __objc_intobj" ))
1759+ {
1760+ auto start = numbers->GetStart ();
1761+ auto end = numbers->GetEnd ();
1762+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantIntegerNumber )->GetWidth ();
1763+ m_data->BeginBulkModifySymbols ();
1764+ for (view_ptr_t i = start; i < end; i += typeWidth)
1765+ {
1766+ reader->Seek (i + ptrSize);
1767+ uint64_t encodingLoc = ReadPointerAccountingForRelocations (reader.get ());
1768+ uint64_t value = reader->Read64 ();
1769+ reader->Seek (encodingLoc);
1770+ uint8_t encoding = reader->Read8 ();
1771+
1772+ switch (encoding)
1773+ {
1774+ case ' c' :
1775+ case ' s' :
1776+ case ' i' :
1777+ case ' l' :
1778+ case ' q' :
1779+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantIntegerNumber ),
1780+ fmt::format (" nsint_{:x}_{}" , i, (int64_t )value), i, true );
1781+ break ;
1782+ case ' C' :
1783+ case ' S' :
1784+ case ' I' :
1785+ case ' L' :
1786+ case ' Q' :
1787+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantIntegerNumber ),
1788+ fmt::format (" nsint_{:x}_{}" , i, value), i, true );
1789+ break ;
1790+ default :
1791+ m_logger->LogWarn (" Unknown type encoding '%c' in number literal object at %p" , encoding, i);
1792+ continue ;
1793+ }
1794+ }
1795+ auto id = m_data->BeginUndoActions ();
1796+ m_symbolQueue->Process ();
1797+ m_data->EndBulkModifySymbols ();
1798+ m_data->ForgetUndoActions (id);
1799+ }
1800+ delete m_symbolQueue;
1801+ }
1802+
1803+ void ObjCProcessor::ProcessNSConstantFloatingPointNumbers ()
1804+ {
1805+ uint64_t ptrSize = m_data->GetAddressSize ();
1806+
1807+ StructureBuilder nsConstantFloatNumberBuilder;
1808+ nsConstantFloatNumberBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1809+ nsConstantFloatNumberBuilder.AddMember (Type::FloatType (4 ), " value" );
1810+ auto type = finalizeStructureBuilder (m_data, nsConstantFloatNumberBuilder, " __NSConstantFloatNumber" );
1811+ m_typeNames.nsConstantFloatNumber = type.first ;
1812+
1813+ StructureBuilder nsConstantDoubleNumberBuilder;
1814+ nsConstantDoubleNumberBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1815+ nsConstantDoubleNumberBuilder.AddMember (Type::FloatType (8 ), " value" );
1816+ type = finalizeStructureBuilder (m_data, nsConstantDoubleNumberBuilder, " __NSConstantDoubleNumber" );
1817+ m_typeNames.nsConstantDoubleNumber = type.first ;
1818+
1819+ StructureBuilder nsConstantDateBuilder;
1820+ nsConstantDateBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1821+ nsConstantDateBuilder.AddMember (Type::FloatType (8 ), " ti" );
1822+ type = finalizeStructureBuilder (m_data, nsConstantDateBuilder, " __NSConstantDate" );
1823+ m_typeNames.nsConstantDate = type.first ;
1824+
1825+ enum SectionType
1826+ {
1827+ Float,
1828+ Double,
1829+ Date,
1830+ };
1831+
1832+ constexpr std::pair<std::string_view, SectionType> sections[] = {
1833+ {" __objc_floatobj" , Float},
1834+ {" __objc_doubleobj" , Double},
1835+ {" __objc_dateobj" , Date},
1836+ };
1837+
1838+ auto reader = GetReader ();
1839+ for (auto & [sectionName, sectionType] : sections)
1840+ {
1841+ auto numbers = GetSectionWithName (sectionName.data ());
1842+ if (!numbers)
1843+ continue ;
1844+
1845+ m_symbolQueue = new SymbolQueue ();
1846+ auto start = numbers->GetStart ();
1847+ auto end = numbers->GetEnd ();
1848+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantDoubleNumber )->GetWidth ();
1849+ m_data->BeginBulkModifySymbols ();
1850+ for (view_ptr_t i = start; i < end; i += typeWidth)
1851+ {
1852+ reader->Seek (i + ptrSize);
1853+
1854+ QualifiedName* typeName = nullptr ;
1855+ std::string name;
1856+
1857+ switch (sectionType)
1858+ {
1859+ case Float:
1860+ {
1861+ float value = 0 ;
1862+ reader->Read (&value, sizeof (value));
1863+ name = fmt::format (" nsfloat_{:x}_{}" , i, value);
1864+ typeName = &m_typeNames.nsConstantFloatNumber ;
1865+ break ;
1866+ }
1867+ case Double:
1868+ {
1869+ double value = 0 ;
1870+ reader->Read (&value, sizeof (value));
1871+ name = fmt::format (" nsdouble_{:x}_{}" , i, value);
1872+ typeName = &m_typeNames.nsConstantDoubleNumber ;
1873+ break ;
1874+ }
1875+ case Date:
1876+ {
1877+ double value = 0 ;
1878+ reader->Read (&value, sizeof (value));
1879+ name = fmt::format (" nsdate_{:x}_{}" , i, value);
1880+ typeName = &m_typeNames.nsConstantDate ;
1881+ break ;
1882+ }
1883+ }
1884+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, *typeName), name, i, true );
1885+ }
1886+ auto id = m_data->BeginUndoActions ();
1887+ m_symbolQueue->Process ();
1888+ m_data->EndBulkModifySymbols ();
1889+ m_data->ForgetUndoActions (id);
1890+ delete m_symbolQueue;
1891+ }
1892+ }
1893+
1894+ void ObjCProcessor::ProcessNSConstantDatas ()
1895+ {
1896+ m_symbolQueue = new SymbolQueue ();
1897+ uint64_t ptrSize = m_data->GetAddressSize ();
1898+
1899+ StructureBuilder nsConstantDataBuilder;
1900+ nsConstantDataBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1901+ nsConstantDataBuilder.AddMember (Type::IntegerType (ptrSize, false ), " length" );
1902+ nsConstantDataBuilder.AddMember (Type::PointerType (ptrSize, Type::IntegerType (1 , false )), " bytes" );
1903+ auto type = finalizeStructureBuilder (m_data, nsConstantDataBuilder, " __NSConstantData" );
1904+ m_typeNames.nsConstantData = type.first ;
1905+
1906+ auto reader = GetReader ();
1907+ if (auto datas = GetSectionWithName (" __objc_dataobj" ))
1908+ {
1909+ auto start = datas->GetStart ();
1910+ auto end = datas->GetEnd ();
1911+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantData )->GetWidth ();
1912+ m_data->BeginBulkModifySymbols ();
1913+ for (view_ptr_t i = start; i < end; i += typeWidth)
1914+ {
1915+ reader->Seek (i + ptrSize);
1916+ uint64_t length = reader->ReadPointer ();
1917+ auto dataLoc = ReadPointerAccountingForRelocations (reader.get ());
1918+ DefineObjCSymbol (DataSymbol, Type::ArrayType (Type::IntegerType (1 , false ), length),
1919+ fmt::format (" nsdata_{:x}_data" , i), dataLoc, true );
1920+ DefineObjCSymbol (
1921+ DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantData ), fmt::format (" nsdata_{:x}" , i), i, true );
1922+ }
1923+ auto id = m_data->BeginUndoActions ();
1924+ m_symbolQueue->Process ();
1925+ m_data->EndBulkModifySymbols ();
1926+ m_data->ForgetUndoActions (id);
1927+ }
1928+ delete m_symbolQueue;
1929+ }
1930+
16541931void ObjCProcessor::AddRelocatedPointer (uint64_t location, uint64_t rewrite)
16551932{
16561933 m_relocationPointerRewrites[location] = rewrite;
0 commit comments