Skip to content

Commit

Permalink
Merge pull request #146 from p-x9/feature/trie-tree-search
Browse files Browse the repository at this point in the history
  • Loading branch information
p-x9 authored Nov 23, 2024
2 parents 94fe4fa + 4620021 commit 4153326
Show file tree
Hide file tree
Showing 22 changed files with 694 additions and 402 deletions.
18 changes: 9 additions & 9 deletions Sources/MachOKit/DyldCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,12 @@ extension DyldCache {
}

extension DyldCache {
public typealias DylibsTrieEntries = DataTrieTree<DylibsTrieNodeContent>
public typealias DylibsTrie = DataTrieTree<DylibsTrieNodeContent>

/// Dylibs trie is for searching by dylib name.
///
/// The ``dylibIndices`` are retrieved from this trie tree.
public var dylibsTrieEntries: DylibsTrieEntries? {
public var dylibsTrie: DylibsTrie? {
guard mainCacheHeader.dylibsTrieAddr > 0,
mainCacheHeader.hasProperty(\.dylibsTrieSize) else {
return nil
Expand All @@ -246,20 +246,20 @@ extension DyldCache {
/// 0 /usr/lib/libobjc.dylib
/// ```
public var dylibIndices: [DylibIndex] {
guard let dylibsTrieEntries else {
guard let dylibsTrie else {
return []
}
return dylibsTrieEntries.dylibIndices
return dylibsTrie.dylibIndices
}
}

extension DyldCache {
public typealias ProgramsTrieEntries = DataTrieTree<ProgramsTrieNodeContent>
public typealias ProgramsTrie = DataTrieTree<ProgramsTrieNodeContent>

/// Pair of program name/cdhash and offset to prebuiltLoaderSet
///
/// The ``programOffsets`` are retrieved from this trie tree.
public var programsTrieEntries: ProgramsTrieEntries? {
public var programsTrie: ProgramsTrie? {
guard mainCacheHeader.programTrieAddr > 0,
mainCacheHeader.hasProperty(\.programTrieSize) else {
return nil
Expand All @@ -269,7 +269,7 @@ extension DyldCache {
}
let size = mainCacheHeader.programTrieSize

return ProgramsTrieEntries(
return ProgramsTrie(
data: fileHandle.readData(offset: offset, size: Int(size))
)
}
Expand All @@ -284,10 +284,10 @@ extension DyldCache {
/// 131776 /cdhash/fed26a75645fed2a674b5c4d01001bfa69b9dbea
/// ```
public var programOffsets: [ProgramOffset] {
guard let programsTrieEntries else {
guard let programsTrie else {
return []
}
return programsTrieEntries.programOffsets
return programsTrie.programOffsets
}

/// Get the prebuiltLoaderSet indicated by programOffset.
Expand Down
18 changes: 9 additions & 9 deletions Sources/MachOKit/DyldCacheLoaded.swift
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,12 @@ extension DyldCacheLoaded {
}

extension DyldCacheLoaded {
public typealias DylibsTrieEntries = MemoryTrieTree<DylibsTrieNodeContent>
public typealias DylibsTrie = MemoryTrieTree<DylibsTrieNodeContent>

/// Dylibs trie is for searching by dylib name.
///
/// The ``dylibIndices`` are retrieved from this trie tree.
public var dylibsTrieEntries: DylibsTrieEntries? {
public var dylibsTrie: DylibsTrie? {
guard header.dylibsTrieAddr > 0,
header.hasProperty(\.dylibsTrieSize),
let slide else {
Expand Down Expand Up @@ -242,20 +242,20 @@ extension DyldCacheLoaded {
/// 0 /usr/lib/libobjc.dylib
/// ```
public var dylibIndices: [DylibIndex] {
guard let dylibsTrieEntries else {
guard let dylibsTrie else {
return []
}
return dylibsTrieEntries.dylibIndices
return dylibsTrie.dylibIndices
}
}

extension DyldCacheLoaded {
public typealias ProgramsTrieEntries = MemoryTrieTree<ProgramsTrieNodeContent>
public typealias ProgramsTrie = MemoryTrieTree<ProgramsTrieNodeContent>

/// Pair of program name/cdhash and offset to prebuiltLoaderSet
///
/// The ``programOffsets`` are retrieved from this trie tree.
public var programsTrieEntries: ProgramsTrieEntries? {
public var programsTrie: ProgramsTrie? {
guard header.programTrieAddr > 0,
header.hasProperty(\.programTrieSize),
let slide else {
Expand All @@ -268,7 +268,7 @@ extension DyldCacheLoaded {
return nil
}

return ProgramsTrieEntries(
return ProgramsTrie(
basePointer: basePointer,
size: numericCast(size)
)
Expand All @@ -284,10 +284,10 @@ extension DyldCacheLoaded {
/// 131776 /cdhash/fed26a75645fed2a674b5c4d01001bfa69b9dbea
/// ```
public var programOffsets: [ProgramOffset] {
guard let programsTrieEntries else {
guard let programsTrie else {
return []
}
return programsTrieEntries.programOffsets
return programsTrie.programOffsets
}

/// Get the prebuiltLoaderSet indicated by programOffset.
Expand Down
23 changes: 23 additions & 0 deletions Sources/MachOKit/Extension/FixedWidthInteger+.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// FixedWidthInteger+.swift
// MachOKit
//
// Created by p-x9 on 2024/11/20
//
//

import Foundation

extension FixedWidthInteger {
var uleb128Size: Int {
var value = self
var result = 0

repeat {
value = value >> 7
result += 1
} while value != 0

return result
}
}
178 changes: 0 additions & 178 deletions Sources/MachOKit/Extension/Sequence+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,6 @@

import Foundation

extension Sequence<ExportTrieEntry> {
public var exportedSymbols: [ExportedSymbol] {
let entries = Array(self)
guard !entries.isEmpty else { return [] }

let map: [Int: Element] = Dictionary(
uniqueKeysWithValues: entries.map {
($0.offset, $0)
}
)
return extractExportedSymbols(
currentName: "",
currentOffset: 0,
entry: entries[0],
map: map
)
}

/// https://opensource.apple.com/source/dyld/dyld-421.1/interlinked-dylibs/Trie.hpp.auto.html
private func extractExportedSymbols(
currentName: String,
currentOffset: Int,
entry: Element,
map: [Int: Element]
) -> [ExportedSymbol] {
var currentOffset = currentOffset
if let offset = entry.symbolOffset {
currentOffset += Int(bitPattern: offset)
}

guard !entry.children.isEmpty else {
return [
ExportedSymbol(
name: currentName,
offset: currentOffset,
flags: entry.flags ?? [],
ordinal: entry.ordinal,
importedName: entry.importedName,
stub: entry.stub,
resolver: entry.resolver
)
]
}
return entry.children.map {
if let entry = map[Int($0.offset)] {
return extractExportedSymbols(
currentName: currentName + $0.label,
currentOffset: currentOffset,
entry: entry,
map: map
)
} else {
return [
ExportedSymbol(
name: currentName + $0.label,
offset: currentOffset,
flags: entry.flags ?? [],
ordinal: entry.ordinal,
importedName: entry.importedName,
stub: entry.stub,
resolver: entry.resolver
)
]
}
}.flatMap { $0 }
}
}

// https://opensource.apple.com/source/ld64/ld64-253.9/src/other/dyldinfo.cpp.auto.html
extension Sequence<BindOperation> {
func bindings(
Expand Down Expand Up @@ -348,113 +280,3 @@ extension Sequence where Element == CodeSignCodeDirectory {
}
}
}

extension Sequence<DylibsTrieEntry> {
public var dylibIndices: [DylibIndex] {
let entries = Array(self)
guard !entries.isEmpty else { return [] }

let map: [Int: Element] = Dictionary(
uniqueKeysWithValues: entries.map {
($0.offset, $0)
}
)
return extractDylibIndices(
currentName: "",
currentOffset: 0,
entry: entries[0],
map: map
)
}

private func extractDylibIndices(
currentName: String,
currentOffset: Int,
entry: Element,
map: [Int: Element]
) -> [DylibIndex] {
guard !entry.children.isEmpty else {
if let content = entry.content {
return [
.init(name: currentName, index: content.index)
]
}
return []
}
return entry.children.map {
if let entry = map[Int($0.offset)] {
return extractDylibIndices(
currentName: currentName + $0.label,
currentOffset: currentOffset,
entry: entry,
map: map
)
} else {
if let content = entry.content {
return [
.init(
name: currentName + $0.label,
index: content.index
)
]
}
return []
}
}.flatMap { $0 }
}
}

extension Sequence<ProgramsTrieEntry> {
public var programOffsets: [ProgramOffset] {
let entries = Array(self)
guard !entries.isEmpty else { return [] }

let map: [Int: Element] = Dictionary(
uniqueKeysWithValues: entries.map {
($0.offset, $0)
}
)
return extractProgramOffsets(
currentName: "",
currentOffset: 0,
entry: entries[0],
map: map
)
}

private func extractProgramOffsets(
currentName: String,
currentOffset: Int,
entry: Element,
map: [Int: Element]
) -> [ProgramOffset] {
guard !entry.children.isEmpty else {
if let content = entry.content {
return [
.init(name: currentName, offset: content.offset)
]
}
return []
}
return entry.children.map {
if let entry = map[Int($0.offset)] {
return extractProgramOffsets(
currentName: currentName + $0.label,
currentOffset: currentOffset,
entry: entry,
map: map
)
} else {
if let content = entry.content {
return [
.init(
name: currentName + $0.label,
offset: content.offset
)
]
}
return []
}
}.flatMap { $0 }
}
}
Loading

0 comments on commit 4153326

Please sign in to comment.