@@ -1467,6 +1467,15 @@ void ObjCProcessor::ProcessObjCData()
1467
1467
m_relocationPointerRewrites.clear ();
1468
1468
}
1469
1469
1470
+ void ObjCProcessor::ProcessObjCLiterals ()
1471
+ {
1472
+ ProcessCFStrings ();
1473
+ ProcessNSConstantArrays ();
1474
+ ProcessNSConstantDictionaries ();
1475
+ ProcessNSConstantIntegerNumbers ();
1476
+ ProcessNSConstantFloatingPointNumbers ();
1477
+ ProcessNSConstantDatas ();
1478
+ }
1470
1479
1471
1480
void ObjCProcessor::ProcessCFStrings ()
1472
1481
{
@@ -1585,6 +1594,274 @@ void ObjCProcessor::ProcessCFStrings()
1585
1594
delete m_symbolQueue;
1586
1595
}
1587
1596
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
+
1588
1865
void ObjCProcessor::AddRelocatedPointer (uint64_t location, uint64_t rewrite)
1589
1866
{
1590
1867
m_relocationPointerRewrites[location] = rewrite;
0 commit comments