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