Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions objectivec/objc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,13 +581,26 @@ void ObjCProcessor::LoadCategories(ObjCReader* reader, Ref<Section> classPtrSect
categoryBaseClassName = it->second.name;
category.associatedName = it->second.associatedName;
}
else if (auto symbol = m_data->GetSymbolByAddress(catLocation + m_data->GetAddressSize()))
{
if (symbol->GetType() == ImportedDataSymbol || symbol->GetType() == ImportAddressSymbol)
else
{
auto symbol = m_data->GetSymbolByAddress(cat.cls);
if (!symbol)
symbol = SymbolForUnmappedAddress(cat.cls);

if (symbol)
{
const auto& symbolName = symbol->GetFullName();
if (symbolName.size() > 14 && symbolName.rfind("_OBJC_CLASS_$_", 0) == 0)
categoryBaseClassName = symbolName.substr(14, symbolName.size() - 14);
if (symbol->GetType() == ImportedDataSymbol || symbol->GetType() == ImportAddressSymbol || symbol->GetType() == DataSymbol)
{
// Symbols named `_OBJC_CLASS_$_` are references to external classes.
// Symbols named `cls_` are classes defined in a loaded image other than
// the image currently being analyzed. Classes from the current image
// are found via `m_classes`.
const std::string_view symbolName = symbol->GetFullNameRef();
if (symbolName.size() > 14 && symbolName.rfind("_OBJC_CLASS_$_", 0) == 0)
categoryBaseClassName = symbolName.substr(14);
else if (symbolName.size() > 4 && symbolName.rfind("cls_", 0) == 0)
categoryBaseClassName = symbolName.substr(4);
}
}
}
if (categoryBaseClassName.empty())
Expand Down Expand Up @@ -1247,6 +1260,11 @@ uint64_t ObjCProcessor::GetObjCRelativeMethodBaseAddress(ObjCReader* reader)
return 0;
}

Ref<Symbol> ObjCProcessor::SymbolForUnmappedAddress(uint64_t address)
{
return nullptr;
}

void ObjCProcessor::ProcessObjCData(std::optional<std::string> imageName)
{
m_symbolQueue = new SymbolQueue();
Expand Down
1 change: 1 addition & 0 deletions objectivec/objc.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ namespace BinaryNinja {
virtual uint64_t GetObjCRelativeMethodBaseAddress(ObjCReader* reader);
virtual void GetRelativeMethod(ObjCReader* reader, method_t& meth);
virtual std::shared_ptr<ObjCReader> GetReader() = 0;
virtual Ref<Symbol> SymbolForUnmappedAddress(uint64_t address);

public:
virtual ~ObjCProcessor() = default;
Expand Down
20 changes: 20 additions & 0 deletions view/sharedcache/core/ObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,26 @@ uint64_t SharedCacheObjCProcessor::GetObjCRelativeMethodBaseAddress(ObjCReader*
return m_customRelativeMethodSelectorBase.value_or(0);
}

Ref<Symbol> SharedCacheObjCProcessor::SymbolForUnmappedAddress(uint64_t address)
{
if (const auto symbol = m_data->GetSymbolByAddress(address))
return nullptr;

const auto controller = DSC::SharedCacheController::FromView(*m_data);
if (!controller)
return nullptr;

// No existing symbol located, try and search through the symbols of the cache.
auto cacheSymbol = controller->GetCache().GetSymbolAt(address);
if (!cacheSymbol.has_value())
return nullptr;

// Define the new symbol!
Ref<Symbol> symbol(new Symbol(cacheSymbol->type, cacheSymbol->name, address));
m_data->DefineAutoSymbol(symbol);
return symbol;
}

SharedCacheObjCProcessor::SharedCacheObjCProcessor(BinaryView* data, bool isBackedByDatabase) :
ObjCProcessor(data, "SharedCache.ObjC", isBackedByDatabase, true)
{}
2 changes: 2 additions & 0 deletions view/sharedcache/core/ObjC.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ namespace DSCObjC {

void GetRelativeMethod(BinaryNinja::ObjCReader* reader, BinaryNinja::method_t& meth) override;

BinaryNinja::Ref<BinaryNinja::Symbol> SymbolForUnmappedAddress(uint64_t address) override;

public:
SharedCacheObjCProcessor(BinaryNinja::BinaryView* data, bool isBackedByDatabase);

Expand Down