@@ -1467,6 +1467,15 @@ void ObjCProcessor::ProcessObjCData()
14671467 m_relocationPointerRewrites.clear ();
14681468}
14691469
1470+ void ObjCProcessor::ProcessObjCLiterals ()
1471+ {
1472+ ProcessCFStrings ();
1473+ ProcessNSConstantArrays ();
1474+ ProcessNSConstantDictionaries ();
1475+ ProcessNSConstantIntegerNumbers ();
1476+ ProcessNSConstantFloatingPointNumbers ();
1477+ ProcessNSConstantDatas ();
1478+ }
14701479
14711480void ObjCProcessor::ProcessCFStrings ()
14721481{
@@ -1585,6 +1594,274 @@ void ObjCProcessor::ProcessCFStrings()
15851594 delete m_symbolQueue;
15861595}
15871596
1597+ void ObjCProcessor::ProcessNSConstantArrays ()
1598+ {
1599+ m_symbolQueue = new SymbolQueue ();
1600+ uint64_t ptrSize = m_data->GetAddressSize ();
1601+
1602+ auto idType = Type::NamedType (m_data, m_typeNames.id );
1603+ StructureBuilder nsConstantArrayBuilder;
1604+ nsConstantArrayBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1605+ nsConstantArrayBuilder.AddMember (Type::IntegerType (ptrSize, false ), " count" );
1606+ nsConstantArrayBuilder.AddMember (Type::PointerType (ptrSize, idType), " objects" );
1607+ auto type = finalizeStructureBuilder (m_data, nsConstantArrayBuilder, " __NSConstantArray" );
1608+ m_typeNames.nsConstantArray = type.first ;
1609+
1610+ auto reader = GetReader ();
1611+ if (auto arrays = GetSectionWithName (" __objc_arrayobj" ))
1612+ {
1613+ auto start = arrays->GetStart ();
1614+ auto end = arrays->GetEnd ();
1615+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantArray )->GetWidth ();
1616+ m_data->BeginBulkModifySymbols ();
1617+ for (view_ptr_t i = start; i < end; i += typeWidth)
1618+ {
1619+ reader->Seek (i + ptrSize);
1620+ uint64_t count = reader->ReadPointer ();
1621+ auto dataLoc = ReadPointerAccountingForRelocations (reader.get ());
1622+ DefineObjCSymbol (
1623+ DataSymbol, Type::ArrayType (idType, count), fmt::format (" nsarray_{:x}_data" , i), dataLoc, true );
1624+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantArray ),
1625+ fmt::format (" nsarray_{:x}" , i), i, true );
1626+ }
1627+ auto id = m_data->BeginUndoActions ();
1628+ m_symbolQueue->Process ();
1629+ m_data->EndBulkModifySymbols ();
1630+ m_data->ForgetUndoActions (id);
1631+ }
1632+ delete m_symbolQueue;
1633+ }
1634+
1635+ void ObjCProcessor::ProcessNSConstantDictionaries ()
1636+ {
1637+ m_symbolQueue = new SymbolQueue ();
1638+ uint64_t ptrSize = m_data->GetAddressSize ();
1639+
1640+ auto idType = Type::NamedType (m_data, m_typeNames.id );
1641+ StructureBuilder nsConstantDictionaryBuilder;
1642+ nsConstantDictionaryBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1643+ nsConstantDictionaryBuilder.AddMember (Type::IntegerType (ptrSize, false ), " options" );
1644+ nsConstantDictionaryBuilder.AddMember (Type::IntegerType (ptrSize, false ), " count" );
1645+ nsConstantDictionaryBuilder.AddMember (Type::PointerType (ptrSize, idType), " keys" );
1646+ nsConstantDictionaryBuilder.AddMember (Type::PointerType (ptrSize, idType), " objects" );
1647+ auto type = finalizeStructureBuilder (m_data, nsConstantDictionaryBuilder, " __NSConstantDictionary" );
1648+ m_typeNames.nsConstantDictionary = type.first ;
1649+
1650+ auto reader = GetReader ();
1651+ if (auto dicts = GetSectionWithName (" __objc_dictobj" ))
1652+ {
1653+ auto start = dicts->GetStart ();
1654+ auto end = dicts->GetEnd ();
1655+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantDictionary )->GetWidth ();
1656+ m_data->BeginBulkModifySymbols ();
1657+ for (view_ptr_t i = start; i < end; i += typeWidth)
1658+ {
1659+ reader->Seek (i + (ptrSize * 2 ));
1660+ // TODO: Do we need to do anything with `options`? It appears to always be 1.
1661+ uint64_t count = reader->ReadPointer ();
1662+ auto keysLoc = ReadPointerAccountingForRelocations (reader.get ());
1663+ auto objectsLoc = ReadPointerAccountingForRelocations (reader.get ());
1664+ DefineObjCSymbol (
1665+ DataSymbol, Type::ArrayType (idType, count), fmt::format (" nsdict_{:x}_keys" , i), keysLoc, true );
1666+ DefineObjCSymbol (
1667+ DataSymbol, Type::ArrayType (idType, count), fmt::format (" nsdict_{:x}_objects" , i), objectsLoc, true );
1668+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantDictionary ),
1669+ fmt::format (" nsdict_{:x}" , i), i, true );
1670+ }
1671+ auto id = m_data->BeginUndoActions ();
1672+ m_symbolQueue->Process ();
1673+ m_data->EndBulkModifySymbols ();
1674+ m_data->ForgetUndoActions (id);
1675+ }
1676+ delete m_symbolQueue;
1677+ }
1678+
1679+ void ObjCProcessor::ProcessNSConstantIntegerNumbers ()
1680+ {
1681+ m_symbolQueue = new SymbolQueue ();
1682+ uint64_t ptrSize = m_data->GetAddressSize ();
1683+
1684+ StructureBuilder nsConstantIntegerNumberBuilder;
1685+ nsConstantIntegerNumberBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1686+ nsConstantIntegerNumberBuilder.AddMember (Type::PointerType (ptrSize, Type::IntegerType (1 , true )), " encoding" );
1687+ nsConstantIntegerNumberBuilder.AddMember (Type::IntegerType (ptrSize, true ), " value" );
1688+ auto type = finalizeStructureBuilder (m_data, nsConstantIntegerNumberBuilder, " __NSConstantIntegerNumber" );
1689+ m_typeNames.nsConstantIntegerNumber = type.first ;
1690+
1691+ auto reader = GetReader ();
1692+ if (auto numbers = GetSectionWithName (" __objc_intobj" ))
1693+ {
1694+ auto start = numbers->GetStart ();
1695+ auto end = numbers->GetEnd ();
1696+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantIntegerNumber )->GetWidth ();
1697+ m_data->BeginBulkModifySymbols ();
1698+ for (view_ptr_t i = start; i < end; i += typeWidth)
1699+ {
1700+ reader->Seek (i + ptrSize);
1701+ uint64_t encodingLoc = ReadPointerAccountingForRelocations (reader.get ());
1702+ uint64_t value = reader->Read64 ();
1703+ reader->Seek (encodingLoc);
1704+ uint8_t encoding = reader->Read8 ();
1705+
1706+ switch (encoding)
1707+ {
1708+ case ' c' :
1709+ case ' s' :
1710+ case ' i' :
1711+ case ' l' :
1712+ case ' q' :
1713+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantIntegerNumber ),
1714+ fmt::format (" nsint_{:x}_{}" , i, (int64_t )value), i, true );
1715+ break ;
1716+ case ' C' :
1717+ case ' S' :
1718+ case ' I' :
1719+ case ' L' :
1720+ case ' Q' :
1721+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantIntegerNumber ),
1722+ fmt::format (" nsint_{:x}_{}" , i, value), i, true );
1723+ break ;
1724+ default :
1725+ m_logger->LogWarn (" Unknown type encoding '%c' in number literal object at %p" , encoding, i);
1726+ continue ;
1727+ }
1728+ }
1729+ auto id = m_data->BeginUndoActions ();
1730+ m_symbolQueue->Process ();
1731+ m_data->EndBulkModifySymbols ();
1732+ m_data->ForgetUndoActions (id);
1733+ }
1734+ delete m_symbolQueue;
1735+ }
1736+
1737+ void ObjCProcessor::ProcessNSConstantFloatingPointNumbers ()
1738+ {
1739+ uint64_t ptrSize = m_data->GetAddressSize ();
1740+
1741+ StructureBuilder nsConstantFloatNumberBuilder;
1742+ nsConstantFloatNumberBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1743+ nsConstantFloatNumberBuilder.AddMember (Type::FloatType (4 ), " value" );
1744+ auto type = finalizeStructureBuilder (m_data, nsConstantFloatNumberBuilder, " __NSConstantFloatNumber" );
1745+ m_typeNames.nsConstantFloatNumber = type.first ;
1746+
1747+ StructureBuilder nsConstantDoubleNumberBuilder;
1748+ nsConstantDoubleNumberBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1749+ nsConstantDoubleNumberBuilder.AddMember (Type::FloatType (8 ), " value" );
1750+ type = finalizeStructureBuilder (m_data, nsConstantDoubleNumberBuilder, " __NSConstantDoubleNumber" );
1751+ m_typeNames.nsConstantDoubleNumber = type.first ;
1752+
1753+ StructureBuilder nsConstantDateBuilder;
1754+ nsConstantDateBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1755+ nsConstantDateBuilder.AddMember (Type::FloatType (8 ), " ti" );
1756+ type = finalizeStructureBuilder (m_data, nsConstantDateBuilder, " __NSConstantDate" );
1757+ m_typeNames.nsConstantDate = type.first ;
1758+
1759+ enum SectionType
1760+ {
1761+ Float,
1762+ Double,
1763+ Date,
1764+ };
1765+
1766+ constexpr std::pair<std::string_view, SectionType> sections[] = {
1767+ {" __objc_floatobj" , Float},
1768+ {" __objc_doubleobj" , Double},
1769+ {" __objc_dateobj" , Date},
1770+ };
1771+
1772+ auto reader = GetReader ();
1773+ for (auto & [sectionName, sectionType] : sections)
1774+ {
1775+ auto numbers = GetSectionWithName (sectionName.data ());
1776+ if (!numbers)
1777+ continue ;
1778+
1779+ m_symbolQueue = new SymbolQueue ();
1780+ auto start = numbers->GetStart ();
1781+ auto end = numbers->GetEnd ();
1782+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantDoubleNumber )->GetWidth ();
1783+ m_data->BeginBulkModifySymbols ();
1784+ for (view_ptr_t i = start; i < end; i += typeWidth)
1785+ {
1786+ reader->Seek (i + ptrSize);
1787+
1788+ QualifiedName* typeName = nullptr ;
1789+ std::string name;
1790+
1791+ switch (sectionType)
1792+ {
1793+ case Float:
1794+ {
1795+ float value = 0 ;
1796+ reader->Read (&value, sizeof (value));
1797+ name = fmt::format (" nsfloat_{:x}_{}" , i, value);
1798+ typeName = &m_typeNames.nsConstantFloatNumber ;
1799+ break ;
1800+ }
1801+ case Double:
1802+ {
1803+ double value = 0 ;
1804+ reader->Read (&value, sizeof (value));
1805+ name = fmt::format (" nsdouble_{:x}_{}" , i, value);
1806+ typeName = &m_typeNames.nsConstantDoubleNumber ;
1807+ break ;
1808+ }
1809+ case Date:
1810+ {
1811+ double value = 0 ;
1812+ reader->Read (&value, sizeof (value));
1813+ name = fmt::format (" nsdate_{:x}_{}" , i, value);
1814+ typeName = &m_typeNames.nsConstantDate ;
1815+ break ;
1816+ }
1817+ }
1818+ DefineObjCSymbol (DataSymbol, Type::NamedType (m_data, *typeName), name, i, true );
1819+ }
1820+ auto id = m_data->BeginUndoActions ();
1821+ m_symbolQueue->Process ();
1822+ m_data->EndBulkModifySymbols ();
1823+ m_data->ForgetUndoActions (id);
1824+ delete m_symbolQueue;
1825+ }
1826+ }
1827+
1828+ void ObjCProcessor::ProcessNSConstantDatas ()
1829+ {
1830+ m_symbolQueue = new SymbolQueue ();
1831+ uint64_t ptrSize = m_data->GetAddressSize ();
1832+
1833+ StructureBuilder nsConstantDataBuilder;
1834+ nsConstantDataBuilder.AddMember (Type::PointerType (ptrSize, Type::VoidType ()), " isa" );
1835+ nsConstantDataBuilder.AddMember (Type::IntegerType (ptrSize, false ), " length" );
1836+ nsConstantDataBuilder.AddMember (Type::PointerType (ptrSize, Type::IntegerType (1 , false )), " bytes" );
1837+ auto type = finalizeStructureBuilder (m_data, nsConstantDataBuilder, " __NSConstantData" );
1838+ m_typeNames.nsConstantData = type.first ;
1839+
1840+ auto reader = GetReader ();
1841+ if (auto datas = GetSectionWithName (" __objc_dataobj" ))
1842+ {
1843+ auto start = datas->GetStart ();
1844+ auto end = datas->GetEnd ();
1845+ auto typeWidth = Type::NamedType (m_data, m_typeNames.nsConstantData )->GetWidth ();
1846+ m_data->BeginBulkModifySymbols ();
1847+ for (view_ptr_t i = start; i < end; i += typeWidth)
1848+ {
1849+ reader->Seek (i + ptrSize);
1850+ uint64_t length = reader->ReadPointer ();
1851+ auto dataLoc = ReadPointerAccountingForRelocations (reader.get ());
1852+ DefineObjCSymbol (DataSymbol, Type::ArrayType (Type::IntegerType (1 , false ), length),
1853+ fmt::format (" nsdata_{:x}_data" , i), dataLoc, true );
1854+ DefineObjCSymbol (
1855+ DataSymbol, Type::NamedType (m_data, m_typeNames.nsConstantData ), fmt::format (" nsdata_{:x}" , i), i, true );
1856+ }
1857+ auto id = m_data->BeginUndoActions ();
1858+ m_symbolQueue->Process ();
1859+ m_data->EndBulkModifySymbols ();
1860+ m_data->ForgetUndoActions (id);
1861+ }
1862+ delete m_symbolQueue;
1863+ }
1864+
15881865void ObjCProcessor::AddRelocatedPointer (uint64_t location, uint64_t rewrite)
15891866{
15901867 m_relocationPointerRewrites[location] = rewrite;
0 commit comments