| 1463 | |
| 1464 | |
| 1465 | void ObjCProcessor::ProcessCFStrings() |
| 1466 | { |
| 1467 | m_symbolQueue = new SymbolQueue(); |
| 1468 | uint64_t ptrSize = m_data->GetAddressSize(); |
| 1469 | // https://github.com/apple/llvm-project/blob/next/clang/lib/CodeGen/CodeGenModule.cpp#L6129 |
| 1470 | // See also ASTContext.cpp ctrl+f __NSConstantString_tag |
| 1471 | |
| 1472 | // The place these flags are used is unclear, along with any clear flag definitions, but they are useful for |
| 1473 | // introspection |
| 1474 | EnumerationBuilder __cfStringFlagBuilder; |
| 1475 | __cfStringFlagBuilder.AddMemberWithValue("SwiftABI", 0b1); |
| 1476 | __cfStringFlagBuilder.AddMemberWithValue("Swift4_1", 0b100); |
| 1477 | // LLVM also sets 0x7c0 (0b11111000000) on both UTF8 and UTF16 strings however it is unclear what this denotes. |
| 1478 | __cfStringFlagBuilder.AddMemberWithValue("UTF8", 0b1000); |
| 1479 | __cfStringFlagBuilder.AddMemberWithValue("UTF16", 0b10000); |
| 1480 | auto type = finalizeEnumerationBuilder(m_data, __cfStringFlagBuilder, ptrSize, {"CFStringFlag"}); |
| 1481 | m_typeNames.cfStringFlag = type.first; |
| 1482 | |
| 1483 | StructureBuilder __cfStringStructBuilder; |
| 1484 | __cfStringStructBuilder.AddMember(Type::PointerType(ptrSize, Type::VoidType()), "isa"); |
| 1485 | __cfStringStructBuilder.AddMember(Type::NamedType(m_data, m_typeNames.cfStringFlag), "flags"); |
| 1486 | __cfStringStructBuilder.AddMember(Type::PointerType(ptrSize, Type::IntegerType(1, true)), "data"); |
| 1487 | __cfStringStructBuilder.AddMember(Type::IntegerType(ptrSize, false), "length"); |
| 1488 | type = finalizeStructureBuilder(m_data, __cfStringStructBuilder, "__NSConstantString"); |
| 1489 | m_typeNames.cfString = type.first; |
| 1490 | |
| 1491 | StructureBuilder __cfStringUTF16StructBuilder; |
| 1492 | __cfStringUTF16StructBuilder.AddMember(Type::PointerType(ptrSize, Type::VoidType()), "isa"); |
| 1493 | __cfStringUTF16StructBuilder.AddMember(Type::NamedType(m_data, m_typeNames.cfStringFlag), "flags"); |
| 1494 | __cfStringUTF16StructBuilder.AddMember(Type::PointerType(ptrSize, Type::IntegerType(2, true)), "data"); |
| 1495 | __cfStringUTF16StructBuilder.AddMember(Type::IntegerType(ptrSize, false), "length"); |
| 1496 | type = finalizeStructureBuilder(m_data, __cfStringUTF16StructBuilder, "__NSConstantString_UTF16"); |
| 1497 | m_typeNames.cfStringUTF16 = type.first; |
| 1498 | |
| 1499 | auto reader = GetReader(); |
| 1500 | if (auto cfstrings = GetSectionWithName("__cfstring")) |
| 1501 | { |
| 1502 | auto start = cfstrings->GetStart(); |
| 1503 | auto end = cfstrings->GetEnd(); |
| 1504 | auto typeWidth = Type::NamedType(m_data, m_typeNames.cfString)->GetWidth(); |
| 1505 | m_data->BeginBulkModifySymbols(); |
| 1506 | for (view_ptr_t i = start; i < end; i += typeWidth) |
| 1507 | { |
| 1508 | reader->Seek(i + ptrSize); |
| 1509 | uint64_t flags = reader->ReadPointer(); |
| 1510 | auto strLoc = ReadPointerAccountingForRelocations(reader.get()); |
| 1511 | auto size = reader->ReadPointer(); |
| 1512 | std::string str; |
| 1513 | if (flags & 0b10000) // UTF16 |
| 1514 | { |
| 1515 | auto data = m_data->ReadBuffer(strLoc, size * 2); |
| 1516 | |
| 1517 | str = ""; |
| 1518 | for (uint64_t bufferOff = 0; bufferOff < size * 2; bufferOff += 2) |
| 1519 | { |
| 1520 | uint8_t* rawData = static_cast<uint8_t*>(data.GetData()); |
| 1521 | uint8_t* offsetAddress = rawData + bufferOff; |
| 1522 | uint16_t c = *reinterpret_cast<uint16_t*>(offsetAddress); |
no test coverage detected